diff --git a/cura/Settings/MachineManager.py b/cura/Settings/MachineManager.py index 520f95e293..e0e81fba1b 100755 --- a/cura/Settings/MachineManager.py +++ b/cura/Settings/MachineManager.py @@ -304,6 +304,7 @@ class MachineManager(QObject): quality.nameChanged.connect(self._onQualityNameChanged) self._active_container_stack = self._global_container_stack + self.activeStackChanged.emit() self._error_check_timer.start() diff --git a/plugins/3MFReader/ThreeMFWorkspaceReader.py b/plugins/3MFReader/ThreeMFWorkspaceReader.py index 22a9291acb..c8d1c85273 100755 --- a/plugins/3MFReader/ThreeMFWorkspaceReader.py +++ b/plugins/3MFReader/ThreeMFWorkspaceReader.py @@ -370,7 +370,7 @@ class ThreeMFWorkspaceReader(WorkspaceReader): ## Overrides an ExtruderStack in the given GlobalStack and returns the new ExtruderStack. def _overrideExtruderStack(self, global_stack, extruder_file_content): - # get extruder position first + # Get extruder position first extruder_config = configparser.ConfigParser() extruder_config.read_string(extruder_file_content) if not extruder_config.has_option("metadata", "position"): @@ -378,10 +378,9 @@ class ThreeMFWorkspaceReader(WorkspaceReader): Logger.log("e", "Could not find 'metadata/position' in extruder stack file") raise RuntimeError(msg) extruder_position = extruder_config.get("metadata", "position") - extruder_stack = global_stack.extruders[extruder_position] - # override the given extruder stack + # Override the given extruder stack extruder_stack.deserialize(extruder_file_content) # return the new ExtruderStack @@ -699,8 +698,9 @@ class ThreeMFWorkspaceReader(WorkspaceReader): extruder_file_content = archive.open(extruder_stack_file, "r").read().decode("utf-8") if self._resolve_strategies["machine"] == "override": - # deserialize new extruder stack over the current ones - stack = self._overrideExtruderStack(global_stack, extruder_file_content) + if global_stack.getProperty("machine_extruder_count", "value") > 1: + # deserialize new extruder stack over the current ones (if any) + stack = self._overrideExtruderStack(global_stack, extruder_file_content) elif self._resolve_strategies["machine"] == "new": new_id = extruder_stack_id_map[container_id] @@ -732,8 +732,8 @@ class ThreeMFWorkspaceReader(WorkspaceReader): # Create a new definition_changes container if it was empty if stack.definitionChanges == self._container_registry.getEmptyInstanceContainer(): stack.setDefinitionChanges(CuraStackBuilder.createDefinitionChangesContainer(stack, stack._id + "_settings")) - - extruder_stacks.append(stack) + if global_stack.getProperty("machine_extruder_count", "value") > 1: + extruder_stacks.append(stack) except: Logger.logException("w", "We failed to serialize the stack. Trying to clean up.") # Something went really wrong. Try to remove any data that we added. diff --git a/plugins/UM3NetworkPrinting/ClusterControlItem.qml b/plugins/UM3NetworkPrinting/ClusterControlItem.qml index bcb5b0bd57..194337cca0 100644 --- a/plugins/UM3NetworkPrinting/ClusterControlItem.qml +++ b/plugins/UM3NetworkPrinting/ClusterControlItem.qml @@ -6,11 +6,13 @@ import Cura 1.0 as Cura Component { - Item + Rectangle { id: base property var manager: Cura.MachineManager.printerOutputDevices[0] anchors.fill: parent + color: UM.Theme.getColor("viewport_background") + property var lineColor: "#DCDCDC" // TODO: Should be linked to theme. property var cornerRadius: 4 * screenScaleFactor // TODO: Should be linked to theme. @@ -27,24 +29,17 @@ Component id: activePrintersLabel font: UM.Theme.getFont("large") anchors.horizontalCenter: parent.horizontalCenter + anchors.topMargin: UM.Theme.getSize("default_margin").height + anchors.top: parent.top text: Cura.MachineManager.printerOutputDevices[0].name } - Label - { - id: printerGroupLabel - anchors.top: activePrintersLabel.bottom - text: catalog.i18nc("@label", "Printer Group").toUpperCase() - anchors.horizontalCenter: parent.horizontalCenter - font: UM.Theme.getFont("very_small") - opacity: 0.65 - } Rectangle { id: printJobArea border.width: UM.Theme.getSize("default_lining").width border.color: lineColor - anchors.top: printerGroupLabel.bottom + anchors.top: activePrintersLabel.bottom anchors.topMargin: UM.Theme.getSize("default_margin").height anchors.left: parent.left anchors.leftMargin: UM.Theme.getSize("default_margin").width @@ -240,4 +235,4 @@ Component } } } -} \ No newline at end of file +} diff --git a/plugins/UM3NetworkPrinting/ClusterMonitorItem.qml b/plugins/UM3NetworkPrinting/ClusterMonitorItem.qml index 48fb0a33fc..c1d852072f 100644 --- a/plugins/UM3NetworkPrinting/ClusterMonitorItem.qml +++ b/plugins/UM3NetworkPrinting/ClusterMonitorItem.qml @@ -11,7 +11,7 @@ Component { width: maximumWidth height: maximumHeight - color: "#FFFFFF" // TODO; Should not be hardcoded. + color: UM.Theme.getColor("viewport_background") property var emphasisColor: "#44c0ff" //TODO: should be linked to theme. property var lineColor: "#DCDCDC" // TODO: Should be linked to theme. @@ -49,7 +49,7 @@ Component anchors.topMargin: UM.Theme.getSize("default_margin").height anchors.top: parent.top anchors.horizontalCenter: parent.horizontalCenter - + width: Math.min(800 * screenScaleFactor, maximumWidth) height: children.height visible: OutputDevice.connectedPrinters.length != 0 diff --git a/plugins/UM3NetworkPrinting/DiscoverUM3Action.qml b/plugins/UM3NetworkPrinting/DiscoverUM3Action.qml index 11ebdd818b..1bcbd1c4b9 100644 --- a/plugins/UM3NetworkPrinting/DiscoverUM3Action.qml +++ b/plugins/UM3NetworkPrinting/DiscoverUM3Action.qml @@ -389,4 +389,4 @@ Cura.MachineAction } ] } -} \ No newline at end of file +} diff --git a/plugins/UM3NetworkPrinting/NetworkClusterPrinterOutputDevice.py b/plugins/UM3NetworkPrinting/NetworkClusterPrinterOutputDevice.py index 94bd6bc9a3..32ed18bc9f 100644 --- a/plugins/UM3NetworkPrinting/NetworkClusterPrinterOutputDevice.py +++ b/plugins/UM3NetworkPrinting/NetworkClusterPrinterOutputDevice.py @@ -13,10 +13,12 @@ from PyQt5.QtGui import QDesktopServices from PyQt5.QtNetwork import QNetworkAccessManager, QNetworkReply from PyQt5.QtQml import QQmlComponent, QQmlContext from UM.Application import Application +from UM.Decorators import override from UM.Logger import Logger from UM.Message import Message from UM.OutputDevice import OutputDeviceError from UM.i18n import i18nCatalog +from UM.Qt.Duration import Duration, DurationFormat from . import NetworkPrinterOutputDevice @@ -44,6 +46,7 @@ class NetworkClusterPrinterOutputDevice(NetworkPrinterOutputDevice.NetworkPrinte else: name = key + self._authentication_state = NetworkPrinterOutputDevice.AuthState.Authenticated # The printer is always authenticated self._plugin_path = plugin_path self.setName(name) @@ -110,6 +113,20 @@ class NetworkClusterPrinterOutputDevice(NetworkPrinterOutputDevice.NetworkPrinte temporary_translation3 = i18n_catalog.i18n("{printer_name} has finished printing '{job_name}'. Please collect the print and confirm clearing the build plate.") #When finished. temporary_translation4 = i18n_catalog.i18n("{printer_name} is reserved to print '{job_name}'. Please change the printer's configuration to match the job, for it to start printing.") #When configuration changed. + ## No authentication, so requestAuthentication should do exactly nothing + @pyqtSlot() + def requestAuthentication(self, message_id = None, action_id = "Retry"): + pass # Cura Connect doesn't do any authorization + + def setAuthenticationState(self, auth_state): + self._authentication_state = NetworkPrinterOutputDevice.AuthState.Authenticated # The printer is always authenticated + + def _verifyAuthentication(self): + pass + + def _checkAuthentication(self): + Logger.log("d", "_checkAuthentication Cura Connect - nothing to be done") + @pyqtProperty(QObject, notify=selectedPrinterChanged) def controlItem(self): # TODO: Probably not the nicest way to do this. This needs to be done better at some point in time. @@ -173,18 +190,19 @@ class NetworkClusterPrinterOutputDevice(NetworkPrinterOutputDevice.NetworkPrinte def _requestClusterStatus(self): # TODO: Handle timeout. We probably want to know if the cluster is still reachable or not. - url = QUrl(self._api_base_uri + "print_jobs/") - print_jobs_request = QNetworkRequest(url) - self._addUserAgentHeader(print_jobs_request) - self._manager.get(print_jobs_request) - # See _finishedPrintJobsRequest() - url = QUrl(self._api_base_uri + "printers/") printers_request = QNetworkRequest(url) self._addUserAgentHeader(printers_request) self._manager.get(printers_request) # See _finishedPrintersRequest() + if self._printers: # if printers is not empty + url = QUrl(self._api_base_uri + "print_jobs/") + print_jobs_request = QNetworkRequest(url) + self._addUserAgentHeader(print_jobs_request) + self._manager.get(print_jobs_request) + # See _finishedPrintJobsRequest() + def _finishedPrintJobsRequest(self, reply): try: json_data = json.loads(bytes(reply.readAll()).decode("utf-8")) @@ -275,7 +293,10 @@ class NetworkClusterPrinterOutputDevice(NetworkPrinterOutputDevice.NetworkPrinte self._file_name = "%s.gcode.gz" % file_name self._showProgressMessage() - self._request = self._buildSendPrintJobHttpRequest(require_printer_name) + new_request = self._buildSendPrintJobHttpRequest(require_printer_name) + if new_request is None or self._stage != OutputStage.uploading: + return + self._request = new_request self._reply = self._manager.post(self._request, self._multipart) self._reply.uploadProgress.connect(self._onUploadProgress) # See _finishedPostPrintJobRequest() @@ -294,7 +315,7 @@ class NetworkClusterPrinterOutputDevice(NetworkPrinterOutputDevice.NetworkPrinte gcode = getattr(Application.getInstance().getController().getScene(), "gcode_list") compressed_gcode = self._compressGcode(gcode) if compressed_gcode is None: - return # User aborted print, so stop trying. + return None # User aborted print, so stop trying. part.setBody(compressed_gcode) self._multipart.append(part) @@ -331,7 +352,7 @@ class NetworkClusterPrinterOutputDevice(NetworkPrinterOutputDevice.NetworkPrinte for line in gcode: if not self._compressing_print: self._progress_message.hide() - return # Stop trying to zip, abort was called. + return None # Stop trying to zip, abort was called. batched_line += line # if the gcode was read from a gcode file, self._gcode will be a list of all lines in that file. # Compressing line by line in this case is extremely slow, so we need to batch them. @@ -489,7 +510,8 @@ class NetworkClusterPrinterOutputDevice(NetworkPrinterOutputDevice.NetworkPrinte printer_name = self.__getPrinterNameFromUuid(print_job["assigned_to"]) if printer_name is None: - printer_name = i18n_catalog.i18nc("@info:status", "Unknown printer") + # don't report on yet unknown printers + continue message_text = (i18n_catalog.i18n("{printer_name} is reserved to print '{job_name}'. Please change the printer's configuration to match the job, for it to start printing.") .format(printer_name=printer_name, job_name=print_job["name"])) @@ -625,9 +647,7 @@ class NetworkClusterPrinterOutputDevice(NetworkPrinterOutputDevice.NetworkPrinte request.setRawHeader(b"User-agent", b"CuraPrintClusterOutputDevice Plugin") def _cleanupRequest(self): - self._reply = None self._request = None - self._multipart = None self._stage = OutputStage.ready self._file_name = None @@ -680,8 +700,11 @@ class NetworkClusterPrinterOutputDevice(NetworkPrinterOutputDevice.NetworkPrinte Logger.log("d", "User aborted sending print to remote.") self._progress_message.hide() self._compressing_print = False - self._stage = OutputStage.ready if self._reply: self._reply.abort() - self._reply = None + self._stage = OutputStage.ready Application.getInstance().showPrintMonitor.emit(False) + + @pyqtSlot(int, result=str) + def formatDuration(self, seconds): + return Duration(seconds).getDisplayString(DurationFormat.Format.Short) diff --git a/plugins/UM3NetworkPrinting/NetworkPrinterOutputDevice.py b/plugins/UM3NetworkPrinting/NetworkPrinterOutputDevice.py index 15cd2bb1b3..994f332d46 100755 --- a/plugins/UM3NetworkPrinting/NetworkPrinterOutputDevice.py +++ b/plugins/UM3NetworkPrinting/NetworkPrinterOutputDevice.py @@ -335,8 +335,11 @@ class NetworkPrinterOutputDevice(PrinterOutputDevice): if self._image_reply: try: + try: + self._image_reply.downloadProgress.disconnect(self._onStreamDownloadProgress) + except TypeError: + pass #The signal was never connected. self._image_reply.abort() - self._image_reply.downloadProgress.disconnect(self._onStreamDownloadProgress) except RuntimeError: pass # It can happen that the wrapped c++ object is already deleted. self._image_reply = None @@ -427,7 +430,7 @@ class NetworkPrinterOutputDevice(PrinterOutputDevice): Logger.log("d", "Requestion authentication for %s due to action %s" % (self._key, action_id)) self._authentication_failed_message.hide() self._not_authenticated_message.hide() - self._authentication_state = AuthState.NotAuthenticated + self.setAuthenticationState(AuthState.NotAuthenticated) self._authentication_counter = 0 self._authentication_requested_message.setProgress(0) self._authentication_id = None @@ -614,7 +617,7 @@ class NetworkPrinterOutputDevice(PrinterOutputDevice): # Reset authentication state self._authentication_requested_message.hide() - self._authentication_state = AuthState.NotAuthenticated + self.setAuthenticationState(AuthState.NotAuthenticated) self._authentication_counter = 0 self._authentication_timer.stop() diff --git a/plugins/UM3NetworkPrinting/OpenPanelButton.qml b/plugins/UM3NetworkPrinting/OpenPanelButton.qml index 2a59d0fa83..4bc1728f76 100644 --- a/plugins/UM3NetworkPrinting/OpenPanelButton.qml +++ b/plugins/UM3NetworkPrinting/OpenPanelButton.qml @@ -14,5 +14,58 @@ Button { tooltip: catalog.i18nc("@info:tooltip", "Opens the print jobs page with your default web browser.") text: catalog.i18nc("@action:button", "View print jobs") - style: UM.Theme.styles.sidebar_action_button + // FIXME: This button style is copied and duplicated from SaveButton.qml + style: ButtonStyle { + background: Rectangle + { + border.width: UM.Theme.getSize("default_lining").width + border.color: + { + if(!control.enabled) + return UM.Theme.getColor("action_button_disabled_border"); + else if(control.pressed) + return UM.Theme.getColor("print_button_ready_pressed_border"); + else if(control.hovered) + return UM.Theme.getColor("print_button_ready_hovered_border"); + else + return UM.Theme.getColor("print_button_ready_border"); + } + color: + { + if(!control.enabled) + return UM.Theme.getColor("action_button_disabled"); + else if(control.pressed) + return UM.Theme.getColor("print_button_ready_pressed"); + else if(control.hovered) + return UM.Theme.getColor("print_button_ready_hovered"); + else + return UM.Theme.getColor("print_button_ready"); + } + + Behavior on color { ColorAnimation { duration: 50; } } + + implicitWidth: actualLabel.contentWidth + (UM.Theme.getSize("sidebar_margin").width * 2) + + Label { + id: actualLabel + anchors.centerIn: parent + color: + { + if(!control.enabled) + return UM.Theme.getColor("action_button_disabled_text"); + else if(control.pressed) + return UM.Theme.getColor("print_button_ready_text"); + else if(control.hovered) + return UM.Theme.getColor("print_button_ready_text"); + else + return UM.Theme.getColor("print_button_ready_text"); + } + font: UM.Theme.getFont("action_button") + text: control.text; + } + } + label: Item { } + } + + } diff --git a/plugins/UM3NetworkPrinting/PrinterInfoBlock.qml b/plugins/UM3NetworkPrinting/PrinterInfoBlock.qml index e548c9e9d7..2b55cd9152 100644 --- a/plugins/UM3NetworkPrinting/PrinterInfoBlock.qml +++ b/plugins/UM3NetworkPrinting/PrinterInfoBlock.qml @@ -14,14 +14,7 @@ Rectangle function getPrettyTime(time) { - var hours = Math.floor(time / 3600) - time -= hours * 3600 - var minutes = Math.floor(time / 60); - time -= minutes * 60 - var seconds = Math.floor(time); - - var finalTime = strPadLeft(hours, "0", 2) + ':' + strPadLeft(minutes,'0',2)+ ':' + strPadLeft(seconds,'0',2); - return finalTime; + return OutputDevice.formatDuration(time) } function formatPrintJobPercent(printJob) @@ -37,6 +30,23 @@ Rectangle return Math.min(100, Math.round(printJob.time_elapsed / printJob.time_total * 100)) + "%"; } + function printerStatusText(printer) + { + switch (printer.status) + { + case "pre_print": + return catalog.i18nc("@label", "Preparing to print") + case "printing": + return catalog.i18nc("@label:status", "Printing"); + case "idle": + return catalog.i18nc("@label:status", "Available"); + case "unreachable": // TODO: new string + case "maintenance": // TODO: new string + case "unknown": + default: + return catalog.i18nc("@label", "Unknown"); + } + } id: printerDelegate property var printer @@ -143,14 +153,14 @@ Rectangle anchors.right: printProgressArea.left anchors.rightMargin: UM.Theme.getSize("default_margin").width color: emphasisColor - UM.RecolorImage + + Image { - anchors.verticalCenter: parent.verticalCenter - anchors.horizontalCenter: parent.horizontalCenter + width: 40 * screenScaleFactor + height: width + anchors.right: parent.right + anchors.rightMargin: parent.rightMargin source: "camera-icon.svg" - width: sourceSize.width - height: sourceSize.height * width / sourceSize.width - color: "white" } } @@ -217,6 +227,9 @@ Rectangle //border.color: lineColor height: 40 * screenScaleFactor anchors.left: parent.left + property var showPercent: { + return printJob != null && (["printing", "post_print", "pre_print", "sent_to_printer"].indexOf(printJob.status) !== -1); + } Label { @@ -232,7 +245,7 @@ Rectangle return catalog.i18nc("@label:status", "Disabled"); } - if(printJob != null) + if ((printJob != null) && ((printer.status === "pre_print") || (printer.status === "printing"))) { switch (printJob.status) { @@ -263,16 +276,17 @@ Rectangle case "aborted": return catalog.i18nc("@label:status", "Print aborted"); default: - return ""; + return printerStatusText(printer); } } - return catalog.i18nc("@label:status", "Available"); + return printerStatusText(printer); } elide: Text.ElideRight font: UM.Theme.getFont("small") } + Label { id: progressText @@ -282,10 +296,44 @@ Rectangle anchors.top: statusText.top text: formatPrintJobPercent(printJob) - visible: printJob != null && (["printing", "post_print", "pre_print", "sent_to_printer"].indexOf(printJob.status) !== -1) + visible: printProgressTitleBar.showPercent opacity: 0.65 font: UM.Theme.getFont("very_small") } + + Image + { + width: statusText.height + height: width + anchors.right: parent.right + anchors.rightMargin: UM.Theme.getSize("default_margin").width + anchors.top: statusText.top + + visible: ! printProgressTitleBar.showPercent + + source: { + if ( ! printer.enabled) + { + return "blocked-icon.svg"; + } + if (printJob != null) + { + if(printJob.status === "queued") + { + if (printJob.configuration_changes_required != null && printJob.configuration_changes_required.length !== 0) + { + return "action-required-icon.svg"; + } + } + else if (printJob.status === "wait_cleanup") + { + return "checkmark-icon.svg"; + } + } + return ""; // We're not going to show it, so it will not be resolved as a url. + } + } + Rectangle { //TODO: This will become a progress bar in the future @@ -308,7 +356,7 @@ Rectangle width: parent.width - 2 * UM.Theme.getSize("default_margin").width - visible: showExtended + visible: printProgressArea.showExtended Label // Status detail { diff --git a/plugins/UM3NetworkPrinting/UM3InfoComponents.qml b/plugins/UM3NetworkPrinting/UM3InfoComponents.qml index a5ed944773..2c3902dcff 100644 --- a/plugins/UM3NetworkPrinting/UM3InfoComponents.qml +++ b/plugins/UM3NetworkPrinting/UM3InfoComponents.qml @@ -121,4 +121,4 @@ Item } UM.I18nCatalog{id: catalog; name:"cura"} -} \ No newline at end of file +} diff --git a/plugins/UM3NetworkPrinting/action-required-icon.svg b/plugins/UM3NetworkPrinting/action-required-icon.svg new file mode 100644 index 0000000000..e7768849c6 --- /dev/null +++ b/plugins/UM3NetworkPrinting/action-required-icon.svg @@ -0,0 +1,10 @@ + + + + + + + + + + diff --git a/plugins/UM3NetworkPrinting/blocked-icon.svg b/plugins/UM3NetworkPrinting/blocked-icon.svg new file mode 100644 index 0000000000..03bbe24e16 --- /dev/null +++ b/plugins/UM3NetworkPrinting/blocked-icon.svg @@ -0,0 +1,3 @@ + + + diff --git a/plugins/UM3NetworkPrinting/camera-icon.svg b/plugins/UM3NetworkPrinting/camera-icon.svg index 2aafc4b6f4..29adfa5875 100644 --- a/plugins/UM3NetworkPrinting/camera-icon.svg +++ b/plugins/UM3NetworkPrinting/camera-icon.svg @@ -1,3 +1,6 @@ - - - + + + + + + \ No newline at end of file diff --git a/plugins/UM3NetworkPrinting/checkmark-icon.svg b/plugins/UM3NetworkPrinting/checkmark-icon.svg new file mode 100644 index 0000000000..9d4507e551 --- /dev/null +++ b/plugins/UM3NetworkPrinting/checkmark-icon.svg @@ -0,0 +1,3 @@ + + + diff --git a/resources/definitions/ultimaker2.def.json b/resources/definitions/ultimaker2.def.json index 0a9a7bf7ce..6974e61938 100644 --- a/resources/definitions/ultimaker2.def.json +++ b/resources/definitions/ultimaker2.def.json @@ -14,6 +14,7 @@ "platform_texture": "Ultimaker2backplate.png", "platform_offset": [9, 0, 0], "has_materials": false, + "has_machine_quality": true, "first_start_actions": ["UM2UpgradeSelection"], "supported_actions":["UM2UpgradeSelection", "UpgradeFirmware"] }, diff --git a/resources/qml/Cura.qml b/resources/qml/Cura.qml index 2399fb4395..9fecf23ca9 100755 --- a/resources/qml/Cura.qml +++ b/resources/qml/Cura.qml @@ -386,8 +386,6 @@ UM.MainWindow visible: opacity > 0 opacity: base.showPrintMonitor ? 1 : 0 - Behavior on opacity { NumberAnimation { duration: 100; } } - MouseArea { anchors.fill: parent acceptedButtons: Qt.AllButtons @@ -818,7 +816,7 @@ UM.MainWindow Connections { - target: Printer + target: CuraApplication onShowDiscardOrKeepProfileChanges: { discardOrKeepProfileChangesDialog.show() diff --git a/resources/qml/SidebarSimple.qml b/resources/qml/SidebarSimple.qml index 9987268d57..f8c3173c11 100644 --- a/resources/qml/SidebarSimple.qml +++ b/resources/qml/SidebarSimple.qml @@ -76,7 +76,7 @@ Item property var totalTicks: 0 property var availableTotalTicks: 0 - property var activeQualityId: 0 + property var activeQualityIndex: 0 property var qualitySliderStepWidth: 0 property var qualitySliderAvailableMin : 0 @@ -97,7 +97,7 @@ Item // Set selected value if (Cura.MachineManager.activeQualityId == qualityItem.id) { - qualityModel.activeQualityId = i + qualityModel.activeQualityIndex = i } // Set min available @@ -144,9 +144,13 @@ Item // check, the ticks count cannot be less than zero if(Cura.ProfilesModel.rowCount() != 0) + { qualityModel.totalTicks = Cura.ProfilesModel.rowCount() - 1 // minus one, because slider starts from 0 + } else + { qualityModel.totalTicks = 0 + } } } @@ -264,7 +268,7 @@ Item maximumValue: qualityModel.qualitySliderAvailableMax >= 0 ? qualityModel.qualitySliderAvailableMax : 0 stepSize: 1 - value: qualityModel.activeQualityId + value: qualityModel.activeQualityIndex width: qualityModel.qualitySliderStepWidth * qualityModel.availableTotalTicks @@ -292,10 +296,11 @@ Item } onValueChanged: { - if(Cura.MachineManager.activeMachine != null) + // Only change if an active machine is set and the slider is visible at all. + if(Cura.MachineManager.activeMachine != null && visible) { //Prevent updating during view initializing. Trigger only if the value changed by user - if(qualitySlider.value != qualityModel.activeQualityId) + if(qualitySlider.value != qualityModel.activeQualityIndex) { //start updating with short delay qualitySliderChangeTimer.start(); diff --git a/resources/themes/cura-dark/theme.json b/resources/themes/cura-dark/theme.json index 187896aa28..f39fe96c37 100644 --- a/resources/themes/cura-dark/theme.json +++ b/resources/themes/cura-dark/theme.json @@ -16,7 +16,7 @@ "secondary": [241, 242, 242, 255], "topbar_background_color": [0, 0, 0, 0], - "topbar_background_color_monitoring": [39, 44, 48, 255], + "topbar_background_color_monitoring": [0, 0, 0, 0], "topbar_button_text_active": [255, 255, 255, 255], "topbar_button_text_inactive": [128, 128, 128, 255], diff --git a/resources/themes/cura-light/theme.json b/resources/themes/cura-light/theme.json index 96ccd469b6..5d50618eea 100644 --- a/resources/themes/cura-light/theme.json +++ b/resources/themes/cura-light/theme.json @@ -68,7 +68,7 @@ "secondary": [245, 245, 245, 255], "topbar_background_color": [255, 255, 255, 0], - "topbar_background_color_monitoring": [255, 255, 255, 255], + "topbar_background_color_monitoring": [255, 255, 255, 0], "topbar_button_text_active": [0, 0, 0, 255], "topbar_button_text_inactive": [128, 128, 128, 255], diff --git a/tests/TestMachineAction.py b/tests/TestMachineAction.py index 8a38668aaf..0118874a0b 100755 --- a/tests/TestMachineAction.py +++ b/tests/TestMachineAction.py @@ -1,6 +1,8 @@ #Todo: Write tests import pytest +# QtApplication needs to be imported first to prevent import errors. +from UM.Qt.QtApplication import QtApplication from cura.MachineAction import MachineAction from cura.MachineActionManager import MachineActionManager, NotUniqueMachineActionError, UnknownMachineActionError