mirror of
https://github.com/Ultimaker/Cura.git
synced 2025-07-25 15:44:04 -06:00
Fix creating a jobname after loading a file
Moves jobname creation out of qml and into python. CURA-1619
This commit is contained in:
parent
14a8b8a1a4
commit
bb18bf6a30
5 changed files with 79 additions and 83 deletions
|
@ -436,21 +436,6 @@ class CuraApplication(QtApplication):
|
||||||
self._platform_activity = True if count > 0 else False
|
self._platform_activity = True if count > 0 else False
|
||||||
self.activityChanged.emit()
|
self.activityChanged.emit()
|
||||||
|
|
||||||
@pyqtSlot(str)
|
|
||||||
def setJobName(self, name):
|
|
||||||
# when a file is opened using the terminal; the filename comes from _onFileLoaded and still contains its
|
|
||||||
# extension. This cuts the extension off if necessary.
|
|
||||||
name = os.path.splitext(name)[0]
|
|
||||||
if self._job_name != name:
|
|
||||||
self._job_name = name
|
|
||||||
self.jobNameChanged.emit()
|
|
||||||
|
|
||||||
jobNameChanged = pyqtSignal()
|
|
||||||
|
|
||||||
@pyqtProperty(str, notify = jobNameChanged)
|
|
||||||
def jobName(self):
|
|
||||||
return self._job_name
|
|
||||||
|
|
||||||
# Remove all selected objects from the scene.
|
# Remove all selected objects from the scene.
|
||||||
@pyqtSlot()
|
@pyqtSlot()
|
||||||
def deleteSelection(self):
|
def deleteSelection(self):
|
||||||
|
|
|
@ -1,14 +1,17 @@
|
||||||
# Copyright (c) 2015 Ultimaker B.V.
|
# Copyright (c) 2015 Ultimaker B.V.
|
||||||
# Cura is released under the terms of the AGPLv3 or higher.
|
# Cura is released under the terms of the AGPLv3 or higher.
|
||||||
|
|
||||||
from PyQt5.QtCore import QObject, pyqtSignal, pyqtProperty
|
from PyQt5.QtCore import QObject, pyqtSignal, pyqtProperty, pyqtSlot
|
||||||
|
|
||||||
from UM.Application import Application
|
from UM.Application import Application
|
||||||
from UM.Qt.Duration import Duration
|
from UM.Qt.Duration import Duration
|
||||||
|
from UM.Preferences import Preferences
|
||||||
|
|
||||||
import math
|
import math
|
||||||
|
import os.path
|
||||||
|
import unicodedata
|
||||||
|
|
||||||
## A class for processing and calculating minimum, current and maximum print time.
|
## A class for processing and calculating minimum, current and maximum print time as well as managing the job name
|
||||||
#
|
#
|
||||||
# This class contains all the logic relating to calculation and slicing for the
|
# This class contains all the logic relating to calculation and slicing for the
|
||||||
# time/quality slider concept. It is a rather tricky combination of event handling
|
# time/quality slider concept. It is a rather tricky combination of event handling
|
||||||
|
@ -22,6 +25,8 @@ import math
|
||||||
# - When that is done, we update the minimum print time and start the final slice pass, the "high quality settings pass".
|
# - When that is done, we update the minimum print time and start the final slice pass, the "high quality settings pass".
|
||||||
# - When the high quality pass is done, we update the maximum print time.
|
# - When the high quality pass is done, we update the maximum print time.
|
||||||
#
|
#
|
||||||
|
# This class also mangles the current machine name and the filename of the first loaded mesh into a job name.
|
||||||
|
# This job name is requested by the JobSpecs qml file.
|
||||||
class PrintInformation(QObject):
|
class PrintInformation(QObject):
|
||||||
class SlicePass:
|
class SlicePass:
|
||||||
CurrentSettings = 1
|
CurrentSettings = 1
|
||||||
|
@ -45,14 +50,17 @@ class PrintInformation(QObject):
|
||||||
if self._backend:
|
if self._backend:
|
||||||
self._backend.printDurationMessage.connect(self._onPrintDurationMessage)
|
self._backend.printDurationMessage.connect(self._onPrintDurationMessage)
|
||||||
|
|
||||||
|
self._job_name = ""
|
||||||
|
Application.getInstance().globalContainerStackChanged.connect(self._onGlobalStackChanged)
|
||||||
|
|
||||||
currentPrintTimeChanged = pyqtSignal()
|
currentPrintTimeChanged = pyqtSignal()
|
||||||
|
|
||||||
@pyqtProperty(Duration, notify = currentPrintTimeChanged)
|
@pyqtProperty(Duration, notify = currentPrintTimeChanged)
|
||||||
def currentPrintTime(self):
|
def currentPrintTime(self):
|
||||||
return self._current_print_time
|
return self._current_print_time
|
||||||
|
|
||||||
materialAmountChanged = pyqtSignal()
|
materialAmountChanged = pyqtSignal()
|
||||||
|
|
||||||
@pyqtProperty(float, notify = materialAmountChanged)
|
@pyqtProperty(float, notify = materialAmountChanged)
|
||||||
def materialAmount(self):
|
def materialAmount(self):
|
||||||
return self._material_amount
|
return self._material_amount
|
||||||
|
@ -66,3 +74,43 @@ class PrintInformation(QObject):
|
||||||
r = Application.getInstance().getGlobalContainerStack().getProperty("material_diameter", "value") / 2
|
r = Application.getInstance().getGlobalContainerStack().getProperty("material_diameter", "value") / 2
|
||||||
self._material_amount = round((amount / (math.pi * r ** 2)) / 1000, 2)
|
self._material_amount = round((amount / (math.pi * r ** 2)) / 1000, 2)
|
||||||
self.materialAmountChanged.emit()
|
self.materialAmountChanged.emit()
|
||||||
|
|
||||||
|
@pyqtSlot(str)
|
||||||
|
def setJobName(self, name):
|
||||||
|
# when a file is opened using the terminal; the filename comes from _onFileLoaded and still contains its
|
||||||
|
# extension. This cuts the extension off if necessary.
|
||||||
|
name = os.path.splitext(name)[0]
|
||||||
|
if self._job_name != name:
|
||||||
|
self._job_name = name
|
||||||
|
self.jobNameChanged.emit()
|
||||||
|
|
||||||
|
jobNameChanged = pyqtSignal()
|
||||||
|
|
||||||
|
@pyqtProperty(str, notify = jobNameChanged)
|
||||||
|
def jobName(self):
|
||||||
|
return self._job_name
|
||||||
|
|
||||||
|
@pyqtSlot(str, result = str)
|
||||||
|
def createJobName(self, base_name):
|
||||||
|
base_name = self._stripAccents(base_name)
|
||||||
|
if Preferences.getInstance().getValue("cura/jobname_prefix"):
|
||||||
|
return self._abbr_machine + "_" + base_name
|
||||||
|
else:
|
||||||
|
return base_name
|
||||||
|
|
||||||
|
def _onGlobalStackChanged(self):
|
||||||
|
global_stack_name = Application.getInstance().getGlobalContainerStack().getName()
|
||||||
|
split_name = global_stack_name.split(" ")
|
||||||
|
abbr_machine = ""
|
||||||
|
for word in split_name:
|
||||||
|
if(word.lower() == "ultimaker"):
|
||||||
|
abbr_machine += "UM"
|
||||||
|
elif word.isdigit():
|
||||||
|
abbr_machine += word
|
||||||
|
else:
|
||||||
|
abbr_machine += self._stripAccents(word.strip("()[]{}#").upper())[0]
|
||||||
|
|
||||||
|
self._abbr_machine = abbr_machine
|
||||||
|
|
||||||
|
def _stripAccents(self, str):
|
||||||
|
return ''.join(char for char in unicodedata.normalize('NFD', str) if unicodedata.category(char) != 'Mn')
|
|
@ -93,7 +93,7 @@ UM.MainWindow
|
||||||
text: catalog.i18nc("@action:inmenu menubar:file", "&Save Selection to File");
|
text: catalog.i18nc("@action:inmenu menubar:file", "&Save Selection to File");
|
||||||
enabled: UM.Selection.hasSelection;
|
enabled: UM.Selection.hasSelection;
|
||||||
iconName: "document-save-as";
|
iconName: "document-save-as";
|
||||||
onTriggered: UM.OutputDeviceManager.requestWriteSelectionToDevice("local_file", Printer.jobName, { "filter_by_machine": false });
|
onTriggered: UM.OutputDeviceManager.requestWriteSelectionToDevice("local_file", PrintInformation.jobName, { "filter_by_machine": false });
|
||||||
}
|
}
|
||||||
Menu
|
Menu
|
||||||
{
|
{
|
||||||
|
@ -109,7 +109,7 @@ UM.MainWindow
|
||||||
MenuItem
|
MenuItem
|
||||||
{
|
{
|
||||||
text: model.description;
|
text: model.description;
|
||||||
onTriggered: UM.OutputDeviceManager.requestWriteToDevice(model.id, Printer.jobName, { "filter_by_machine": false });
|
onTriggered: UM.OutputDeviceManager.requestWriteToDevice(model.id, PrintInformation.jobName, { "filter_by_machine": false });
|
||||||
}
|
}
|
||||||
onObjectAdded: saveAllMenu.insertItem(index, object)
|
onObjectAdded: saveAllMenu.insertItem(index, object)
|
||||||
onObjectRemoved: saveAllMenu.removeItem(object)
|
onObjectRemoved: saveAllMenu.removeItem(object)
|
||||||
|
|
|
@ -10,62 +10,25 @@ import UM 1.1 as UM
|
||||||
import Cura 1.0 as Cura
|
import Cura 1.0 as Cura
|
||||||
|
|
||||||
Rectangle {
|
Rectangle {
|
||||||
id: base;
|
id: base
|
||||||
|
|
||||||
property bool activity: Printer.getPlatformActivity;
|
property bool activity: Printer.getPlatformActivity
|
||||||
property string fileBaseName
|
property string fileBaseName
|
||||||
property variant activeMachineName: Cura.MachineManager.activeMachineName
|
property variant activeMachineName: Cura.MachineManager.activeMachineName
|
||||||
|
|
||||||
onActiveMachineNameChanged:
|
onActiveMachineNameChanged:
|
||||||
{
|
{
|
||||||
base.createFileName()
|
printJobTextfield.text = PrintInformation.createJobName(base.fileBaseName);
|
||||||
}
|
}
|
||||||
|
|
||||||
UM.I18nCatalog { id: catalog; name:"cura"}
|
UM.I18nCatalog { id: catalog; name:"cura"}
|
||||||
|
|
||||||
property variant printDuration: PrintInformation.currentPrintTime;
|
property variant printDuration: PrintInformation.currentPrintTime
|
||||||
property real printMaterialAmount: PrintInformation.materialAmount;
|
property real printMaterialAmount: PrintInformation.materialAmount
|
||||||
|
|
||||||
height: childrenRect.height
|
height: childrenRect.height
|
||||||
color: "transparent"
|
color: "transparent"
|
||||||
|
|
||||||
function createFileName()
|
|
||||||
{
|
|
||||||
var splitMachineName = Cura.MachineManager.activeMachineName.split(" ")
|
|
||||||
var abbrMachine = "";
|
|
||||||
if ((UM.Preferences.getValue("cura/jobname_prefix")))
|
|
||||||
{
|
|
||||||
for (var i = 0; i < splitMachineName.length; i++)
|
|
||||||
{
|
|
||||||
if (splitMachineName[i].search(/ultimaker/i) != -1)
|
|
||||||
{
|
|
||||||
abbrMachine += "UM";
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
if (splitMachineName[i].charAt(0).search(/[0-9]/g) == -1)
|
|
||||||
{
|
|
||||||
abbrMachine += splitMachineName[i].charAt(0);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
var regExpAdditives = /[0-9\+]/g;
|
|
||||||
var resultAdditives = splitMachineName[i].match(regExpAdditives);
|
|
||||||
if (resultAdditives != null)
|
|
||||||
{
|
|
||||||
for (var j = 0; j < resultAdditives.length; j++)
|
|
||||||
{
|
|
||||||
abbrMachine += resultAdditives[j];
|
|
||||||
}
|
|
||||||
}
|
|
||||||
printJobTextfield.text = abbrMachine + "_" + base.fileBaseName;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
printJobTextfield.text = base.fileBaseName;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
Connections
|
Connections
|
||||||
{
|
{
|
||||||
target: backgroundItem
|
target: backgroundItem
|
||||||
|
@ -78,20 +41,20 @@ Rectangle {
|
||||||
onActivityChanged: {
|
onActivityChanged: {
|
||||||
if (activity == true && base.fileBaseName == ''){
|
if (activity == true && base.fileBaseName == ''){
|
||||||
//this only runs when you open a file from the terminal (or something that works the same way; for example when you drag a file on the icon in MacOS or use 'open with' on Windows)
|
//this only runs when you open a file from the terminal (or something that works the same way; for example when you drag a file on the icon in MacOS or use 'open with' on Windows)
|
||||||
base.fileBaseName = Printer.jobName //it gets the fileBaseName from CuraApplication.py because this saves the filebase when the file is opened using the terminal (or something alike)
|
base.fileBaseName = PrintInformation.jobName; //get the fileBaseName from PrintInformation.py because this saves the filebase when the file is opened using the terminal (or something alike)
|
||||||
base.createFileName()
|
printJobTextfield.text = PrintInformation.createJobName(base.fileBaseName);
|
||||||
}
|
}
|
||||||
if (activity == true && base.fileBaseName != ''){
|
if (activity == true && base.fileBaseName != ''){
|
||||||
//this runs in all other cases where there is a mesh on the buildplate (activity == true). It uses the fileBaseName from the hasMesh signal
|
//this runs in all other cases where there is a mesh on the buildplate (activity == true). It uses the fileBaseName from the hasMesh signal
|
||||||
base.createFileName()
|
printJobTextfield.text = PrintInformation.createJobName(base.fileBaseName);
|
||||||
}
|
}
|
||||||
if (activity == false){
|
if (activity == false){
|
||||||
//When there is no mesh in the buildplate; the printJobTextField is set to an empty string so it doesn't set an empty string as a jobName (which is later used for saving the file)
|
//When there is no mesh in the buildplate; the printJobTextField is set to an empty string so it doesn't set an empty string as a jobName (which is later used for saving the file)
|
||||||
printJobTextfield.text = ''
|
printJobTextfield.text = '';
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Rectangle
|
Rectangle
|
||||||
{
|
{
|
||||||
id: jobNameRow
|
id: jobNameRow
|
||||||
anchors.top: parent.top
|
anchors.top: parent.top
|
||||||
|
@ -112,22 +75,22 @@ Rectangle {
|
||||||
width: UM.Theme.getSize("save_button_specs_icons").width
|
width: UM.Theme.getSize("save_button_specs_icons").width
|
||||||
height: UM.Theme.getSize("save_button_specs_icons").height
|
height: UM.Theme.getSize("save_button_specs_icons").height
|
||||||
|
|
||||||
onClicked:
|
onClicked:
|
||||||
{
|
{
|
||||||
printJobTextfield.selectAll()
|
printJobTextfield.selectAll();
|
||||||
printJobTextfield.focus = true
|
printJobTextfield.focus = true;
|
||||||
}
|
}
|
||||||
style: ButtonStyle
|
style: ButtonStyle
|
||||||
{
|
{
|
||||||
background: Rectangle
|
background: Rectangle
|
||||||
{
|
{
|
||||||
color: "transparent"
|
color: "transparent"
|
||||||
UM.RecolorImage
|
UM.RecolorImage
|
||||||
{
|
{
|
||||||
width: UM.Theme.getSize("save_button_specs_icons").width
|
width: UM.Theme.getSize("save_button_specs_icons").width;
|
||||||
height: UM.Theme.getSize("save_button_specs_icons").height
|
height: UM.Theme.getSize("save_button_specs_icons").height;
|
||||||
sourceSize.width: width
|
sourceSize.width: width;
|
||||||
sourceSize.height: width
|
sourceSize.height: width;
|
||||||
color: control.hovered ? UM.Theme.getColor("setting_control_button_hover") : UM.Theme.getColor("text");
|
color: control.hovered ? UM.Theme.getColor("setting_control_button_hover") : UM.Theme.getColor("text");
|
||||||
source: UM.Theme.getIcon("pencil");
|
source: UM.Theme.getIcon("pencil");
|
||||||
}
|
}
|
||||||
|
@ -147,15 +110,15 @@ Rectangle {
|
||||||
text: ''
|
text: ''
|
||||||
horizontalAlignment: TextInput.AlignRight
|
horizontalAlignment: TextInput.AlignRight
|
||||||
onTextChanged: {
|
onTextChanged: {
|
||||||
Printer.setJobName(text)
|
PrintInformation.setJobName(text);
|
||||||
}
|
}
|
||||||
onEditingFinished: {
|
onEditingFinished: {
|
||||||
if (printJobTextfield.text != ''){
|
if (printJobTextfield.text != ''){
|
||||||
printJobTextfield.focus = false
|
printJobTextfield.focus = false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
validator: RegExpValidator {
|
validator: RegExpValidator {
|
||||||
regExp: /^[^\\ \/ \.]*$/
|
regExp: /^[^\\ \/ \*\?\|\[\]]*$/
|
||||||
}
|
}
|
||||||
style: TextFieldStyle{
|
style: TextFieldStyle{
|
||||||
textColor: UM.Theme.getColor("setting_control_text");
|
textColor: UM.Theme.getColor("setting_control_text");
|
||||||
|
@ -200,7 +163,7 @@ Rectangle {
|
||||||
sourceSize.width: width
|
sourceSize.width: width
|
||||||
sourceSize.height: width
|
sourceSize.height: width
|
||||||
color: UM.Theme.getColor("text_subtext")
|
color: UM.Theme.getColor("text_subtext")
|
||||||
source: UM.Theme.getIcon("print_time");
|
source: UM.Theme.getIcon("print_time")
|
||||||
}
|
}
|
||||||
Label{
|
Label{
|
||||||
id: timeSpec
|
id: timeSpec
|
||||||
|
@ -221,7 +184,7 @@ Rectangle {
|
||||||
sourceSize.width: width
|
sourceSize.width: width
|
||||||
sourceSize.height: width
|
sourceSize.height: width
|
||||||
color: UM.Theme.getColor("text_subtext")
|
color: UM.Theme.getColor("text_subtext")
|
||||||
source: UM.Theme.getIcon("category_material");
|
source: UM.Theme.getIcon("category_material")
|
||||||
}
|
}
|
||||||
Label{
|
Label{
|
||||||
id: lengthSpec
|
id: lengthSpec
|
||||||
|
@ -229,7 +192,7 @@ Rectangle {
|
||||||
anchors.verticalCenter: parent.verticalCenter
|
anchors.verticalCenter: parent.verticalCenter
|
||||||
font: UM.Theme.getFont("small")
|
font: UM.Theme.getFont("small")
|
||||||
color: UM.Theme.getColor("text_subtext")
|
color: UM.Theme.getColor("text_subtext")
|
||||||
text: base.printMaterialAmount <= 0 ? catalog.i18nc("@label", "0.0 m") : catalog.i18nc("@label", "%1 m").arg(base.printMaterialAmount)
|
text: catalog.i18nc("@label", "%1 m").arg(base.printMaterialAmount > 0 ? base.printMaterialAmount : 0)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -98,7 +98,7 @@ Rectangle {
|
||||||
text: UM.OutputDeviceManager.activeDeviceShortDescription
|
text: UM.OutputDeviceManager.activeDeviceShortDescription
|
||||||
onClicked:
|
onClicked:
|
||||||
{
|
{
|
||||||
UM.OutputDeviceManager.requestWriteToDevice(UM.OutputDeviceManager.activeDevice, Printer.jobName, { "filter_by_machine": true })
|
UM.OutputDeviceManager.requestWriteToDevice(UM.OutputDeviceManager.activeDevice, PrintInformation.jobName, { "filter_by_machine": true })
|
||||||
}
|
}
|
||||||
|
|
||||||
style: ButtonStyle {
|
style: ButtonStyle {
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue