From b17ff081d6bc6c63ad3909c954d964a4d358554b Mon Sep 17 00:00:00 2001 From: Diego Prado Gesto Date: Mon, 11 Sep 2017 09:35:27 +0200 Subject: [PATCH 01/23] Added the FirmwareUpdateChecker to Cura - CURA-4224 --- .../FirmwareUpdateChecker.py | 33 ++++++++ .../FirmwareUpdateCheckerJob.py | 79 +++++++++++++++++++ plugins/FirmwareUpdateChecker/__init__.py | 14 ++++ plugins/FirmwareUpdateChecker/plugin.json | 8 ++ 4 files changed, 134 insertions(+) create mode 100644 plugins/FirmwareUpdateChecker/FirmwareUpdateChecker.py create mode 100644 plugins/FirmwareUpdateChecker/FirmwareUpdateCheckerJob.py create mode 100644 plugins/FirmwareUpdateChecker/__init__.py create mode 100644 plugins/FirmwareUpdateChecker/plugin.json diff --git a/plugins/FirmwareUpdateChecker/FirmwareUpdateChecker.py b/plugins/FirmwareUpdateChecker/FirmwareUpdateChecker.py new file mode 100644 index 0000000000..3b58a56481 --- /dev/null +++ b/plugins/FirmwareUpdateChecker/FirmwareUpdateChecker.py @@ -0,0 +1,33 @@ +# Copyright (c) 2015 Ultimaker B.V. +# Cura is released under the terms of the AGPLv3 or higher. + +from UM.Extension import Extension +from UM.Preferences import Preferences +from UM.i18n import i18nCatalog + +from .FirmwareUpdateCheckerJob import FirmwareUpdateCheckerJob + +i18n_catalog = i18nCatalog("cura") + + +## This Extension checks for new versions of the firmware based on the latest checked version number. +# The plugin is currently only usable for applications maintained by Ultimaker. But it should be relatively easy +# to change it to work for other applications. +class FirmwareUpdateChecker(Extension): + url = "http://software.ultimaker.com/jedi/releases/latest.version" + + def __init__(self): + super().__init__() + + Preferences.getInstance().addPreference("info/latest_checked_firmware", "") + self.checkFirmwareVersion(True) + + ## Connect with software.ultimaker.com, load latest.version and check version info. + # If the version info is different from the current version, spawn a message to + # allow the user to download it. + # + # \param silent type(boolean) Suppresses messages other than "new version found" messages. + # This is used when checking for a new firmware version at startup. + def checkFirmwareVersion(self, silent = False): + job = FirmwareUpdateCheckerJob(silent = silent, url = self.url) + job.start() \ No newline at end of file diff --git a/plugins/FirmwareUpdateChecker/FirmwareUpdateCheckerJob.py b/plugins/FirmwareUpdateChecker/FirmwareUpdateCheckerJob.py new file mode 100644 index 0000000000..913ac96025 --- /dev/null +++ b/plugins/FirmwareUpdateChecker/FirmwareUpdateCheckerJob.py @@ -0,0 +1,79 @@ +# Copyright (c) 2015 Ultimaker B.V. +# Cura is released under the terms of the AGPLv3 or higher. + +from UM.Preferences import Preferences +from UM.Application import Application +from UM.Message import Message +from UM.Logger import Logger +from UM.Job import Job + +import urllib.request +import codecs + +from PyQt5.QtCore import QUrl +from PyQt5.QtGui import QDesktopServices + + +from UM.i18n import i18nCatalog +i18n_catalog = i18nCatalog("cura") + + +## This job checks if there is an update available on the provided URL. +class FirmwareUpdateCheckerJob(Job): + def __init__(self, silent = False, url = None): + super().__init__() + self.silent = silent + self._url = url + self._download_url = None # If an update was found, the download_url will be set to the location of the new version. + + ## Callback for the message that is spawned when there is a new version. + def actionTriggered(self, message, action): + if action == "download": + if self._download_url is not None: + QDesktopServices.openUrl(QUrl(self._download_url)) + + def run(self): + self._download_url = None # Reset download ur. + if not self._url: + Logger.log("e", "Can not check for a new release. URL not set!") + return + + Logger.log("i", "Checking for new version of firmware") + try: + request = urllib.request.Request(self._url) + current_version_file = urllib.request.urlopen(request) + reader = codecs.getreader("utf-8") + + # Nothing to parse, just get the string + # TODO: In the future may be done by parsing a JSON file + current_version = reader(current_version_file).readline().rstrip() + Logger.log("i", "Reading firmware version: %s" % current_version) + + # If it is the first time the version is checked, the checked_version is None + checked_version = Preferences.getInstance().getValue("info/latest_checked_firmware") + active_machine = Preferences.getInstance().getValue("cura/active_machine") + # If it is not None, then we compare between the checked_version and the current_version + # Now we just do that if the active printer is Ultimaker 3 or Ultimaker 3 Extended + if ((active_machine == "Ultimaker 3 Extended") or (active_machine == "Ultimaker 3"))\ + and ((checked_version is None) or (checked_version != current_version)): + message = Message(i18n_catalog.i18nc("@info", "New %s firmware available

To ensure that your " + "%s is equiped with the latest features it is recommended " + "to update the firmware regularly. This can be done on the " + "%s (when connected to the network) or via USB." + % (active_machine, active_machine, active_machine))) + message.addAction("download", i18n_catalog.i18nc("@action:button", "Download"), "[no_icon]", "[no_description]") + + # If we do this in a cool way, the download url should be available in the JSON file + self._download_url = "https://ultimaker.com/en/resources/20500-upgrade-firmware" + message.actionTriggered.connect(self.actionTriggered) + # Sometimes it's shown, sometimes not + #message.show() + Application.getInstance().showMessage(message) + + Preferences.getInstance().setValue("info/latest_checked_firmware", current_version) + + except Exception as e: + Logger.log("w", "Failed to check for new version: %s" % e) + if not self.silent: + Message(i18n_catalog.i18nc("@info", "Could not access update information.")).show() + return \ No newline at end of file diff --git a/plugins/FirmwareUpdateChecker/__init__.py b/plugins/FirmwareUpdateChecker/__init__.py new file mode 100644 index 0000000000..5da6130772 --- /dev/null +++ b/plugins/FirmwareUpdateChecker/__init__.py @@ -0,0 +1,14 @@ +# Copyright (c) 2015 Ultimaker B.V. +# Cura is released under the terms of the AGPLv3 or higher. + +from UM.i18n import i18nCatalog +from . import FirmwareUpdateChecker + +i18n_catalog = i18nCatalog("cura") + +def getMetaData(): + return { + } + +def register(app): + return { "extension": FirmwareUpdateChecker.FirmwareUpdateChecker()} diff --git a/plugins/FirmwareUpdateChecker/plugin.json b/plugins/FirmwareUpdateChecker/plugin.json new file mode 100644 index 0000000000..d6a9f9fbd7 --- /dev/null +++ b/plugins/FirmwareUpdateChecker/plugin.json @@ -0,0 +1,8 @@ +{ + "name": "Firmware Update Checker", + "author": "Ultimaker B.V.", + "version": "1.0.0", + "description": "Checks for firmware updates.", + "api": 4, + "i18n-catalog": "cura" +} From a8ff1e188f9e5856003264d796763dac5aaaf18c Mon Sep 17 00:00:00 2001 From: Tim Kuipers Date: Wed, 26 Jul 2017 15:24:42 +0200 Subject: [PATCH 02/23] feat: Cross infill types and zig_zaggify_infill --- resources/definitions/fdmprinter.def.json | 13 ++++++++++++- 1 file changed, 12 insertions(+), 1 deletion(-) diff --git a/resources/definitions/fdmprinter.def.json b/resources/definitions/fdmprinter.def.json index 0e871ffad5..8cb8043cdb 100755 --- a/resources/definitions/fdmprinter.def.json +++ b/resources/definitions/fdmprinter.def.json @@ -1365,7 +1365,9 @@ "quarter_cubic": "Quarter Cubic", "concentric": "Concentric", "concentric_3d": "Concentric 3D", - "zigzag": "Zig Zag" + "zigzag": "Zig Zag", + "cross": "Cross", + "cross_3d": "Cross 3D" }, "default_value": "grid", "enabled": "infill_sparse_density > 0", @@ -1373,6 +1375,15 @@ "limit_to_extruder": "infill_extruder_nr", "settable_per_mesh": true }, + "zig_zaggify_infill": + { + "label": "Connect Infill Lines", + "description": "Connect the ends where the infill pattern meets the inner wall using a lines which follows the shape of the inner wall. Enabling this setting can make the infill adhere to the walls better and reduces the effects on infill on the quality of vertical surfaces. Disabling this setting reduces the amount of material used.", + "type": "bool", + "default_value": true, + "enabled": "infill_pattern == 'cross' or infill_pattern == 'cross_3d'", + "settable_per_mesh": true + }, "infill_angles": { "label": "Infill Line Directions", From be6dcdafbdc336b886278831dc1f06122a1ba01c Mon Sep 17 00:00:00 2001 From: Tim Kuipers Date: Wed, 26 Jul 2017 18:10:25 +0200 Subject: [PATCH 03/23] lil: explicitly set cross infill density --- resources/definitions/fdmprinter.def.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/resources/definitions/fdmprinter.def.json b/resources/definitions/fdmprinter.def.json index 8cb8043cdb..39c1343870 100755 --- a/resources/definitions/fdmprinter.def.json +++ b/resources/definitions/fdmprinter.def.json @@ -1343,7 +1343,7 @@ "default_value": 2, "minimum_value": "0", "minimum_value_warning": "infill_line_width", - "value": "0 if infill_sparse_density == 0 else (infill_line_width * 100) / infill_sparse_density * (2 if infill_pattern == 'grid' else (3 if infill_pattern == 'triangles' or infill_pattern == 'cubic' or infill_pattern == 'cubicsubdiv' else (2 if infill_pattern == 'tetrahedral' or infill_pattern == 'quarter_cubic' else 1)))", + "value": "0 if infill_sparse_density == 0 else (infill_line_width * 100) / infill_sparse_density * (2 if infill_pattern == 'grid' else (3 if infill_pattern == 'triangles' or infill_pattern == 'cubic' or infill_pattern == 'cubicsubdiv' else (2 if infill_pattern == 'tetrahedral' or infill_pattern == 'quarter_cubic' else (1 if infill_pattern == 'cross' or infill_pattern == 'cross_3d' else 1))))", "limit_to_extruder": "infill_extruder_nr", "settable_per_mesh": true } From 80992dd44c6bd6ea82beea8ef2c89f7a99c25e05 Mon Sep 17 00:00:00 2001 From: Diego Prado Gesto Date: Tue, 12 Sep 2017 17:22:17 +0200 Subject: [PATCH 04/23] The checker now runs also when the user adds a new printer - CURA-4224 --- .../FirmwareUpdateChecker.py | 21 +++++-- .../FirmwareUpdateCheckerJob.py | 55 +++++++++++-------- 2 files changed, 48 insertions(+), 28 deletions(-) diff --git a/plugins/FirmwareUpdateChecker/FirmwareUpdateChecker.py b/plugins/FirmwareUpdateChecker/FirmwareUpdateChecker.py index 3b58a56481..f20b8be584 100644 --- a/plugins/FirmwareUpdateChecker/FirmwareUpdateChecker.py +++ b/plugins/FirmwareUpdateChecker/FirmwareUpdateChecker.py @@ -1,11 +1,14 @@ # Copyright (c) 2015 Ultimaker B.V. # Cura is released under the terms of the AGPLv3 or higher. - +from UM.Application import Application from UM.Extension import Extension from UM.Preferences import Preferences +from UM.Logger import Logger from UM.i18n import i18nCatalog +from cura.Settings.GlobalStack import GlobalStack from .FirmwareUpdateCheckerJob import FirmwareUpdateCheckerJob +from UM.Settings.ContainerRegistry import ContainerRegistry i18n_catalog = i18nCatalog("cura") @@ -19,8 +22,18 @@ class FirmwareUpdateChecker(Extension): def __init__(self): super().__init__() + # Initialize the Preference called `latest_checked_firmware` that stores the last version + # checked for the UM3. In the future if we need to check other printers' firmware Preferences.getInstance().addPreference("info/latest_checked_firmware", "") - self.checkFirmwareVersion(True) + + # Listen to a Signal that indicates a change in the active printer + ContainerRegistry.getInstance().containerAdded.connect(self._onContainerAdded) + + def _onContainerAdded(self, container): + # Only take care when a new GlobaStack was added + if (isinstance(container, GlobalStack)): + Logger.log("i", "You have a '%s' in printer list. Let's check the firmware!" % container.getId()) + self.checkFirmwareVersion(container, True) ## Connect with software.ultimaker.com, load latest.version and check version info. # If the version info is different from the current version, spawn a message to @@ -28,6 +41,6 @@ class FirmwareUpdateChecker(Extension): # # \param silent type(boolean) Suppresses messages other than "new version found" messages. # This is used when checking for a new firmware version at startup. - def checkFirmwareVersion(self, silent = False): - job = FirmwareUpdateCheckerJob(silent = silent, url = self.url) + def checkFirmwareVersion(self, container = None, silent = False): + job = FirmwareUpdateCheckerJob(container = container, silent = silent, url = self.url) job.start() \ No newline at end of file diff --git a/plugins/FirmwareUpdateChecker/FirmwareUpdateCheckerJob.py b/plugins/FirmwareUpdateChecker/FirmwareUpdateCheckerJob.py index 913ac96025..9e0db57ed7 100644 --- a/plugins/FirmwareUpdateChecker/FirmwareUpdateCheckerJob.py +++ b/plugins/FirmwareUpdateChecker/FirmwareUpdateCheckerJob.py @@ -20,8 +20,9 @@ i18n_catalog = i18nCatalog("cura") ## This job checks if there is an update available on the provided URL. class FirmwareUpdateCheckerJob(Job): - def __init__(self, silent = False, url = None): + def __init__(self, container = None, silent = False, url = None): super().__init__() + self._container = container self.silent = silent self._url = url self._download_url = None # If an update was found, the download_url will be set to the location of the new version. @@ -38,38 +39,44 @@ class FirmwareUpdateCheckerJob(Job): Logger.log("e", "Can not check for a new release. URL not set!") return - Logger.log("i", "Checking for new version of firmware") try: request = urllib.request.Request(self._url) current_version_file = urllib.request.urlopen(request) reader = codecs.getreader("utf-8") - # Nothing to parse, just get the string - # TODO: In the future may be done by parsing a JSON file - current_version = reader(current_version_file).readline().rstrip() - Logger.log("i", "Reading firmware version: %s" % current_version) + machine_name = self._container.getId() - # If it is the first time the version is checked, the checked_version is None - checked_version = Preferences.getInstance().getValue("info/latest_checked_firmware") - active_machine = Preferences.getInstance().getValue("cura/active_machine") # If it is not None, then we compare between the checked_version and the current_version - # Now we just do that if the active printer is Ultimaker 3 or Ultimaker 3 Extended - if ((active_machine == "Ultimaker 3 Extended") or (active_machine == "Ultimaker 3"))\ - and ((checked_version is None) or (checked_version != current_version)): - message = Message(i18n_catalog.i18nc("@info", "New %s firmware available

To ensure that your " - "%s is equiped with the latest features it is recommended " - "to update the firmware regularly. This can be done on the " - "%s (when connected to the network) or via USB." - % (active_machine, active_machine, active_machine))) - message.addAction("download", i18n_catalog.i18nc("@action:button", "Download"), "[no_icon]", "[no_description]") + # Now we just do that if the active printer is Ultimaker 3 or Ultimaker 3 Extended or any + # other Ultimaker 3 that will come in the future + if (machine_name[0:11] == "Ultimaker 3"): - # If we do this in a cool way, the download url should be available in the JSON file - self._download_url = "https://ultimaker.com/en/resources/20500-upgrade-firmware" - message.actionTriggered.connect(self.actionTriggered) - # Sometimes it's shown, sometimes not - #message.show() - Application.getInstance().showMessage(message) + # Nothing to parse, just get the string + # TODO: In the future may be done by parsing a JSON file with diferent version for each printer model + current_version = reader(current_version_file).readline().rstrip() + Logger.log("i", "Reading firmware version of %s: %s" % (machine_name, current_version)) + # If it is the first time the version is checked, the checked_version is None + checked_version = Preferences.getInstance().getValue("info/latest_checked_firmware") + + # If the checked_version is '', it's because is the first time we check firmware and in this case + # we will not show the notification, but we will store it for the next time + if (checked_version != "") and (checked_version != current_version): + message = Message(i18n_catalog.i18nc("@info", "New %s firmware available

To ensure that your " + "%s is equiped with the latest features it is recommended " + "to update the firmware regularly. This can be done on the " + "%s (when connected to the network) or via USB." + % (machine_name, machine_name, machine_name))) + message.addAction("download", i18n_catalog.i18nc("@action:button", "Download"), "[no_icon]", "[no_description]") + + # If we do this in a cool way, the download url should be available in the JSON file + self._download_url = "https://ultimaker.com/en/resources/20500-upgrade-firmware" + message.actionTriggered.connect(self.actionTriggered) + Application.getInstance().showMessage(message) + + # The first time we want to store the current version, the notification will not be shown, + # because the new version of Cura will be release before the firmware and we don't want to + # notify the user when no new firmware version is available. Preferences.getInstance().setValue("info/latest_checked_firmware", current_version) except Exception as e: From 37ec3bbb26fb8aa027c4e4f9e558e82d55359f9b Mon Sep 17 00:00:00 2001 From: Tim Kuipers Date: Tue, 12 Sep 2017 18:19:59 +0200 Subject: [PATCH 05/23] cross pattern for support --- resources/definitions/fdmprinter.def.json | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/resources/definitions/fdmprinter.def.json b/resources/definitions/fdmprinter.def.json index 39c1343870..33ec19acd8 100755 --- a/resources/definitions/fdmprinter.def.json +++ b/resources/definitions/fdmprinter.def.json @@ -3366,7 +3366,8 @@ "triangles": "Triangles", "concentric": "Concentric", "concentric_3d": "Concentric 3D", - "zigzag": "Zig Zag" + "zigzag": "Zig Zag", + "cross": "Cross" }, "default_value": "zigzag", "enabled": "support_enable", From 15790b3965b76cf6d941aeab59b5b01bc7eb01e3 Mon Sep 17 00:00:00 2001 From: Tim Kuipers Date: Tue, 12 Sep 2017 19:18:28 +0200 Subject: [PATCH 06/23] feat: cross 3d experimental algorithm parameters --- resources/definitions/fdmprinter.def.json | 24 +++++++++++++++++++++++ 1 file changed, 24 insertions(+) diff --git a/resources/definitions/fdmprinter.def.json b/resources/definitions/fdmprinter.def.json index 33ec19acd8..01b2b0b498 100755 --- a/resources/definitions/fdmprinter.def.json +++ b/resources/definitions/fdmprinter.def.json @@ -5186,6 +5186,30 @@ "limit_to_extruder": "top_bottom_extruder_nr", "settable_per_mesh": true }, + "cross_infill_pocket_size": + { + "label": "Cross 3D Pocket Size", + "description": "The size of pockets at four-way crossings in the cross 3D pattern at heights where the pattern is touching itself.", + "unit": "mm", + "type": "float", + "default_value": 2.0, + "value": "infill_line_distance", + "minimum_value": "0", + "maximum_value_warning": "infill_line_distance * math.sqrt(2)", + "enabled": "infill_pattern == 'cross_3d'", + "limit_to_extruder": "infill_extruder_nr", + "settable_per_mesh": true + }, + "cross_infill_apply_pockets_alternatingly": + { + "label": "Alternate Cross 3D Pockets", + "description": "Only apply pockets at half of the four-way crossings in the cross 3D pattern and alternate the location of the pockets between heights where the pattern is touching itself.", + "type": "bool", + "default_value": true, + "enabled": "infill_pattern == 'cross_3d'", + "limit_to_extruder": "infill_extruder_nr", + "settable_per_mesh": true + }, "spaghetti_infill_enabled": { "label": "Spaghetti Infill", From aa2c7c2ff6a0b4d695d3499ed043e797b940dd12 Mon Sep 17 00:00:00 2001 From: Diego Prado Gesto Date: Wed, 13 Sep 2017 10:22:07 +0200 Subject: [PATCH 07/23] Checking first if the user has enabled the 'check for updates' preference - CURA-4224 --- plugins/FirmwareUpdateChecker/FirmwareUpdateChecker.py | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/plugins/FirmwareUpdateChecker/FirmwareUpdateChecker.py b/plugins/FirmwareUpdateChecker/FirmwareUpdateChecker.py index f20b8be584..994493a4e6 100644 --- a/plugins/FirmwareUpdateChecker/FirmwareUpdateChecker.py +++ b/plugins/FirmwareUpdateChecker/FirmwareUpdateChecker.py @@ -26,8 +26,11 @@ class FirmwareUpdateChecker(Extension): # checked for the UM3. In the future if we need to check other printers' firmware Preferences.getInstance().addPreference("info/latest_checked_firmware", "") - # Listen to a Signal that indicates a change in the active printer - ContainerRegistry.getInstance().containerAdded.connect(self._onContainerAdded) + # Listen to a Signal that indicates a change in the list of printers, just if the user has enabled the + # 'check for updates' option + Preferences.getInstance().addPreference("info/automatic_update_check", True) + if Preferences.getInstance().getValue("info/automatic_update_check"): + ContainerRegistry.getInstance().containerAdded.connect(self._onContainerAdded) def _onContainerAdded(self, container): # Only take care when a new GlobaStack was added From 84ad9c6ad1edd08216df0834298fd558c1268920 Mon Sep 17 00:00:00 2001 From: Lipu Fei Date: Wed, 13 Sep 2017 12:48:48 +0200 Subject: [PATCH 08/23] Add "available" flag for quality profiles CURA-4182 Add "available" flag for quality profile model so the slider can use it to show available and unavailable profiles. --- cura/QualityManager.py | 13 ++++- cura/Settings/ProfilesModel.py | 80 +++++++++++++++++++++++++---- resources/qml/Menus/ProfileMenu.qml | 1 + 3 files changed, 84 insertions(+), 10 deletions(-) diff --git a/cura/QualityManager.py b/cura/QualityManager.py index e92829e546..813d23ea13 100644 --- a/cura/QualityManager.py +++ b/cura/QualityManager.py @@ -82,6 +82,17 @@ class QualityManager: return list(common_quality_types) + def findAllQualitiesForMachineAndMaterials(self, machine_definition: "DefinitionContainerInterface", material_containers: List[InstanceContainer]) -> List[InstanceContainer]: + # Determine the common set of quality types which can be + # applied to all of the materials for this machine. + quality_type_dict = self.__fetchQualityTypeDictForMaterial(machine_definition, material_containers[0]) + qualities = set(quality_type_dict.values()) + for material_container in material_containers[1:]: + next_quality_type_dict = self.__fetchQualityTypeDictForMaterial(machine_definition, material_container) + qualities.update(set(next_quality_type_dict.values())) + + return list(qualities) + ## Fetches a dict of quality types names to quality profiles for a combination of machine and material. # # \param machine_definition \type{DefinitionContainer} the machine definition. @@ -121,7 +132,7 @@ class QualityManager: # \param material_container \type{InstanceContainer} the material. # \return \type{List[InstanceContainer]} the list of suitable qualities. def findAllQualitiesForMachineMaterial(self, machine_definition: "DefinitionContainerInterface", material_container: InstanceContainer) -> List[InstanceContainer]: - criteria = {"type": "quality" } + criteria = {"type": "quality"} result = self._getFilteredContainersForStack(machine_definition, [material_container], **criteria) if not result: basic_materials = self._getBasicMaterials(material_container) diff --git a/cura/Settings/ProfilesModel.py b/cura/Settings/ProfilesModel.py index 545f44401a..2942577fc6 100644 --- a/cura/Settings/ProfilesModel.py +++ b/cura/Settings/ProfilesModel.py @@ -1,6 +1,8 @@ -# Copyright (c) 2016 Ultimaker B.V. +# Copyright (c) 2017 Ultimaker B.V. # Cura is released under the terms of the AGPLv3 or higher. +from collections import OrderedDict + from PyQt5.QtCore import Qt from UM.Application import Application @@ -10,14 +12,19 @@ from UM.Settings.Models.InstanceContainersModel import InstanceContainersModel from cura.QualityManager import QualityManager from cura.Settings.ExtruderManager import ExtruderManager + ## QML Model for listing the current list of valid quality profiles. # class ProfilesModel(InstanceContainersModel): LayerHeightRole = Qt.UserRole + 1001 + LayerHeightWithoutUnitRole = Qt.UserRole + 1002 + AvailableRole = Qt.UserRole + 1003 def __init__(self, parent = None): super().__init__(parent) self.addRoleName(self.LayerHeightRole, "layer_height") + self.addRoleName(self.LayerHeightWithoutUnitRole, "layer_height_without_unit") + self.addRoleName(self.AvailableRole, "available") Application.getInstance().globalContainerStackChanged.connect(self._update) @@ -47,8 +54,9 @@ class ProfilesModel(InstanceContainersModel): global_container_stack = Application.getInstance().getGlobalContainerStack() if global_container_stack is None: return [] + global_stack_definition = global_container_stack.getBottom() - # Get the list of extruders and place the selected extruder at the front of the list. + # Get the list of extruders and place the selected extruder at the front of the list. extruder_manager = ExtruderManager.getInstance() active_extruder = extruder_manager.getActiveExtruderStack() extruder_stacks = extruder_manager.getActiveExtruderStacks() @@ -56,10 +64,22 @@ class ProfilesModel(InstanceContainersModel): extruder_stacks.remove(active_extruder) extruder_stacks = [active_extruder] + extruder_stacks - # Fetch the list of useable qualities across all extruders. + if ExtruderManager.getInstance().getActiveExtruderStacks(): + # Multi-extruder machine detected. + materials = [extruder.material for extruder in extruder_stacks] + else: + # Machine with one extruder. + materials = [global_container_stack.material] + + # Fetch the list of usable qualities across all extruders. # The actual list of quality profiles come from the first extruder in the extruder list. - return QualityManager.getInstance().findAllUsableQualitiesForMachineAndExtruders(global_container_stack, - extruder_stacks) + result = QualityManager.getInstance().findAllQualitiesForMachineAndMaterials(global_stack_definition, + materials) + for quality in QualityManager.getInstance().findAllUsableQualitiesForMachineAndExtruders( + global_container_stack, extruder_stacks): + if quality not in result: + result.append(quality) + return result ## Re-computes the items in this model, and adds the layer height role. def _recomputeItems(self): @@ -67,6 +87,17 @@ class ProfilesModel(InstanceContainersModel): global_container_stack = Application.getInstance().getGlobalContainerStack() if global_container_stack is None: return + + # Get the list of extruders and place the selected extruder at the front of the list. + extruder_manager = ExtruderManager.getInstance() + active_extruder = extruder_manager.getActiveExtruderStack() + extruder_stacks = extruder_manager.getActiveExtruderStacks() + if active_extruder in extruder_stacks: + extruder_stacks.remove(active_extruder) + extruder_stacks = [active_extruder] + extruder_stacks + # Get a list of available qualities for this machine and material + qualities = QualityManager.getInstance().findAllUsableQualitiesForMachineAndExtruders(global_container_stack, + extruder_stacks) container_registry = ContainerRegistry.getInstance() machine_manager = Application.getInstance().getMachineManager() @@ -74,17 +105,44 @@ class ProfilesModel(InstanceContainersModel): if not unit: unit = "" + # group all quality items according to quality_types, so we know which profile suits the currently + # active machine and material, and later yield the right ones. + tmp_all_quality_items = OrderedDict() for item in super()._recomputeItems(): + profile = container_registry.findContainers(id = item["id"]) + quality_type = profile[0].getMetaDataEntry("quality_type") if profile else "" + + if quality_type not in tmp_all_quality_items: + tmp_all_quality_items[quality_type] = {"suitable_container": None, + "all_containers": []} + + tmp_all_quality_items[quality_type]["all_containers"].append(item) + if tmp_all_quality_items[quality_type]["suitable_container"] is None and profile[0] in qualities: + tmp_all_quality_items[quality_type]["suitable_container"] = item + + # reverse the ordering (finest first, coarsest last) + all_quality_items = OrderedDict() + for key in reversed(tmp_all_quality_items.keys()): + all_quality_items[key] = tmp_all_quality_items[key] + + for data_item in all_quality_items.values(): + item = data_item["suitable_container"] + if item is None: + item = data_item["all_containers"][0] + profile = container_registry.findContainers(id = item["id"]) if not profile: item["layer_height"] = "" #Can't update a profile that is unknown. + item["available"] = False yield item continue - #Easy case: This profile defines its own layer height. profile = profile[0] + item["available"] = profile in qualities + + #Easy case: This profile defines its own layer height. if profile.hasProperty("layer_height", "value"): - item["layer_height"] = str(profile.getProperty("layer_height", "value")) + unit + self._setItemLayerHeight(item, profile.getProperty("layer_height", "value"), unit) yield item continue @@ -102,7 +160,7 @@ class ProfilesModel(InstanceContainersModel): else: quality = None if quality and quality.hasProperty("layer_height", "value"): - item["layer_height"] = str(quality.getProperty("layer_height", "value")) + unit + self._setItemLayerHeight(item, quality.getProperty("layer_height", "value"), unit) yield item continue @@ -112,5 +170,9 @@ class ProfilesModel(InstanceContainersModel): skip_until_container = global_container_stack.variant if not skip_until_container or skip_until_container == ContainerRegistry.getInstance().getEmptyInstanceContainer(): #No variant in stack. skip_until_container = global_container_stack.getBottom() - item["layer_height"] = str(global_container_stack.getRawProperty("layer_height", "value", skip_until_container = skip_until_container.getId())) + unit #Fall through to the currently loaded material. + self._setItemLayerHeight(item, global_container_stack.getRawProperty("layer_height", "value", skip_until_container = skip_until_container.getId()), unit) # Fall through to the currently loaded material. yield item + + def _setItemLayerHeight(self, item, value, unit): + item["layer_height"] = str(value) + unit + item["layer_height_without_unit"] = str(value) diff --git a/resources/qml/Menus/ProfileMenu.qml b/resources/qml/Menus/ProfileMenu.qml index 4a2908277e..d6412c50be 100644 --- a/resources/qml/Menus/ProfileMenu.qml +++ b/resources/qml/Menus/ProfileMenu.qml @@ -22,6 +22,7 @@ Menu checked: Cura.MachineManager.activeQualityChangesId == "" && Cura.MachineManager.activeQualityType == model.metadata.quality_type exclusiveGroup: group onTriggered: Cura.MachineManager.setActiveQuality(model.id) + visible: model.available } onObjectAdded: menu.insertItem(index, object); From d82a1daacf588350c85045750d19ac915500153e Mon Sep 17 00:00:00 2001 From: Lipu Fei Date: Wed, 13 Sep 2017 15:18:43 +0200 Subject: [PATCH 09/23] Add new quality/resolution slider CURA-4182 --- resources/qml/SidebarSimple.qml | 379 ++++++++++++++++++++++++- resources/themes/cura-light/theme.json | 8 + 2 files changed, 385 insertions(+), 2 deletions(-) diff --git a/resources/qml/SidebarSimple.qml b/resources/qml/SidebarSimple.qml index c2c1562fbb..cd93a7c546 100644 --- a/resources/qml/SidebarSimple.qml +++ b/resources/qml/SidebarSimple.qml @@ -35,12 +35,386 @@ Item { width: childrenRect.width height: childrenRect.height + + // + // Quality profile + // + Text + { + id: resolutionLabel + anchors.top: resolutionSlider.top + anchors.topMargin: UM.Theme.getSize("default_margin").height / 4 + anchors.left: parent.left + anchors.leftMargin: UM.Theme.getSize("sidebar_margin").width + width: UM.Theme.getSize("sidebar").width * .45 - UM.Theme.getSize("sidebar_margin").width + + text: catalog.i18nc("@label", "Layer Height") + font: UM.Theme.getFont("default") + color: UM.Theme.getColor("text") + } + + Text + { + id: speedLabel + anchors.bottom: resolutionSlider.bottom + anchors.left: parent.left + anchors.leftMargin: UM.Theme.getSize("sidebar_margin").width + + text: catalog.i18nc("@label", "Print Speed") + font: UM.Theme.getFont("default") + color: UM.Theme.getColor("text") + } + + Text + { + id: speedLabelSlower + anchors.top: speedLabel.top + anchors.left: resolutionSlider.left + + text: catalog.i18nc("@label", "Slower") + font: UM.Theme.getFont("default") + color: UM.Theme.getColor("text") + horizontalAlignment: Text.AlignLeft + } + + Text + { + id: speedLabelFaster + anchors.top: speedLabel.top + anchors.right: resolutionSlider.right + + text: catalog.i18nc("@label", "Faster") + font: UM.Theme.getFont("default") + color: UM.Theme.getColor("text") + horizontalAlignment: Text.AlignRight + } + + Item + { + id: resolutionSlider + anchors.top: parent.top + anchors.topMargin: UM.Theme.getSize("default_margin").height / 2 + anchors.left: infillCellRight.left + anchors.right: infillCellRight.right + width: UM.Theme.getSize("sidebar").width * .55 + height: UM.Theme.getSize("quality_slider_bar").height * 30 + + property var model: Cura.ProfilesModel + + Connections + { + target: Cura.ProfilesModel + onItemsChanged: + { + resolutionSlider.updateCurrentQualityIndex(); + resolutionSlider.updateBar(); + } + } + + Connections + { + target: Cura.MachineManager + onActiveQualityChanged: + { + resolutionSlider.updateCurrentQualityIndex(); + resolutionSlider.updateBar(); + } + } + + Component.onCompleted: + { + updateCurrentQualityIndex(); + updateBar(); + } + + function updateCurrentQualityIndex() + { + for (var i = 0; i < resolutionSlider.model.rowCount(); ++i) + { + if (Cura.MachineManager.activeQualityId == resolutionSlider.model.getItem(i).id) + { + if (resolutionSlider.currentQualityIndex != i) + { + resolutionSlider.currentQualityIndex = i; + } + return; + } + } + resolutionSlider.currentQualityIndex = undefined; + } + + function updateBar() + { + fullRangeMax = Cura.ProfilesModel.rowCount(); + + // set avaiableMin + var foundAvaiableMin = false; + for (var i = 0; i < Cura.ProfilesModel.rowCount(); ++i) + { + if (Cura.ProfilesModel.getItem(i).available) + { + avaiableMin = i; + foundAvaiableMin = true; + break; + } + } + if (!foundAvaiableMin) + { + avaiableMin = undefined; + } + + var foundAvaiableMax = false; + for (var i = Cura.ProfilesModel.rowCount() - 1; i >= 0; --i) + { + if (Cura.ProfilesModel.getItem(i).available) + { + avaiableMax = i; + foundAvaiableMax = true; + break; + } + } + if (!foundAvaiableMax) + { + avaiableMax = undefined; + } + + currentHover = undefined; + backgroundBar.requestPaint(); + } + + property var fullRangeMin: 0 + property var fullRangeMax: model.rowCount() + + property var avaiableMin + property var avaiableMax + property var currentQualityIndex + property var currentHover + + //TODO: get from theme + property var barLeftRightMargin: 5 + property var tickLeftRightMargin: 2 + property var tickMargin: 15 + property var tickThickness: 1 + property var tickWidth: 1 + property var tickHeight: 5 + property var tickTextHeight: 8 + property var totalTickCount: fullRangeMax - fullRangeMin + property var selectedCircleDiameter: 10 + + property var showQualityText: false + + property var tickStepSize: (width - (barLeftRightMargin + tickLeftRightMargin) * 2) / (totalTickCount > 1 ? totalTickCount - 1 : 1) + property var tickAreaList: + { + var area_list = []; + if (avaiableMin != undefined && avaiableMax != undefined) + { + for (var i = avaiableMin; i <= avaiableMax; ++i) + { + var start_x = (barLeftRightMargin + tickLeftRightMargin) + tickStepSize * (i - fullRangeMin); + var diameter = tickStepSize * 0.9; + start_x = start_x + tickWidth / 2 - (diameter / 2); + var end_x = start_x + diameter; + var start_y = height / 2 - diameter / 2; + var end_y = start_y + diameter; + + var area = {"id": i, + "start_x": start_x, "end_x": end_x, + "start_y": start_y, "end_y": end_y, + }; + area_list.push(area); + } + } + return area_list; + } + + onCurrentHoverChanged: + { + backgroundBar.requestPaint(); + } + onCurrentQualityIndex: + { + backgroundBar.requestPaint(); + } + + // background bar + Canvas + { + id: backgroundBar + anchors.fill: parent + + Timer { + interval: 16 + running: true + repeat: true + onTriggered: backgroundBar.requestPaint() + } + + onPaint: + { + var ctx = getContext("2d"); + ctx.reset(); + ctx.fillStyle = UM.Theme.getColor("quality_slider_unavailable"); + + const bar_left_right_margin = resolutionSlider.barLeftRightMargin; + const tick_left_right_margin = resolutionSlider.tickLeftRightMargin; + const tick_margin = resolutionSlider.tickMargin; + const bar_thickness = resolutionSlider.tickThickness; + const tick_width = resolutionSlider.tickWidth; + const tick_height = resolutionSlider.tickHeight; + const tick_text_height = resolutionSlider.tickTextHeight; + const selected_circle_diameter = resolutionSlider.selectedCircleDiameter; + + // draw unavailable bar + const bar_top = parent.height / 2 - bar_thickness / 2; + ctx.fillRect(bar_left_right_margin, bar_top, width - bar_left_right_margin * 2, bar_thickness); + + // draw unavailable ticks + var total_tick_count = resolutionSlider.totalTickCount; + const step_size = resolutionSlider.tickStepSize; + var current_start_x = bar_left_right_margin + tick_left_right_margin; + + const tick_top = parent.height / 2 - tick_height / 2; + + for (var i = 0; i < total_tick_count; ++i) + { + ctx.fillRect(current_start_x, tick_top, tick_width, tick_height); + current_start_x += step_size; + } + + // draw available bar and ticks + if (resolutionSlider.avaiableMin != undefined && resolutionSlider.avaiableMax != undefined) + { + current_start_x = (bar_left_right_margin + tick_left_right_margin) + step_size * (resolutionSlider.avaiableMin - resolutionSlider.fullRangeMin); + ctx.fillStyle = UM.Theme.getColor("quality_slider_available"); + total_tick_count = resolutionSlider.avaiableMax - resolutionSlider.avaiableMin + 1; + + const available_bar_width = step_size * (total_tick_count - 1); + ctx.fillRect(current_start_x, bar_top, available_bar_width, bar_thickness); + + for (var i = 0; i < total_tick_count; ++i) + { + ctx.fillRect(current_start_x, tick_top, tick_width, tick_height); + current_start_x += step_size; + } + } + + // print the selected circle + if (resolutionSlider.currentQualityIndex != undefined) + { + var circle_start_x = (bar_left_right_margin + tick_left_right_margin) + step_size * (resolutionSlider.currentQualityIndex - resolutionSlider.fullRangeMin); + circle_start_x = circle_start_x + tick_width / 2 - selected_circle_diameter / 2; + var circle_start_y = height / 2 - selected_circle_diameter / 2; + ctx.fillStyle = UM.Theme.getColor("quality_slider_handle"); + ctx.beginPath(); + ctx.ellipse(circle_start_x, circle_start_y, selected_circle_diameter, selected_circle_diameter); + ctx.fill(); + ctx.closePath(); + } + + // print the hovered circle + if (resolutionSlider.currentHover != undefined && resolutionSlider.currentHover != resolutionSlider.currentQualityIndex) + { + var circle_start_x = (bar_left_right_margin + tick_left_right_margin) + step_size * (resolutionSlider.currentHover - resolutionSlider.fullRangeMin); + circle_start_x = circle_start_x + tick_width / 2 - selected_circle_diameter / 2; + var circle_start_y = height / 2 - selected_circle_diameter / 2; + ctx.fillStyle = UM.Theme.getColor("quality_slider_handle_hover"); + ctx.beginPath(); + ctx.ellipse(circle_start_x, circle_start_y, selected_circle_diameter, selected_circle_diameter); + ctx.fill(); + ctx.closePath(); + } + + // print layer height texts + total_tick_count = resolutionSlider.totalTickCount; + const step_size = resolutionSlider.tickStepSize; + current_start_x = bar_left_right_margin + tick_left_right_margin; + for (var i = 0; i < total_tick_count; ++i) + { + const text_top = parent.height / 2 - tick_height - tick_text_height; + ctx.fillStyle = UM.Theme.getColor("quality_slider_text"); + + ctx.font = "12px sans-serif"; + const string_length = resolutionSlider.model.getItem(i).layer_height_without_unit.length; + const offset = string_length / 2 * 4; + + var start_x = current_start_x - offset; + if (i == 0) + { + start_x = 0; + } + else if (i == total_tick_count - 1) + { + start_x = current_start_x - offset * 2; + } + + ctx.fillText(resolutionSlider.model.getItem(i).layer_height_without_unit, start_x, text_top); + current_start_x += step_size; + } + + // print currently selected quality text + if (resolutionSlider.showQualityText && resolutionSlider.currentQualityIndex != undefine) + { + const text_top = parent.height / 2 + tick_height + tick_text_height * 2; + total_tick_count = resolutionSlider.totalTickCount; + const step_size = resolutionSlider.tickStepSize; + current_start_x = (tick_left_right_margin) + step_size * (resolutionSlider.currentQualityIndex - resolutionSlider.fullRangeMin); + ctx.fillStyle = UM.Theme.getColor("quality_slider_text"); + ctx.fillText(resolutionSlider.model.getItem(resolutionSlider.currentQualityIndex).name, current_start_x - 6, text_top); + } + } + + MouseArea + { + anchors.fill: parent + hoverEnabled: true + + onClicked: + { + for (var i = 0; i < resolutionSlider.tickAreaList.length; ++i) + { + var area = resolutionSlider.tickAreaList[i]; + if (area.start_x <= mouseX && mouseX <= area.end_x && area.start_y <= mouseY && mouseY <= area.end_y) + { + resolutionSlider.currentHover = undefined; + resolutionSlider.currentQualityIndex = area.id; + + Cura.MachineManager.setActiveQuality(resolutionSlider.model.getItem(resolutionSlider.currentQualityIndex).id); + return; + } + } + resolutionSlider.currentHover = undefined; + } + onPositionChanged: + { + for (var i = 0; i < resolutionSlider.tickAreaList.length; ++i) + { + var area = resolutionSlider.tickAreaList[i]; + if (area.start_x <= mouseX && mouseX <= area.end_x && area.start_y <= mouseY && mouseY <= area.end_y) + { + resolutionSlider.currentHover = area.id; + return; + } + } + resolutionSlider.currentHover = undefined; + } + onExited: + { + resolutionSlider.currentHover = undefined; + } + } + } + } + + // + // Infill + // Item { id: infillCellLeft - anchors.top: parent.top + anchors.top: speedLabel.top + anchors.topMargin: UM.Theme.getSize("sidebar_margin").height * 1.2 anchors.left: parent.left - anchors.topMargin: UM.Theme.getSize("sidebar_margin").height * 0.8 width: UM.Theme.getSize("sidebar").width * .45 - UM.Theme.getSize("sidebar_margin").width height: childrenRect.height @@ -69,6 +443,7 @@ Item anchors.left: infillCellLeft.right anchors.top: infillCellLeft.top + anchors.topMargin: UM.Theme.getSize("sidebar_margin").height Repeater { diff --git a/resources/themes/cura-light/theme.json b/resources/themes/cura-light/theme.json index 6fd8f43b3e..1271dfbe71 100644 --- a/resources/themes/cura-light/theme.json +++ b/resources/themes/cura-light/theme.json @@ -196,6 +196,12 @@ "slider_handle_border": [39, 44, 48, 255], "slider_text_background": [255, 255, 255, 255], + "quality_slider_unavailable": [179, 179, 179, 255], + "quality_slider_available": [0, 0, 0, 255], + "quality_slider_handle": [0, 0, 0, 255], + "quality_slider_handle_hover": [127, 127, 127, 255], + "quality_slider_text": [0, 0, 0, 255], + "checkbox": [255, 255, 255, 255], "checkbox_hover": [255, 255, 255, 255], "checkbox_border": [64, 69, 72, 255], @@ -338,6 +344,8 @@ "scrollbar": [0.75, 0.5], + "quality_slider_bar": [1, 0.2], + "slider_groove": [0.3, 0.3], "slider_handle": [1.0, 1.0], "slider_layerview_size": [1.0, 22.0], From 3d6648fc5909b56947b622ed471df58fa623c6b2 Mon Sep 17 00:00:00 2001 From: Lipu Fei Date: Wed, 13 Sep 2017 17:12:51 +0200 Subject: [PATCH 10/23] Rearrange quality profile slider and dropdown box CURA-4182 - Remove the quality profile dropdown box from Recommended mode - Move the quality profile dropdown box to Custom mode --- resources/qml/Settings/SettingView.qml | 87 +++++++++++++++++++++++++- resources/qml/Sidebar.qml | 85 +------------------------ 2 files changed, 87 insertions(+), 85 deletions(-) diff --git a/resources/qml/Settings/SettingView.qml b/resources/qml/Settings/SettingView.qml index b6b79ed3d4..8dd8670f05 100644 --- a/resources/qml/Settings/SettingView.qml +++ b/resources/qml/Settings/SettingView.qml @@ -9,6 +9,8 @@ import QtQuick.Layouts 1.1 import UM 1.2 as UM import Cura 1.0 as Cura +import "../Menus" + Item { id: base; @@ -18,6 +20,88 @@ Item signal showTooltip(Item item, point location, string text); signal hideTooltip(); + Item + { + id: globalProfileRow + height: UM.Theme.getSize("sidebar_setup").height + visible: !sidebar.monitoringPrint && !sidebar.hideSettings + + anchors + { + top: parent.top + left: parent.left + leftMargin: UM.Theme.getSize("sidebar_margin").width + right: parent.right + rightMargin: UM.Theme.getSize("sidebar_margin").width + } + + Text + { + id: globalProfileLabel + text: catalog.i18nc("@label","Profile:"); + width: parent.width * 0.45 - UM.Theme.getSize("sidebar_margin").width - 2 + font: UM.Theme.getFont("default"); + color: UM.Theme.getColor("text"); + verticalAlignment: Text.AlignVCenter + anchors.top: parent.top + anchors.bottom: parent.bottom + } + + ToolButton + { + id: globalProfileSelection + + text: { + var result = Cura.MachineManager.activeQualityName; + if (Cura.MachineManager.activeQualityLayerHeight > 0) { + result += " "; + result += " - "; + result += Cura.MachineManager.activeQualityLayerHeight + "mm"; + result += ""; + } + return result; + } + enabled: !header.currentExtruderVisible || header.currentExtruderIndex > -1 + + width: parent.width * 0.55 + height: UM.Theme.getSize("setting_control").height + anchors.left: globalProfileLabel.right + anchors.right: parent.right + tooltip: Cura.MachineManager.activeQualityName + style: UM.Theme.styles.sidebar_header_button + activeFocusOnPress: true; + menu: ProfileMenu { } + + UM.SimpleButton + { + id: customisedSettings + + visible: Cura.MachineManager.hasUserSettings + height: parent.height * 0.6 + width: parent.height * 0.6 + + anchors.verticalCenter: parent.verticalCenter + anchors.right: parent.right + anchors.rightMargin: UM.Theme.getSize("setting_preferences_button_margin").width - UM.Theme.getSize("sidebar_margin").width + + color: hovered ? UM.Theme.getColor("setting_control_button_hover") : UM.Theme.getColor("setting_control_button"); + iconSource: UM.Theme.getIcon("star"); + + onClicked: + { + forceActiveFocus(); + Cura.Actions.manageProfiles.trigger() + } + onEntered: + { + var content = catalog.i18nc("@tooltip","Some setting/override values are different from the values stored in the profile.\n\nClick to open the profile manager.") + base.showTooltip(globalProfileRow, Qt.point(-UM.Theme.getSize("sidebar_margin").width, 0), content) + } + onExited: base.hideTooltip() + } + } + } + Rectangle { id: filterContainer @@ -40,7 +124,8 @@ Item anchors { - top: parent.top + top: globalProfileRow.bottom + topMargin: UM.Theme.getSize("sidebar_margin").height left: parent.left leftMargin: UM.Theme.getSize("sidebar_margin").width right: parent.right diff --git a/resources/qml/Sidebar.qml b/resources/qml/Sidebar.qml index ba357f40a5..4c6172c558 100755 --- a/resources/qml/Sidebar.qml +++ b/resources/qml/Sidebar.qml @@ -203,95 +203,12 @@ Rectangle } } - Item - { - id: globalProfileRow - height: UM.Theme.getSize("sidebar_setup").height - visible: !sidebar.monitoringPrint && !sidebar.hideSettings - - anchors - { - top: settingsModeSelection.bottom - topMargin: UM.Theme.getSize("sidebar_margin").height - left: parent.left - leftMargin: UM.Theme.getSize("sidebar_margin").width - right: parent.right - rightMargin: UM.Theme.getSize("sidebar_margin").width - } - - Text - { - id: globalProfileLabel - text: catalog.i18nc("@label","Profile:"); - width: parent.width * 0.45 - UM.Theme.getSize("sidebar_margin").width - 2 - font: UM.Theme.getFont("default"); - color: UM.Theme.getColor("text"); - verticalAlignment: Text.AlignVCenter - anchors.top: parent.top - anchors.bottom: parent.bottom - } - - ToolButton - { - id: globalProfileSelection - - text: { - var result = Cura.MachineManager.activeQualityName; - if (Cura.MachineManager.activeQualityLayerHeight > 0) { - result += " "; - result += " - "; - result += Cura.MachineManager.activeQualityLayerHeight + "mm"; - result += ""; - } - return result; - } - enabled: !header.currentExtruderVisible || header.currentExtruderIndex > -1 - - width: parent.width * 0.55 - height: UM.Theme.getSize("setting_control").height - anchors.left: globalProfileLabel.right - anchors.right: parent.right - tooltip: Cura.MachineManager.activeQualityName - style: UM.Theme.styles.sidebar_header_button - activeFocusOnPress: true; - menu: ProfileMenu { } - - UM.SimpleButton - { - id: customisedSettings - - visible: Cura.MachineManager.hasUserSettings - height: parent.height * 0.6 - width: parent.height * 0.6 - - anchors.verticalCenter: parent.verticalCenter - anchors.right: parent.right - anchors.rightMargin: UM.Theme.getSize("setting_preferences_button_margin").width - UM.Theme.getSize("sidebar_margin").width - - color: hovered ? UM.Theme.getColor("setting_control_button_hover") : UM.Theme.getColor("setting_control_button"); - iconSource: UM.Theme.getIcon("star"); - - onClicked: - { - forceActiveFocus(); - Cura.Actions.manageProfiles.trigger() - } - onEntered: - { - var content = catalog.i18nc("@tooltip","Some setting/override values are different from the values stored in the profile.\n\nClick to open the profile manager.") - base.showTooltip(globalProfileRow, Qt.point(-UM.Theme.getSize("sidebar_margin").width, 0), content) - } - onExited: base.hideTooltip() - } - } - } - StackView { id: sidebarContents anchors.bottom: footerSeparator.top - anchors.top: globalProfileRow.bottom + anchors.top: settingsModeSelection.bottom anchors.topMargin: UM.Theme.getSize("sidebar_margin").height anchors.left: base.left anchors.right: base.right From be57ccb127fe560fae3b7b5e66e1e6cb195d9b3f Mon Sep 17 00:00:00 2001 From: Lipu Fei Date: Wed, 13 Sep 2017 17:44:53 +0200 Subject: [PATCH 11/23] Minor fixes CURA-4224 - Fix code style - Fix typos --- .../FirmwareUpdateChecker/FirmwareUpdateChecker.py | 12 ++++++------ .../FirmwareUpdateCheckerJob.py | 10 +++++----- plugins/FirmwareUpdateChecker/__init__.py | 10 ++++++---- 3 files changed, 17 insertions(+), 15 deletions(-) diff --git a/plugins/FirmwareUpdateChecker/FirmwareUpdateChecker.py b/plugins/FirmwareUpdateChecker/FirmwareUpdateChecker.py index 994493a4e6..770aace3fe 100644 --- a/plugins/FirmwareUpdateChecker/FirmwareUpdateChecker.py +++ b/plugins/FirmwareUpdateChecker/FirmwareUpdateChecker.py @@ -1,6 +1,6 @@ -# Copyright (c) 2015 Ultimaker B.V. +# Copyright (c) 2017 Ultimaker B.V. # Cura is released under the terms of the AGPLv3 or higher. -from UM.Application import Application + from UM.Extension import Extension from UM.Preferences import Preferences from UM.Logger import Logger @@ -33,9 +33,9 @@ class FirmwareUpdateChecker(Extension): ContainerRegistry.getInstance().containerAdded.connect(self._onContainerAdded) def _onContainerAdded(self, container): - # Only take care when a new GlobaStack was added - if (isinstance(container, GlobalStack)): - Logger.log("i", "You have a '%s' in printer list. Let's check the firmware!" % container.getId()) + # Only take care when a new GlobalStack was added + if isinstance(container, GlobalStack): + Logger.log("i", "You have a '%s' in printer list. Let's check the firmware!", container.getId()) self.checkFirmwareVersion(container, True) ## Connect with software.ultimaker.com, load latest.version and check version info. @@ -46,4 +46,4 @@ class FirmwareUpdateChecker(Extension): # This is used when checking for a new firmware version at startup. def checkFirmwareVersion(self, container = None, silent = False): job = FirmwareUpdateCheckerJob(container = container, silent = silent, url = self.url) - job.start() \ No newline at end of file + job.start() diff --git a/plugins/FirmwareUpdateChecker/FirmwareUpdateCheckerJob.py b/plugins/FirmwareUpdateChecker/FirmwareUpdateCheckerJob.py index 9e0db57ed7..b95a2b1097 100644 --- a/plugins/FirmwareUpdateChecker/FirmwareUpdateCheckerJob.py +++ b/plugins/FirmwareUpdateChecker/FirmwareUpdateCheckerJob.py @@ -1,4 +1,4 @@ -# Copyright (c) 2015 Ultimaker B.V. +# Copyright (c) 2017 Ultimaker B.V. # Cura is released under the terms of the AGPLv3 or higher. from UM.Preferences import Preferences @@ -49,12 +49,12 @@ class FirmwareUpdateCheckerJob(Job): # If it is not None, then we compare between the checked_version and the current_version # Now we just do that if the active printer is Ultimaker 3 or Ultimaker 3 Extended or any # other Ultimaker 3 that will come in the future - if (machine_name[0:11] == "Ultimaker 3"): + if machine_name[0:11] == "Ultimaker 3": # Nothing to parse, just get the string # TODO: In the future may be done by parsing a JSON file with diferent version for each printer model current_version = reader(current_version_file).readline().rstrip() - Logger.log("i", "Reading firmware version of %s: %s" % (machine_name, current_version)) + Logger.log("i", "Reading firmware version of %s: %s", machine_name, current_version) # If it is the first time the version is checked, the checked_version is None checked_version = Preferences.getInstance().getValue("info/latest_checked_firmware") @@ -80,7 +80,7 @@ class FirmwareUpdateCheckerJob(Job): Preferences.getInstance().setValue("info/latest_checked_firmware", current_version) except Exception as e: - Logger.log("w", "Failed to check for new version: %s" % e) + Logger.log("w", "Failed to check for new version: %s", e) if not self.silent: Message(i18n_catalog.i18nc("@info", "Could not access update information.")).show() - return \ No newline at end of file + return diff --git a/plugins/FirmwareUpdateChecker/__init__.py b/plugins/FirmwareUpdateChecker/__init__.py index 5da6130772..b7343dc565 100644 --- a/plugins/FirmwareUpdateChecker/__init__.py +++ b/plugins/FirmwareUpdateChecker/__init__.py @@ -1,14 +1,16 @@ -# Copyright (c) 2015 Ultimaker B.V. +# Copyright (c) 2017 Ultimaker B.V. # Cura is released under the terms of the AGPLv3 or higher. from UM.i18n import i18nCatalog + from . import FirmwareUpdateChecker i18n_catalog = i18nCatalog("cura") + def getMetaData(): - return { - } + return {} + def register(app): - return { "extension": FirmwareUpdateChecker.FirmwareUpdateChecker()} + return {"extension": FirmwareUpdateChecker.FirmwareUpdateChecker()} From 9567a6921d3af0a27e5de7236b44ecbfc45c6d89 Mon Sep 17 00:00:00 2001 From: Lipu Fei Date: Thu, 14 Sep 2017 08:23:26 +0200 Subject: [PATCH 12/23] Fix code style CURA-4224 --- plugins/FirmwareUpdateChecker/FirmwareUpdateChecker.py | 4 ++-- plugins/FirmwareUpdateChecker/FirmwareUpdateCheckerJob.py | 1 - 2 files changed, 2 insertions(+), 3 deletions(-) diff --git a/plugins/FirmwareUpdateChecker/FirmwareUpdateChecker.py b/plugins/FirmwareUpdateChecker/FirmwareUpdateChecker.py index 770aace3fe..1c099705b1 100644 --- a/plugins/FirmwareUpdateChecker/FirmwareUpdateChecker.py +++ b/plugins/FirmwareUpdateChecker/FirmwareUpdateChecker.py @@ -17,7 +17,7 @@ i18n_catalog = i18nCatalog("cura") # The plugin is currently only usable for applications maintained by Ultimaker. But it should be relatively easy # to change it to work for other applications. class FirmwareUpdateChecker(Extension): - url = "http://software.ultimaker.com/jedi/releases/latest.version" + JEDI_VERSION_URL = "http://software.ultimaker.com/jedi/releases/latest.version" def __init__(self): super().__init__() @@ -45,5 +45,5 @@ class FirmwareUpdateChecker(Extension): # \param silent type(boolean) Suppresses messages other than "new version found" messages. # This is used when checking for a new firmware version at startup. def checkFirmwareVersion(self, container = None, silent = False): - job = FirmwareUpdateCheckerJob(container = container, silent = silent, url = self.url) + job = FirmwareUpdateCheckerJob(container = container, silent = silent, url = self.JEDI_VERSION_URL) job.start() diff --git a/plugins/FirmwareUpdateChecker/FirmwareUpdateCheckerJob.py b/plugins/FirmwareUpdateChecker/FirmwareUpdateCheckerJob.py index b95a2b1097..a13c856742 100644 --- a/plugins/FirmwareUpdateChecker/FirmwareUpdateCheckerJob.py +++ b/plugins/FirmwareUpdateChecker/FirmwareUpdateCheckerJob.py @@ -13,7 +13,6 @@ import codecs from PyQt5.QtCore import QUrl from PyQt5.QtGui import QDesktopServices - from UM.i18n import i18nCatalog i18n_catalog = i18nCatalog("cura") From a48507546fa9db2aac5ba2bc0c62e94f67bd678d Mon Sep 17 00:00:00 2001 From: Lipu Fei Date: Thu, 14 Sep 2017 08:34:01 +0200 Subject: [PATCH 13/23] More defensive machine name and version check CURA-4224 --- plugins/FirmwareUpdateChecker/FirmwareUpdateCheckerJob.py | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/plugins/FirmwareUpdateChecker/FirmwareUpdateCheckerJob.py b/plugins/FirmwareUpdateChecker/FirmwareUpdateCheckerJob.py index a13c856742..352d32c0fb 100644 --- a/plugins/FirmwareUpdateChecker/FirmwareUpdateCheckerJob.py +++ b/plugins/FirmwareUpdateChecker/FirmwareUpdateCheckerJob.py @@ -43,13 +43,14 @@ class FirmwareUpdateCheckerJob(Job): current_version_file = urllib.request.urlopen(request) reader = codecs.getreader("utf-8") - machine_name = self._container.getId() + # get machine name from the definition container + machine_name = self._container.definition.getName().lower() + machine_name_parts = machine_name.split(" ") # If it is not None, then we compare between the checked_version and the current_version # Now we just do that if the active printer is Ultimaker 3 or Ultimaker 3 Extended or any # other Ultimaker 3 that will come in the future - if machine_name[0:11] == "Ultimaker 3": - + if len(machine_name_parts) >= 2 and machine_name_parts[:2] == ["ultimaker", "3"]: # Nothing to parse, just get the string # TODO: In the future may be done by parsing a JSON file with diferent version for each printer model current_version = reader(current_version_file).readline().rstrip() From 5df5dfec029e6685789012ecacafb6815dabc179 Mon Sep 17 00:00:00 2001 From: Lipu Fei Date: Thu, 14 Sep 2017 08:50:23 +0200 Subject: [PATCH 14/23] Auto-adjust mode tab position based on text length CURA-4322 --- resources/qml/Sidebar.qml | 13 +++++++++++-- 1 file changed, 11 insertions(+), 2 deletions(-) diff --git a/resources/qml/Sidebar.qml b/resources/qml/Sidebar.qml index ba357f40a5..c598af7d99 100755 --- a/resources/qml/Sidebar.qml +++ b/resources/qml/Sidebar.qml @@ -125,7 +125,6 @@ Rectangle font: UM.Theme.getFont("large") color: UM.Theme.getColor("text") visible: !monitoringPrint - elide: Text.ElideRight } Rectangle { @@ -135,7 +134,17 @@ Rectangle height: UM.Theme.getSize("sidebar_header_mode_toggle").height anchors.right: parent.right anchors.rightMargin: UM.Theme.getSize("sidebar_margin").width - anchors.top: headerSeparator.bottom + anchors.top: + { + if (settingsModeLabel.contentWidth >= parent.width - width - UM.Theme.getSize("sidebar_margin").width) + { + return settingsModeLabel.bottom; + } + else + { + return headerSeparator.bottom; + } + } anchors.topMargin: UM.Theme.getSize("sidebar_margin").height visible: !monitoringPrint && !hideSettings Component{ From c5c6ed8b2b5faa38b10d53c29205bada08f3e363 Mon Sep 17 00:00:00 2001 From: ChrisTerBeke Date: Thu, 14 Sep 2017 09:59:13 +0200 Subject: [PATCH 15/23] CURA-4318 fix colors and layouts for dark design --- plugins/LayerView/LayerView.qml | 4 +- resources/qml/SidebarSimple.qml | 4 +- resources/themes/cura-dark/images/logo.svg | 72 ++++++++++++++++++++++ resources/themes/cura-dark/theme.json | 32 ++++------ 4 files changed, 90 insertions(+), 22 deletions(-) create mode 100644 resources/themes/cura-dark/images/logo.svg diff --git a/plugins/LayerView/LayerView.qml b/plugins/LayerView/LayerView.qml index 8927d59017..26087b8b65 100755 --- a/plugins/LayerView/LayerView.qml +++ b/plugins/LayerView/LayerView.qml @@ -519,8 +519,8 @@ Item anchors.horizontalCenter: parent.horizontalCenter radius: parent.handleRadius color: parent.lowerHandleColor - border.width: UM.Theme.getSize("default_lining").width - border.color: UM.Theme.getColor("slider_handle_border") +// border.width: UM.Theme.getSize("default_lining").width +// border.color: UM.Theme.getColor("slider_handle_border") visible: slider.layersVisible diff --git a/resources/qml/SidebarSimple.qml b/resources/qml/SidebarSimple.qml index c2c1562fbb..ffb5e1f00b 100644 --- a/resources/qml/SidebarSimple.qml +++ b/resources/qml/SidebarSimple.qml @@ -35,6 +35,8 @@ Item { width: childrenRect.width height: childrenRect.height + color: UM.Theme.getColor("sidebar") + Item { id: infillCellLeft @@ -479,7 +481,7 @@ Item anchors.top: parent.top wrapMode: Text.WordWrap //: Tips label - text: catalog.i18nc("@label", "Need help improving your prints?
Read the Ultimaker Troubleshooting Guides").arg("https://ultimaker.com/en/troubleshooting") + "".arg(UM.Theme.getIcon("play")) + text: catalog.i18nc("@label", "Need help improving your prints?
Read the Ultimaker Troubleshooting Guides").arg("https://ultimaker.com/en/troubleshooting") font: UM.Theme.getFont("default"); color: UM.Theme.getColor("text"); linkColor: UM.Theme.getColor("text_link") diff --git a/resources/themes/cura-dark/images/logo.svg b/resources/themes/cura-dark/images/logo.svg new file mode 100644 index 0000000000..236b413b66 --- /dev/null +++ b/resources/themes/cura-dark/images/logo.svg @@ -0,0 +1,72 @@ + + + + + + image/svg+xml + + + + + + + + + + + + + diff --git a/resources/themes/cura-dark/theme.json b/resources/themes/cura-dark/theme.json index dbe19bd298..586db9761f 100644 --- a/resources/themes/cura-dark/theme.json +++ b/resources/themes/cura-dark/theme.json @@ -121,14 +121,13 @@ "progressbar_background": [255, 255, 255, 48], "progressbar_control": [255, 255, 255, 197], - "slider_groove": [39, 44, 48, 75], - "slider_groove_border": [39, 44, 48, 0], - "slider_groove_fill": [39, 44, 48, 182], + "slider_groove": [245, 245, 245, 255], + "slider_groove_border": [127, 127, 127, 255], + "slider_groove_fill": [127, 127, 127, 255], "slider_handle": [255, 255, 255, 255], + "slider_handle_hover": [77, 182, 226, 255], "slider_handle_border": [39, 44, 48, 255], - "slider_handle_hover": [255, 255, 255, 255], - "slider_handle_hover_border": [39, 44, 48, 255], - "slider_text_background": [39, 44, 48, 255], + "slider_text_background": [255, 255, 255, 255], "checkbox": [43, 48, 52, 255], "checkbox_hover": [43, 48, 52, 255], @@ -140,18 +139,6 @@ "tooltip": [39, 44, 48, 255], "tooltip_text": [255, 255, 255, 204], - "message_background": [255, 255, 255, 200], - "message_text": [0, 0, 0, 255], - "message_border": [191, 191, 191, 200], - "message_button": [255, 255, 255, 255], - "message_button_hover": [12, 169, 227, 255], - "message_button_active": [32, 166, 219, 255], - "message_button_text": [24, 41, 77, 255], - "message_button_text_hover": [255, 255, 255, 255], - "message_button_text_active": [255, 255, 255, 255], - "message_progressbar_background": [255, 255, 255, 255], - "message_progressbar_control": [12, 169, 227, 255], - "tool_panel_background": [39, 44, 48, 255], "status_offline": [0, 0, 0, 255], @@ -198,6 +185,13 @@ "layerview_support_infill": [0, 255, 255, 255], "layerview_move_combing": [0, 0, 255, 255], "layerview_move_retraction": [128, 128, 255, 255], - "layerview_support_interface": [64, 192, 255, 255] + "layerview_support_interface": [64, 192, 255, 255], + + "material_compatibility_warning": [255, 255, 255, 255], + + "topbar_button_text_inactive": [255, 255, 255, 255], + "topbar_button_text_active": [255, 255, 255, 255], + "topbar_button_text_hovered": [255, 255, 255, 255], + "topbar_background_color_monitoring": [39, 44, 48, 255] } } From 9ec1d5d54abf2997a950b135b0d9900077cb4f4a Mon Sep 17 00:00:00 2001 From: ChrisTerBeke Date: Thu, 14 Sep 2017 10:21:30 +0200 Subject: [PATCH 16/23] Add CuraEngine.exe to git ignore --- .gitignore | 1 + 1 file changed, 1 insertion(+) diff --git a/.gitignore b/.gitignore index 9c9d57f175..03ae94a87f 100644 --- a/.gitignore +++ b/.gitignore @@ -10,6 +10,7 @@ resources/i18n/en_7S resources/i18n/x-test resources/firmware resources/materials +CuraEngine.exe LC_MESSAGES .cache *.qmlc From 96c1e7ea8be341217376d8367d5b59b5ec07cd1c Mon Sep 17 00:00:00 2001 From: ChrisTerBeke Date: Thu, 14 Sep 2017 10:58:22 +0200 Subject: [PATCH 17/23] CURA-4182 dark design fixes for quality slider --- resources/themes/cura-dark/theme.json | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/resources/themes/cura-dark/theme.json b/resources/themes/cura-dark/theme.json index 586db9761f..906a5c280e 100644 --- a/resources/themes/cura-dark/theme.json +++ b/resources/themes/cura-dark/theme.json @@ -192,6 +192,12 @@ "topbar_button_text_inactive": [255, 255, 255, 255], "topbar_button_text_active": [255, 255, 255, 255], "topbar_button_text_hovered": [255, 255, 255, 255], - "topbar_background_color_monitoring": [39, 44, 48, 255] + "topbar_background_color_monitoring": [39, 44, 48, 255], + + "quality_slider_unavailable": [179, 179, 179, 255], + "quality_slider_available": [255, 255, 255, 255], + "quality_slider_handle": [255, 255, 255, 255], + "quality_slider_handle_hover": [127, 127, 127, 255], + "quality_slider_text": [255, 255, 255, 255] } } From 7144720d788b4d22608bac7920ad885d9b95abf6 Mon Sep 17 00:00:00 2001 From: Lipu Fei Date: Thu, 14 Sep 2017 11:34:45 +0200 Subject: [PATCH 18/23] Redesign splash window CURA-4215 - Rectangle splash window - Fix for splash window crash - Enable antialias - Fix for longer loading text in some languages --- cura/CuraSplashScreen.py | 25 ++++++++++++++----------- resources/images/cura.png | Bin 52943 -> 56143 bytes resources/images/loading.png | Bin 3585 -> 0 bytes 3 files changed, 14 insertions(+), 11 deletions(-) delete mode 100644 resources/images/loading.png diff --git a/cura/CuraSplashScreen.py b/cura/CuraSplashScreen.py index dd4dd9b2cc..7e25855655 100644 --- a/cura/CuraSplashScreen.py +++ b/cura/CuraSplashScreen.py @@ -2,10 +2,9 @@ # Uranium is released under the terms of the AGPLv3 or higher. from threading import Thread, Event -import time -from PyQt5.QtCore import Qt, QCoreApplication -from PyQt5.QtGui import QPixmap, QColor, QFont, QFontMetrics, QImage, QPen +from PyQt5.QtCore import Qt +from PyQt5.QtGui import QPixmap, QColor, QFont, QPen, QPainter from PyQt5.QtWidgets import QSplashScreen from UM.Resources import Resources @@ -22,8 +21,6 @@ class CuraSplashScreen(QSplashScreen): self._current_message = "" - self._loading_image = QImage(Resources.getPath(Resources.Images, "loading.png")) - self._loading_image = self._loading_image.scaled(30, 30, Qt.KeepAspectRatio) self._loading_image_rotation_angle = 0 self._to_stop = False @@ -46,6 +43,8 @@ class CuraSplashScreen(QSplashScreen): painter.save() painter.setPen(QColor(255, 255, 255, 255)) + painter.setRenderHint(QPainter.Antialiasing) + painter.setRenderHint(QPainter.Antialiasing, True) version = Application.getInstance().getVersion().split("-") buildtype = Application.getInstance().getBuildType() @@ -56,25 +55,30 @@ class CuraSplashScreen(QSplashScreen): font = QFont() # Using system-default font here font.setPointSize(34) painter.setFont(font) - painter.drawText(275, 87, 330 * self._scale, 230 * self._scale, Qt.AlignLeft | Qt.AlignBottom, version[0]) + painter.drawText(300, 110, 330 * self._scale, 230 * self._scale, Qt.AlignLeft | Qt.AlignTop, version[0]) if len(version) > 1: font.setPointSize(12) painter.setFont(font) - painter.drawText(320, 82, 330 * self._scale, 255 * self._scale, Qt.AlignLeft | Qt.AlignBottom, version[1]) + painter.setPen(QColor(200, 200, 200, 255)) + painter.drawText(343, 160, 330 * self._scale, 255 * self._scale, Qt.AlignLeft | Qt.AlignTop, version[1]) + painter.setPen(QColor(255, 255, 255, 255)) # draw the loading image pen = QPen() - pen.setWidth(4 * self._scale) + pen.setWidth(6 * self._scale) pen.setColor(QColor(255, 255, 255, 255)) painter.setPen(pen) - painter.drawArc(130, 380, 32 * self._scale, 32 * self._scale, self._loading_image_rotation_angle * 16, 300 * 16) + #painter.drawArc(100, 350, 32 * self._scale, 32 * self._scale, self._loading_image_rotation_angle * 16, 300 * 16) + painter.drawArc(60, 350, 32 * self._scale, 32 * self._scale, self._loading_image_rotation_angle * 16, 300 * 16) # draw message text if self._current_message: font = QFont() # Using system-default font here font.setPointSize(16) painter.setFont(font) - painter.drawText(180, 243, 330 * self._scale, 230 * self._scale, Qt.AlignLeft | Qt.AlignBottom, + #painter.drawText(150, 328, 316, 64, + painter.drawText(100, 328, 260, 64, + Qt.AlignLeft | Qt.AlignVCenter | Qt.TextWordWrap, self._current_message) painter.restore() @@ -86,7 +90,6 @@ class CuraSplashScreen(QSplashScreen): self._current_message = message self.messageChanged.emit(message) - self.repaint() def close(self): # set stop flags diff --git a/resources/images/cura.png b/resources/images/cura.png index f3aacf32a768942f8243d620391c3a7a788de0b5..e3d069e8da73e01a561a5dbad46f5bdee9189763 100644 GIT binary patch literal 56143 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 diff --git a/resources/images/loading.png b/resources/images/loading.png deleted file mode 100644 index c9a0151b28da8e1846ff465b13f93ce092ec0457..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 3585 zcmW+(2{=^k`<_ru){$+rU|M7}SwfaFKEo6vX(oKuEE8euW5}+IU8qF%CF?LF%ix=+ zkWn<0WhRj|CTm%<#sB>N=Q{6suXE0G&h^~yd7k^ePr~h6H-z|4@Pj}gA!8#$959pq zH^4`Lqc0z=1(^7VC}VRlu!Vu|#RKQZe2uJ$Kz#83#vv>tLEI{`#T7#r%FKgeCm8x9=NIv!g~EO*mBT^>5-csF89 zp1a;@w^@?+-bUf69Ej(I0M@;0<;BOGM* zGC`pI@OkWF5?xZUl&94E>wz=drlD&g@NNC~aXMRh{~GE81a%Hp;*v~H#~p$-7__F= zK4gE>Gt-Uds4yYD!Nuu`>9~hi_x56@tPvFxaXCzT2 zxbEMB)4}{O!&oP)7$>W<EAOx}74kb)!DM{m(D!cmEvT{TC zK%mc!UZd))>IKHcAYNM>?t&;yJ_fs-SPbm*gLs{pn=!d-CGOc-?Cg9u!RTmJOTSY! zW(v#h84hrl=3!6o@nf; z))~5v$*HcYvR-9ZOx3Cu7+RefKL-B+dp$kZqm|NgcGP<>i$a%ovEDCBXK0;uQ>doD zqELcI8jZ2yv>3)wfm&$!%3b^V12NxstFFQB>JMJ)Qli+yQ|Xyv%e2z5AH|3s@ew zggDx7JT*w=h{O=oAfspIyK18%6pw~Wkkc9uh(Q%Sy*5blz5^Y7T2zH)cc3g20kY>MV!dS0H~b zac3kKyQvLo#9fDXW|w6>o|KM;WN(MPhTEs6NM?kedj6=P26JM@f7@N*q787TpNP9{l2n0c6zrT$OsUUbz=RD~Cbr!;sbP6S>=#&6f z{5cvsY5-Pt{xAITSjgWD?sikrm>GwpZ(*Ss_hwlRJJR@Ao4Z}48JwbSDqDxJ74)ML z&j@yeAPXXal7rE@wEINpjejI92&PwZSaBV38yBrJ!c(WWJgK%0DohU`&M8@F)d=3R z8qE&z`87UPoZ+&a^NZbSBd~hyAVfI$8lD%X4rCGM^z-iwon2gq_>+G-G+|Jk+9T*mDkB8B+$--S2o*bu%oF4gCk0r#_+gbb!%i;nB{ozng|={&vi z%zz!VIn40K^s5_S(v5Dzw-4mVSNe!t2`bQs+9q34SZ!|Bf+^^0#I8IcC^GP40Ieoc z>D}tH3bsv2dZL|Al&Yl@R9Ny(i)0;wm=8w9e}%3+OVRsV>NWDdD^$E|rF(8|k)Wu}m{O=^&YkJ z19Wb z0w*Sla!aey!b>^jZk6W^KdhO9pgy>lF-Co-RP4gQVA#^NJ8j1V9*@qG>%}oQAK)<+Mt>rHcnNtLynW~17UPEjDhsabs0qs^sChB;V|W~g5<5b~@{N;f4Z9&K!+GE+FV_igUF1(ic6*~&ULXC|9zXY*pWoto{UFcp zpPy?9tG_iGijnfP8D80fj4c?2ASzsH{v+E}XGJaC>2mq$&S~5Yz4!lsNirs{{?(@@ zTq4=aj?w@H-3ffDH`=PldL;+WO)1kfRZEyR9#F4bK!h{8i#hv5hh)`zA&m??HO6#6 zi`D<;a&J#D3M_>GGzYe~uoz>B(Vnwhr$;ZOs4@!}!I7%Ic7)FWSvCmD-Wo4|w@nPa zRpVeN^r(=e8)U;FscN6ypjT*qmc7C99mWL zyz#2D^ccsGdJSj)JEV0VTsAu4kcK+~i1I8^2o)bjwc4zz|5(2E45v6+9y6p-lwQ2B z@vSm+1>dh8Zjt#fdV~6FtkG-J<{+JbBCr4*zA*k>AHpYrUmW`WF-P-5o#!O6oeGd7 zLCO;I5m2fN<9u6ht}<7t1)+D$$!QTwMJ*y6L^b5h3FlazS6=@z`i||ldW(1Y&1J9F zy#yYtL+IHJNavQh*A01)G|7eO{ek08H$%q}eZ-nFBFK~IV_Eh5&*gyS_3&FhRTReQ zsZ+|R51(A?TSGgRE-5mtcCX~|I@+p)07ha3S5Rlt_5XTb4#R(P&yLV5!S(3(Jn|X% z?=%x?moWp_h_y-G?L=+vTt`R8+pupG-Sa8a8%3qgBAZvs+!^MW!v=!6#C(9!5j}4l z{L#2laVlj#@MpR;rqXC&-SO>qon`|_yg&I|W;P3SymC&~km(sna-$|d&OF62F_piq z#+1ov`7GBzyshPvhKC(@ivX;zYx6Zz=hS3vQSowQBTS`E$$S|u(Susa&Q>h7Ql9#v zYk&1(&^wvsjzs=|YvSR7XZe z4(#g$e2o-Jm%@+-ghi!{mmCxdJXfr+@0~4Qv#>LpJym%X&|l-HL$x+xveb7Lr@CCk z(Io4PHGZsbU?Q5*AHvLXUZrP+X5t!D-1IPYD25@<$d*qAXzOg zoEx^8|GpDibN8_8)`z>iEk_Csw9J|1Si_}TZg`p{Qb`9S*{fud4W4GpFo;ZhxYIb;|{ zxU~4U`UvbEj0{jT1U2GM0mD)8XUGBE<`S9qgF`z~Uu?>LD5(R#YanCvEkhd0@zMVQ Dgh1n@ From 9683dcae729de449f5cde838d14dce53bbb1ec2d Mon Sep 17 00:00:00 2001 From: Lipu Fei Date: Thu, 14 Sep 2017 11:44:09 +0200 Subject: [PATCH 19/23] Remose useless code CURA-4215 --- cura/CuraSplashScreen.py | 2 -- 1 file changed, 2 deletions(-) diff --git a/cura/CuraSplashScreen.py b/cura/CuraSplashScreen.py index 7e25855655..f6c004dc7a 100644 --- a/cura/CuraSplashScreen.py +++ b/cura/CuraSplashScreen.py @@ -68,7 +68,6 @@ class CuraSplashScreen(QSplashScreen): pen.setWidth(6 * self._scale) pen.setColor(QColor(255, 255, 255, 255)) painter.setPen(pen) - #painter.drawArc(100, 350, 32 * self._scale, 32 * self._scale, self._loading_image_rotation_angle * 16, 300 * 16) painter.drawArc(60, 350, 32 * self._scale, 32 * self._scale, self._loading_image_rotation_angle * 16, 300 * 16) # draw message text @@ -76,7 +75,6 @@ class CuraSplashScreen(QSplashScreen): font = QFont() # Using system-default font here font.setPointSize(16) painter.setFont(font) - #painter.drawText(150, 328, 316, 64, painter.drawText(100, 328, 260, 64, Qt.AlignLeft | Qt.AlignVCenter | Qt.TextWordWrap, self._current_message) From d14ac9e258690ea6d26ddb0c4e8967649477e5b6 Mon Sep 17 00:00:00 2001 From: Lipu Fei Date: Thu, 14 Sep 2017 12:08:27 +0200 Subject: [PATCH 20/23] Fix text overlapping problem for adhesion in recommended mode CURA-4322 --- resources/qml/SidebarSimple.qml | 2 ++ 1 file changed, 2 insertions(+) diff --git a/resources/qml/SidebarSimple.qml b/resources/qml/SidebarSimple.qml index 276eacef29..4e68dfcbc0 100644 --- a/resources/qml/SidebarSimple.qml +++ b/resources/qml/SidebarSimple.qml @@ -766,6 +766,8 @@ Item visible: adhesionCheckBox.visible anchors.left: parent.left anchors.leftMargin: UM.Theme.getSize("sidebar_margin").width + anchors.right: infillCellLeft.right + anchors.rightMargin: UM.Theme.getSize("sidebar_margin").width anchors.verticalCenter: adhesionCheckBox.verticalCenter text: catalog.i18nc("@label", "Build Plate Adhesion"); font: UM.Theme.getFont("default"); From 3073fcf6f7c8631d857e50a07120a0e52ed5e3f7 Mon Sep 17 00:00:00 2001 From: ChrisTerBeke Date: Thu, 14 Sep 2017 12:43:07 +0200 Subject: [PATCH 21/23] CURA-4318 add white icon for unknown printer status in dark theme --- .../themes/cura-dark/icons/tab_status_unknown.svg | 15 +++++++++++++++ 1 file changed, 15 insertions(+) create mode 100644 resources/themes/cura-dark/icons/tab_status_unknown.svg diff --git a/resources/themes/cura-dark/icons/tab_status_unknown.svg b/resources/themes/cura-dark/icons/tab_status_unknown.svg new file mode 100644 index 0000000000..249ae55554 --- /dev/null +++ b/resources/themes/cura-dark/icons/tab_status_unknown.svg @@ -0,0 +1,15 @@ + + + + Unknown + Created with Sketch. + + + + + + + + + + \ No newline at end of file From 3812a478cf43196c0d99c2e5dc327040067cc16f Mon Sep 17 00:00:00 2001 From: Lipu Fei Date: Thu, 14 Sep 2017 12:50:53 +0200 Subject: [PATCH 22/23] Only use lowercase for string comparison CURA-4224 --- plugins/FirmwareUpdateChecker/FirmwareUpdateCheckerJob.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/plugins/FirmwareUpdateChecker/FirmwareUpdateCheckerJob.py b/plugins/FirmwareUpdateChecker/FirmwareUpdateCheckerJob.py index 352d32c0fb..108cfa4c0d 100644 --- a/plugins/FirmwareUpdateChecker/FirmwareUpdateCheckerJob.py +++ b/plugins/FirmwareUpdateChecker/FirmwareUpdateCheckerJob.py @@ -44,8 +44,8 @@ class FirmwareUpdateCheckerJob(Job): reader = codecs.getreader("utf-8") # get machine name from the definition container - machine_name = self._container.definition.getName().lower() - machine_name_parts = machine_name.split(" ") + machine_name = self._container.definition.getName() + machine_name_parts = machine_name.lower().split(" ") # If it is not None, then we compare between the checked_version and the current_version # Now we just do that if the active printer is Ultimaker 3 or Ultimaker 3 Extended or any From 17986aa4adbfce1f356ffb54fa80dc038da17afe Mon Sep 17 00:00:00 2001 From: ChrisTerBeke Date: Thu, 14 Sep 2017 13:04:29 +0200 Subject: [PATCH 23/23] CURA-4318 add border to toolbar buttons in dark theme, outline fix for unknown printer status icon in dark theme --- resources/themes/cura-dark/icons/tab_status_unknown.svg | 2 +- resources/themes/cura-dark/theme.json | 2 ++ resources/themes/cura-light/icons/tab_status_unknown.svg | 2 +- resources/themes/cura-light/theme.json | 4 +++- 4 files changed, 7 insertions(+), 3 deletions(-) diff --git a/resources/themes/cura-dark/icons/tab_status_unknown.svg b/resources/themes/cura-dark/icons/tab_status_unknown.svg index 249ae55554..94dc47c018 100644 --- a/resources/themes/cura-dark/icons/tab_status_unknown.svg +++ b/resources/themes/cura-dark/icons/tab_status_unknown.svg @@ -5,7 +5,7 @@ Created with Sketch. - + diff --git a/resources/themes/cura-dark/theme.json b/resources/themes/cura-dark/theme.json index 906a5c280e..5c77f5144d 100644 --- a/resources/themes/cura-dark/theme.json +++ b/resources/themes/cura-dark/theme.json @@ -141,6 +141,8 @@ "tool_panel_background": [39, 44, 48, 255], + "tool_button_border": [255, 255, 255, 38], + "status_offline": [0, 0, 0, 255], "status_ready": [0, 205, 0, 255], "status_busy": [12, 169, 227, 255], diff --git a/resources/themes/cura-light/icons/tab_status_unknown.svg b/resources/themes/cura-light/icons/tab_status_unknown.svg index f195ae238a..a6aea3be84 100644 --- a/resources/themes/cura-light/icons/tab_status_unknown.svg +++ b/resources/themes/cura-light/icons/tab_status_unknown.svg @@ -5,7 +5,7 @@ Created with Sketch. - + diff --git a/resources/themes/cura-light/theme.json b/resources/themes/cura-light/theme.json index 1271dfbe71..fb6e43d0be 100644 --- a/resources/themes/cura-light/theme.json +++ b/resources/themes/cura-light/theme.json @@ -221,7 +221,7 @@ "tooltip": [68, 192, 255, 255], "tooltip_text": [255, 255, 255, 255], - "tool_button_border": [39, 44, 48, 255], + "tool_button_border": [255, 255, 255, 0], "message_background": [255, 255, 255, 255], "message_shadow": [0, 0, 0, 120], @@ -338,6 +338,8 @@ "button_tooltip": [1.0, 1.3], "button_tooltip_arrow": [0.25, 0.25], + "tool_button_border": [1.0, 0], + "progressbar": [26.0, 0.4], "progressbar_radius": [0, 0], "progressbar_control": [8.0, 0.4],