diff --git a/cura/API/Account.py b/cura/API/Account.py index 64d63c7025..397e220478 100644 --- a/cura/API/Account.py +++ b/cura/API/Account.py @@ -38,12 +38,13 @@ class Account(QObject): self._callback_port = 32118 self._oauth_root = "https://account.ultimaker.com" + self._cloud_api_root = "https://api.ultimaker.com" self._oauth_settings = OAuth2Settings( OAUTH_SERVER_URL= self._oauth_root, CALLBACK_PORT=self._callback_port, CALLBACK_URL="http://localhost:{}/callback".format(self._callback_port), - CLIENT_ID="um----------------------------ultimaker_cura", + CLIENT_ID="um---------------ultimaker_cura_drive_plugin", CLIENT_SCOPES="account.user.read drive.backup.read drive.backup.write packages.download packages.rating.read packages.rating.write", AUTH_DATA_PREFERENCE_KEY="general/ultimaker_auth_data", AUTH_SUCCESS_REDIRECT="{}/app/auth-success".format(self._oauth_root), diff --git a/cura/BuildVolume.py b/cura/BuildVolume.py index f837f5cef7..aa1f170707 100755 --- a/cura/BuildVolume.py +++ b/cura/BuildVolume.py @@ -83,7 +83,14 @@ class BuildVolume(SceneNode): " with printed models."), title = catalog.i18nc("@info:title", "Build Volume")) self._global_container_stack = None + + self._stack_change_timer = QTimer() + self._stack_change_timer.setInterval(100) + self._stack_change_timer.setSingleShot(True) + self._stack_change_timer.timeout.connect(self._onStackChangeTimerFinished) + self._application.globalContainerStackChanged.connect(self._onStackChanged) + self._onStackChanged() self._engine_ready = False @@ -105,6 +112,8 @@ class BuildVolume(SceneNode): self._setting_change_timer.setSingleShot(True) self._setting_change_timer.timeout.connect(self._onSettingChangeTimerFinished) + + # Must be after setting _build_volume_message, apparently that is used in getMachineManager. # activeQualityChanged is always emitted after setActiveVariant, setActiveMaterial and setActiveQuality. # Therefore this works. @@ -526,8 +535,11 @@ class BuildVolume(SceneNode): if extra_z != self._extra_z_clearance: self._extra_z_clearance = extra_z - ## Update the build volume visualization def _onStackChanged(self): + self._stack_change_timer.start() + + ## Update the build volume visualization + def _onStackChangeTimerFinished(self): if self._global_container_stack: self._global_container_stack.propertyChanged.disconnect(self._onSettingPropertyChanged) extruders = ExtruderManager.getInstance().getActiveExtruderStacks() diff --git a/cura/CuraApplication.py b/cura/CuraApplication.py index 95b94c01c7..e59c4e2895 100755 --- a/cura/CuraApplication.py +++ b/cura/CuraApplication.py @@ -434,6 +434,7 @@ class CuraApplication(QtApplication): "XmlMaterialProfile", #Cura crashes without this one. "Toolbox", #This contains the interface to enable/disable plug-ins, so if you disable it you can't enable it back. "PrepareStage", #Cura is useless without this one since you can't load models. + "PreviewStage", #This shows the list of the plugin views that are installed in Cura. "MonitorStage", #Major part of Cura's functionality. "LocalFileOutputDevice", #Major part of Cura's functionality. "LocalContainerProvider", #Cura is useless without any profiles or setting definitions. @@ -626,9 +627,7 @@ class CuraApplication(QtApplication): self._message_box_callback(button, *self._message_box_callback_arguments) self._message_box_callback = None self._message_box_callback_arguments = [] - - showPrintMonitor = pyqtSignal(bool, arguments = ["show"]) - + def setSaveDataEnabled(self, enabled: bool) -> None: self._save_data_enabled = enabled @@ -1659,7 +1658,9 @@ class CuraApplication(QtApplication): is_non_sliceable = "." + file_extension in self._non_sliceable_extensions if is_non_sliceable: - self.callLater(lambda: self.getController().setActiveView("SimulationView")) + # Need to switch first to the preview stage and then to layer view + self.callLater(lambda: (self.getController().setActiveStage("PreviewStage"), + self.getController().setActiveView("SimulationView"))) block_slicing_decorator = BlockSlicingDecorator() node.addDecorator(block_slicing_decorator) diff --git a/cura/CuraView.py b/cura/CuraView.py new file mode 100644 index 0000000000..978c651b43 --- /dev/null +++ b/cura/CuraView.py @@ -0,0 +1,24 @@ +# Copyright (c) 2018 Ultimaker B.V. +# Cura is released under the terms of the LGPLv3 or higher. + +from PyQt5.QtCore import pyqtProperty, QUrl + +from UM.View.View import View + + +# Since Cura has a few pre-defined "space claims" for the locations of certain components, we've provided some structure +# to indicate this. +# MainComponent works in the same way the MainComponent of a stage. +# the stageMenuComponent returns an item that should be used somehwere in the stage menu. It's up to the active stage +# to actually do something with this. +class CuraView(View): + def __init__(self, parent = None) -> None: + super().__init__(parent) + + @pyqtProperty(QUrl, constant = True) + def mainComponent(self) -> QUrl: + return self.getDisplayComponent("main") + + @pyqtProperty(QUrl, constant = True) + def stageMenuComponent(self) -> QUrl: + return self.getDisplayComponent("menu") \ No newline at end of file diff --git a/cura/Machines/MachineErrorChecker.py b/cura/Machines/MachineErrorChecker.py index 06f064315b..fb11123af6 100644 --- a/cura/Machines/MachineErrorChecker.py +++ b/cura/Machines/MachineErrorChecker.py @@ -64,21 +64,21 @@ class MachineErrorChecker(QObject): def _onMachineChanged(self) -> None: if self._global_stack: - self._global_stack.propertyChanged.disconnect(self.startErrorCheck) + self._global_stack.propertyChanged.disconnect(self.startErrorCheckPropertyChanged) self._global_stack.containersChanged.disconnect(self.startErrorCheck) for extruder in self._global_stack.extruders.values(): - extruder.propertyChanged.disconnect(self.startErrorCheck) + extruder.propertyChanged.disconnect(self.startErrorCheckPropertyChanged) extruder.containersChanged.disconnect(self.startErrorCheck) self._global_stack = self._machine_manager.activeMachine if self._global_stack: - self._global_stack.propertyChanged.connect(self.startErrorCheck) + self._global_stack.propertyChanged.connect(self.startErrorCheckPropertyChanged) self._global_stack.containersChanged.connect(self.startErrorCheck) for extruder in self._global_stack.extruders.values(): - extruder.propertyChanged.connect(self.startErrorCheck) + extruder.propertyChanged.connect(self.startErrorCheckPropertyChanged) extruder.containersChanged.connect(self.startErrorCheck) hasErrorUpdated = pyqtSignal() @@ -93,6 +93,13 @@ class MachineErrorChecker(QObject): def needToWaitForResult(self) -> bool: return self._need_to_check or self._check_in_progress + # Start the error check for property changed + # this is seperate from the startErrorCheck because it ignores a number property types + def startErrorCheckPropertyChanged(self, key, property_name): + if property_name != "value": + return + self.startErrorCheck() + # Starts the error check timer to schedule a new error check. def startErrorCheck(self, *args) -> None: if not self._check_in_progress: diff --git a/cura/Machines/Models/BaseMaterialsModel.py b/cura/Machines/Models/BaseMaterialsModel.py index ef2e760330..629e5c2b48 100644 --- a/cura/Machines/Models/BaseMaterialsModel.py +++ b/cura/Machines/Models/BaseMaterialsModel.py @@ -1,5 +1,6 @@ # Copyright (c) 2018 Ultimaker B.V. # Cura is released under the terms of the LGPLv3 or higher. +from typing import Optional, Dict, Set from PyQt5.QtCore import Qt, pyqtSignal, pyqtProperty from UM.Qt.ListModel import ListModel @@ -9,6 +10,9 @@ from UM.Qt.ListModel import ListModel # Those 2 models are used by the material drop down menu to show generic materials and branded materials separately. # The extruder position defined here is being used to bound a menu to the correct extruder. This is used in the top # bar menu "Settings" -> "Extruder nr" -> "Material" -> this menu +from cura.Machines.MaterialNode import MaterialNode + + class BaseMaterialsModel(ListModel): extruderPositionChanged = pyqtSignal() @@ -54,8 +58,8 @@ class BaseMaterialsModel(ListModel): self._extruder_position = 0 self._extruder_stack = None - self._available_materials = None - self._favorite_ids = None + self._available_materials = None # type: Optional[Dict[str, MaterialNode]] + self._favorite_ids = set() # type: Set[str] def _updateExtruderStack(self): global_stack = self._machine_manager.activeMachine @@ -102,8 +106,10 @@ class BaseMaterialsModel(ListModel): return False extruder_stack = global_stack.extruders[extruder_position] - - self._available_materials = self._material_manager.getAvailableMaterialsForMachineExtruder(global_stack, extruder_stack) + available_materials = self._material_manager.getAvailableMaterialsForMachineExtruder(global_stack, extruder_stack) + if available_materials == self._available_materials: + return False + self._available_materials = available_materials if self._available_materials is None: return False diff --git a/cura/Machines/Models/FavoriteMaterialsModel.py b/cura/Machines/Models/FavoriteMaterialsModel.py index 18fe310c44..cc273e55ce 100644 --- a/cura/Machines/Models/FavoriteMaterialsModel.py +++ b/cura/Machines/Models/FavoriteMaterialsModel.py @@ -4,17 +4,14 @@ from UM.Logger import Logger from cura.Machines.Models.BaseMaterialsModel import BaseMaterialsModel -class FavoriteMaterialsModel(BaseMaterialsModel): +class FavoriteMaterialsModel(BaseMaterialsModel): def __init__(self, parent = None): super().__init__(parent) self._update() def _update(self): - - # Perform standard check and reset if the check fails if not self._canUpdate(): - self.setItems([]) return # Get updated list of favorites diff --git a/cura/Machines/Models/GenericMaterialsModel.py b/cura/Machines/Models/GenericMaterialsModel.py index c276b865bf..8f41dd6a70 100644 --- a/cura/Machines/Models/GenericMaterialsModel.py +++ b/cura/Machines/Models/GenericMaterialsModel.py @@ -11,10 +11,7 @@ class GenericMaterialsModel(BaseMaterialsModel): self._update() def _update(self): - - # Perform standard check and reset if the check fails if not self._canUpdate(): - self.setItems([]) return # Get updated list of favorites diff --git a/cura/Machines/Models/MaterialBrandsModel.py b/cura/Machines/Models/MaterialBrandsModel.py index 458e4d9b47..ac82cf6670 100644 --- a/cura/Machines/Models/MaterialBrandsModel.py +++ b/cura/Machines/Models/MaterialBrandsModel.py @@ -28,12 +28,8 @@ class MaterialBrandsModel(BaseMaterialsModel): self._update() def _update(self): - - # Perform standard check and reset if the check fails if not self._canUpdate(): - self.setItems([]) return - # Get updated list of favorites self._favorite_ids = self._material_manager.getFavorites() diff --git a/cura/OAuth2/AuthorizationHelpers.py b/cura/OAuth2/AuthorizationHelpers.py index f75ad9c9f9..762d0db069 100644 --- a/cura/OAuth2/AuthorizationHelpers.py +++ b/cura/OAuth2/AuthorizationHelpers.py @@ -81,9 +81,14 @@ class AuthorizationHelpers: # \param access_token: The encoded JWT token. # \return: Dict containing some profile data. def parseJWT(self, access_token: str) -> Optional["UserProfile"]: - token_request = requests.get("{}/check-token".format(self._settings.OAUTH_SERVER_URL), headers = { - "Authorization": "Bearer {}".format(access_token) - }) + try: + token_request = requests.get("{}/check-token".format(self._settings.OAUTH_SERVER_URL), headers = { + "Authorization": "Bearer {}".format(access_token) + }) + except ConnectionError: + # Connection was suddenly dropped. Nothing we can do about that. + Logger.logException("e", "Something failed while attempting to parse the JWT token") + return None if token_request.status_code not in (200, 201): Logger.log("w", "Could not retrieve token data from auth server: %s", token_request.text) return None diff --git a/cura/OAuth2/Models.py b/cura/OAuth2/Models.py index 83fc22554f..0515e789e6 100644 --- a/cura/OAuth2/Models.py +++ b/cura/OAuth2/Models.py @@ -1,4 +1,6 @@ # Copyright (c) 2018 Ultimaker B.V. +# Cura is released under the terms of the LGPLv3 or higher. + from typing import Optional diff --git a/cura/PrintInformation.py b/cura/PrintInformation.py index 22c3eb1734..e863689e21 100644 --- a/cura/PrintInformation.py +++ b/cura/PrintInformation.py @@ -394,21 +394,7 @@ class PrintInformation(QObject): return active_machine_type_name = global_container_stack.definition.getName() - abbr_machine = "" - for word in re.findall(r"[\w']+", active_machine_type_name): - if word.lower() == "ultimaker": - abbr_machine += "UM" - elif word.isdigit(): - abbr_machine += word - else: - stripped_word = self._stripAccents(word.upper()) - # - use only the first character if the word is too long (> 3 characters) - # - use the whole word if it's not too long (<= 3 characters) - if len(stripped_word) > 3: - stripped_word = stripped_word[0] - abbr_machine += stripped_word - - self._abbr_machine = abbr_machine + self._abbr_machine = self._application.getMachineManager().getAbbreviatedMachineName(active_machine_type_name) ## Utility method that strips accents from characters (eg: รข -> a) def _stripAccents(self, to_strip: str) -> str: diff --git a/cura/PrinterOutputDevice.py b/cura/PrinterOutputDevice.py index 969aa3c460..99c48189cc 100644 --- a/cura/PrinterOutputDevice.py +++ b/cura/PrinterOutputDevice.py @@ -211,6 +211,11 @@ class PrinterOutputDevice(QObject, OutputDevice): self._unique_configurations.sort(key = lambda k: k.printerType) self.uniqueConfigurationsChanged.emit() + # Returns the unique configurations of the printers within this output device + @pyqtProperty("QStringList", notify = uniqueConfigurationsChanged) + def uniquePrinterTypes(self) -> List[str]: + return list(set([configuration.printerType for configuration in self._unique_configurations])) + def _onPrintersChanged(self) -> None: for printer in self._printers: printer.configurationChanged.connect(self._updateUniqueConfigurations) @@ -238,4 +243,4 @@ class PrinterOutputDevice(QObject, OutputDevice): if not self._firmware_updater: return - self._firmware_updater.updateFirmware(firmware_file) \ No newline at end of file + self._firmware_updater.updateFirmware(firmware_file) diff --git a/cura/Scene/ConvexHullDecorator.py b/cura/Scene/ConvexHullDecorator.py index 0c03ae615b..661106dec7 100644 --- a/cura/Scene/ConvexHullDecorator.py +++ b/cura/Scene/ConvexHullDecorator.py @@ -187,7 +187,10 @@ class ConvexHullDecorator(SceneNodeDecorator): for child in self._node.getChildren(): child_hull = child.callDecoration("_compute2DConvexHull") if child_hull: - points = numpy.append(points, child_hull.getPoints(), axis = 0) + try: + points = numpy.append(points, child_hull.getPoints(), axis = 0) + except ValueError: + pass if points.size < 3: return None diff --git a/cura/Settings/ExtruderManager.py b/cura/Settings/ExtruderManager.py index 9089ba96e9..8fa0172305 100755 --- a/cura/Settings/ExtruderManager.py +++ b/cura/Settings/ExtruderManager.py @@ -63,7 +63,7 @@ class ExtruderManager(QObject): if not self._application.getGlobalContainerStack(): return None # No active machine, so no active extruder. try: - return self._extruder_trains[self._application.getGlobalContainerStack().getId()][str(self._active_extruder_index)].getId() + return self._extruder_trains[self._application.getGlobalContainerStack().getId()][str(self.activeExtruderIndex)].getId() except KeyError: # Extruder index could be -1 if the global tab is selected, or the entry doesn't exist if the machine definition is wrong. return None @@ -83,8 +83,9 @@ class ExtruderManager(QObject): # \param index The index of the new active extruder. @pyqtSlot(int) def setActiveExtruderIndex(self, index: int) -> None: - self._active_extruder_index = index - self.activeExtruderChanged.emit() + if self._active_extruder_index != index: + self._active_extruder_index = index + self.activeExtruderChanged.emit() @pyqtProperty(int, notify = activeExtruderChanged) def activeExtruderIndex(self) -> int: @@ -144,7 +145,7 @@ class ExtruderManager(QObject): @pyqtSlot(result = QObject) def getActiveExtruderStack(self) -> Optional["ExtruderStack"]: - return self.getExtruderStack(self._active_extruder_index) + return self.getExtruderStack(self.activeExtruderIndex) ## Get an extruder stack by index def getExtruderStack(self, index) -> Optional["ExtruderStack"]: @@ -344,6 +345,7 @@ class ExtruderManager(QObject): if extruders_changed: self.extrudersChanged.emit(global_stack_id) self.setActiveExtruderIndex(0) + self.activeExtruderChanged.emit() # After 3.4, all single-extrusion machines have their own extruder definition files instead of reusing # "fdmextruder". We need to check a machine here so its extruder definition is correct according to this. diff --git a/cura/Settings/ExtruderStack.py b/cura/Settings/ExtruderStack.py index d7faedb71c..edb0e7d41f 100644 --- a/cura/Settings/ExtruderStack.py +++ b/cura/Settings/ExtruderStack.py @@ -52,8 +52,8 @@ class ExtruderStack(CuraContainerStack): return super().getNextStack() def setEnabled(self, enabled: bool) -> None: - if "enabled" not in self._metadata: - self.setMetaDataEntry("enabled", "True") + if self.getMetaDataEntry("enabled", True) == enabled: # No change. + return # Don't emit a signal then. self.setMetaDataEntry("enabled", str(enabled)) self.enabledChanged.emit() diff --git a/cura/Settings/ExtrudersModel.py b/cura/Settings/ExtrudersModel.py index 52fc502bfc..e19617c8ef 100644 --- a/cura/Settings/ExtrudersModel.py +++ b/cura/Settings/ExtrudersModel.py @@ -1,4 +1,4 @@ -# Copyright (c) 2017 Ultimaker B.V. +# Copyright (c) 2018 Ultimaker B.V. # Cura is released under the terms of the LGPLv3 or higher. from PyQt5.QtCore import Qt, pyqtSignal, pyqtSlot, pyqtProperty, QTimer @@ -24,8 +24,6 @@ class ExtrudersModel(UM.Qt.ListModel.ListModel): ## Human-readable name of the extruder. NameRole = Qt.UserRole + 2 - ## Is the extruder enabled? - EnabledRole = Qt.UserRole + 9 ## Colour of the material loaded in the extruder. ColorRole = Qt.UserRole + 3 @@ -47,6 +45,12 @@ class ExtrudersModel(UM.Qt.ListModel.ListModel): VariantRole = Qt.UserRole + 7 StackRole = Qt.UserRole + 8 + MaterialBrandRole = Qt.UserRole + 9 + ColorNameRole = Qt.UserRole + 10 + + ## Is the extruder enabled? + EnabledRole = Qt.UserRole + 11 + ## List of colours to display if there is no material or the material has no known # colour. defaultColors = ["#ffc924", "#86ec21", "#22eeee", "#245bff", "#9124ff", "#ff24c8"] @@ -67,7 +71,8 @@ class ExtrudersModel(UM.Qt.ListModel.ListModel): self.addRoleName(self.MaterialRole, "material") self.addRoleName(self.VariantRole, "variant") self.addRoleName(self.StackRole, "stack") - + self.addRoleName(self.MaterialBrandRole, "material_brand") + self.addRoleName(self.ColorNameRole, "color_name") self._update_extruder_timer = QTimer() self._update_extruder_timer.setInterval(100) self._update_extruder_timer.setSingleShot(True) @@ -160,7 +165,7 @@ class ExtrudersModel(UM.Qt.ListModel.ListModel): def __updateExtruders(self): extruders_changed = False - if self.rowCount() != 0: + if self.count != 0: extruders_changed = True items = [] @@ -172,7 +177,7 @@ class ExtrudersModel(UM.Qt.ListModel.ListModel): machine_extruder_count = global_container_stack.getProperty("machine_extruder_count", "value") for extruder in Application.getInstance().getExtruderManager().getActiveExtruderStacks(): - position = extruder.getMetaDataEntry("position", default = "0") # Get the position + position = extruder.getMetaDataEntry("position", default = "0") try: position = int(position) except ValueError: @@ -183,7 +188,8 @@ class ExtrudersModel(UM.Qt.ListModel.ListModel): default_color = self.defaultColors[position] if 0 <= position < len(self.defaultColors) else self.defaultColors[0] color = extruder.material.getMetaDataEntry("color_code", default = default_color) if extruder.material else default_color - + material_brand = extruder.material.getMetaDataEntry("brand", default = "generic") + color_name = extruder.material.getMetaDataEntry("color_name") # construct an item with only the relevant information item = { "id": extruder.getId(), @@ -195,6 +201,8 @@ class ExtrudersModel(UM.Qt.ListModel.ListModel): "material": extruder.material.getName() if extruder.material else "", "variant": extruder.variant.getName() if extruder.variant else "", # e.g. print core "stack": extruder, + "material_brand": material_brand, + "color_name": color_name } items.append(item) @@ -216,6 +224,6 @@ class ExtrudersModel(UM.Qt.ListModel.ListModel): "definition": "" } items.append(item) - - self.setItems(items) - self.modelChanged.emit() + if self._items != items: + self.setItems(items) + self.modelChanged.emit() diff --git a/cura/Settings/GlobalStack.py b/cura/Settings/GlobalStack.py index da1ec61254..44ceee9511 100755 --- a/cura/Settings/GlobalStack.py +++ b/cura/Settings/GlobalStack.py @@ -3,8 +3,8 @@ from collections import defaultdict import threading -from typing import Any, Dict, Optional, Set, TYPE_CHECKING -from PyQt5.QtCore import pyqtProperty, pyqtSlot +from typing import Any, Dict, Optional, Set, TYPE_CHECKING, List +from PyQt5.QtCore import pyqtProperty, pyqtSlot, pyqtSignal from UM.Decorators import override from UM.MimeTypeDatabase import MimeType, MimeTypeDatabase @@ -42,13 +42,23 @@ class GlobalStack(CuraContainerStack): # Per thread we have our own resolving_settings, or strange things sometimes occur. self._resolving_settings = defaultdict(set) #type: Dict[str, Set[str]] # keys are thread names + extrudersChanged = pyqtSignal() + ## Get the list of extruders of this stack. # # \return The extruders registered with this stack. - @pyqtProperty("QVariantMap") + @pyqtProperty("QVariantMap", notify = extrudersChanged) def extruders(self) -> Dict[str, "ExtruderStack"]: return self._extruders + @pyqtProperty("QVariantList", notify = extrudersChanged) + def extruderList(self) -> List["ExtruderStack"]: + result_tuple_list = sorted(list(self.extruders.items()), key=lambda x: int(x[0])) + result_list = [item[1] for item in result_tuple_list] + + machine_extruder_count = self.getProperty("machine_extruder_count", "value") + return result_list[:machine_extruder_count] + @classmethod def getLoadingPriority(cls) -> int: return 2 diff --git a/cura/Settings/MachineManager.py b/cura/Settings/MachineManager.py index 33c386bae2..c375ce01d1 100755 --- a/cura/Settings/MachineManager.py +++ b/cura/Settings/MachineManager.py @@ -3,6 +3,8 @@ import collections import time +import re +import unicodedata from typing import Any, Callable, List, Dict, TYPE_CHECKING, Optional, cast from UM.ConfigurationErrorMessage import ConfigurationErrorMessage @@ -872,7 +874,7 @@ class MachineManager(QObject): caution_message = Message(catalog.i18nc( "@info:generic", "Settings have been changed to match the current availability of extruders: [%s]" % ", ".join(add_user_changes)), - lifetime=0, + lifetime = 0, title = catalog.i18nc("@info:title", "Settings updated")) caution_message.show() @@ -1534,9 +1536,32 @@ class MachineManager(QObject): name = self._current_quality_group.name return name + @pyqtProperty(bool, notify = activeQualityGroupChanged) + def hasNotSupportedQuality(self) -> bool: + return self._current_quality_group is None and self._current_quality_changes_group is None + def _updateUponMaterialMetadataChange(self) -> None: if self._global_container_stack is None: return with postponeSignals(*self._getContainerChangedSignals(), compress = CompressTechnique.CompressPerParameterValue): self.updateMaterialWithVariant(None) self._updateQualityWithMaterial() + + ## This function will translate any printer type name to an abbreviated printer type name + @pyqtSlot(str, result = str) + def getAbbreviatedMachineName(self, machine_type_name: str) -> str: + abbr_machine = "" + for word in re.findall(r"[\w']+", machine_type_name): + if word.lower() == "ultimaker": + abbr_machine += "UM" + elif word.isdigit(): + abbr_machine += word + else: + stripped_word = "".join(char for char in unicodedata.normalize("NFD", word.upper()) if unicodedata.category(char) != "Mn") + # - use only the first character if the word is too long (> 3 characters) + # - use the whole word if it's not too long (<= 3 characters) + if len(stripped_word) > 3: + stripped_word = stripped_word[0] + abbr_machine += stripped_word + + return abbr_machine diff --git a/cura/Stages/CuraStage.py b/cura/Stages/CuraStage.py index b2f6d61799..e8537fb6b9 100644 --- a/cura/Stages/CuraStage.py +++ b/cura/Stages/CuraStage.py @@ -1,23 +1,33 @@ -# Copyright (c) 2017 Ultimaker B.V. +# Copyright (c) 2018 Ultimaker B.V. # Cura is released under the terms of the LGPLv3 or higher. + from PyQt5.QtCore import pyqtProperty, QUrl from UM.Stage import Stage +# Since Cura has a few pre-defined "space claims" for the locations of certain components, we've provided some structure +# to indicate this. +# * The StageMenuComponent is the horizontal area below the stage bar. This should be used to show stage specific +# buttons and elements. This component will be drawn over the bar & main component. +# * The MainComponent is the component that will be drawn starting from the bottom of the stageBar and fills the rest +# of the screen. class CuraStage(Stage): - - def __init__(self, parent = None): + def __init__(self, parent = None) -> None: super().__init__(parent) @pyqtProperty(str, constant = True) - def stageId(self): + def stageId(self) -> str: return self.getPluginId() @pyqtProperty(QUrl, constant = True) - def mainComponent(self): + def mainComponent(self) -> QUrl: return self.getDisplayComponent("main") @pyqtProperty(QUrl, constant = True) - def sidebarComponent(self): + def sidebarComponent(self) -> QUrl: return self.getDisplayComponent("sidebar") + + @pyqtProperty(QUrl, constant = True) + def stageMenuComponent(self) -> QUrl: + return self.getDisplayComponent("menu") \ No newline at end of file diff --git a/plugins/CuraEngineBackend/CuraEngineBackend.py b/plugins/CuraEngineBackend/CuraEngineBackend.py index 58bc74f3f1..7ede6b6736 100755 --- a/plugins/CuraEngineBackend/CuraEngineBackend.py +++ b/plugins/CuraEngineBackend/CuraEngineBackend.py @@ -203,7 +203,7 @@ class CuraEngineBackend(QObject, Backend): @pyqtSlot() def stopSlicing(self) -> None: - self.backendStateChange.emit(BackendState.NotStarted) + self.setState(BackendState.NotStarted) if self._slicing: # We were already slicing. Stop the old job. self._terminate() self._createSocket() @@ -322,7 +322,7 @@ class CuraEngineBackend(QObject, Backend): self._start_slice_job = None if job.isCancelled() or job.getError() or job.getResult() == StartJobResult.Error: - self.backendStateChange.emit(BackendState.Error) + self.setState(BackendState.Error) self.backendError.emit(job) return @@ -331,10 +331,10 @@ class CuraEngineBackend(QObject, Backend): self._error_message = Message(catalog.i18nc("@info:status", "Unable to slice with the current material as it is incompatible with the selected machine or configuration."), title = catalog.i18nc("@info:title", "Unable to slice")) self._error_message.show() - self.backendStateChange.emit(BackendState.Error) + self.setState(BackendState.Error) self.backendError.emit(job) else: - self.backendStateChange.emit(BackendState.NotStarted) + self.setState(BackendState.NotStarted) return if job.getResult() == StartJobResult.SettingError: @@ -362,10 +362,10 @@ class CuraEngineBackend(QObject, Backend): self._error_message = Message(catalog.i18nc("@info:status", "Unable to slice with the current settings. The following settings have errors: {0}").format(", ".join(error_labels)), title = catalog.i18nc("@info:title", "Unable to slice")) self._error_message.show() - self.backendStateChange.emit(BackendState.Error) + self.setState(BackendState.Error) self.backendError.emit(job) else: - self.backendStateChange.emit(BackendState.NotStarted) + self.setState(BackendState.NotStarted) return elif job.getResult() == StartJobResult.ObjectSettingError: @@ -386,7 +386,7 @@ class CuraEngineBackend(QObject, Backend): self._error_message = Message(catalog.i18nc("@info:status", "Unable to slice due to some per-model settings. The following settings have errors on one or more models: {error_labels}").format(error_labels = ", ".join(errors.values())), title = catalog.i18nc("@info:title", "Unable to slice")) self._error_message.show() - self.backendStateChange.emit(BackendState.Error) + self.setState(BackendState.Error) self.backendError.emit(job) return @@ -395,16 +395,16 @@ class CuraEngineBackend(QObject, Backend): self._error_message = Message(catalog.i18nc("@info:status", "Unable to slice because the prime tower or prime position(s) are invalid."), title = catalog.i18nc("@info:title", "Unable to slice")) self._error_message.show() - self.backendStateChange.emit(BackendState.Error) + self.setState(BackendState.Error) self.backendError.emit(job) else: - self.backendStateChange.emit(BackendState.NotStarted) + self.setState(BackendState.NotStarted) if job.getResult() == StartJobResult.ObjectsWithDisabledExtruder: self._error_message = Message(catalog.i18nc("@info:status", "Unable to slice because there are objects associated with disabled Extruder %s." % job.getMessage()), title = catalog.i18nc("@info:title", "Unable to slice")) self._error_message.show() - self.backendStateChange.emit(BackendState.Error) + self.setState(BackendState.Error) self.backendError.emit(job) return @@ -413,10 +413,10 @@ class CuraEngineBackend(QObject, Backend): self._error_message = Message(catalog.i18nc("@info:status", "Nothing to slice because none of the models fit the build volume. Please scale or rotate models to fit."), title = catalog.i18nc("@info:title", "Unable to slice")) self._error_message.show() - self.backendStateChange.emit(BackendState.Error) + self.setState(BackendState.Error) self.backendError.emit(job) else: - self.backendStateChange.emit(BackendState.NotStarted) + self.setState(BackendState.NotStarted) self._invokeSlice() return @@ -424,7 +424,7 @@ class CuraEngineBackend(QObject, Backend): self._socket.sendMessage(job.getSliceMessage()) # Notify the user that it's now up to the backend to do it's job - self.backendStateChange.emit(BackendState.Processing) + self.setState(BackendState.Processing) if self._slice_start_time: Logger.log("d", "Sending slice message took %s seconds", time() - self._slice_start_time ) @@ -442,7 +442,7 @@ class CuraEngineBackend(QObject, Backend): for node in DepthFirstIterator(self._scene.getRoot()): #type: ignore #Ignore type error because iter() should get called automatically by Python syntax. if node.callDecoration("isBlockSlicing"): enable_timer = False - self.backendStateChange.emit(BackendState.Disabled) + self.setState(BackendState.Disabled) self._is_disabled = True gcode_list = node.callDecoration("getGCodeList") if gcode_list is not None: @@ -451,7 +451,7 @@ class CuraEngineBackend(QObject, Backend): if self._use_timer == enable_timer: return self._use_timer if enable_timer: - self.backendStateChange.emit(BackendState.NotStarted) + self.setState(BackendState.NotStarted) self.enableTimer() return True else: @@ -518,7 +518,7 @@ class CuraEngineBackend(QObject, Backend): self._build_plates_to_be_sliced.append(build_plate_number) self.printDurationMessage.emit(source_build_plate_number, {}, []) self.processingProgress.emit(0.0) - self.backendStateChange.emit(BackendState.NotStarted) + self.setState(BackendState.NotStarted) # if not self._use_timer: # With manually having to slice, we want to clear the old invalid layer data. self._clearLayerData(build_plate_changed) @@ -567,7 +567,7 @@ class CuraEngineBackend(QObject, Backend): self.stopSlicing() self.markSliceAll() self.processingProgress.emit(0.0) - self.backendStateChange.emit(BackendState.NotStarted) + self.setState(BackendState.NotStarted) if not self._use_timer: # With manually having to slice, we want to clear the old invalid layer data. self._clearLayerData() @@ -613,7 +613,7 @@ class CuraEngineBackend(QObject, Backend): # \param message The protobuf message containing the slicing progress. def _onProgressMessage(self, message: Arcus.PythonMessage) -> None: self.processingProgress.emit(message.amount) - self.backendStateChange.emit(BackendState.Processing) + self.setState(BackendState.Processing) def _invokeSlice(self) -> None: if self._use_timer: @@ -632,7 +632,7 @@ class CuraEngineBackend(QObject, Backend): # # \param message The protobuf message signalling that slicing is finished. def _onSlicingFinishedMessage(self, message: Arcus.PythonMessage) -> None: - self.backendStateChange.emit(BackendState.Done) + self.setState(BackendState.Done) self.processingProgress.emit(1.0) gcode_list = self._scene.gcode_dict[self._start_slice_job_build_plate] #type: ignore #Because we generate this attribute dynamically. diff --git a/plugins/CuraEngineBackend/ProcessSlicedLayersJob.py b/plugins/CuraEngineBackend/ProcessSlicedLayersJob.py index 594bf3a43e..71c96880e8 100644 --- a/plugins/CuraEngineBackend/ProcessSlicedLayersJob.py +++ b/plugins/CuraEngineBackend/ProcessSlicedLayersJob.py @@ -195,7 +195,7 @@ class ProcessSlicedLayersJob(Job): if extruders: material_color_map = numpy.zeros((len(extruders), 4), dtype=numpy.float32) for extruder in extruders: - position = int(extruder.getMetaDataEntry("position", default="0")) # Get the position + position = int(extruder.getMetaDataEntry("position", default = "0")) try: default_color = ExtrudersModel.defaultColors[position] except IndexError: diff --git a/plugins/CuraEngineBackend/StartSliceJob.py b/plugins/CuraEngineBackend/StartSliceJob.py index 9679360ad5..d3882a1209 100644 --- a/plugins/CuraEngineBackend/StartSliceJob.py +++ b/plugins/CuraEngineBackend/StartSliceJob.py @@ -323,7 +323,7 @@ class StartSliceJob(Job): value = stack.getProperty(key, "value") result[key] = value Job.yieldThread() - + result["print_bed_temperature"] = result["material_bed_temperature"] # Renamed settings. result["print_temperature"] = result["material_print_temperature"] result["time"] = time.strftime("%H:%M:%S") #Some extra settings. diff --git a/plugins/FirmwareUpdater/FirmwareUpdaterMachineAction.qml b/plugins/FirmwareUpdater/FirmwareUpdaterMachineAction.qml index 9a56dbb20a..b5b6c15f50 100644 --- a/plugins/FirmwareUpdater/FirmwareUpdaterMachineAction.qml +++ b/plugins/FirmwareUpdater/FirmwareUpdaterMachineAction.qml @@ -22,7 +22,7 @@ Cura.MachineAction { id: firmwareUpdaterMachineAction anchors.fill: parent; - UM.I18nCatalog { id: catalog; name:"cura"} + UM.I18nCatalog { id: catalog; name: "cura"} spacing: UM.Theme.getSize("default_margin").height Label diff --git a/plugins/ImageReader/ConfigUI.qml b/plugins/ImageReader/ConfigUI.qml index 12c6aa8dde..b9ff2e4453 100644 --- a/plugins/ImageReader/ConfigUI.qml +++ b/plugins/ImageReader/ConfigUI.qml @@ -20,7 +20,7 @@ UM.Dialog GridLayout { - UM.I18nCatalog{id: catalog; name:"cura"} + UM.I18nCatalog{id: catalog; name: "cura"} anchors.fill: parent; Layout.fillWidth: true columnSpacing: 16 * screenScaleFactor diff --git a/plugins/MachineSettingsAction/MachineSettingsAction.qml b/plugins/MachineSettingsAction/MachineSettingsAction.qml index 004b4e3cfc..c88a721a84 100644 --- a/plugins/MachineSettingsAction/MachineSettingsAction.qml +++ b/plugins/MachineSettingsAction/MachineSettingsAction.qml @@ -1,4 +1,4 @@ -// Copyright (c) 2016 Ultimaker B.V. +// Copyright (c) 2018 Ultimaker B.V. // Cura is released under the terms of the LGPLv3 or higher. import QtQuick 2.2 @@ -23,7 +23,7 @@ Cura.MachineAction target: base.extrudersModel onModelChanged: { - var extruderCount = base.extrudersModel.rowCount(); + var extruderCount = base.extrudersModel.count; base.extruderTabsCount = extruderCount; } } diff --git a/plugins/ModelChecker/ModelChecker.qml b/plugins/ModelChecker/ModelChecker.qml index 98db233bf8..ddeed063b1 100644 --- a/plugins/ModelChecker/ModelChecker.qml +++ b/plugins/ModelChecker/ModelChecker.qml @@ -4,19 +4,19 @@ import QtQuick 2.2 import QtQuick.Controls 1.1 import QtQuick.Controls.Styles 1.1 -import QtQuick.Layouts 1.1 -import QtQuick.Dialogs 1.1 -import QtQuick.Window 2.2 import UM 1.2 as UM -import Cura 1.0 as Cura Button { id: modelCheckerButton - UM.I18nCatalog{id: catalog; name:"cura"} + UM.I18nCatalog + { + id: catalog + name: "cura" + } visible: manager.hasWarnings tooltip: catalog.i18nc("@info:tooltip", "Some things could be problematic in this print. Click to see tips for adjustment.") @@ -25,6 +25,8 @@ Button width: UM.Theme.getSize("save_button_specs_icons").width height: UM.Theme.getSize("save_button_specs_icons").height + anchors.verticalCenter: parent ? parent.verticalCenter : undefined + style: ButtonStyle { background: Item @@ -33,7 +35,6 @@ Button { width: UM.Theme.getSize("save_button_specs_icons").width; height: UM.Theme.getSize("save_button_specs_icons").height; - sourceSize.width: width; sourceSize.height: width; color: control.hovered ? UM.Theme.getColor("text_scene_hover") : UM.Theme.getColor("text_scene"); source: "model_checker.svg" diff --git a/plugins/MonitorStage/MonitorMainView.qml b/plugins/MonitorStage/MonitorMain.qml similarity index 67% rename from plugins/MonitorStage/MonitorMainView.qml rename to plugins/MonitorStage/MonitorMain.qml index c48f6d0aab..1f287fc0fa 100644 --- a/plugins/MonitorStage/MonitorMainView.qml +++ b/plugins/MonitorStage/MonitorMain.qml @@ -1,45 +1,40 @@ -// Copyright (c) 2017 Ultimaker B.V. - -import QtQuick 2.2 -import QtQuick.Controls 1.1 - -import UM 1.3 as UM -import Cura 1.0 as Cura - -Item -{ - // parent could be undefined as this component is not visible at all times - width: parent ? parent.width : 0 - height: parent ? parent.height : 0 - - // We show a nice overlay on the 3D viewer when the current output device has no monitor view - Rectangle - { - id: viewportOverlay - - color: UM.Theme.getColor("viewport_overlay") - width: parent.width - height: parent.height - - MouseArea - { - anchors.fill: parent - acceptedButtons: Qt.AllButtons - onWheel: wheel.accepted = true - } - } - - Loader - { - id: monitorViewComponent - - width: parent.width - height: parent.height - - property real maximumWidth: parent.width - property real maximumHeight: parent.height - - sourceComponent: Cura.MachineManager.printerOutputDevices.length > 0 ? Cura.MachineManager.printerOutputDevices[0].monitorItem: null - visible: sourceComponent != null - } -} +// Copyright (c) 2017 Ultimaker B.V. + +import QtQuick 2.10 +import QtQuick.Controls 1.4 + +import UM 1.3 as UM +import Cura 1.0 as Cura + + +Item +{ + // We show a nice overlay on the 3D viewer when the current output device has no monitor view + Rectangle + { + id: viewportOverlay + + color: UM.Theme.getColor("viewport_overlay") + anchors.fill: parent + MouseArea + { + anchors.fill: parent + acceptedButtons: Qt.AllButtons + onWheel: wheel.accepted = true + } + } + + Loader + { + id: monitorViewComponent + + anchors.fill: parent + + height: parent.height + + property real maximumWidth: parent.width + property real maximumHeight: parent.height + + sourceComponent: Cura.MachineManager.printerOutputDevices.length > 0 ? Cura.MachineManager.printerOutputDevices[0].monitorItem: null + } +} diff --git a/plugins/MonitorStage/MonitorMenu.qml b/plugins/MonitorStage/MonitorMenu.qml new file mode 100644 index 0000000000..bc95c276e8 --- /dev/null +++ b/plugins/MonitorStage/MonitorMenu.qml @@ -0,0 +1,23 @@ +// Copyright (c) 2018 Ultimaker B.V. +// Cura is released under the terms of the LGPLv3 or higher. + +import QtQuick 2.7 +import QtQuick.Controls 2.3 + +import UM 1.3 as UM +import Cura 1.1 as Cura + +Item +{ + signal showTooltip(Item item, point location, string text) + signal hideTooltip() + + Cura.MachineSelector + { + id: machineSelection + headerCornerSide: Cura.RoundedRectangle.Direction.All + width: UM.Theme.getSize("machine_selector_widget").width + height: parent.height + anchors.centerIn: parent + } +} \ No newline at end of file diff --git a/plugins/MonitorStage/MonitorStage.py b/plugins/MonitorStage/MonitorStage.py index ace201e994..69b7f20f4e 100644 --- a/plugins/MonitorStage/MonitorStage.py +++ b/plugins/MonitorStage/MonitorStage.py @@ -65,15 +65,10 @@ class MonitorStage(CuraStage): # We can only connect now, as we need to be sure that everything is loaded (plugins get created quite early) Application.getInstance().getMachineManager().outputDevicesChanged.connect(self._onOutputDevicesChanged) self._onOutputDevicesChanged() - self._updateMainOverlay() - self._updateSidebar() - def _updateMainOverlay(self): - main_component_path = os.path.join(PluginRegistry.getInstance().getPluginPath("MonitorStage"), - "MonitorMainView.qml") - self.addDisplayComponent("main", main_component_path) - - def _updateSidebar(self): - sidebar_component_path = os.path.join(Resources.getPath(Application.getInstance().ResourceTypes.QmlFiles), - "MonitorSidebar.qml") - self.addDisplayComponent("sidebar", sidebar_component_path) + plugin_path = Application.getInstance().getPluginRegistry().getPluginPath(self.getPluginId()) + if plugin_path is not None: + menu_component_path = os.path.join(plugin_path, "MonitorMenu.qml") + main_component_path = os.path.join(plugin_path, "MonitorMain.qml") + self.addDisplayComponent("menu", menu_component_path) + self.addDisplayComponent("main", main_component_path) diff --git a/plugins/MonitorStage/__init__.py b/plugins/MonitorStage/__init__.py index bdaf53a36c..0468e6319b 100644 --- a/plugins/MonitorStage/__init__.py +++ b/plugins/MonitorStage/__init__.py @@ -7,14 +7,16 @@ from . import MonitorStage from UM.i18n import i18nCatalog i18n_catalog = i18nCatalog("cura") + def getMetaData(): return { "stage": { "name": i18n_catalog.i18nc("@item:inmenu", "Monitor"), - "weight": 1 + "weight": 2 } } + def register(app): return { "stage": MonitorStage.MonitorStage() diff --git a/plugins/PerObjectSettingsTool/PerObjectSettingsPanel.qml b/plugins/PerObjectSettingsTool/PerObjectSettingsPanel.qml index 5d4e17a102..0e2bd88619 100644 --- a/plugins/PerObjectSettingsTool/PerObjectSettingsPanel.qml +++ b/plugins/PerObjectSettingsTool/PerObjectSettingsPanel.qml @@ -265,7 +265,6 @@ Item { anchors.verticalCenter: parent.verticalCenter width: parent.width height: width - sourceSize.width: width sourceSize.height: width color: control.hovered ? UM.Theme.getColor("setting_control_button_hover") : UM.Theme.getColor("setting_control_button") source: UM.Theme.getIcon("minus") diff --git a/plugins/PostProcessingPlugin/PostProcessingPlugin.qml b/plugins/PostProcessingPlugin/PostProcessingPlugin.qml index d492e06462..b962f4d53b 100644 --- a/plugins/PostProcessingPlugin/PostProcessingPlugin.qml +++ b/plugins/PostProcessingPlugin/PostProcessingPlugin.qml @@ -31,7 +31,7 @@ UM.Dialog Item { - UM.I18nCatalog{id: catalog; name:"cura"} + UM.I18nCatalog{id: catalog; name: "cura"} id: base property int columnWidth: Math.round((base.width / 2) - UM.Theme.getSize("default_margin").width) property int textMargin: Math.round(UM.Theme.getSize("default_margin").width / 2) @@ -141,7 +141,6 @@ UM.Dialog anchors.horizontalCenter: parent.horizontalCenter width: Math.round(control.width / 2.7) height: Math.round(control.height / 2.7) - sourceSize.width: width sourceSize.height: width color: palette.text source: UM.Theme.getIcon("cross1") @@ -176,7 +175,6 @@ UM.Dialog anchors.horizontalCenter: parent.horizontalCenter width: Math.round(control.width / 2.5) height: Math.round(control.height / 2.5) - sourceSize.width: width sourceSize.height: width color: control.enabled ? palette.text : disabledPalette.text source: UM.Theme.getIcon("arrow_bottom") @@ -211,7 +209,6 @@ UM.Dialog anchors.horizontalCenter: parent.horizontalCenter width: Math.round(control.width / 2.5) height: Math.round(control.height / 2.5) - sourceSize.width: width sourceSize.height: width color: control.enabled ? palette.text : disabledPalette.text source: UM.Theme.getIcon("arrow_top") @@ -260,7 +257,7 @@ UM.Dialog Rectangle { - color: UM.Theme.getColor("sidebar") + color: UM.Theme.getColor("main_background") anchors.left: activeScripts.right anchors.leftMargin: UM.Theme.getSize("default_margin").width anchors.right: parent.right @@ -415,7 +412,7 @@ UM.Dialog } } - Cura.SidebarTooltip + Cura.PrintSetupTooltip { id: tooltip } @@ -498,7 +495,6 @@ UM.Dialog anchors.horizontalCenter: parent.horizontalCenter width: Math.round(parent.width / 2) height: Math.round(parent.height / 2) - sourceSize.width: width sourceSize.height: height color: !control.enabled ? UM.Theme.getColor("action_button_disabled_text") : control.pressed ? UM.Theme.getColor("action_button_active_text") : diff --git a/plugins/PrepareStage/PrepareMenu.qml b/plugins/PrepareStage/PrepareMenu.qml new file mode 100644 index 0000000000..b7980bc30b --- /dev/null +++ b/plugins/PrepareStage/PrepareMenu.qml @@ -0,0 +1,134 @@ +// Copyright (c) 2018 Ultimaker B.V. +// Cura is released under the terms of the LGPLv3 or higher. + +import QtQuick 2.7 +import QtQuick.Layouts 1.1 +import QtQuick.Controls 2.3 + +import UM 1.3 as UM +import Cura 1.1 as Cura + +import QtGraphicalEffects 1.0 // For the dropshadow + +Item +{ + id: prepareMenu + + UM.I18nCatalog + { + id: catalog + name: "cura" + } + + // Item to ensure that all of the buttons are nicely centered. + Item + { + anchors.horizontalCenter: parent.horizontalCenter + width: openFileButton.width + itemRow.width + UM.Theme.getSize("default_margin").width + height: parent.height + + RowLayout + { + id: itemRow + + anchors.left: openFileButton.right + anchors.leftMargin: UM.Theme.getSize("default_margin").width + + width: Math.round(0.9 * prepareMenu.width) + height: parent.height + spacing: 0 + + Cura.MachineSelector + { + id: machineSelection + headerCornerSide: Cura.RoundedRectangle.Direction.Left + Layout.minimumWidth: UM.Theme.getSize("machine_selector_widget").width + Layout.maximumWidth: UM.Theme.getSize("machine_selector_widget").width + Layout.fillWidth: true + Layout.fillHeight: true + } + + // Separator line + Rectangle + { + height: parent.height + width: UM.Theme.getSize("default_lining").width + color: UM.Theme.getColor("lining") + } + + Cura.ConfigurationMenu + { + Layout.fillHeight: true + Layout.fillWidth: true + Layout.preferredWidth: itemRow.width - machineSelection.width - printSetupSelectorItem.width - 2 * UM.Theme.getSize("default_lining").width + } + + // Separator line + Rectangle + { + height: parent.height + width: UM.Theme.getSize("default_lining").width + color: UM.Theme.getColor("lining") + } + + Item + { + id: printSetupSelectorItem + // This is a work around to prevent the printSetupSelector from having to be re-loaded every time + // a stage switch is done. + children: [printSetupSelector] + height: childrenRect.height + width: childrenRect.width + } + } + + Button + { + id: openFileButton + height: UM.Theme.getSize("stage_menu").height + width: UM.Theme.getSize("stage_menu").height + onClicked: Cura.Actions.open.trigger() + hoverEnabled: true + + contentItem: Item + { + anchors.fill: parent + UM.RecolorImage + { + id: buttonIcon + anchors.centerIn: parent + source: UM.Theme.getIcon("load") + width: UM.Theme.getSize("button_icon").width + height: UM.Theme.getSize("button_icon").height + color: UM.Theme.getColor("toolbar_button_text") + + sourceSize.height: height + } + } + + background: Rectangle + { + id: background + height: UM.Theme.getSize("stage_menu").height + width: UM.Theme.getSize("stage_menu").height + + radius: UM.Theme.getSize("default_radius").width + color: openFileButton.hovered ? UM.Theme.getColor("action_button_hovered") : UM.Theme.getColor("action_button") + } + + DropShadow + { + id: shadow + // Don't blur the shadow + radius: 0 + anchors.fill: background + source: background + verticalOffset: 2 + visible: true + color: UM.Theme.getColor("action_button_shadow") + // Should always be drawn behind the background. + z: background.z - 1 + } + } + } +} diff --git a/plugins/PrepareStage/PrepareStage.py b/plugins/PrepareStage/PrepareStage.py index c3c9f0a1f8..b22f3385b8 100644 --- a/plugins/PrepareStage/PrepareStage.py +++ b/plugins/PrepareStage/PrepareStage.py @@ -2,13 +2,14 @@ # Cura is released under the terms of the LGPLv3 or higher. import os.path from UM.Application import Application +from UM.PluginRegistry import PluginRegistry from UM.Resources import Resources from cura.Stages.CuraStage import CuraStage + ## Stage for preparing model (slicing). class PrepareStage(CuraStage): - def __init__(self, parent = None): super().__init__(parent) Application.getInstance().engineCreatedSignal.connect(self._engineCreated) @@ -16,4 +17,7 @@ class PrepareStage(CuraStage): def _engineCreated(self): sidebar_component_path = os.path.join(Resources.getPath(Application.getInstance().ResourceTypes.QmlFiles), "PrepareSidebar.qml") + + menu_component_path = os.path.join(PluginRegistry.getInstance().getPluginPath("PrepareStage"), "PrepareMenu.qml") + self.addDisplayComponent("menu", menu_component_path) self.addDisplayComponent("sidebar", sidebar_component_path) diff --git a/plugins/PreviewStage/PreviewMain.qml b/plugins/PreviewStage/PreviewMain.qml new file mode 100644 index 0000000000..04241783e9 --- /dev/null +++ b/plugins/PreviewStage/PreviewMain.qml @@ -0,0 +1,18 @@ +// Copyright (c) 2018 Ultimaker B.V. +// Cura is released under the terms of the LGPLv3 or higher. + +import QtQuick 2.4 +import QtQuick.Controls 1.2 +import QtQuick.Layouts 1.1 +import QtQuick.Controls.Styles 1.1 + +import UM 1.0 as UM +import Cura 1.0 as Cura + + +Loader +{ + id: previewMain + + source: UM.Controller.activeView != null && UM.Controller.activeView.mainComponent != null ? UM.Controller.activeView.mainComponent : "" +} \ No newline at end of file diff --git a/plugins/PreviewStage/PreviewMenu.qml b/plugins/PreviewStage/PreviewMenu.qml new file mode 100644 index 0000000000..1543536160 --- /dev/null +++ b/plugins/PreviewStage/PreviewMenu.qml @@ -0,0 +1,74 @@ +// Copyright (c) 2018 Ultimaker B.V. +// Cura is released under the terms of the LGPLv3 or higher. + +import QtQuick 2.7 +import QtQuick.Controls 2.3 + +import UM 1.3 as UM +import Cura 1.1 as Cura + +Item +{ + id: previewMenu + + property real itemHeight: height - 2 * UM.Theme.getSize("default_lining").width + + UM.I18nCatalog + { + id: catalog + name: "cura" + } + + + Row + { + id: stageMenuRow + anchors.centerIn: parent + height: parent.height + + Cura.ViewsSelector + { + id: viewsSelector + height: parent.height + width: UM.Theme.getSize("views_selector").width + headerCornerSide: Cura.RoundedRectangle.Direction.Left + } + + // Separator line + Rectangle + { + height: parent.height + // If there is no viewPanel, we only need a single spacer, so hide this one. + visible: viewPanel.source != "" + width: visible ? UM.Theme.getSize("default_lining").width : 0 + + color: UM.Theme.getColor("lining") + } + + Loader + { + id: viewPanel + height: parent.height + width: childrenRect.width + source: UM.Controller.activeView != null && UM.Controller.activeView.stageMenuComponent != null ? UM.Controller.activeView.stageMenuComponent : "" + } + + // Separator line + Rectangle + { + height: parent.height + width: UM.Theme.getSize("default_lining").width + color: UM.Theme.getColor("lining") + } + + Item + { + id: printSetupSelectorItem + // This is a work around to prevent the printSetupSelector from having to be re-loaded every time + // a stage switch is done. + children: [printSetupSelector] + height: childrenRect.height + width: childrenRect.width + } + } +} diff --git a/plugins/PreviewStage/PreviewStage.py b/plugins/PreviewStage/PreviewStage.py new file mode 100644 index 0000000000..1c487c8340 --- /dev/null +++ b/plugins/PreviewStage/PreviewStage.py @@ -0,0 +1,51 @@ +# Copyright (c) 2018 Ultimaker B.V. +# Cura is released under the terms of the LGPLv3 or higher. + +import os.path + +from UM.Qt.QtApplication import QtApplication +from cura.Stages.CuraStage import CuraStage + +from typing import TYPE_CHECKING, Optional + +if TYPE_CHECKING: + from UM.View.View import View + + +## Displays a preview of what you're about to print. +# +# The Python component of this stage just loads PreviewMain.qml for display +# when the stage is selected, and makes sure that it reverts to the previous +# view when the previous stage is activated. +class PreviewStage(CuraStage): + def __init__(self, application: QtApplication, parent = None) -> None: + super().__init__(parent) + self._application = application + self._application.engineCreatedSignal.connect(self._engineCreated) + self._previously_active_view = None # type: Optional[View] + + ## When selecting the stage, remember which was the previous view so that + # we can revert to that view when we go out of the stage later. + def onStageSelected(self) -> None: + self._previously_active_view = self._application.getController().getActiveView() + + ## Called when going to a different stage (away from the Preview Stage). + # + # When going to a different stage, the view should be reverted to what it + # was before. Normally, that just reverts it to solid view. + def onStageDeselected(self) -> None: + if self._previously_active_view is not None: + self._application.getController().setActiveView(self._previously_active_view.getPluginId()) + self._previously_active_view = None + + ## Delayed load of the QML files. + # + # We need to make sure that the QML engine is running before we can load + # these. + def _engineCreated(self) -> None: + plugin_path = self._application.getPluginRegistry().getPluginPath(self.getPluginId()) + if plugin_path is not None: + menu_component_path = os.path.join(plugin_path, "PreviewMenu.qml") + main_component_path = os.path.join(plugin_path, "PreviewMain.qml") + self.addDisplayComponent("menu", menu_component_path) + self.addDisplayComponent("main", main_component_path) diff --git a/plugins/PreviewStage/__init__.py b/plugins/PreviewStage/__init__.py new file mode 100644 index 0000000000..424f573e4a --- /dev/null +++ b/plugins/PreviewStage/__init__.py @@ -0,0 +1,22 @@ +# Copyright (c) 2018 Ultimaker B.V. +# Cura is released under the terms of the LGPLv3 or higher. + +from . import PreviewStage + +from UM.i18n import i18nCatalog +i18n_catalog = i18nCatalog("cura") + + +def getMetaData(): + return { + "stage": { + "name": i18n_catalog.i18nc("@item:inmenu", "Preview"), + "weight": 1 + } + } + + +def register(app): + return { + "stage": PreviewStage.PreviewStage(app) + } diff --git a/plugins/PreviewStage/plugin.json b/plugins/PreviewStage/plugin.json new file mode 100644 index 0000000000..9349da2b0e --- /dev/null +++ b/plugins/PreviewStage/plugin.json @@ -0,0 +1,8 @@ +{ + "name": "Preview Stage", + "author": "Ultimaker B.V.", + "version": "1.0.0", + "description": "Provides a preview stage in Cura.", + "api": 5, + "i18n-catalog": "cura" +} \ No newline at end of file diff --git a/plugins/SimulationView/LayerSlider.qml b/plugins/SimulationView/LayerSlider.qml index 1552506969..42b8cf0ba0 100644 --- a/plugins/SimulationView/LayerSlider.qml +++ b/plugins/SimulationView/LayerSlider.qml @@ -13,23 +13,20 @@ Item { id: sliderRoot - // handle properties - property real handleSize: 10 + // Handle properties + property real handleSize: UM.Theme.getSize("slider_handle").width property real handleRadius: handleSize / 2 property real minimumRangeHandleSize: handleSize / 2 - property color upperHandleColor: "black" - property color lowerHandleColor: "black" - property color rangeHandleColor: "black" - property color handleActiveColor: "white" - property real handleLabelWidth: width + property color upperHandleColor: UM.Theme.getColor("slider_handle") + property color lowerHandleColor: UM.Theme.getColor("slider_handle") + property color rangeHandleColor: UM.Theme.getColor("slider_groove_fill") + property color handleActiveColor: UM.Theme.getColor("slider_handle_active") property var activeHandle: upperHandle - // track properties - property real trackThickness: 4 // width of the slider track - property real trackRadius: trackThickness / 2 - property color trackColor: "white" - property real trackBorderWidth: 1 // width of the slider track border - property color trackBorderColor: "black" + // Track properties + property real trackThickness: UM.Theme.getSize("slider_groove").width // width of the slider track + property real trackRadius: UM.Theme.getSize("slider_groove_radius").width + property color trackColor: UM.Theme.getColor("slider_groove") // value properties property real maximumValue: 100 @@ -80,7 +77,7 @@ Item return Math.min(Math.max(value, sliderRoot.minimumValue), sliderRoot.maximumValue) } - // slider track + // Slider track Rectangle { id: track @@ -90,8 +87,6 @@ Item radius: sliderRoot.trackRadius anchors.centerIn: sliderRoot color: sliderRoot.trackColor - border.width: sliderRoot.trackBorderWidth - border.color: sliderRoot.trackBorderColor visible: sliderRoot.layersVisible } @@ -106,7 +101,7 @@ Item anchors.horizontalCenter: sliderRoot.horizontalCenter visible: sliderRoot.layersVisible - // set the new value when dragging + // Set the new value when dragging function onHandleDragged() { sliderRoot.manuallyChanged = true @@ -140,9 +135,10 @@ Item Rectangle { - width: sliderRoot.trackThickness - 2 * sliderRoot.trackBorderWidth + width: sliderRoot.trackThickness height: parent.height + sliderRoot.handleSize anchors.centerIn: parent + radius: sliderRoot.trackRadius color: sliderRoot.rangeHandleColor } @@ -167,9 +163,9 @@ Item id: rangleHandleLabel height: sliderRoot.handleSize + UM.Theme.getSize("default_margin").height - x: parent.x - width - UM.Theme.getSize("default_margin").width + x: parent.x + parent.width + UM.Theme.getSize("default_margin").width anchors.verticalCenter: parent.verticalCenter - target: Qt.point(sliderRoot.width, y + height / 2) + target: Qt.point(sliderRoot.width + width, y + height / 2) visible: sliderRoot.activeHandle == parent // custom properties @@ -275,7 +271,7 @@ Item id: upperHandleLabel height: sliderRoot.handleSize + UM.Theme.getSize("default_margin").height - x: parent.x - width - UM.Theme.getSize("default_margin").width + x: parent.x - parent.width - width anchors.verticalCenter: parent.verticalCenter target: Qt.point(sliderRoot.width, y + height / 2) visible: sliderRoot.activeHandle == parent @@ -385,9 +381,9 @@ Item id: lowerHandleLabel height: sliderRoot.handleSize + UM.Theme.getSize("default_margin").height - x: parent.x - width - UM.Theme.getSize("default_margin").width + x: parent.x - parent.width - width anchors.verticalCenter: parent.verticalCenter - target: Qt.point(sliderRoot.width, y + height / 2) + target: Qt.point(sliderRoot.width + width, y + height / 2) visible: sliderRoot.activeHandle == parent // custom properties diff --git a/plugins/SimulationView/PathSlider.qml b/plugins/SimulationView/PathSlider.qml index f3c28fb5f7..c7a43c6407 100644 --- a/plugins/SimulationView/PathSlider.qml +++ b/plugins/SimulationView/PathSlider.qml @@ -14,19 +14,17 @@ Item id: sliderRoot // handle properties - property real handleSize: 10 + property real handleSize: UM.Theme.getSize("slider_handle").width property real handleRadius: handleSize / 2 - property color handleColor: "black" - property color handleActiveColor: "white" - property color rangeColor: "black" + property color handleColor: UM.Theme.getColor("slider_handle") + property color handleActiveColor: UM.Theme.getColor("slider_handle_active") + property color rangeColor: UM.Theme.getColor("slider_groove_fill") property real handleLabelWidth: width // track properties - property real trackThickness: 4 // width of the slider track - property real trackRadius: trackThickness / 2 - property color trackColor: "white" - property real trackBorderWidth: 1 // width of the slider track border - property color trackBorderColor: "black" + property real trackThickness: UM.Theme.getSize("slider_groove").width + property real trackRadius: UM.Theme.getSize("slider_groove_radius").width + property color trackColor: UM.Theme.getColor("slider_groove") // value properties property real maximumValue: 100 @@ -68,8 +66,6 @@ Item radius: sliderRoot.trackRadius anchors.centerIn: sliderRoot color: sliderRoot.trackColor - border.width: sliderRoot.trackBorderWidth - border.color: sliderRoot.trackBorderColor visible: sliderRoot.pathsVisible } @@ -86,9 +82,10 @@ Item Rectangle { - height: sliderRoot.trackThickness - 2 * sliderRoot.trackBorderWidth + height: sliderRoot.trackThickness width: parent.width + sliderRoot.handleSize anchors.centerIn: parent + radius: sliderRoot.trackRadius color: sliderRoot.rangeColor } } diff --git a/plugins/SimulationView/SimulationView.py b/plugins/SimulationView/SimulationView.py index 0ae8b4d9e4..6a0ffc1666 100644 --- a/plugins/SimulationView/SimulationView.py +++ b/plugins/SimulationView/SimulationView.py @@ -16,6 +16,7 @@ from UM.Mesh.MeshBuilder import MeshBuilder from UM.Message import Message from UM.Platform import Platform from UM.PluginRegistry import PluginRegistry +from UM.Qt.QtApplication import QtApplication from UM.Resources import Resources from UM.Scene.Iterator.DepthFirstIterator import DepthFirstIterator @@ -26,8 +27,8 @@ from UM.View.GL.OpenGL import OpenGL from UM.View.GL.OpenGLContext import OpenGLContext from UM.View.GL.ShaderProgram import ShaderProgram -from UM.View.View import View from UM.i18n import i18nCatalog +from cura.CuraView import CuraView from cura.Scene.ConvexHullNode import ConvexHullNode from cura.CuraApplication import CuraApplication @@ -48,15 +49,15 @@ catalog = i18nCatalog("cura") ## View used to display g-code paths. -class SimulationView(View): +class SimulationView(CuraView): # Must match SimulationView.qml LAYER_VIEW_TYPE_MATERIAL_TYPE = 0 LAYER_VIEW_TYPE_LINE_TYPE = 1 LAYER_VIEW_TYPE_FEEDRATE = 2 LAYER_VIEW_TYPE_THICKNESS = 3 - def __init__(self) -> None: - super().__init__() + def __init__(self, parent = None) -> None: + super().__init__(parent) self._max_layers = 0 self._current_layer_num = 0 @@ -113,6 +114,16 @@ class SimulationView(View): self._wireprint_warning_message = Message(catalog.i18nc("@info:status", "Cura does not accurately display layers when Wire Printing is enabled"), title = catalog.i18nc("@info:title", "Simulation View")) + QtApplication.getInstance().engineCreatedSignal.connect(self._onEngineCreated) + + def _onEngineCreated(self) -> None: + plugin_path = PluginRegistry.getInstance().getPluginPath(self.getPluginId()) + if plugin_path: + self.addDisplayComponent("main", os.path.join(plugin_path, "SimulationViewMainComponent.qml")) + self.addDisplayComponent("menu", os.path.join(plugin_path, "SimulationViewMenuComponent.qml")) + else: + Logger.log("e", "Unable to find the path for %s", self.getPluginId()) + def _evaluateCompatibilityMode(self) -> bool: return OpenGLContext.isLegacyOpenGL() or bool(Application.getInstance().getPreferences().getValue("view/force_layer_view_compatibility_mode")) diff --git a/plugins/SimulationView/SimulationView.qml b/plugins/SimulationView/SimulationView.qml deleted file mode 100644 index be124157fb..0000000000 --- a/plugins/SimulationView/SimulationView.qml +++ /dev/null @@ -1,808 +0,0 @@ -// Copyright (c) 2018 Ultimaker B.V. -// Cura is released under the terms of the LGPLv3 or higher. - -import QtQuick 2.4 -import QtQuick.Controls 1.2 -import QtQuick.Layouts 1.1 -import QtQuick.Controls.Styles 1.1 - -import UM 1.0 as UM -import Cura 1.0 as Cura - -Item -{ - id: base - width: - { - if (UM.SimulationView.compatibilityMode) - { - return UM.Theme.getSize("layerview_menu_size_compatibility").width; - } - else - { - return UM.Theme.getSize("layerview_menu_size").width; - } - } - height: { - if (viewSettings.collapsed) - { - if (UM.SimulationView.compatibilityMode) - { - return UM.Theme.getSize("layerview_menu_size_compatibility_collapsed").height; - } - return UM.Theme.getSize("layerview_menu_size_collapsed").height; - } - else if (UM.SimulationView.compatibilityMode) - { - return UM.Theme.getSize("layerview_menu_size_compatibility").height; - } - else if (UM.Preferences.getValue("layerview/layer_view_type") == 0) - { - return UM.Theme.getSize("layerview_menu_size_material_color_mode").height + UM.SimulationView.extruderCount * (UM.Theme.getSize("layerview_row").height + UM.Theme.getSize("layerview_row_spacing").height) - } - else - { - return UM.Theme.getSize("layerview_menu_size").height + UM.SimulationView.extruderCount * (UM.Theme.getSize("layerview_row").height + UM.Theme.getSize("layerview_row_spacing").height) - } - } - Behavior on height { NumberAnimation { duration: 100 } } - - property var buttonTarget: - { - if(parent != null) - { - var force_binding = parent.y; // ensure this gets reevaluated when the panel moves - return base.mapFromItem(parent.parent, parent.buttonTarget.x, parent.buttonTarget.y) - } - return Qt.point(0,0) - } - - Rectangle - { - id: layerViewMenu - anchors.right: parent.right - anchors.top: parent.top - width: parent.width - height: parent.height - clip: true - z: layerSlider.z - 1 - color: UM.Theme.getColor("tool_panel_background") - border.width: UM.Theme.getSize("default_lining").width - border.color: UM.Theme.getColor("lining") - - Button { - id: collapseButton - anchors.top: parent.top - anchors.topMargin: Math.round(UM.Theme.getSize("default_margin").height + (UM.Theme.getSize("layerview_row").height - UM.Theme.getSize("default_margin").height) / 2) - anchors.right: parent.right - anchors.rightMargin: UM.Theme.getSize("default_margin").width - - width: UM.Theme.getSize("standard_arrow").width - height: UM.Theme.getSize("standard_arrow").height - - onClicked: viewSettings.collapsed = !viewSettings.collapsed - - style: ButtonStyle - { - background: UM.RecolorImage - { - width: control.width - height: control.height - sourceSize.width: width - sourceSize.height: width - color: UM.Theme.getColor("setting_control_text") - source: viewSettings.collapsed ? UM.Theme.getIcon("arrow_left") : UM.Theme.getIcon("arrow_bottom") - } - label: Label{ } - } - } - - ColumnLayout - { - id: viewSettings - - property bool collapsed: false - property var extruder_opacities: UM.Preferences.getValue("layerview/extruder_opacities").split("|") - property bool show_travel_moves: UM.Preferences.getValue("layerview/show_travel_moves") - property bool show_helpers: UM.Preferences.getValue("layerview/show_helpers") - property bool show_skin: UM.Preferences.getValue("layerview/show_skin") - property bool show_infill: UM.Preferences.getValue("layerview/show_infill") - // if we are in compatibility mode, we only show the "line type" - property bool show_legend: UM.SimulationView.compatibilityMode ? true : UM.Preferences.getValue("layerview/layer_view_type") == 1 - property bool show_gradient: UM.SimulationView.compatibilityMode ? false : UM.Preferences.getValue("layerview/layer_view_type") == 2 || UM.Preferences.getValue("layerview/layer_view_type") == 3 - property bool show_feedrate_gradient: show_gradient && UM.Preferences.getValue("layerview/layer_view_type") == 2 - property bool show_thickness_gradient: show_gradient && UM.Preferences.getValue("layerview/layer_view_type") == 3 - property bool only_show_top_layers: UM.Preferences.getValue("view/only_show_top_layers") - property int top_layer_count: UM.Preferences.getValue("view/top_layer_count") - - anchors.top: parent.top - anchors.topMargin: UM.Theme.getSize("default_margin").height - anchors.left: parent.left - anchors.leftMargin: UM.Theme.getSize("default_margin").width - anchors.right: parent.right - anchors.rightMargin: UM.Theme.getSize("default_margin").width - spacing: UM.Theme.getSize("layerview_row_spacing").height - - Label - { - id: layerViewTypesLabel - anchors.left: parent.left - text: catalog.i18nc("@label","Color scheme") - font: UM.Theme.getFont("default"); - visible: !UM.SimulationView.compatibilityMode - Layout.fillWidth: true - color: UM.Theme.getColor("setting_control_text") - } - - ListModel // matches SimulationView.py - { - id: layerViewTypes - } - - Component.onCompleted: - { - layerViewTypes.append({ - text: catalog.i18nc("@label:listbox", "Material Color"), - type_id: 0 - }) - layerViewTypes.append({ - text: catalog.i18nc("@label:listbox", "Line Type"), - type_id: 1 - }) - layerViewTypes.append({ - text: catalog.i18nc("@label:listbox", "Feedrate"), - type_id: 2 - }) - layerViewTypes.append({ - text: catalog.i18nc("@label:listbox", "Layer thickness"), - type_id: 3 // these ids match the switching in the shader - }) - } - - ComboBox - { - id: layerTypeCombobox - anchors.left: parent.left - Layout.fillWidth: true - Layout.preferredWidth: UM.Theme.getSize("layerview_row").width - model: layerViewTypes - visible: !UM.SimulationView.compatibilityMode - style: UM.Theme.styles.combobox - anchors.right: parent.right - - onActivated: - { - UM.Preferences.setValue("layerview/layer_view_type", index); - } - - Component.onCompleted: - { - currentIndex = UM.SimulationView.compatibilityMode ? 1 : UM.Preferences.getValue("layerview/layer_view_type"); - updateLegends(currentIndex); - } - - function updateLegends(type_id) - { - // update visibility of legends - viewSettings.show_legend = UM.SimulationView.compatibilityMode || (type_id == 1); - viewSettings.show_gradient = !UM.SimulationView.compatibilityMode && (type_id == 2 || type_id == 3); - viewSettings.show_feedrate_gradient = viewSettings.show_gradient && (type_id == 2); - viewSettings.show_thickness_gradient = viewSettings.show_gradient && (type_id == 3); - } - } - - Label - { - id: compatibilityModeLabel - anchors.left: parent.left - text: catalog.i18nc("@label","Compatibility Mode") - font: UM.Theme.getFont("default") - color: UM.Theme.getColor("text") - visible: UM.SimulationView.compatibilityMode - Layout.fillWidth: true - Layout.preferredHeight: UM.Theme.getSize("layerview_row").height - Layout.preferredWidth: UM.Theme.getSize("layerview_row").width - } - - Item - { - height: Math.round(UM.Theme.getSize("default_margin").width / 2) - width: width - } - - Connections - { - target: UM.Preferences - onPreferenceChanged: - { - layerTypeCombobox.currentIndex = UM.SimulationView.compatibilityMode ? 1 : UM.Preferences.getValue("layerview/layer_view_type"); - layerTypeCombobox.updateLegends(layerTypeCombobox.currentIndex); - playButton.pauseSimulation(); - viewSettings.extruder_opacities = UM.Preferences.getValue("layerview/extruder_opacities").split("|"); - viewSettings.show_travel_moves = UM.Preferences.getValue("layerview/show_travel_moves"); - viewSettings.show_helpers = UM.Preferences.getValue("layerview/show_helpers"); - viewSettings.show_skin = UM.Preferences.getValue("layerview/show_skin"); - viewSettings.show_infill = UM.Preferences.getValue("layerview/show_infill"); - viewSettings.only_show_top_layers = UM.Preferences.getValue("view/only_show_top_layers"); - viewSettings.top_layer_count = UM.Preferences.getValue("view/top_layer_count"); - } - } - - Repeater - { - model: Cura.ExtrudersModel{} - CheckBox - { - id: extrudersModelCheckBox - checked: viewSettings.extruder_opacities[index] > 0.5 || viewSettings.extruder_opacities[index] == undefined || viewSettings.extruder_opacities[index] == "" - onClicked: - { - viewSettings.extruder_opacities[index] = checked ? 1.0 : 0.0 - UM.Preferences.setValue("layerview/extruder_opacities", viewSettings.extruder_opacities.join("|")); - } - visible: !UM.SimulationView.compatibilityMode - enabled: index + 1 <= 4 - Rectangle - { - anchors.verticalCenter: parent.verticalCenter - anchors.right: extrudersModelCheckBox.right - width: UM.Theme.getSize("layerview_legend_size").width - height: UM.Theme.getSize("layerview_legend_size").height - color: model.color - radius: Math.round(width / 2) - border.width: UM.Theme.getSize("default_lining").width - border.color: UM.Theme.getColor("lining") - visible: !viewSettings.show_legend & !viewSettings.show_gradient - } - Layout.fillWidth: true - Layout.preferredHeight: UM.Theme.getSize("layerview_row").height + UM.Theme.getSize("default_lining").height - Layout.preferredWidth: UM.Theme.getSize("layerview_row").width - style: UM.Theme.styles.checkbox - Label - { - text: model.name - elide: Text.ElideRight - color: UM.Theme.getColor("setting_control_text") - font: UM.Theme.getFont("default") - anchors.verticalCenter: parent.verticalCenter - anchors.left: extrudersModelCheckBox.left; - anchors.right: extrudersModelCheckBox.right; - anchors.leftMargin: UM.Theme.getSize("checkbox").width + Math.round(UM.Theme.getSize("default_margin").width/2) - anchors.rightMargin: UM.Theme.getSize("default_margin").width * 2 - } - } - } - - Repeater - { - model: ListModel - { - id: typesLegendModel - Component.onCompleted: - { - typesLegendModel.append({ - label: catalog.i18nc("@label", "Show Travels"), - initialValue: viewSettings.show_travel_moves, - preference: "layerview/show_travel_moves", - colorId: "layerview_move_combing" - }); - typesLegendModel.append({ - label: catalog.i18nc("@label", "Show Helpers"), - initialValue: viewSettings.show_helpers, - preference: "layerview/show_helpers", - colorId: "layerview_support" - }); - typesLegendModel.append({ - label: catalog.i18nc("@label", "Show Shell"), - initialValue: viewSettings.show_skin, - preference: "layerview/show_skin", - colorId: "layerview_inset_0" - }); - typesLegendModel.append({ - label: catalog.i18nc("@label", "Show Infill"), - initialValue: viewSettings.show_infill, - preference: "layerview/show_infill", - colorId: "layerview_infill" - }); - } - } - - CheckBox - { - id: legendModelCheckBox - checked: model.initialValue - onClicked: - { - UM.Preferences.setValue(model.preference, checked); - } - Rectangle - { - anchors.verticalCenter: parent.verticalCenter - anchors.right: legendModelCheckBox.right - width: UM.Theme.getSize("layerview_legend_size").width - height: UM.Theme.getSize("layerview_legend_size").height - color: UM.Theme.getColor(model.colorId) - border.width: UM.Theme.getSize("default_lining").width - border.color: UM.Theme.getColor("lining") - visible: viewSettings.show_legend - } - Layout.fillWidth: true - Layout.preferredHeight: UM.Theme.getSize("layerview_row").height + UM.Theme.getSize("default_lining").height - Layout.preferredWidth: UM.Theme.getSize("layerview_row").width - style: UM.Theme.styles.checkbox - Label - { - text: label - font: UM.Theme.getFont("default") - elide: Text.ElideRight - color: UM.Theme.getColor("setting_control_text") - anchors.verticalCenter: parent.verticalCenter - anchors.left: legendModelCheckBox.left; - anchors.right: legendModelCheckBox.right; - anchors.leftMargin: UM.Theme.getSize("checkbox").width + Math.round(UM.Theme.getSize("default_margin").width/2) - anchors.rightMargin: UM.Theme.getSize("default_margin").width * 2 - } - } - } - - CheckBox - { - checked: viewSettings.only_show_top_layers - onClicked: - { - UM.Preferences.setValue("view/only_show_top_layers", checked ? 1.0 : 0.0); - } - text: catalog.i18nc("@label", "Only Show Top Layers") - visible: UM.SimulationView.compatibilityMode - style: UM.Theme.styles.checkbox - } - CheckBox - { - checked: viewSettings.top_layer_count == 5 - onClicked: - { - UM.Preferences.setValue("view/top_layer_count", checked ? 5 : 1); - } - text: catalog.i18nc("@label", "Show 5 Detailed Layers On Top") - visible: UM.SimulationView.compatibilityMode - style: UM.Theme.styles.checkbox - } - - Repeater - { - model: ListModel - { - id: typesLegendModelNoCheck - Component.onCompleted: - { - typesLegendModelNoCheck.append({ - label: catalog.i18nc("@label", "Top / Bottom"), - colorId: "layerview_skin", - }); - typesLegendModelNoCheck.append({ - label: catalog.i18nc("@label", "Inner Wall"), - colorId: "layerview_inset_x", - }); - } - } - - Label - { - text: label - visible: viewSettings.show_legend - id: typesLegendModelLabel - Rectangle - { - anchors.verticalCenter: parent.verticalCenter - anchors.right: typesLegendModelLabel.right - width: UM.Theme.getSize("layerview_legend_size").width - height: UM.Theme.getSize("layerview_legend_size").height - color: UM.Theme.getColor(model.colorId) - border.width: UM.Theme.getSize("default_lining").width - border.color: UM.Theme.getColor("lining") - visible: viewSettings.show_legend - } - Layout.fillWidth: true - Layout.preferredHeight: UM.Theme.getSize("layerview_row").height + UM.Theme.getSize("default_lining").height - Layout.preferredWidth: UM.Theme.getSize("layerview_row").width - color: UM.Theme.getColor("setting_control_text") - font: UM.Theme.getFont("default") - } - } - - // Text for the minimum, maximum and units for the feedrates and layer thickness - Item - { - id: gradientLegend - visible: viewSettings.show_gradient - width: parent.width - height: UM.Theme.getSize("layerview_row").height - anchors - { - topMargin: UM.Theme.getSize("slider_layerview_margin").height - horizontalCenter: parent.horizontalCenter - } - - Label - { - text: minText() - anchors.left: parent.left - color: UM.Theme.getColor("setting_control_text") - font: UM.Theme.getFont("default") - - function minText() - { - if (UM.SimulationView.layerActivity && CuraApplication.platformActivity) - { - // Feedrate selected - if (UM.Preferences.getValue("layerview/layer_view_type") == 2) - { - return parseFloat(UM.SimulationView.getMinFeedrate()).toFixed(2) - } - // Layer thickness selected - if (UM.Preferences.getValue("layerview/layer_view_type") == 3) - { - return parseFloat(UM.SimulationView.getMinThickness()).toFixed(2) - } - } - return catalog.i18nc("@label","min") - } - } - - Label - { - text: unitsText() - anchors.horizontalCenter: parent.horizontalCenter - color: UM.Theme.getColor("setting_control_text") - font: UM.Theme.getFont("default") - - function unitsText() - { - if (UM.SimulationView.layerActivity && CuraApplication.platformActivity) - { - // Feedrate selected - if (UM.Preferences.getValue("layerview/layer_view_type") == 2) - { - return "mm/s" - } - // Layer thickness selected - if (UM.Preferences.getValue("layerview/layer_view_type") == 3) - { - return "mm" - } - } - return "" - } - } - - Label - { - text: maxText() - anchors.right: parent.right - color: UM.Theme.getColor("setting_control_text") - font: UM.Theme.getFont("default") - - function maxText() - { - if (UM.SimulationView.layerActivity && CuraApplication.platformActivity) - { - // Feedrate selected - if (UM.Preferences.getValue("layerview/layer_view_type") == 2) - { - return parseFloat(UM.SimulationView.getMaxFeedrate()).toFixed(2) - } - // Layer thickness selected - if (UM.Preferences.getValue("layerview/layer_view_type") == 3) - { - return parseFloat(UM.SimulationView.getMaxThickness()).toFixed(2) - } - } - return catalog.i18nc("@label","max") - } - } - } - - // Gradient colors for feedrate - Rectangle - { // In QML 5.9 can be changed by LinearGradient - // Invert values because then the bar is rotated 90 degrees - id: feedrateGradient - visible: viewSettings.show_feedrate_gradient - anchors.left: parent.right - height: parent.width - width: Math.round(UM.Theme.getSize("layerview_row").height * 1.5) - border.width: UM.Theme.getSize("default_lining").width - border.color: UM.Theme.getColor("lining") - transform: Rotation {origin.x: 0; origin.y: 0; angle: 90} - gradient: Gradient - { - GradientStop - { - position: 0.000 - color: Qt.rgba(1, 0.5, 0, 1) - } - GradientStop - { - position: 0.625 - color: Qt.rgba(0.375, 0.5, 0, 1) - } - GradientStop - { - position: 0.75 - color: Qt.rgba(0.25, 1, 0, 1) - } - GradientStop - { - position: 1.0 - color: Qt.rgba(0, 0, 1, 1) - } - } - } - - // Gradient colors for layer thickness (similar to parula colormap) - Rectangle // In QML 5.9 can be changed by LinearGradient - { - // Invert values because then the bar is rotated 90 degrees - id: thicknessGradient - visible: viewSettings.show_thickness_gradient - anchors.left: parent.right - height: parent.width - width: Math.round(UM.Theme.getSize("layerview_row").height * 1.5) - border.width: UM.Theme.getSize("default_lining").width - border.color: UM.Theme.getColor("lining") - transform: Rotation {origin.x: 0; origin.y: 0; angle: 90} - gradient: Gradient - { - GradientStop - { - position: 0.000 - color: Qt.rgba(1, 1, 0, 1) - } - GradientStop - { - position: 0.25 - color: Qt.rgba(1, 0.75, 0.25, 1) - } - GradientStop - { - position: 0.5 - color: Qt.rgba(0, 0.75, 0.5, 1) - } - GradientStop - { - position: 0.75 - color: Qt.rgba(0, 0.375, 0.75, 1) - } - GradientStop - { - position: 1.0 - color: Qt.rgba(0, 0, 0.5, 1) - } - } - } - } - } - - Item - { - id: slidersBox - - width: parent.width - visible: UM.SimulationView.layerActivity && CuraApplication.platformActivity - - anchors - { - top: parent.bottom - topMargin: UM.Theme.getSize("slider_layerview_margin").height - left: parent.left - } - - PathSlider - { - id: pathSlider - - height: UM.Theme.getSize("slider_handle").width - anchors.left: playButton.right - anchors.leftMargin: UM.Theme.getSize("default_margin").width - anchors.right: parent.right - visible: !UM.SimulationView.compatibilityMode - - // custom properties - handleValue: UM.SimulationView.currentPath - maximumValue: UM.SimulationView.numPaths - handleSize: UM.Theme.getSize("slider_handle").width - trackThickness: UM.Theme.getSize("slider_groove").width - trackColor: UM.Theme.getColor("slider_groove") - trackBorderColor: UM.Theme.getColor("slider_groove_border") - handleColor: UM.Theme.getColor("slider_handle") - handleActiveColor: UM.Theme.getColor("slider_handle_active") - rangeColor: UM.Theme.getColor("slider_groove_fill") - - // update values when layer data changes - Connections - { - target: UM.SimulationView - onMaxPathsChanged: pathSlider.setHandleValue(UM.SimulationView.currentPath) - onCurrentPathChanged: - { - // Only pause the simulation when the layer was changed manually, not when the simulation is running - if (pathSlider.manuallyChanged) - { - playButton.pauseSimulation() - } - pathSlider.setHandleValue(UM.SimulationView.currentPath) - } - } - - // make sure the slider handlers show the correct value after switching views - Component.onCompleted: - { - pathSlider.setHandleValue(UM.SimulationView.currentPath) - } - } - - LayerSlider - { - id: layerSlider - - width: UM.Theme.getSize("slider_handle").width - height: UM.Theme.getSize("layerview_menu_size").height - - anchors - { - top: !UM.SimulationView.compatibilityMode ? pathSlider.bottom : parent.top - topMargin: !UM.SimulationView.compatibilityMode ? UM.Theme.getSize("default_margin").height : 0 - right: parent.right - rightMargin: UM.Theme.getSize("slider_layerview_margin").width - } - - // custom properties - upperValue: UM.SimulationView.currentLayer - lowerValue: UM.SimulationView.minimumLayer - maximumValue: UM.SimulationView.numLayers - handleSize: UM.Theme.getSize("slider_handle").width - trackThickness: UM.Theme.getSize("slider_groove").width - trackColor: UM.Theme.getColor("slider_groove") - trackBorderColor: UM.Theme.getColor("slider_groove_border") - upperHandleColor: UM.Theme.getColor("slider_handle") - lowerHandleColor: UM.Theme.getColor("slider_handle") - rangeHandleColor: UM.Theme.getColor("slider_groove_fill") - handleActiveColor: UM.Theme.getColor("slider_handle_active") - handleLabelWidth: UM.Theme.getSize("slider_layerview_background").width - - // update values when layer data changes - Connections - { - target: UM.SimulationView - onMaxLayersChanged: layerSlider.setUpperValue(UM.SimulationView.currentLayer) - onMinimumLayerChanged: layerSlider.setLowerValue(UM.SimulationView.minimumLayer) - onCurrentLayerChanged: - { - // Only pause the simulation when the layer was changed manually, not when the simulation is running - if (layerSlider.manuallyChanged) - { - playButton.pauseSimulation() - } - layerSlider.setUpperValue(UM.SimulationView.currentLayer) - } - } - - // make sure the slider handlers show the correct value after switching views - Component.onCompleted: - { - layerSlider.setLowerValue(UM.SimulationView.minimumLayer) - layerSlider.setUpperValue(UM.SimulationView.currentLayer) - } - } - - // Play simulation button - Button - { - id: playButton - iconSource: "./resources/simulation_resume.svg" - style: UM.Theme.styles.small_tool_button - visible: !UM.SimulationView.compatibilityMode - anchors - { - verticalCenter: pathSlider.verticalCenter - } - - property var status: 0 // indicates if it's stopped (0) or playing (1) - - onClicked: - { - switch(status) - { - case 0: - { - resumeSimulation() - break - } - case 1: - { - pauseSimulation() - break - } - } - } - - function pauseSimulation() - { - UM.SimulationView.setSimulationRunning(false) - iconSource = "./resources/simulation_resume.svg" - simulationTimer.stop() - status = 0 - layerSlider.manuallyChanged = true - pathSlider.manuallyChanged = true - } - - function resumeSimulation() - { - UM.SimulationView.setSimulationRunning(true) - iconSource = "./resources/simulation_pause.svg" - simulationTimer.start() - layerSlider.manuallyChanged = false - pathSlider.manuallyChanged = false - } - } - - Timer - { - id: simulationTimer - interval: 100 - running: false - repeat: true - onTriggered: - { - var currentPath = UM.SimulationView.currentPath - var numPaths = UM.SimulationView.numPaths - var currentLayer = UM.SimulationView.currentLayer - var numLayers = UM.SimulationView.numLayers - // When the user plays the simulation, if the path slider is at the end of this layer, we start - // the simulation at the beginning of the current layer. - if (playButton.status == 0) - { - if (currentPath >= numPaths) - { - UM.SimulationView.setCurrentPath(0) - } - else - { - UM.SimulationView.setCurrentPath(currentPath+1) - } - } - // If the simulation is already playing and we reach the end of a layer, then it automatically - // starts at the beginning of the next layer. - else - { - if (currentPath >= numPaths) - { - // At the end of the model, the simulation stops - if (currentLayer >= numLayers) - { - playButton.pauseSimulation() - } - else - { - UM.SimulationView.setCurrentLayer(currentLayer+1) - UM.SimulationView.setCurrentPath(0) - } - } - else - { - UM.SimulationView.setCurrentPath(currentPath+1) - } - } - // The status must be set here instead of in the resumeSimulation function otherwise it won't work - // correctly, because part of the logic is in this trigger function. - playButton.status = 1 - } - } - } - - FontMetrics - { - id: fontMetrics - font: UM.Theme.getFont("default") - } -} diff --git a/plugins/SimulationView/SimulationViewMainComponent.qml b/plugins/SimulationView/SimulationViewMainComponent.qml new file mode 100644 index 0000000000..16b049c921 --- /dev/null +++ b/plugins/SimulationView/SimulationViewMainComponent.qml @@ -0,0 +1,211 @@ +// Copyright (c) 2018 Ultimaker B.V. +// Cura is released under the terms of the LGPLv3 or higher. + +import QtQuick 2.4 +import QtQuick.Controls 1.2 +import QtQuick.Layouts 1.1 +import QtQuick.Controls.Styles 1.1 + +import UM 1.4 as UM +import Cura 1.0 as Cura + +Item +{ + property bool is_simulation_playing: false + visible: UM.SimulationView.layerActivity && CuraApplication.platformActivity + + PathSlider + { + id: pathSlider + height: UM.Theme.getSize("slider_handle").width + width: UM.Theme.getSize("slider_layerview_size").height + + anchors.bottom: parent.bottom + anchors.bottomMargin: UM.Theme.getSize("default_margin").height + + anchors.horizontalCenter: parent.horizontalCenter + + visible: !UM.SimulationView.compatibilityMode + + // Custom properties + handleValue: UM.SimulationView.currentPath + maximumValue: UM.SimulationView.numPaths + + // Update values when layer data changes. + Connections + { + target: UM.SimulationView + onMaxPathsChanged: pathSlider.setHandleValue(UM.SimulationView.currentPath) + onCurrentPathChanged: + { + // Only pause the simulation when the layer was changed manually, not when the simulation is running + if (pathSlider.manuallyChanged) + { + playButton.pauseSimulation() + } + pathSlider.setHandleValue(UM.SimulationView.currentPath) + } + } + + // Ensure that the slider handlers show the correct value after switching views. + Component.onCompleted: + { + pathSlider.setHandleValue(UM.SimulationView.currentPath) + } + + } + + UM.SimpleButton + { + id: playButton + iconSource: !is_simulation_playing ? "./resources/simulation_resume.svg": "./resources/simulation_pause.svg" + width: UM.Theme.getSize("small_button").width + height: UM.Theme.getSize("small_button").height + hoverColor: UM.Theme.getColor("slider_handle_active") + color: UM.Theme.getColor("slider_handle") + iconMargin: UM.Theme.getSize("thick_lining").width + visible: !UM.SimulationView.compatibilityMode + + Connections + { + target: UM.Preferences + onPreferenceChanged: + { + playButton.pauseSimulation() + } + } + + anchors + { + right: pathSlider.left + verticalCenter: pathSlider.verticalCenter + } + + onClicked: + { + if(is_simulation_playing) + { + pauseSimulation() + } + else + { + resumeSimulation() + } + } + + function pauseSimulation() + { + UM.SimulationView.setSimulationRunning(false) + simulationTimer.stop() + is_simulation_playing = false + layerSlider.manuallyChanged = true + pathSlider.manuallyChanged = true + } + + function resumeSimulation() + { + UM.SimulationView.setSimulationRunning(true) + simulationTimer.start() + layerSlider.manuallyChanged = false + pathSlider.manuallyChanged = false + } + } + + Timer + { + id: simulationTimer + interval: 100 + running: false + repeat: true + onTriggered: + { + var currentPath = UM.SimulationView.currentPath + var numPaths = UM.SimulationView.numPaths + var currentLayer = UM.SimulationView.currentLayer + var numLayers = UM.SimulationView.numLayers + + // When the user plays the simulation, if the path slider is at the end of this layer, we start + // the simulation at the beginning of the current layer. + if (!is_simulation_playing) + { + if (currentPath >= numPaths) + { + UM.SimulationView.setCurrentPath(0) + } + else + { + UM.SimulationView.setCurrentPath(currentPath + 1) + } + } + // If the simulation is already playing and we reach the end of a layer, then it automatically + // starts at the beginning of the next layer. + else + { + if (currentPath >= numPaths) + { + // At the end of the model, the simulation stops + if (currentLayer >= numLayers) + { + playButton.pauseSimulation() + } + else + { + UM.SimulationView.setCurrentLayer(currentLayer + 1) + UM.SimulationView.setCurrentPath(0) + } + } + else + { + UM.SimulationView.setCurrentPath(currentPath + 1) + } + } + // The status must be set here instead of in the resumeSimulation function otherwise it won't work + // correctly, because part of the logic is in this trigger function. + is_simulation_playing = true + } + } + + LayerSlider + { + id: layerSlider + + width: UM.Theme.getSize("slider_handle").width + height: UM.Theme.getSize("slider_layerview_size").height + + anchors + { + right: parent.right + verticalCenter: parent.verticalCenter + rightMargin: UM.Theme.getSize("default_margin").width + } + + // Custom properties + upperValue: UM.SimulationView.currentLayer + lowerValue: UM.SimulationView.minimumLayer + maximumValue: UM.SimulationView.numLayers + + // Update values when layer data changes + Connections + { + target: UM.SimulationView + onMaxLayersChanged: layerSlider.setUpperValue(UM.SimulationView.currentLayer) + onMinimumLayerChanged: layerSlider.setLowerValue(UM.SimulationView.minimumLayer) + onCurrentLayerChanged: + { + // Only pause the simulation when the layer was changed manually, not when the simulation is running + if (layerSlider.manuallyChanged) + { + playButton.pauseSimulation() + } + layerSlider.setUpperValue(UM.SimulationView.currentLayer) + } + } + + // Make sure the slider handlers show the correct value after switching views + Component.onCompleted: + { + layerSlider.setLowerValue(UM.SimulationView.minimumLayer) + layerSlider.setUpperValue(UM.SimulationView.currentLayer) + } + } +} \ No newline at end of file diff --git a/plugins/SimulationView/SimulationViewMenuComponent.qml b/plugins/SimulationView/SimulationViewMenuComponent.qml new file mode 100644 index 0000000000..58b2bfe520 --- /dev/null +++ b/plugins/SimulationView/SimulationViewMenuComponent.qml @@ -0,0 +1,530 @@ +// Copyright (c) 2018 Ultimaker B.V. +// Cura is released under the terms of the LGPLv3 or higher. + +import QtQuick 2.4 +import QtQuick.Controls 1.2 +import QtQuick.Layouts 1.1 +import QtQuick.Controls.Styles 1.1 +import QtGraphicalEffects 1.0 + +import UM 1.0 as UM +import Cura 1.0 as Cura + + +Cura.ExpandableComponent +{ + id: base + + width: UM.Theme.getSize("layerview_menu_size").width + contentHeaderTitle: catalog.i18nc("@label", "Color scheme") + + Connections + { + target: UM.Preferences + onPreferenceChanged: + { + layerTypeCombobox.currentIndex = UM.SimulationView.compatibilityMode ? 1 : UM.Preferences.getValue("layerview/layer_view_type") + layerTypeCombobox.updateLegends(layerTypeCombobox.currentIndex) + viewSettings.extruder_opacities = UM.Preferences.getValue("layerview/extruder_opacities").split("|") + viewSettings.show_travel_moves = UM.Preferences.getValue("layerview/show_travel_moves") + viewSettings.show_helpers = UM.Preferences.getValue("layerview/show_helpers") + viewSettings.show_skin = UM.Preferences.getValue("layerview/show_skin") + viewSettings.show_infill = UM.Preferences.getValue("layerview/show_infill") + viewSettings.only_show_top_layers = UM.Preferences.getValue("view/only_show_top_layers") + viewSettings.top_layer_count = UM.Preferences.getValue("view/top_layer_count") + } + } + + headerItem: Label + { + id: layerViewTypesLabel + text: catalog.i18nc("@label", "Color scheme") + font: UM.Theme.getFont("default") + color: UM.Theme.getColor("setting_control_text") + height: base.height + verticalAlignment: Text.AlignVCenter + } + + contentItem: Column + { + id: viewSettings + + property var extruder_opacities: UM.Preferences.getValue("layerview/extruder_opacities").split("|") + property bool show_travel_moves: UM.Preferences.getValue("layerview/show_travel_moves") + property bool show_helpers: UM.Preferences.getValue("layerview/show_helpers") + property bool show_skin: UM.Preferences.getValue("layerview/show_skin") + property bool show_infill: UM.Preferences.getValue("layerview/show_infill") + + // If we are in compatibility mode, we only show the "line type" + property bool show_legend: UM.SimulationView.compatibilityMode ? true : UM.Preferences.getValue("layerview/layer_view_type") == 1 + property bool show_gradient: UM.SimulationView.compatibilityMode ? false : UM.Preferences.getValue("layerview/layer_view_type") == 2 || UM.Preferences.getValue("layerview/layer_view_type") == 3 + property bool show_feedrate_gradient: show_gradient && UM.Preferences.getValue("layerview/layer_view_type") == 2 + property bool show_thickness_gradient: show_gradient && UM.Preferences.getValue("layerview/layer_view_type") == 3 + property bool only_show_top_layers: UM.Preferences.getValue("view/only_show_top_layers") + property int top_layer_count: UM.Preferences.getValue("view/top_layer_count") + + width: UM.Theme.getSize("layerview_menu_size").width - 2 * UM.Theme.getSize("default_margin").width + height: implicitHeight + + spacing: UM.Theme.getSize("layerview_row_spacing").height + + ListModel // matches SimulationView.py + { + id: layerViewTypes + } + + Component.onCompleted: + { + layerViewTypes.append({ + text: catalog.i18nc("@label:listbox", "Material Color"), + type_id: 0 + }) + layerViewTypes.append({ + text: catalog.i18nc("@label:listbox", "Line Type"), + type_id: 1 + }) + layerViewTypes.append({ + text: catalog.i18nc("@label:listbox", "Feedrate"), + type_id: 2 + }) + layerViewTypes.append({ + text: catalog.i18nc("@label:listbox", "Layer thickness"), + type_id: 3 // these ids match the switching in the shader + }) + } + + ComboBox + { + id: layerTypeCombobox + width: parent.width + model: layerViewTypes + visible: !UM.SimulationView.compatibilityMode + style: UM.Theme.styles.combobox + + onActivated: + { + UM.Preferences.setValue("layerview/layer_view_type", index); + } + + Component.onCompleted: + { + currentIndex = UM.SimulationView.compatibilityMode ? 1 : UM.Preferences.getValue("layerview/layer_view_type"); + updateLegends(currentIndex); + } + + function updateLegends(type_id) + { + // Update the visibility of the legends. + viewSettings.show_legend = UM.SimulationView.compatibilityMode || (type_id == 1); + viewSettings.show_gradient = !UM.SimulationView.compatibilityMode && (type_id == 2 || type_id == 3); + viewSettings.show_feedrate_gradient = viewSettings.show_gradient && (type_id == 2); + viewSettings.show_thickness_gradient = viewSettings.show_gradient && (type_id == 3); + } + } + + Label + { + id: compatibilityModeLabel + text: catalog.i18nc("@label","Compatibility Mode") + font: UM.Theme.getFont("default") + color: UM.Theme.getColor("text") + visible: UM.SimulationView.compatibilityMode + height: UM.Theme.getSize("layerview_row").height + width: parent.width + renderType: Text.NativeRendering + } + + Item // Spacer + { + height: Math.round(UM.Theme.getSize("default_margin").width / 2) + width: width + } + + Repeater + { + model: Cura.ExtrudersModel{} + + CheckBox + { + id: extrudersModelCheckBox + checked: viewSettings.extruder_opacities[index] > 0.5 || viewSettings.extruder_opacities[index] == undefined || viewSettings.extruder_opacities[index] == "" + height: UM.Theme.getSize("layerview_row").height + UM.Theme.getSize("default_lining").height + width: parent.width + visible: !UM.SimulationView.compatibilityMode + enabled: index < 4 + + onClicked: + { + viewSettings.extruder_opacities[index] = checked ? 1.0 : 0.0 + UM.Preferences.setValue("layerview/extruder_opacities", viewSettings.extruder_opacities.join("|")); + } + + style: UM.Theme.styles.checkbox + + Rectangle + { + anchors.verticalCenter: parent.verticalCenter + anchors.right: extrudersModelCheckBox.right + width: UM.Theme.getSize("layerview_legend_size").width + height: UM.Theme.getSize("layerview_legend_size").height + color: model.color + radius: Math.round(width / 2) + border.width: UM.Theme.getSize("default_lining").width + border.color: UM.Theme.getColor("lining") + visible: !viewSettings.show_legend && !viewSettings.show_gradient + } + + Label + { + text: model.name + elide: Text.ElideRight + color: UM.Theme.getColor("setting_control_text") + font: UM.Theme.getFont("default") + anchors + { + verticalCenter: parent.verticalCenter + left: extrudersModelCheckBox.left + right: extrudersModelCheckBox.right + leftMargin: UM.Theme.getSize("checkbox").width + Math.round(UM.Theme.getSize("default_margin").width / 2) + rightMargin: UM.Theme.getSize("default_margin").width * 2 + } + renderType: Text.NativeRendering + } + } + } + + Repeater + { + model: ListModel + { + id: typesLegendModel + Component.onCompleted: + { + typesLegendModel.append({ + label: catalog.i18nc("@label", "Show Travels"), + initialValue: viewSettings.show_travel_moves, + preference: "layerview/show_travel_moves", + colorId: "layerview_move_combing" + }); + typesLegendModel.append({ + label: catalog.i18nc("@label", "Show Helpers"), + initialValue: viewSettings.show_helpers, + preference: "layerview/show_helpers", + colorId: "layerview_support" + }); + typesLegendModel.append({ + label: catalog.i18nc("@label", "Show Shell"), + initialValue: viewSettings.show_skin, + preference: "layerview/show_skin", + colorId: "layerview_inset_0" + }); + typesLegendModel.append({ + label: catalog.i18nc("@label", "Show Infill"), + initialValue: viewSettings.show_infill, + preference: "layerview/show_infill", + colorId: "layerview_infill" + }); + } + } + + CheckBox + { + id: legendModelCheckBox + checked: model.initialValue + onClicked: UM.Preferences.setValue(model.preference, checked) + height: UM.Theme.getSize("layerview_row").height + UM.Theme.getSize("default_lining").height + width: parent.width + + style: UM.Theme.styles.checkbox + + Rectangle + { + anchors.verticalCenter: parent.verticalCenter + anchors.right: legendModelCheckBox.right + width: UM.Theme.getSize("layerview_legend_size").width + height: UM.Theme.getSize("layerview_legend_size").height + color: UM.Theme.getColor(model.colorId) + border.width: UM.Theme.getSize("default_lining").width + border.color: UM.Theme.getColor("lining") + visible: viewSettings.show_legend + } + + Label + { + text: label + font: UM.Theme.getFont("default") + elide: Text.ElideRight + renderType: Text.NativeRendering + color: UM.Theme.getColor("setting_control_text") + anchors.verticalCenter: parent.verticalCenter + anchors.left: legendModelCheckBox.left + anchors.right: legendModelCheckBox.right + anchors.leftMargin: UM.Theme.getSize("checkbox").width + Math.round(UM.Theme.getSize("default_margin").width / 2) + anchors.rightMargin: UM.Theme.getSize("default_margin").width * 2 + } + } + } + + CheckBox + { + checked: viewSettings.only_show_top_layers + onClicked: UM.Preferences.setValue("view/only_show_top_layers", checked ? 1.0 : 0.0) + text: catalog.i18nc("@label", "Only Show Top Layers") + visible: UM.SimulationView.compatibilityMode + style: UM.Theme.styles.checkbox + width: parent.width + } + + CheckBox + { + checked: viewSettings.top_layer_count == 5 + onClicked: UM.Preferences.setValue("view/top_layer_count", checked ? 5 : 1) + text: catalog.i18nc("@label", "Show 5 Detailed Layers On Top") + width: parent.width + visible: UM.SimulationView.compatibilityMode + style: UM.Theme.styles.checkbox + } + + Repeater + { + model: ListModel + { + id: typesLegendModelNoCheck + Component.onCompleted: + { + typesLegendModelNoCheck.append({ + label: catalog.i18nc("@label", "Top / Bottom"), + colorId: "layerview_skin", + }); + typesLegendModelNoCheck.append({ + label: catalog.i18nc("@label", "Inner Wall"), + colorId: "layerview_inset_x", + }); + } + } + + Label + { + text: label + visible: viewSettings.show_legend + id: typesLegendModelLabel + + height: UM.Theme.getSize("layerview_row").height + UM.Theme.getSize("default_lining").height + width: parent.width + color: UM.Theme.getColor("setting_control_text") + font: UM.Theme.getFont("default") + renderType: Text.NativeRendering + Rectangle + { + anchors.verticalCenter: parent.verticalCenter + anchors.right: typesLegendModelLabel.right + + width: UM.Theme.getSize("layerview_legend_size").width + height: UM.Theme.getSize("layerview_legend_size").height + + color: UM.Theme.getColor(model.colorId) + + border.width: UM.Theme.getSize("default_lining").width + border.color: UM.Theme.getColor("lining") + } + } + } + + // Text for the minimum, maximum and units for the feedrates and layer thickness + Item + { + id: gradientLegend + visible: viewSettings.show_gradient + width: parent.width + height: UM.Theme.getSize("layerview_row").height + + Label + { + text: + { + if (UM.SimulationView.layerActivity && CuraApplication.platformActivity) + { + // Feedrate selected + if (UM.Preferences.getValue("layerview/layer_view_type") == 2) + { + return parseFloat(UM.SimulationView.getMinFeedrate()).toFixed(2) + } + // Layer thickness selected + if (UM.Preferences.getValue("layerview/layer_view_type") == 3) + { + return parseFloat(UM.SimulationView.getMinThickness()).toFixed(2) + } + } + return catalog.i18nc("@label","min") + } + anchors.left: parent.left + color: UM.Theme.getColor("setting_control_text") + font: UM.Theme.getFont("default") + renderType: Text.NativeRendering + } + + Label + { + text: { + if (UM.SimulationView.layerActivity && CuraApplication.platformActivity) + { + // Feedrate selected + if (UM.Preferences.getValue("layerview/layer_view_type") == 2) + { + return "mm/s" + } + // Layer thickness selected + if (UM.Preferences.getValue("layerview/layer_view_type") == 3) + { + return "mm" + } + } + return "" + } + + anchors.horizontalCenter: parent.horizontalCenter + color: UM.Theme.getColor("setting_control_text") + font: UM.Theme.getFont("default") + } + + Label + { + text: { + if (UM.SimulationView.layerActivity && CuraApplication.platformActivity) + { + // Feedrate selected + if (UM.Preferences.getValue("layerview/layer_view_type") == 2) + { + return parseFloat(UM.SimulationView.getMaxFeedrate()).toFixed(2) + } + // Layer thickness selected + if (UM.Preferences.getValue("layerview/layer_view_type") == 3) + { + return parseFloat(UM.SimulationView.getMaxThickness()).toFixed(2) + } + } + return catalog.i18nc("@label","max") + } + + anchors.right: parent.right + color: UM.Theme.getColor("setting_control_text") + font: UM.Theme.getFont("default") + } + } + + // Gradient colors for feedrate + Rectangle + { + id: feedrateGradient + visible: viewSettings.show_feedrate_gradient + anchors.left: parent.left + anchors.right: parent.right + height: Math.round(UM.Theme.getSize("layerview_row").height * 1.5) + border.width: UM.Theme.getSize("default_lining").width + border.color: UM.Theme.getColor("lining") + + LinearGradient + { + anchors + { + left: parent.left + leftMargin: UM.Theme.getSize("default_lining").width + right: parent.right + rightMargin: UM.Theme.getSize("default_lining").width + top: parent.top + topMargin: UM.Theme.getSize("default_lining").width + bottom: parent.bottom + bottomMargin: UM.Theme.getSize("default_lining").width + } + start: Qt.point(0, 0) + end: Qt.point(parent.width, 0) + gradient: Gradient + { + GradientStop + { + position: 0.000 + color: Qt.rgba(0, 0, 1, 1) + } + GradientStop + { + position: 0.25 + color: Qt.rgba(0.25, 1, 0, 1) + } + GradientStop + { + position: 0.375 + color: Qt.rgba(0.375, 0.5, 0, 1) + } + GradientStop + { + position: 1.0 + color: Qt.rgba(1, 0.5, 0, 1) + } + } + } + } + + // Gradient colors for layer thickness (similar to parula colormap) + Rectangle + { + id: thicknessGradient + visible: viewSettings.show_thickness_gradient + anchors.left: parent.left + anchors.right: parent.right + height: Math.round(UM.Theme.getSize("layerview_row").height * 1.5) + border.width: UM.Theme.getSize("default_lining").width + border.color: UM.Theme.getColor("lining") + + LinearGradient + { + anchors + { + left: parent.left + leftMargin: UM.Theme.getSize("default_lining").width + right: parent.right + rightMargin: UM.Theme.getSize("default_lining").width + top: parent.top + topMargin: UM.Theme.getSize("default_lining").width + bottom: parent.bottom + bottomMargin: UM.Theme.getSize("default_lining").width + } + start: Qt.point(0, 0) + end: Qt.point(parent.width, 0) + gradient: Gradient + { + GradientStop + { + position: 0.000 + color: Qt.rgba(0, 0, 0.5, 1) + } + GradientStop + { + position: 0.25 + color: Qt.rgba(0, 0.375, 0.75, 1) + } + GradientStop + { + position: 0.5 + color: Qt.rgba(0, 0.75, 0.5, 1) + } + GradientStop + { + position: 0.75 + color: Qt.rgba(1, 0.75, 0.25, 1) + } + GradientStop + { + position: 1.0 + color: Qt.rgba(1, 1, 0, 1) + } + } + } + } + } + + FontMetrics + { + id: fontMetrics + font: UM.Theme.getFont("default") + } +} diff --git a/plugins/SimulationView/__init__.py b/plugins/SimulationView/__init__.py index 360fdc1de9..420ee60660 100644 --- a/plugins/SimulationView/__init__.py +++ b/plugins/SimulationView/__init__.py @@ -8,19 +8,21 @@ from . import SimulationViewProxy, SimulationView catalog = i18nCatalog("cura") + def getMetaData(): return { "view": { "name": catalog.i18nc("@item:inlistbox", "Layer view"), - "view_panel": "SimulationView.qml", - "weight": 2 + "weight": 0 } } + def createSimulationViewProxy(engine, script_engine): return SimulationViewProxy.SimulationViewProxy() + def register(app): simulation_view = SimulationView.SimulationView() qmlRegisterSingletonType(SimulationViewProxy.SimulationViewProxy, "UM", 1, 0, "SimulationView", simulation_view.getProxy) - return { "view": SimulationView.SimulationView()} + return { "view": simulation_view} diff --git a/plugins/SolidView/__init__.py b/plugins/SolidView/__init__.py index db2e48f489..34148fcf05 100644 --- a/plugins/SolidView/__init__.py +++ b/plugins/SolidView/__init__.py @@ -10,7 +10,8 @@ def getMetaData(): return { "view": { "name": i18n_catalog.i18nc("@item:inmenu", "Solid view"), - "weight": 0 + "weight": 0, + "visible": False } } diff --git a/plugins/Toolbox/resources/qml/Toolbox.qml b/plugins/Toolbox/resources/qml/Toolbox.qml index 9a98c998b0..9ede2a6bda 100644 --- a/plugins/Toolbox/resources/qml/Toolbox.qml +++ b/plugins/Toolbox/resources/qml/Toolbox.qml @@ -14,17 +14,17 @@ Window modality: Qt.ApplicationModal flags: Qt.Dialog | Qt.CustomizeWindowHint | Qt.WindowTitleHint | Qt.WindowCloseButtonHint - width: 720 * screenScaleFactor - height: 640 * screenScaleFactor + width: Math.floor(720 * screenScaleFactor) + height: Math.floor(640 * screenScaleFactor) minimumWidth: width maximumWidth: minimumWidth minimumHeight: height maximumHeight: minimumHeight - color: UM.Theme.getColor("sidebar") + color: UM.Theme.getColor("main_background") UM.I18nCatalog { id: catalog - name:"cura" + name: "cura" } Item { @@ -95,6 +95,7 @@ Window licenseDialog.show(); } } + ToolboxLicenseDialog { id: licenseDialog diff --git a/plugins/Toolbox/resources/qml/ToolboxAuthorPage.qml b/plugins/Toolbox/resources/qml/ToolboxAuthorPage.qml index 4aaea20813..7b026566c3 100644 --- a/plugins/Toolbox/resources/qml/ToolboxAuthorPage.qml +++ b/plugins/Toolbox/resources/qml/ToolboxAuthorPage.qml @@ -1,7 +1,7 @@ // Copyright (c) 2018 Ultimaker B.V. // Toolbox is released under the terms of the LGPLv3 or higher. -import QtQuick 2.3 +import QtQuick 2.10 import QtQuick.Controls 1.4 import QtQuick.Controls.Styles 1.4 import UM 1.1 as UM @@ -59,6 +59,7 @@ Item wrapMode: Text.WordWrap width: parent.width height: UM.Theme.getSize("toolbox_property_label").height + renderType: Text.NativeRendering } Label { @@ -70,6 +71,7 @@ Item left: title.left topMargin: UM.Theme.getSize("default_margin").height } + renderType: Text.NativeRendering } Column { @@ -86,14 +88,16 @@ Item Label { text: catalog.i18nc("@label", "Website") + ":" - font: UM.Theme.getFont("very_small") + font: UM.Theme.getFont("default") color: UM.Theme.getColor("text_medium") + renderType: Text.NativeRendering } Label { text: catalog.i18nc("@label", "Email") + ":" - font: UM.Theme.getFont("very_small") + font: UM.Theme.getFont("default") color: UM.Theme.getColor("text_medium") + renderType: Text.NativeRendering } } Column @@ -118,10 +122,11 @@ Item } return "" } - font: UM.Theme.getFont("very_small") + font: UM.Theme.getFont("default") color: UM.Theme.getColor("text") linkColor: UM.Theme.getColor("text_link") onLinkActivated: Qt.openUrlExternally(link) + renderType: Text.NativeRendering } Label @@ -134,10 +139,11 @@ Item } return "" } - font: UM.Theme.getFont("very_small") + font: UM.Theme.getFont("default") color: UM.Theme.getColor("text") linkColor: UM.Theme.getColor("text_link") onLinkActivated: Qt.openUrlExternally(link) + renderType: Text.NativeRendering } } Rectangle diff --git a/plugins/Toolbox/resources/qml/ToolboxBackColumn.qml b/plugins/Toolbox/resources/qml/ToolboxBackColumn.qml index 8524b7d1e5..edb1967fee 100644 --- a/plugins/Toolbox/resources/qml/ToolboxBackColumn.qml +++ b/plugins/Toolbox/resources/qml/ToolboxBackColumn.qml @@ -1,7 +1,7 @@ // Copyright (c) 2018 Ultimaker B.V. // Toolbox is released under the terms of the LGPLv3 or higher. -import QtQuick 2.2 +import QtQuick 2.10 import QtQuick.Controls 1.4 import QtQuick.Controls.Styles 1.4 import UM 1.1 as UM @@ -64,6 +64,7 @@ Item font: UM.Theme.getFont("default_bold") horizontalAlignment: Text.AlignRight width: control.width + renderType: Text.NativeRendering } } } diff --git a/plugins/Toolbox/resources/qml/ToolboxCompatibilityChart.qml b/plugins/Toolbox/resources/qml/ToolboxCompatibilityChart.qml index 9121b97eca..db4e8c628f 100644 --- a/plugins/Toolbox/resources/qml/ToolboxCompatibilityChart.qml +++ b/plugins/Toolbox/resources/qml/ToolboxCompatibilityChart.qml @@ -1,7 +1,7 @@ // Copyright (c) 2018 Ultimaker B.V. // Toolbox is released under the terms of the LGPLv3 or higher. -import QtQuick 2.7 +import QtQuick 2.10 import QtQuick.Controls 1.4 import QtQuick.Controls.Styles 1.4 import UM 1.1 as UM @@ -67,6 +67,7 @@ Item wrapMode: Text.WordWrap color: UM.Theme.getColor("text_medium") font: UM.Theme.getFont("medium") + renderType: Text.NativeRendering } TableView @@ -90,7 +91,7 @@ Item model: packageData.supported_configs headerDelegate: Rectangle { - color: UM.Theme.getColor("sidebar") + color: UM.Theme.getColor("main_background") height: UM.Theme.getSize("toolbox_chart_row").height Label { @@ -99,6 +100,7 @@ Item text: styleData.value || "" color: UM.Theme.getColor("text") font: UM.Theme.getFont("default_bold") + renderType: Text.NativeRendering } Rectangle { @@ -118,6 +120,7 @@ Item text: styleData.value || "" color: UM.Theme.getColor("text_medium") font: UM.Theme.getFont("default") + renderType: Text.NativeRendering } } itemDelegate: Item @@ -130,6 +133,7 @@ Item text: styleData.value || "" color: UM.Theme.getColor("text_medium") font: UM.Theme.getFont("default") + renderType: Text.NativeRendering } } @@ -144,6 +148,7 @@ Item elide: Text.ElideRight color: UM.Theme.getColor("text_medium") font: UM.Theme.getFont("default") + renderType: Text.NativeRendering } } @@ -228,9 +233,10 @@ Item return result } - font: UM.Theme.getFont("very_small") + font: UM.Theme.getFont("default") color: UM.Theme.getColor("text") linkColor: UM.Theme.getColor("text_link") onLinkActivated: Qt.openUrlExternally(link) + renderType: Text.NativeRendering } } diff --git a/plugins/Toolbox/resources/qml/ToolboxConfirmUninstallResetDialog.qml b/plugins/Toolbox/resources/qml/ToolboxConfirmUninstallResetDialog.qml index 2c5d08aa72..e238132680 100644 --- a/plugins/Toolbox/resources/qml/ToolboxConfirmUninstallResetDialog.qml +++ b/plugins/Toolbox/resources/qml/ToolboxConfirmUninstallResetDialog.qml @@ -1,7 +1,7 @@ // Copyright (c) 2018 Ultimaker B.V. // Cura is released under the terms of the LGPLv3 or higher. -import QtQuick 2.2 +import QtQuick 2.10 import QtQuick.Controls 1.1 import QtQuick.Controls.Styles 1.1 import QtQuick.Layouts 1.1 @@ -66,6 +66,7 @@ UM.Dialog anchors.right: parent.right font: UM.Theme.getFont("default") wrapMode: Text.WordWrap + renderType: Text.NativeRendering } // Buttons diff --git a/plugins/Toolbox/resources/qml/ToolboxDetailList.qml b/plugins/Toolbox/resources/qml/ToolboxDetailList.qml index 2e5eae098c..4e44ea7d0b 100644 --- a/plugins/Toolbox/resources/qml/ToolboxDetailList.qml +++ b/plugins/Toolbox/resources/qml/ToolboxDetailList.qml @@ -26,10 +26,19 @@ Item } height: childrenRect.height + 2 * UM.Theme.getSize("wide_margin").height spacing: UM.Theme.getSize("default_margin").height + Repeater { model: toolbox.packagesModel - delegate: ToolboxDetailTile {} + delegate: Loader + { + // FIXME: When using asynchronous loading, on Mac and Windows, the tile may fail to load complete, + // leaving an empty space below the title part. We turn it off for now to make it work on Mac and + // Windows. + // Can be related to this QT bug: https://bugreports.qt.io/browse/QTBUG-50992 + asynchronous: false + source: "ToolboxDetailTile.qml" + } } } } diff --git a/plugins/Toolbox/resources/qml/ToolboxDetailPage.qml b/plugins/Toolbox/resources/qml/ToolboxDetailPage.qml index 7b48aaebef..7983be8aef 100644 --- a/plugins/Toolbox/resources/qml/ToolboxDetailPage.qml +++ b/plugins/Toolbox/resources/qml/ToolboxDetailPage.qml @@ -1,7 +1,7 @@ // Copyright (c) 2018 Ultimaker B.V. // Toolbox is released under the terms of the LGPLv3 or higher. -import QtQuick 2.3 +import QtQuick 2.10 import QtQuick.Controls 1.4 import QtQuick.Controls.Styles 1.4 import UM 1.1 as UM @@ -37,7 +37,7 @@ Item leftMargin: UM.Theme.getSize("wide_margin").width topMargin: UM.Theme.getSize("wide_margin").height } - color: white //Always a white background for image (regardless of theme). + color: "white" //Always a white background for image (regardless of theme). Image { anchors.fill: parent @@ -65,6 +65,7 @@ Item wrapMode: Text.WordWrap width: parent.width height: UM.Theme.getSize("toolbox_property_label").height + renderType: Text.NativeRendering } Column @@ -82,26 +83,30 @@ Item Label { text: catalog.i18nc("@label", "Version") + ":" - font: UM.Theme.getFont("very_small") + font: UM.Theme.getFont("default") color: UM.Theme.getColor("text_medium") + renderType: Text.NativeRendering } Label { text: catalog.i18nc("@label", "Last updated") + ":" - font: UM.Theme.getFont("very_small") + font: UM.Theme.getFont("default") color: UM.Theme.getColor("text_medium") + renderType: Text.NativeRendering } Label { text: catalog.i18nc("@label", "Author") + ":" - font: UM.Theme.getFont("very_small") + font: UM.Theme.getFont("default") color: UM.Theme.getColor("text_medium") + renderType: Text.NativeRendering } Label { text: catalog.i18nc("@label", "Downloads") + ":" - font: UM.Theme.getFont("very_small") + font: UM.Theme.getFont("default") color: UM.Theme.getColor("text_medium") + renderType: Text.NativeRendering } } Column @@ -119,8 +124,9 @@ Item Label { text: details === null ? "" : (details.version || catalog.i18nc("@label", "Unknown")) - font: UM.Theme.getFont("very_small") + font: UM.Theme.getFont("default") color: UM.Theme.getColor("text") + renderType: Text.NativeRendering } Label { @@ -133,8 +139,9 @@ Item var date = new Date(details.last_updated) return date.toLocaleString(UM.Preferences.getValue("general/language")) } - font: UM.Theme.getFont("very_small") + font: UM.Theme.getFont("default") color: UM.Theme.getColor("text") + renderType: Text.NativeRendering } Label { @@ -149,16 +156,18 @@ Item return "" + details.author_name + "" } } - font: UM.Theme.getFont("very_small") + font: UM.Theme.getFont("default") color: UM.Theme.getColor("text") linkColor: UM.Theme.getColor("text_link") onLinkActivated: Qt.openUrlExternally(link) + renderType: Text.NativeRendering } Label { text: details === null ? "" : (details.download_count || catalog.i18nc("@label", "Unknown")) - font: UM.Theme.getFont("very_small") + font: UM.Theme.getFont("default") color: UM.Theme.getColor("text") + renderType: Text.NativeRendering } } Rectangle diff --git a/plugins/Toolbox/resources/qml/ToolboxDetailTile.qml b/plugins/Toolbox/resources/qml/ToolboxDetailTile.qml index 1d701543ce..43f97baf3f 100644 --- a/plugins/Toolbox/resources/qml/ToolboxDetailTile.qml +++ b/plugins/Toolbox/resources/qml/ToolboxDetailTile.qml @@ -1,7 +1,7 @@ // Copyright (c) 2018 Ultimaker B.V. // Toolbox is released under the terms of the LGPLv3 or higher. -import QtQuick 2.7 +import QtQuick 2.10 import QtQuick.Controls 1.4 import QtQuick.Controls.Styles 1.4 import UM 1.1 as UM @@ -31,6 +31,7 @@ Item wrapMode: Text.WordWrap color: UM.Theme.getColor("text") font: UM.Theme.getFont("medium_bold") + renderType: Text.NativeRendering } Label { @@ -42,6 +43,7 @@ Item wrapMode: Text.WordWrap color: UM.Theme.getColor("text") font: UM.Theme.getFont("default") + renderType: Text.NativeRendering } } diff --git a/plugins/Toolbox/resources/qml/ToolboxDetailTileActions.qml b/plugins/Toolbox/resources/qml/ToolboxDetailTileActions.qml index cd1e4cdbda..7160dafa2d 100644 --- a/plugins/Toolbox/resources/qml/ToolboxDetailTileActions.qml +++ b/plugins/Toolbox/resources/qml/ToolboxDetailTileActions.qml @@ -1,40 +1,69 @@ // Copyright (c) 2018 Ultimaker B.V. // Toolbox is released under the terms of the LGPLv3 or higher. -import QtQuick 2.7 +import QtQuick 2.10 import QtQuick.Controls 1.4 import QtQuick.Controls.Styles 1.4 import UM 1.1 as UM +import Cura 1.1 as Cura Column { property bool installed: toolbox.isInstalled(model.id) property bool canUpdate: toolbox.canUpdate(model.id) + property bool loginRequired: model.login_required && !Cura.API.account.isLoggedIn + width: UM.Theme.getSize("toolbox_action_button").width spacing: UM.Theme.getSize("narrow_margin").height - ToolboxProgressButton + Item { - id: installButton - active: toolbox.isDownloading && toolbox.activePackage == model - complete: installed - readyAction: function() + width: installButton.width + height: installButton.height + ToolboxProgressButton { - toolbox.activePackage = model - toolbox.startDownload(model.download_url) + id: installButton + active: toolbox.isDownloading && toolbox.activePackage == model + onReadyAction: + { + toolbox.activePackage = model + toolbox.startDownload(model.download_url) + } + onActiveAction: toolbox.cancelDownload() + + // Don't allow installing while another download is running + enabled: installed || (!(toolbox.isDownloading && toolbox.activePackage != model) && !loginRequired) + opacity: enabled ? 1.0 : 0.5 + visible: !updateButton.visible && !installed// Don't show when the update button is visible } - activeAction: function() + + Cura.SecondaryButton { - toolbox.cancelDownload() + visible: installed + onClicked: toolbox.viewCategory = "installed" + text: catalog.i18nc("@action:button", "Installed") + fixedWidthMode: true + width: installButton.width + height: installButton.height } - completeAction: function() + } + + Label + { + wrapMode: Text.WordWrap + text: catalog.i18nc("@label:The string between and is the highlighted link", "Log in is required to install or update") + font: UM.Theme.getFont("default") + color: UM.Theme.getColor("text") + linkColor: UM.Theme.getColor("text_link") + visible: loginRequired + width: installButton.width + renderType: Text.NativeRendering + + MouseArea { - toolbox.viewCategory = "installed" + anchors.fill: parent + onClicked: Cura.API.account.login() } - // Don't allow installing while another download is running - enabled: installed || !(toolbox.isDownloading && toolbox.activePackage != model) - opacity: enabled ? 1.0 : 0.5 - visible: !updateButton.visible // Don't show when the update button is visible } ToolboxProgressButton @@ -44,20 +73,19 @@ Column readyLabel: catalog.i18nc("@action:button", "Update") activeLabel: catalog.i18nc("@action:button", "Updating") completeLabel: catalog.i18nc("@action:button", "Updated") - readyAction: function() + + onReadyAction: { toolbox.activePackage = model toolbox.update(model.id) } - activeAction: function() - { - toolbox.cancelDownload() - } + onActiveAction: toolbox.cancelDownload() // Don't allow installing while another download is running - enabled: !(toolbox.isDownloading && toolbox.activePackage != model) + enabled: !(toolbox.isDownloading && toolbox.activePackage != model) && !loginRequired opacity: enabled ? 1.0 : 0.5 visible: canUpdate } + Connections { target: toolbox diff --git a/plugins/Toolbox/resources/qml/ToolboxDownloadsGrid.qml b/plugins/Toolbox/resources/qml/ToolboxDownloadsGrid.qml index c586828969..85f0ff8be4 100644 --- a/plugins/Toolbox/resources/qml/ToolboxDownloadsGrid.qml +++ b/plugins/Toolbox/resources/qml/ToolboxDownloadsGrid.qml @@ -1,7 +1,7 @@ // Copyright (c) 2018 Ultimaker B.V. // Toolbox is released under the terms of the LGPLv3 or higher. -import QtQuick 2.7 +import QtQuick 2.10 import QtQuick.Controls 1.4 import QtQuick.Controls.Styles 1.4 import QtQuick.Layouts 1.3 @@ -23,8 +23,9 @@ Column width: parent.width color: UM.Theme.getColor("text_medium") font: UM.Theme.getFont("medium") + renderType: Text.NativeRendering } - GridLayout + Grid { id: grid width: parent.width - 2 * parent.padding @@ -34,10 +35,12 @@ Column Repeater { model: gridArea.model - delegate: ToolboxDownloadsGridTile + delegate: Loader { - Layout.preferredWidth: (grid.width - (grid.columns - 1) * grid.columnSpacing) / grid.columns - Layout.preferredHeight: UM.Theme.getSize("toolbox_thumbnail_small").height + asynchronous: true + width: Math.round((grid.width - (grid.columns - 1) * grid.columnSpacing) / grid.columns) + height: UM.Theme.getSize("toolbox_thumbnail_small").height + source: "ToolboxDownloadsGridTile.qml" } } } diff --git a/plugins/Toolbox/resources/qml/ToolboxDownloadsGridTile.qml b/plugins/Toolbox/resources/qml/ToolboxDownloadsGridTile.qml index 887140bbfa..357e9e9a72 100644 --- a/plugins/Toolbox/resources/qml/ToolboxDownloadsGridTile.qml +++ b/plugins/Toolbox/resources/qml/ToolboxDownloadsGridTile.qml @@ -1,7 +1,7 @@ // Copyright (c) 2018 Ultimaker B.V. // Toolbox is released under the terms of the LGPLv3 or higher. -import QtQuick 2.3 +import QtQuick 2.10 import QtQuick.Controls 1.4 import QtQuick.Controls.Styles 1.4 import QtQuick.Layouts 1.3 @@ -52,7 +52,6 @@ Item bottom: parent.bottom right: parent.right } - sourceSize.width: width sourceSize.height: height visible: installedPackages != 0 color: (installedPackages == packageCount) ? UM.Theme.getColor("primary") : UM.Theme.getColor("border") @@ -63,6 +62,8 @@ Item { width: parent.width - thumbnail.width - parent.spacing spacing: Math.floor(UM.Theme.getSize("narrow_margin").width) + anchors.top: parent.top + anchors.topMargin: UM.Theme.getSize("default_margin").height Label { id: name @@ -71,6 +72,7 @@ Item wrapMode: Text.WordWrap color: UM.Theme.getColor("text") font: UM.Theme.getFont("default_bold") + renderType: Text.NativeRendering } Label { @@ -81,7 +83,8 @@ Item width: parent.width wrapMode: Text.WordWrap color: UM.Theme.getColor("text_medium") - font: UM.Theme.getFont("very_small") + font: UM.Theme.getFont("default") + renderType: Text.NativeRendering } } } diff --git a/plugins/Toolbox/resources/qml/ToolboxDownloadsShowcase.qml b/plugins/Toolbox/resources/qml/ToolboxDownloadsShowcase.qml index 46f5debfdd..820b74554a 100644 --- a/plugins/Toolbox/resources/qml/ToolboxDownloadsShowcase.qml +++ b/plugins/Toolbox/resources/qml/ToolboxDownloadsShowcase.qml @@ -1,7 +1,7 @@ // Copyright (c) 2018 Ultimaker B.V. // Toolbox is released under the terms of the LGPLv3 or higher. -import QtQuick 2.7 +import QtQuick 2.10 import QtQuick.Controls 1.4 import QtQuick.Controls.Styles 1.4 import UM 1.1 as UM @@ -24,29 +24,33 @@ Rectangle width: parent.width color: UM.Theme.getColor("text_medium") font: UM.Theme.getFont("medium") + renderType: Text.NativeRendering } Grid { height: childrenRect.height spacing: UM.Theme.getSize("wide_margin").width columns: 3 - anchors - { - horizontalCenter: parent.horizontalCenter - } + anchors.horizontalCenter: parent.horizontalCenter + Repeater { - model: { - if ( toolbox.viewCategory == "plugin" ) + model: + { + if (toolbox.viewCategory == "plugin") { return toolbox.pluginsShowcaseModel } - if ( toolbox.viewCategory == "material" ) + if (toolbox.viewCategory == "material") { return toolbox.materialsShowcaseModel } } - delegate: ToolboxDownloadsShowcaseTile {} + delegate: Loader + { + asynchronous: true + source: "ToolboxDownloadsShowcaseTile.qml" + } } } } diff --git a/plugins/Toolbox/resources/qml/ToolboxDownloadsShowcaseTile.qml b/plugins/Toolbox/resources/qml/ToolboxDownloadsShowcaseTile.qml index 4fb70541d2..d1130cf63f 100644 --- a/plugins/Toolbox/resources/qml/ToolboxDownloadsShowcaseTile.qml +++ b/plugins/Toolbox/resources/qml/ToolboxDownloadsShowcaseTile.qml @@ -1,7 +1,7 @@ // Copyright (c) 2018 Ultimaker B.V. // Cura is released under the terms of the LGPLv3 or higher. -import QtQuick 2.7 +import QtQuick 2.10 import QtQuick.Controls 1.4 import QtQuick.Controls.Styles 1.4 import QtGraphicalEffects 1.0 @@ -48,8 +48,6 @@ Rectangle right: parent.right bottomMargin: UM.Theme.getSize("default_lining").width } - sourceSize.width: width - sourceSize.height: height visible: installedPackages != 0 color: (installedPackages == packageCount) ? UM.Theme.getColor("primary") : UM.Theme.getColor("border") source: "../images/installed_check.svg" @@ -81,6 +79,7 @@ Rectangle wrapMode: Text.WordWrap color: UM.Theme.getColor("button_text") font: UM.Theme.getFont("medium_bold") + renderType: Text.NativeRendering } } MouseArea diff --git a/plugins/Toolbox/resources/qml/ToolboxErrorPage.qml b/plugins/Toolbox/resources/qml/ToolboxErrorPage.qml index 600ae2b39f..e57e63dbb9 100644 --- a/plugins/Toolbox/resources/qml/ToolboxErrorPage.qml +++ b/plugins/Toolbox/resources/qml/ToolboxErrorPage.qml @@ -1,7 +1,7 @@ // Copyright (c) 2018 Ultimaker B.V. // Toolbox is released under the terms of the LGPLv3 or higher. -import QtQuick 2.7 +import QtQuick 2.10 import QtQuick.Controls 1.4 import QtQuick.Controls.Styles 1.4 @@ -18,5 +18,6 @@ Rectangle { centerIn: parent } + renderType: Text.NativeRendering } } diff --git a/plugins/Toolbox/resources/qml/ToolboxFooter.qml b/plugins/Toolbox/resources/qml/ToolboxFooter.qml index 5c2a6577ad..2d42ca7269 100644 --- a/plugins/Toolbox/resources/qml/ToolboxFooter.qml +++ b/plugins/Toolbox/resources/qml/ToolboxFooter.qml @@ -1,7 +1,7 @@ // Copyright (c) 2018 Ultimaker B.V. // Toolbox is released under the terms of the LGPLv3 or higher. -import QtQuick 2.2 +import QtQuick 2.10 import QtQuick.Controls 1.4 import QtQuick.Controls.Styles 1.4 import UM 1.1 as UM @@ -26,7 +26,7 @@ Item right: restartButton.right rightMargin: UM.Theme.getSize("default_margin").width } - + renderType: Text.NativeRendering } Button { @@ -56,6 +56,7 @@ Item text: control.text verticalAlignment: Text.AlignVCenter horizontalAlignment: Text.AlignHCenter + renderType: Text.NativeRendering } } } diff --git a/plugins/Toolbox/resources/qml/ToolboxInstalledPage.qml b/plugins/Toolbox/resources/qml/ToolboxInstalledPage.qml index e683f89823..e1d01db59a 100644 --- a/plugins/Toolbox/resources/qml/ToolboxInstalledPage.qml +++ b/plugins/Toolbox/resources/qml/ToolboxInstalledPage.qml @@ -1,7 +1,7 @@ // Copyright (c) 2018 Ultimaker B.V. // Toolbox is released under the terms of the LGPLv3 or higher. -import QtQuick 2.7 +import QtQuick 2.10 import QtQuick.Dialogs 1.1 import QtQuick.Window 2.2 import QtQuick.Controls 1.4 @@ -21,44 +21,40 @@ ScrollView Column { spacing: UM.Theme.getSize("default_margin").height + visible: toolbox.pluginsInstalledModel.items.length > 0 + height: childrenRect.height + 4 * UM.Theme.getSize("default_margin").height + anchors { right: parent.right left: parent.left - leftMargin: UM.Theme.getSize("wide_margin").width - topMargin: UM.Theme.getSize("wide_margin").height - bottomMargin: UM.Theme.getSize("wide_margin").height + margins: UM.Theme.getSize("default_margin").width top: parent.top } - height: childrenRect.height + 4 * UM.Theme.getSize("default_margin").height + Label { - visible: toolbox.pluginsInstalledModel.items.length > 0 - width: parent.width + width: page.width text: catalog.i18nc("@title:tab", "Plugins") color: UM.Theme.getColor("text_medium") font: UM.Theme.getFont("medium") + renderType: Text.NativeRendering } Rectangle { - visible: toolbox.pluginsInstalledModel.items.length > 0 color: "transparent" width: parent.width - height: childrenRect.height + 1 * UM.Theme.getSize("default_lining").width + height: childrenRect.height + UM.Theme.getSize("default_margin").width border.color: UM.Theme.getColor("lining") border.width: UM.Theme.getSize("default_lining").width Column { - height: childrenRect.height anchors { top: parent.top right: parent.right left: parent.left - leftMargin: UM.Theme.getSize("default_margin").width - rightMargin: UM.Theme.getSize("default_margin").width - topMargin: UM.Theme.getSize("default_lining").width - bottomMargin: UM.Theme.getSize("default_lining").width + margins: UM.Theme.getSize("default_margin").width } Repeater { @@ -70,32 +66,27 @@ ScrollView } Label { - visible: toolbox.materialsInstalledModel.items.length > 0 - width: page.width text: catalog.i18nc("@title:tab", "Materials") color: UM.Theme.getColor("text_medium") font: UM.Theme.getFont("medium") + renderType: Text.NativeRendering } + Rectangle { - visible: toolbox.materialsInstalledModel.items.length > 0 color: "transparent" width: parent.width - height: childrenRect.height + 1 * UM.Theme.getSize("default_lining").width + height: childrenRect.height + UM.Theme.getSize("default_margin").width border.color: UM.Theme.getColor("lining") border.width: UM.Theme.getSize("default_lining").width Column { - height: Math.max( UM.Theme.getSize("wide_margin").height, childrenRect.height) anchors { top: parent.top right: parent.right left: parent.left - leftMargin: UM.Theme.getSize("default_margin").width - rightMargin: UM.Theme.getSize("default_margin").width - topMargin: UM.Theme.getSize("default_lining").width - bottomMargin: UM.Theme.getSize("default_lining").width + margins: UM.Theme.getSize("default_margin").width } Repeater { diff --git a/plugins/Toolbox/resources/qml/ToolboxInstalledTile.qml b/plugins/Toolbox/resources/qml/ToolboxInstalledTile.qml index b16564fdd2..593e024309 100644 --- a/plugins/Toolbox/resources/qml/ToolboxInstalledTile.qml +++ b/plugins/Toolbox/resources/qml/ToolboxInstalledTile.qml @@ -1,7 +1,7 @@ // Copyright (c) 2018 Ultimaker B.V. // Toolbox is released under the terms of the LGPLv3 or higher. -import QtQuick 2.7 +import QtQuick 2.10 import QtQuick.Controls 1.4 import QtQuick.Controls.Styles 1.4 import UM 1.1 as UM @@ -51,6 +51,7 @@ Item wrapMode: Text.WordWrap font: UM.Theme.getFont("default_bold") color: pluginInfo.color + renderType: Text.NativeRendering } Label { @@ -60,6 +61,7 @@ Item width: parent.width wrapMode: Text.WordWrap color: pluginInfo.color + renderType: Text.NativeRendering } } Column @@ -88,6 +90,7 @@ Item onLinkActivated: Qt.openUrlExternally("mailto:" + model.author_email + "?Subject=Cura: " + model.name + " Plugin") color: model.enabled ? UM.Theme.getColor("text") : UM.Theme.getColor("lining") linkColor: UM.Theme.getColor("text_link") + renderType: Text.NativeRendering } Label @@ -98,6 +101,7 @@ Item color: UM.Theme.getColor("text") verticalAlignment: Text.AlignVCenter horizontalAlignment: Text.AlignLeft + renderType: Text.NativeRendering } } ToolboxInstalledTileActions diff --git a/plugins/Toolbox/resources/qml/ToolboxInstalledTileActions.qml b/plugins/Toolbox/resources/qml/ToolboxInstalledTileActions.qml index 8fd88b1cfd..61af84fbe5 100644 --- a/plugins/Toolbox/resources/qml/ToolboxInstalledTileActions.qml +++ b/plugins/Toolbox/resources/qml/ToolboxInstalledTileActions.qml @@ -1,15 +1,18 @@ // Copyright (c) 2018 Ultimaker B.V. // Toolbox is released under the terms of the LGPLv3 or higher. -import QtQuick 2.7 +import QtQuick 2.10 import QtQuick.Controls 1.4 import QtQuick.Controls.Styles 1.4 import UM 1.1 as UM +import Cura 1.1 as Cura + Column { property bool canUpdate: false property bool canDowngrade: false + property bool loginRequired: model.login_required && !Cura.API.account.isLoggedIn width: UM.Theme.getSize("toolbox_action_button").width spacing: UM.Theme.getSize("narrow_margin").height @@ -21,6 +24,7 @@ Column font: UM.Theme.getFont("default") wrapMode: Text.WordWrap width: parent.width + renderType: Text.NativeRendering } ToolboxProgressButton @@ -30,59 +34,49 @@ Column readyLabel: catalog.i18nc("@action:button", "Update") activeLabel: catalog.i18nc("@action:button", "Updating") completeLabel: catalog.i18nc("@action:button", "Updated") - readyAction: function() + onReadyAction: { toolbox.activePackage = model toolbox.update(model.id) } - activeAction: function() - { - toolbox.cancelDownload() - } + onActiveAction: toolbox.cancelDownload() + // Don't allow installing while another download is running - enabled: !(toolbox.isDownloading && toolbox.activePackage != model) + enabled: !(toolbox.isDownloading && toolbox.activePackage != model) && !loginRequired opacity: enabled ? 1.0 : 0.5 visible: canUpdate } - Button + Label + { + wrapMode: Text.WordWrap + text: catalog.i18nc("@label:The string between and is the highlighted link", "Log in is required to update") + font: UM.Theme.getFont("default") + color: UM.Theme.getColor("text") + linkColor: UM.Theme.getColor("text_link") + visible: loginRequired + width: updateButton.width + renderType: Text.NativeRendering + + MouseArea + { + anchors.fill: parent + onClicked: Cura.API.account.login() + } + } + + Cura.SecondaryButton { id: removeButton text: canDowngrade ? catalog.i18nc("@action:button", "Downgrade") : catalog.i18nc("@action:button", "Uninstall") visible: !model.is_bundled && model.is_installed enabled: !toolbox.isDownloading - style: ButtonStyle - { - background: Rectangle - { - implicitWidth: UM.Theme.getSize("toolbox_action_button").width - implicitHeight: UM.Theme.getSize("toolbox_action_button").height - color: "transparent" - border - { - width: UM.Theme.getSize("default_lining").width - color: - { - if (control.hovered) - { - return UM.Theme.getColor("primary_hover") - } - else - { - return UM.Theme.getColor("lining") - } - } - } - } - label: Label - { - text: control.text - color: UM.Theme.getColor("text") - verticalAlignment: Text.AlignVCenter - horizontalAlignment: Text.AlignHCenter - font: UM.Theme.getFont("default") - } - } + + width: UM.Theme.getSize("toolbox_action_button").width + height: UM.Theme.getSize("toolbox_action_button").height + + fixedWidthMode: true + onClicked: toolbox.checkPackageUsageAndUninstall(model.id) Connections { diff --git a/plugins/Toolbox/resources/qml/ToolboxLicenseDialog.qml b/plugins/Toolbox/resources/qml/ToolboxLicenseDialog.qml index b8baf7bc83..40b22c268d 100644 --- a/plugins/Toolbox/resources/qml/ToolboxLicenseDialog.qml +++ b/plugins/Toolbox/resources/qml/ToolboxLicenseDialog.qml @@ -1,7 +1,7 @@ // Copyright (c) 2018 Ultimaker B.V. // Toolbox is released under the terms of the LGPLv3 or higher. -import QtQuick 2.2 +import QtQuick 2.10 import QtQuick.Dialogs 1.1 import QtQuick.Window 2.2 import QtQuick.Controls 1.4 @@ -32,6 +32,7 @@ UM.Dialog anchors.right: parent.right text: licenseDialog.pluginName + catalog.i18nc("@label", "This plugin contains a license.\nYou need to accept this license to install this plugin.\nDo you agree with the terms below?") wrapMode: Text.Wrap + renderType: Text.NativeRendering } TextArea { diff --git a/plugins/Toolbox/resources/qml/ToolboxLoadingPage.qml b/plugins/Toolbox/resources/qml/ToolboxLoadingPage.qml index 1ba271dcab..025239bd43 100644 --- a/plugins/Toolbox/resources/qml/ToolboxLoadingPage.qml +++ b/plugins/Toolbox/resources/qml/ToolboxLoadingPage.qml @@ -1,7 +1,7 @@ // Copyright (c) 2018 Ultimaker B.V. // Toolbox is released under the terms of the LGPLv3 or higher. -import QtQuick 2.7 +import QtQuick 2.10 import QtQuick.Controls 1.4 import QtQuick.Controls.Styles 1.4 @@ -18,5 +18,6 @@ Rectangle { centerIn: parent } + renderType: Text.NativeRendering } } diff --git a/plugins/Toolbox/resources/qml/ToolboxProgressButton.qml b/plugins/Toolbox/resources/qml/ToolboxProgressButton.qml index 2744e40ec9..933e3a5900 100644 --- a/plugins/Toolbox/resources/qml/ToolboxProgressButton.qml +++ b/plugins/Toolbox/resources/qml/ToolboxProgressButton.qml @@ -5,6 +5,7 @@ import QtQuick 2.2 import QtQuick.Controls 1.4 import QtQuick.Controls.Styles 1.4 import UM 1.1 as UM +import Cura 1.0 as Cura Item @@ -18,16 +19,19 @@ Item property var activeLabel: catalog.i18nc("@action:button", "Cancel") property var completeLabel: catalog.i18nc("@action:button", "Installed") - property var readyAction: null // Action when button is ready and clicked (likely install) - property var activeAction: null // Action when button is active and clicked (likely cancel) - property var completeAction: null // Action when button is complete and clicked (likely go to installed) + signal readyAction() // Action when button is ready and clicked (likely install) + signal activeAction() // Action when button is active and clicked (likely cancel) + signal completeAction() // Action when button is complete and clicked (likely go to installed) width: UM.Theme.getSize("toolbox_action_button").width height: UM.Theme.getSize("toolbox_action_button").height - Button + Cura.PrimaryButton { id: button + width: UM.Theme.getSize("toolbox_action_button").width + height: UM.Theme.getSize("toolbox_action_button").height + fixedWidthMode: true text: { if (complete) @@ -47,101 +51,15 @@ Item { if (complete) { - return completeAction() + completeAction() } else if (active) { - return activeAction() + activeAction() } else { - return readyAction() - } - } - style: ButtonStyle - { - background: Rectangle - { - implicitWidth: UM.Theme.getSize("toolbox_action_button").width - implicitHeight: UM.Theme.getSize("toolbox_action_button").height - color: - { - if (base.complete) - { - return "transparent" - } - else - { - if (control.hovered) - { - return UM.Theme.getColor("primary_hover") - } - else - { - return UM.Theme.getColor("primary") - } - } - } - border - { - width: - { - if (base.complete) - { - UM.Theme.getSize("default_lining").width - } - else - { - return 0 - } - } - color: - { - if (control.hovered) - { - return UM.Theme.getColor("primary_hover") - } - else - { - return UM.Theme.getColor("lining") - } - } - } - } - label: Label - { - text: control.text - color: - { - if (base.complete) - { - return UM.Theme.getColor("text") - } - else - { - if (control.hovered) - { - return UM.Theme.getColor("button_text_hover") - } - else - { - return UM.Theme.getColor("button_text") - } - } - } - verticalAlignment: Text.AlignVCenter - horizontalAlignment: Text.AlignHCenter - font: - { - if (base.complete) - { - return UM.Theme.getFont("default") - } - else - { - return UM.Theme.getFont("default_bold") - } - } + readyAction() } } } diff --git a/plugins/Toolbox/resources/qml/ToolboxTabButton.qml b/plugins/Toolbox/resources/qml/ToolboxTabButton.qml index 22fb6d73ca..5e1aeaa636 100644 --- a/plugins/Toolbox/resources/qml/ToolboxTabButton.qml +++ b/plugins/Toolbox/resources/qml/ToolboxTabButton.qml @@ -1,51 +1,51 @@ // Copyright (c) 2018 Ultimaker B.V. // Toolbox is released under the terms of the LGPLv3 or higher. -import QtQuick 2.2 -import QtQuick.Controls 1.4 -import QtQuick.Controls.Styles 1.4 +import QtQuick 2.10 +import QtQuick.Controls 2.3 import UM 1.1 as UM Button { + id: control property bool active: false - style: ButtonStyle + hoverEnabled: true + + background: Item { - background: Rectangle + implicitWidth: UM.Theme.getSize("toolbox_header_tab").width + implicitHeight: UM.Theme.getSize("toolbox_header_tab").height + Rectangle { - color: "transparent" - implicitWidth: UM.Theme.getSize("toolbox_header_tab").width - implicitHeight: UM.Theme.getSize("toolbox_header_tab").height - Rectangle - { - visible: control.active - color: UM.Theme.getColor("sidebar_header_highlight_hover") - anchors.bottom: parent.bottom - width: parent.width - height: UM.Theme.getSize("sidebar_header_highlight").height - } - } - label: Label - { - text: control.text - color: - { - if(control.hovered) - { - return UM.Theme.getColor("topbar_button_text_hovered"); - } - if(control.active) - { - return UM.Theme.getColor("topbar_button_text_active"); - } - else - { - return UM.Theme.getColor("topbar_button_text_inactive"); - } - } - font: control.enabled ? (control.active ? UM.Theme.getFont("medium_bold") : UM.Theme.getFont("medium")) : UM.Theme.getFont("default_italic") - verticalAlignment: Text.AlignVCenter - horizontalAlignment: Text.AlignHCenter + visible: control.active + color: UM.Theme.getColor("primary") + anchors.bottom: parent.bottom + width: parent.width + height: UM.Theme.getSize("toolbox_header_highlight").height } } -} + contentItem: Label + { + id: label + text: control.text + color: + { + if(control.hovered) + { + return UM.Theme.getColor("toolbox_header_button_text_hovered"); + } + if(control.active) + { + return UM.Theme.getColor("toolbox_header_button_text_active"); + } + else + { + return UM.Theme.getColor("toolbox_header_button_text_inactive"); + } + } + font: control.enabled ? (control.active ? UM.Theme.getFont("medium_bold") : UM.Theme.getFont("medium")) : UM.Theme.getFont("default_italic") + verticalAlignment: Text.AlignVCenter + horizontalAlignment: Text.AlignHCenter + renderType: Text.NativeRendering + } +} \ No newline at end of file diff --git a/plugins/Toolbox/src/AuthorsModel.py b/plugins/Toolbox/src/AuthorsModel.py index bea3893504..877f8256ee 100644 --- a/plugins/Toolbox/src/AuthorsModel.py +++ b/plugins/Toolbox/src/AuthorsModel.py @@ -2,18 +2,19 @@ # Cura is released under the terms of the LGPLv3 or higher. import re -from typing import Dict +from typing import Dict, List, Optional, Union from PyQt5.QtCore import Qt, pyqtProperty, pyqtSignal from UM.Qt.ListModel import ListModel + ## Model that holds cura packages. By setting the filter property the instances held by this model can be changed. class AuthorsModel(ListModel): - def __init__(self, parent = None): + def __init__(self, parent = None) -> None: super().__init__(parent) - self._metadata = None + self._metadata = None # type: Optional[List[Dict[str, Union[str, List[str], int]]]] self.addRoleName(Qt.UserRole + 1, "id") self.addRoleName(Qt.UserRole + 2, "name") @@ -25,39 +26,40 @@ class AuthorsModel(ListModel): self.addRoleName(Qt.UserRole + 8, "description") # List of filters for queries. The result is the union of the each list of results. - self._filter = {} # type: Dict[str,str] + self._filter = {} # type: Dict[str, str] - def setMetadata(self, data): - self._metadata = data - self._update() + def setMetadata(self, data: List[Dict[str, Union[str, List[str], int]]]): + if self._metadata != data: + self._metadata = data + self._update() - def _update(self): - items = [] + def _update(self) -> None: + items = [] # type: List[Dict[str, Union[str, List[str], int, None]]] if not self._metadata: - self.setItems([]) + self.setItems(items) return for author in self._metadata: items.append({ - "id": author["author_id"], - "name": author["display_name"], - "email": author["email"] if "email" in author else None, - "website": author["website"], - "package_count": author["package_count"] if "package_count" in author else 0, - "package_types": author["package_types"] if "package_types" in author else [], - "icon_url": author["icon_url"] if "icon_url" in author else None, - "description": "Material and quality profiles from {author_name}".format(author_name = author["display_name"]) + "id": author.get("author_id"), + "name": author.get("display_name"), + "email": author.get("email"), + "website": author.get("website"), + "package_count": author.get("package_count", 0), + "package_types": author.get("package_types", []), + "icon_url": author.get("icon_url"), + "description": "Material and quality profiles from {author_name}".format(author_name = author.get("display_name", "")) }) # Filter on all the key-word arguments. for key, value in self._filter.items(): if key is "package_types": - key_filter = lambda item, value = value: value in item["package_types"] + key_filter = lambda item, value = value: value in item["package_types"] # type: ignore elif "*" in value: - key_filter = lambda item, key = key, value = value: self._matchRegExp(item, key, value) + key_filter = lambda item, key = key, value = value: self._matchRegExp(item, key, value) # type: ignore else: - key_filter = lambda item, key = key, value = value: self._matchString(item, key, value) - items = filter(key_filter, items) + key_filter = lambda item, key = key, value = value: self._matchString(item, key, value) # type: ignore + items = filter(key_filter, items) # type: ignore # Execute all filters. filtered_items = list(items) diff --git a/plugins/Toolbox/src/PackagesModel.py b/plugins/Toolbox/src/PackagesModel.py index a31facf75a..bcc02955a2 100644 --- a/plugins/Toolbox/src/PackagesModel.py +++ b/plugins/Toolbox/src/PackagesModel.py @@ -33,20 +33,22 @@ class PackagesModel(ListModel): self.addRoleName(Qt.UserRole + 12, "last_updated") self.addRoleName(Qt.UserRole + 13, "is_bundled") self.addRoleName(Qt.UserRole + 14, "is_active") - self.addRoleName(Qt.UserRole + 15, "is_installed") # Scheduled pkgs are included in the model but should not be marked as actually installed + self.addRoleName(Qt.UserRole + 15, "is_installed") # Scheduled pkgs are included in the model but should not be marked as actually installed self.addRoleName(Qt.UserRole + 16, "has_configs") self.addRoleName(Qt.UserRole + 17, "supported_configs") self.addRoleName(Qt.UserRole + 18, "download_count") self.addRoleName(Qt.UserRole + 19, "tags") self.addRoleName(Qt.UserRole + 20, "links") self.addRoleName(Qt.UserRole + 21, "website") + self.addRoleName(Qt.UserRole + 22, "login_required") # List of filters for queries. The result is the union of the each list of results. self._filter = {} # type: Dict[str, str] def setMetadata(self, data): - self._metadata = data - self._update() + if self._metadata != data: + self._metadata = data + self._update() def _update(self): items = [] @@ -99,6 +101,7 @@ class PackagesModel(ListModel): "tags": package["tags"] if "tags" in package else [], "links": links_dict, "website": package["website"] if "website" in package else None, + "login_required": "login-required" in package.get("tags", []) }) # Filter on all the key-word arguments. diff --git a/plugins/Toolbox/src/Toolbox.py b/plugins/Toolbox/src/Toolbox.py index 667b28c018..b3c0277658 100644 --- a/plugins/Toolbox/src/Toolbox.py +++ b/plugins/Toolbox/src/Toolbox.py @@ -32,8 +32,8 @@ i18n_catalog = i18nCatalog("cura") ## The Toolbox class is responsible of communicating with the server through the API class Toolbox(QObject, Extension): - DEFAULT_CLOUD_API_ROOT = "https://api.ultimaker.com" #type: str - DEFAULT_CLOUD_API_VERSION = 1 #type: int + DEFAULT_CLOUD_API_ROOT = "https://api.ultimaker.com" # type: str + DEFAULT_CLOUD_API_VERSION = 1 # type: int def __init__(self, application: CuraApplication) -> None: super().__init__() @@ -67,31 +67,26 @@ class Toolbox(QObject, Extension): self._old_plugin_ids = set() # type: Set[str] self._old_plugin_metadata = dict() # type: Dict[str, Dict[str, Any]] - # Data: - self._metadata = { + # The responses as given by the server parsed to a list. + self._server_response_data = { "authors": [], - "packages": [], - "plugins_showcase": [], - "plugins_available": [], - "plugins_installed": [], - "materials_showcase": [], - "materials_available": [], - "materials_installed": [], - "materials_generic": [] + "packages": [] } # type: Dict[str, List[Any]] # Models: self._models = { "authors": AuthorsModel(self), "packages": PackagesModel(self), - "plugins_showcase": PackagesModel(self), - "plugins_available": PackagesModel(self), - "plugins_installed": PackagesModel(self), - "materials_showcase": AuthorsModel(self), - "materials_available": AuthorsModel(self), - "materials_installed": PackagesModel(self), - "materials_generic": PackagesModel(self) - } # type: Dict[str, ListModel] + } # type: Dict[str, Union[AuthorsModel, PackagesModel]] + + self._plugins_showcase_model = PackagesModel(self) + self._plugins_available_model = PackagesModel(self) + self._plugins_installed_model = PackagesModel(self) + + self._materials_showcase_model = AuthorsModel(self) + self._materials_available_model = AuthorsModel(self) + self._materials_installed_model = PackagesModel(self) + self._materials_generic_model = PackagesModel(self) # These properties are for keeping track of the UI state: # ---------------------------------------------------------------------- @@ -176,12 +171,7 @@ class Toolbox(QObject, Extension): ) self._request_urls = { "authors": QUrl("{base_url}/authors".format(base_url = self._api_url)), - "packages": QUrl("{base_url}/packages".format(base_url = self._api_url)), - "plugins_showcase": QUrl("{base_url}/showcase".format(base_url = self._api_url)), - "plugins_available": QUrl("{base_url}/packages?package_type=plugin".format(base_url = self._api_url)), - "materials_showcase": QUrl("{base_url}/showcase".format(base_url = self._api_url)), - "materials_available": QUrl("{base_url}/packages?package_type=material".format(base_url = self._api_url)), - "materials_generic": QUrl("{base_url}/packages?package_type=material&tags=generic".format(base_url = self._api_url)) + "packages": QUrl("{base_url}/packages".format(base_url = self._api_url)) } @pyqtSlot() @@ -199,12 +189,6 @@ class Toolbox(QObject, Extension): # Make remote requests: self._makeRequestByType("packages") self._makeRequestByType("authors") - # TODO: Uncomment in the future when the tag-filtered api calls work in the cloud server - # self._makeRequestByType("plugins_showcase") - # self._makeRequestByType("plugins_available") - # self._makeRequestByType("materials_showcase") - # self._makeRequestByType("materials_available") - # self._makeRequestByType("materials_generic") # Gather installed packages: self._updateInstalledModels() @@ -249,7 +233,7 @@ class Toolbox(QObject, Extension): "description": plugin_data["plugin"]["description"] } return formatted - except: + except KeyError: Logger.log("w", "Unable to convert plugin meta data %s", str(plugin_data)) return None @@ -287,13 +271,10 @@ class Toolbox(QObject, Extension): if plugin_id not in all_plugin_package_ids) self._old_plugin_metadata = {k: v for k, v in self._old_plugin_metadata.items() if k in self._old_plugin_ids} - self._metadata["plugins_installed"] = all_packages["plugin"] + list(self._old_plugin_metadata.values()) - self._models["plugins_installed"].setMetadata(self._metadata["plugins_installed"]) + self._plugins_installed_model.setMetadata(all_packages["plugin"] + list(self._old_plugin_metadata.values())) self.metadataChanged.emit() if "material" in all_packages: - self._metadata["materials_installed"] = all_packages["material"] - # TODO: ADD MATERIALS HERE ONCE MATERIALS PORTION OF TOOLBOX IS LIVE - self._models["materials_installed"].setMetadata(self._metadata["materials_installed"]) + self._materials_installed_model.setMetadata(all_packages["material"]) self.metadataChanged.emit() @pyqtSlot(str) @@ -447,7 +428,7 @@ class Toolbox(QObject, Extension): def getRemotePackage(self, package_id: str) -> Optional[Dict]: # TODO: make the lookup in a dict, not a loop. canUpdate is called for every item. remote_package = None - for package in self._metadata["packages"]: + for package in self._server_response_data["packages"]: if package["package_id"] == package_id: remote_package = package break @@ -459,11 +440,8 @@ class Toolbox(QObject, Extension): def canUpdate(self, package_id: str) -> bool: local_package = self._package_manager.getInstalledPackageInfo(package_id) if local_package is None: - Logger.log("i", "Could not find package [%s] as installed in the package manager, fall back to check the old plugins", - package_id) local_package = self.getOldPluginPackageMetadata(package_id) if local_package is None: - Logger.log("i", "Could not find package [%s] in the old plugins", package_id) return False remote_package = self.getRemotePackage(package_id) @@ -513,8 +491,8 @@ class Toolbox(QObject, Extension): @pyqtSlot(str, result = int) def getNumberOfInstalledPackagesByAuthor(self, author_id: str) -> int: count = 0 - for package in self._metadata["materials_installed"]: - if package["author"]["author_id"] == author_id: + for package in self._materials_installed_model.items: + if package["author_id"] == author_id: count += 1 return count @@ -522,7 +500,7 @@ class Toolbox(QObject, Extension): @pyqtSlot(str, result = int) def getTotalNumberOfMaterialPackagesByAuthor(self, author_id: str) -> int: count = 0 - for package in self._metadata["packages"]: + for package in self._server_response_data["packages"]: if package["package_type"] == "material": if package["author"]["author_id"] == author_id: count += 1 @@ -536,34 +514,30 @@ class Toolbox(QObject, Extension): # Check for plugins that were installed with the old plugin browser def isOldPlugin(self, plugin_id: str) -> bool: - if plugin_id in self._old_plugin_ids: - return True - return False + return plugin_id in self._old_plugin_ids def getOldPluginPackageMetadata(self, plugin_id: str) -> Optional[Dict[str, Any]]: return self._old_plugin_metadata.get(plugin_id) - def loadingComplete(self) -> bool: + def isLoadingComplete(self) -> bool: populated = 0 - for list in self._metadata.items(): - if len(list) > 0: + for metadata_list in self._server_response_data.items(): + if metadata_list: populated += 1 - if populated == len(self._metadata.items()): - return True - return False + return populated == len(self._server_response_data.items()) # Make API Calls # -------------------------------------------------------------------------- - def _makeRequestByType(self, type: str) -> None: - Logger.log("i", "Marketplace: Requesting %s metadata from server.", type) - request = QNetworkRequest(self._request_urls[type]) + def _makeRequestByType(self, request_type: str) -> None: + Logger.log("i", "Requesting %s metadata from server.", request_type) + request = QNetworkRequest(self._request_urls[request_type]) request.setRawHeader(*self._request_header) if self._network_manager: self._network_manager.get(request) @pyqtSlot(str) def startDownload(self, url: str) -> None: - Logger.log("i", "Marketplace: Attempting to download & install package from %s.", url) + Logger.log("i", "Attempting to download & install package from %s.", url) url = QUrl(url) self._download_request = QNetworkRequest(url) if hasattr(QNetworkRequest, "FollowRedirectsAttribute"): @@ -580,15 +554,15 @@ class Toolbox(QObject, Extension): @pyqtSlot() def cancelDownload(self) -> None: - Logger.log("i", "Marketplace: User cancelled the download of a package.") + Logger.log("i", "User cancelled the download of a package.") self.resetDownload() def resetDownload(self) -> None: if self._download_reply: try: self._download_reply.downloadProgress.disconnect(self._onDownloadProgress) - except TypeError: #Raised when the method is not connected to the signal yet. - pass #Don't need to disconnect. + except TypeError: # Raised when the method is not connected to the signal yet. + pass # Don't need to disconnect. self._download_reply.abort() self._download_reply = None self._download_request = None @@ -614,22 +588,8 @@ class Toolbox(QObject, Extension): self.resetDownload() return - # HACK: These request are not handled independently at this moment, but together from the "packages" call - do_not_handle = [ - "materials_available", - "materials_showcase", - "materials_generic", - "plugins_available", - "plugins_showcase", - ] - if reply.operation() == QNetworkAccessManager.GetOperation: - for type, url in self._request_urls.items(): - - # HACK: Do nothing because we'll handle these from the "packages" call - if type in do_not_handle: - continue - + for response_type, url in self._request_urls.items(): if reply.url() == url: if reply.attribute(QNetworkRequest.HttpStatusCodeAttribute) == 200: try: @@ -642,38 +602,32 @@ class Toolbox(QObject, Extension): return # Create model and apply metadata: - if not self._models[type]: - Logger.log("e", "Could not find the %s model.", type) + if not self._models[response_type]: + Logger.log("e", "Could not find the %s model.", response_type) break - self._metadata[type] = json_data["data"] - self._models[type].setMetadata(self._metadata[type]) + self._server_response_data[response_type] = json_data["data"] + self._models[response_type].setMetadata(self._server_response_data[response_type]) - # Do some auto filtering - # TODO: Make multiple API calls in the future to handle this - if type is "packages": - self._models[type].setFilter({"type": "plugin"}) - self.buildMaterialsModels() - self.buildPluginsModels() - if type is "authors": - self._models[type].setFilter({"package_types": "material"}) - if type is "materials_generic": - self._models[type].setFilter({"tags": "generic"}) + if response_type is "packages": + self._models[response_type].setFilter({"type": "plugin"}) + self.reBuildMaterialsModels() + self.reBuildPluginsModels() + elif response_type is "authors": + self._models[response_type].setFilter({"package_types": "material"}) + self._models[response_type].setFilter({"tags": "generic"}) self.metadataChanged.emit() - if self.loadingComplete() is True: + if self.isLoadingComplete(): self.setViewPage("overview") - return except json.decoder.JSONDecodeError: - Logger.log("w", "Marketplace: Received invalid JSON for %s.", type) + Logger.log("w", "Received invalid JSON for %s.", response_type) break else: self.setViewPage("errored") self.resetDownload() - return - else: # Ignore any operation that is not a get operation pass @@ -684,7 +638,13 @@ class Toolbox(QObject, Extension): self.setDownloadProgress(new_progress) if bytes_sent == bytes_total: self.setIsDownloading(False) - cast(QNetworkReply, self._download_reply).downloadProgress.disconnect(self._onDownloadProgress) + self._download_reply = cast(QNetworkReply, self._download_reply) + self._download_reply.downloadProgress.disconnect(self._onDownloadProgress) + + # Check if the download was sucessfull + if self._download_reply.attribute(QNetworkRequest.HttpStatusCodeAttribute) != 200: + Logger.log("w", "Failed to download package. The following error was returned: %s", json.loads(bytes(self._download_reply.readAll()).decode("utf-8"))) + return # Must not delete the temporary file on Windows self._temp_plugin_file = tempfile.NamedTemporaryFile(mode = "w+b", suffix = ".curapackage", delete = False) file_path = self._temp_plugin_file.name @@ -694,10 +654,10 @@ class Toolbox(QObject, Extension): self._onDownloadComplete(file_path) def _onDownloadComplete(self, file_path: str) -> None: - Logger.log("i", "Marketplace: Download complete.") + Logger.log("i", "Download complete.") package_info = self._package_manager.getPackageInfo(file_path) if not package_info: - Logger.log("w", "Marketplace: Package file [%s] was not a valid CuraPackage.", file_path) + Logger.log("w", "Package file [%s] was not a valid CuraPackage.", file_path) return license_content = self._package_manager.getPackageLicense(file_path) @@ -706,7 +666,6 @@ class Toolbox(QObject, Extension): return self.install(file_path) - return # Getter & Setters for Properties: # -------------------------------------------------------------------------- @@ -729,8 +688,9 @@ class Toolbox(QObject, Extension): return self._is_downloading def setActivePackage(self, package: Dict[str, Any]) -> None: - self._active_package = package - self.activePackageChanged.emit() + if self._active_package != package: + self._active_package = package + self.activePackageChanged.emit() ## The active package is the package that is currently being downloaded @pyqtProperty(QObject, fset = setActivePackage, notify = activePackageChanged) @@ -738,16 +698,18 @@ class Toolbox(QObject, Extension): return self._active_package def setViewCategory(self, category: str = "plugin") -> None: - self._view_category = category - self.viewChanged.emit() + if self._view_category != category: + self._view_category = category + self.viewChanged.emit() @pyqtProperty(str, fset = setViewCategory, notify = viewChanged) def viewCategory(self) -> str: return self._view_category def setViewPage(self, page: str = "overview") -> None: - self._view_page = page - self.viewChanged.emit() + if self._view_page != page: + self._view_page = page + self.viewChanged.emit() @pyqtProperty(str, fset = setViewPage, notify = viewChanged) def viewPage(self) -> str: @@ -755,48 +717,48 @@ class Toolbox(QObject, Extension): # Exposed Models: # -------------------------------------------------------------------------- - @pyqtProperty(QObject, notify = metadataChanged) + @pyqtProperty(QObject, constant=True) def authorsModel(self) -> AuthorsModel: return cast(AuthorsModel, self._models["authors"]) - @pyqtProperty(QObject, notify = metadataChanged) + @pyqtProperty(QObject, constant=True) def packagesModel(self) -> PackagesModel: return cast(PackagesModel, self._models["packages"]) - @pyqtProperty(QObject, notify = metadataChanged) + @pyqtProperty(QObject, constant=True) def pluginsShowcaseModel(self) -> PackagesModel: - return cast(PackagesModel, self._models["plugins_showcase"]) + return self._plugins_showcase_model - @pyqtProperty(QObject, notify = metadataChanged) + @pyqtProperty(QObject, constant=True) def pluginsAvailableModel(self) -> PackagesModel: - return cast(PackagesModel, self._models["plugins_available"]) + return self._plugins_available_model - @pyqtProperty(QObject, notify = metadataChanged) + @pyqtProperty(QObject, constant=True) def pluginsInstalledModel(self) -> PackagesModel: - return cast(PackagesModel, self._models["plugins_installed"]) + return self._plugins_installed_model - @pyqtProperty(QObject, notify = metadataChanged) + @pyqtProperty(QObject, constant=True) def materialsShowcaseModel(self) -> AuthorsModel: - return cast(AuthorsModel, self._models["materials_showcase"]) + return self._materials_showcase_model - @pyqtProperty(QObject, notify = metadataChanged) + @pyqtProperty(QObject, constant=True) def materialsAvailableModel(self) -> AuthorsModel: - return cast(AuthorsModel, self._models["materials_available"]) + return self._materials_available_model - @pyqtProperty(QObject, notify = metadataChanged) + @pyqtProperty(QObject, constant=True) def materialsInstalledModel(self) -> PackagesModel: - return cast(PackagesModel, self._models["materials_installed"]) + return self._materials_installed_model - @pyqtProperty(QObject, notify=metadataChanged) + @pyqtProperty(QObject, constant=True) def materialsGenericModel(self) -> PackagesModel: - return cast(PackagesModel, self._models["materials_generic"]) + return self._materials_generic_model # Filter Models: # -------------------------------------------------------------------------- @pyqtSlot(str, str, str) def filterModelByProp(self, model_type: str, filter_type: str, parameter: str) -> None: if not self._models[model_type]: - Logger.log("w", "Marketplace: Couldn't filter %s model because it doesn't exist.", model_type) + Logger.log("w", "Couldn't filter %s model because it doesn't exist.", model_type) return self._models[model_type].setFilter({filter_type: parameter}) self.filterChanged.emit() @@ -804,7 +766,7 @@ class Toolbox(QObject, Extension): @pyqtSlot(str, "QVariantMap") def setFilters(self, model_type: str, filter_dict: dict) -> None: if not self._models[model_type]: - Logger.log("w", "Marketplace: Couldn't filter %s model because it doesn't exist.", model_type) + Logger.log("w", "Couldn't filter %s model because it doesn't exist.", model_type) return self._models[model_type].setFilter(filter_dict) self.filterChanged.emit() @@ -812,21 +774,21 @@ class Toolbox(QObject, Extension): @pyqtSlot(str) def removeFilters(self, model_type: str) -> None: if not self._models[model_type]: - Logger.log("w", "Marketplace: Couldn't remove filters on %s model because it doesn't exist.", model_type) + Logger.log("w", "Couldn't remove filters on %s model because it doesn't exist.", model_type) return self._models[model_type].setFilter({}) self.filterChanged.emit() # HACK(S): # -------------------------------------------------------------------------- - def buildMaterialsModels(self) -> None: - self._metadata["materials_showcase"] = [] - self._metadata["materials_available"] = [] - self._metadata["materials_generic"] = [] + def reBuildMaterialsModels(self) -> None: + materials_showcase_metadata = [] + materials_available_metadata = [] + materials_generic_metadata = [] - processed_authors = [] # type: List[str] + processed_authors = [] # type: List[str] - for item in self._metadata["packages"]: + for item in self._server_response_data["packages"]: if item["package_type"] == "material": author = item["author"] @@ -835,30 +797,29 @@ class Toolbox(QObject, Extension): # Generic materials to be in the same section if "generic" in item["tags"]: - self._metadata["materials_generic"].append(item) + materials_generic_metadata.append(item) else: if "showcase" in item["tags"]: - self._metadata["materials_showcase"].append(author) + materials_showcase_metadata.append(author) else: - self._metadata["materials_available"].append(author) + materials_available_metadata.append(author) processed_authors.append(author["author_id"]) - self._models["materials_showcase"].setMetadata(self._metadata["materials_showcase"]) - self._models["materials_available"].setMetadata(self._metadata["materials_available"]) - self._models["materials_generic"].setMetadata(self._metadata["materials_generic"]) + self._materials_showcase_model.setMetadata(materials_showcase_metadata) + self._materials_available_model.setMetadata(materials_available_metadata) + self._materials_generic_model.setMetadata(materials_generic_metadata) - def buildPluginsModels(self) -> None: - self._metadata["plugins_showcase"] = [] - self._metadata["plugins_available"] = [] + def reBuildPluginsModels(self) -> None: + plugins_showcase_metadata = [] + plugins_available_metadata = [] - for item in self._metadata["packages"]: + for item in self._server_response_data["packages"]: if item["package_type"] == "plugin": - if "showcase" in item["tags"]: - self._metadata["plugins_showcase"].append(item) + plugins_showcase_metadata.append(item) else: - self._metadata["plugins_available"].append(item) + plugins_available_metadata.append(item) - self._models["plugins_showcase"].setMetadata(self._metadata["plugins_showcase"]) - self._models["plugins_available"].setMetadata(self._metadata["plugins_available"]) + self._plugins_showcase_model.setMetadata(plugins_showcase_metadata) + self._plugins_available_model.setMetadata(plugins_available_metadata) diff --git a/plugins/UM3NetworkPrinting/resources/qml/ClusterControlItem.qml b/plugins/UM3NetworkPrinting/resources/qml/ClusterControlItem.qml deleted file mode 100644 index 068c369a3f..0000000000 --- a/plugins/UM3NetworkPrinting/resources/qml/ClusterControlItem.qml +++ /dev/null @@ -1,110 +0,0 @@ -// Copyright (c) 2018 Ultimaker B.V. -// Cura is released under the terms of the LGPLv3 or higher. - -import QtQuick 2.3 -import QtQuick.Controls 1.4 -import QtQuick.Controls.Styles 1.3 -import UM 1.3 as UM -import Cura 1.0 as Cura - -Component { - Rectangle { - id: base; - property var shadowRadius: UM.Theme.getSize("monitor_shadow_radius").width; - property var cornerRadius: UM.Theme.getSize("monitor_corner_radius").width; - anchors.fill: parent; - color: UM.Theme.getColor("sidebar"); - visible: OutputDevice != null; - - UM.I18nCatalog { - id: catalog; - name: "cura"; - } - - Label { - id: printingLabel; - anchors { - left: parent.left; - leftMargin: 4 * UM.Theme.getSize("default_margin").width; - margins: 2 * UM.Theme.getSize("default_margin").width; - right: parent.right; - top: parent.top; - } - color: UM.Theme.getColor("text"); - elide: Text.ElideRight; - font: UM.Theme.getFont("large"); - text: catalog.i18nc("@label", "Printing"); - } - - Label { - id: managePrintersLabel; - anchors { - bottom: printingLabel.bottom; - right: printerScrollView.right; - rightMargin: 4 * UM.Theme.getSize("default_margin").width; - } - color: UM.Theme.getColor("primary"); // "Cura Blue" - font: UM.Theme.getFont("default"); - linkColor: UM.Theme.getColor("primary"); // "Cura Blue" - text: catalog.i18nc("@label link to connect manager", "Manage printers"); - } - - MouseArea { - anchors.fill: managePrintersLabel; - hoverEnabled: true; - onClicked: Cura.MachineManager.printerOutputDevices[0].openPrinterControlPanel(); - onEntered: managePrintersLabel.font.underline = true; - onExited: managePrintersLabel.font.underline = false; - } - - // Skeleton loading - Column { - id: skeletonLoader; - anchors { - left: parent.left; - leftMargin: UM.Theme.getSize("wide_margin").width; - right: parent.right; - rightMargin: UM.Theme.getSize("wide_margin").width; - top: printingLabel.bottom; - topMargin: UM.Theme.getSize("default_margin").height; - } - spacing: UM.Theme.getSize("default_margin").height - 10; - visible: printerList.count === 0; - - PrinterCard { - printer: null; - } - PrinterCard { - printer: null; - } - } - - // Actual content - ScrollView { - id: printerScrollView; - anchors { - bottom: parent.bottom; - left: parent.left; - right: parent.right; - top: printingLabel.bottom; - topMargin: UM.Theme.getSize("default_margin").height; - } - style: UM.Theme.styles.scrollview; - - ListView { - id: printerList; - property var currentIndex: -1; - anchors { - fill: parent; - leftMargin: UM.Theme.getSize("wide_margin").width; - rightMargin: UM.Theme.getSize("wide_margin").width; - } - delegate: PrinterCard { - printer: modelData; - } - model: OutputDevice.printers; - spacing: UM.Theme.getSize("default_margin").height - 10; - } - } - } -} diff --git a/plugins/UM3NetworkPrinting/resources/qml/DiscoverUM3Action.qml b/plugins/UM3NetworkPrinting/resources/qml/DiscoverUM3Action.qml index 58443115a9..e5f668c70d 100644 --- a/plugins/UM3NetworkPrinting/resources/qml/DiscoverUM3Action.qml +++ b/plugins/UM3NetworkPrinting/resources/qml/DiscoverUM3Action.qml @@ -64,6 +64,7 @@ Cura.MachineAction width: parent.width text: catalog.i18nc("@title:window", "Connect to Networked Printer") wrapMode: Text.WordWrap + renderType: Text.NativeRendering font.pointSize: 18 } @@ -72,6 +73,7 @@ Cura.MachineAction id: pageDescription width: parent.width wrapMode: Text.WordWrap + renderType: Text.NativeRendering text: catalog.i18nc("@label", "To print directly to your printer over the network, please make sure your printer is connected to the network using a network cable or by connecting your printer to your WIFI network. If you don't connect Cura with your printer, you can still use a USB drive to transfer g-code files to your printer.\n\nSelect your printer from the list below:") } @@ -182,6 +184,7 @@ Cura.MachineAction text: listview.model[index].name color: parent.ListView.isCurrentItem ? palette.highlightedText : palette.text elide: Text.ElideRight + renderType: Text.NativeRendering } MouseArea @@ -204,6 +207,7 @@ Cura.MachineAction anchors.left: parent.left anchors.right: parent.right wrapMode: Text.WordWrap + renderType: Text.NativeRendering text: catalog.i18nc("@label", "If your printer is not listed, read the network printing troubleshooting guide").arg("https://ultimaker.com/en/troubleshooting"); onLinkActivated: Qt.openUrlExternally(link) } @@ -221,6 +225,7 @@ Cura.MachineAction text: base.selectedDevice ? base.selectedDevice.name : "" font: UM.Theme.getFont("large") elide: Text.ElideRight + renderType: Text.NativeRendering } Grid { @@ -231,12 +236,14 @@ Cura.MachineAction { width: Math.round(parent.width * 0.5) wrapMode: Text.WordWrap + renderType: Text.NativeRendering text: catalog.i18nc("@label", "Type") } Label { width: Math.round(parent.width * 0.5) wrapMode: Text.WordWrap + renderType: Text.NativeRendering text: { if(base.selectedDevice) @@ -268,24 +275,28 @@ Cura.MachineAction { width: Math.round(parent.width * 0.5) wrapMode: Text.WordWrap + renderType: Text.NativeRendering text: catalog.i18nc("@label", "Firmware version") } Label { width: Math.round(parent.width * 0.5) wrapMode: Text.WordWrap + renderType: Text.NativeRendering text: base.selectedDevice ? base.selectedDevice.firmwareVersion : "" } Label { width: Math.round(parent.width * 0.5) wrapMode: Text.WordWrap + renderType: Text.NativeRendering text: catalog.i18nc("@label", "Address") } Label { width: Math.round(parent.width * 0.5) wrapMode: Text.WordWrap + renderType: Text.NativeRendering text: base.selectedDevice ? base.selectedDevice.ipAddress : "" } } @@ -294,6 +305,7 @@ Cura.MachineAction { width: parent.width wrapMode: Text.WordWrap + renderType: Text.NativeRendering text:{ // The property cluster size does not exist for older UM3 devices. if(!base.selectedDevice || base.selectedDevice.clusterSize == null || base.selectedDevice.clusterSize == 1) @@ -315,6 +327,7 @@ Cura.MachineAction { width: parent.width wrapMode: Text.WordWrap + renderType: Text.NativeRendering visible: base.selectedDevice != null && !base.completeProperties text: catalog.i18nc("@label", "The printer at this address has not yet responded." ) } @@ -358,9 +371,10 @@ Cura.MachineAction Label { - text: catalog.i18nc("@alabel","Enter the IP address or hostname of your printer on the network.") + text: catalog.i18nc("@alabel", "Enter the IP address or hostname of your printer on the network.") width: parent.width wrapMode: Text.WordWrap + renderType: Text.NativeRendering } TextField diff --git a/plugins/UM3NetworkPrinting/resources/qml/HorizontalLine.qml b/plugins/UM3NetworkPrinting/resources/qml/HorizontalLine.qml deleted file mode 100644 index aeb92697ad..0000000000 --- a/plugins/UM3NetworkPrinting/resources/qml/HorizontalLine.qml +++ /dev/null @@ -1,12 +0,0 @@ -// Copyright (c) 2018 Ultimaker B.V. -// Cura is released under the terms of the LGPLv3 or higher. - -import QtQuick 2.3 -import QtQuick.Controls 2.0 -import UM 1.3 as UM - -Rectangle { - color: UM.Theme.getColor("monitor_lining_light"); // TODO: Maybe theme separately? Maybe not. - height: UM.Theme.getSize("default_lining").height; - width: parent.width; -} \ No newline at end of file diff --git a/plugins/UM3NetworkPrinting/resources/qml/MonitorBuildplateConfiguration.qml b/plugins/UM3NetworkPrinting/resources/qml/MonitorBuildplateConfiguration.qml index 9ffb1eabb4..44bd47f904 100644 --- a/plugins/UM3NetworkPrinting/resources/qml/MonitorBuildplateConfiguration.qml +++ b/plugins/UM3NetworkPrinting/resources/qml/MonitorBuildplateConfiguration.qml @@ -27,7 +27,7 @@ Item Row { height: parent.height - spacing: 12 * screenScaleFactor // TODO: Theme! (Should be same as extruder spacing) + spacing: UM.Theme.getSize("print_setup_slider_handle").width // TODO: Theme! (Should be same as extruder spacing) // This wrapper ensures that the buildplate icon is located centered // below an extruder icon. @@ -52,7 +52,7 @@ Item id: buildplateLabel color: "#191919" // TODO: Theme! elide: Text.ElideRight - font: UM.Theme.getFont("very_small") // 12pt, regular + font: UM.Theme.getFont("default") // 12pt, regular text: "" // FIXED-LINE-HEIGHT: diff --git a/plugins/UM3NetworkPrinting/resources/qml/MonitorConfigOverrideDialog.qml b/plugins/UM3NetworkPrinting/resources/qml/MonitorConfigOverrideDialog.qml new file mode 100644 index 0000000000..6a32310dd5 --- /dev/null +++ b/plugins/UM3NetworkPrinting/resources/qml/MonitorConfigOverrideDialog.qml @@ -0,0 +1,142 @@ +// Copyright (c) 2018 Ultimaker B.V. +// Cura is released under the terms of the LGPLv3 or higher. + +import QtQuick 2.3 +import QtQuick.Controls 1.4 +import QtQuick.Layouts 1.3 +import QtQuick.Dialogs 1.2 +import UM 1.3 as UM + +UM.Dialog +{ + id: overrideConfirmationDialog + + property var printer: null + + minimumWidth: screenScaleFactor * 640; + minimumHeight: screenScaleFactor * 320; + width: minimumWidth + height: minimumHeight + title: catalog.i18nc("@title:window", "Configuration Changes") + rightButtons: + [ + Button + { + id: overrideButton + anchors.margins: UM.Theme.getSize("default_margin").width + text: catalog.i18nc("@action:button", "Override") + onClicked: + { + OutputDevice.forceSendJob(printer.activePrintJob.key) + overrideConfirmationDialog.close() + } + }, + Button + { + id: cancelButton + anchors.margins: UM.Theme.getSize("default_margin").width + text: catalog.i18nc("@action:button", "Cancel") + onClicked: + { + overrideConfirmationDialog.reject() + } + } + ] + + Label + { + anchors + { + fill: parent + margins: 36 * screenScaleFactor // TODO: Theme! + bottomMargin: 56 * screenScaleFactor // TODO: Theme! + } + wrapMode: Text.WordWrap + text: + { + if (!printer.activePrintJob) + { + return "" + } + var topLine + if (materialsAreKnown(printer.activePrintJob)) + { + topLine = catalog.i18ncp("@label", "The assigned printer, %1, requires the following configuration change:", "The assigned printer, %1, requires the following configuration changes:", printer.activePrintJob.configurationChanges.length).arg(printer.name) + } + else + { + topLine = catalog.i18nc("@label", "The printer %1 is assigned, but the job contains an unknown material configuration.").arg(printer.name) + } + var result = "

" + topLine +"

\n\n" + for (var i = 0; i < printer.activePrintJob.configurationChanges.length; i++) + { + var change = printer.activePrintJob.configurationChanges[i] + var text + switch (change.typeOfChange) + { + case "material_change": + text = catalog.i18nc("@label", "Change material %1 from %2 to %3.").arg(change.index + 1).arg(change.originName).arg(change.targetName) + break + case "material_insert": + text = catalog.i18nc("@label", "Load %3 as material %1 (This cannot be overridden).").arg(change.index + 1).arg(change.targetName) + break + case "print_core_change": + text = catalog.i18nc("@label", "Change print core %1 from %2 to %3.").arg(change.index + 1).arg(change.originName).arg(change.targetName) + break + case "buildplate_change": + text = catalog.i18nc("@label", "Change build plate to %1 (This cannot be overridden).").arg(formatBuildPlateType(change.target_name)) + break + default: + text = "unknown" + } + result += "

" + text + "

\n\n" + } + var bottomLine = catalog.i18nc("@label", "Override will use the specified settings with the existing printer configuration. This may result in a failed print.") + result += "

" + bottomLine + "

\n\n" + return result + } + } + // Utils + function formatPrintJobName(name) + { + var extensions = [ ".gcode.gz", ".gz", ".gcode", ".ufp" ] + for (var i = 0; i < extensions.length; i++) + { + var extension = extensions[i] + if (name.slice(-extension.length) === extension) + { + name = name.substring(0, name.length - extension.length) + } + } + return name; + } + function materialsAreKnown(job) + { + var conf0 = job.configuration[0] + if (conf0 && !conf0.material.material) + { + return false + } + var conf1 = job.configuration[1] + if (conf1 && !conf1.material.material) + { + return false + } + return true + } + function formatBuildPlateType(buildPlateType) + { + var translationText = "" + switch (buildPlateType) { + case "glass": + translationText = catalog.i18nc("@label", "Glass") + break + case "aluminum": + translationText = catalog.i18nc("@label", "Aluminum") + break + default: + translationText = null + } + return translationText + } +} \ No newline at end of file diff --git a/plugins/UM3NetworkPrinting/resources/qml/MonitorExtruderConfiguration.qml b/plugins/UM3NetworkPrinting/resources/qml/MonitorExtruderConfiguration.qml index afbd4c3641..1e53191d8c 100644 --- a/plugins/UM3NetworkPrinting/resources/qml/MonitorExtruderConfiguration.qml +++ b/plugins/UM3NetworkPrinting/resources/qml/MonitorExtruderConfiguration.qml @@ -49,7 +49,7 @@ Item } color: "#191919" // TODO: Theme! elide: Text.ElideRight - font: UM.Theme.getFont("very_small") // 12pt, regular + font: UM.Theme.getFont("default") // 12pt, regular text: "" // FIXED-LINE-HEIGHT: @@ -66,7 +66,7 @@ Item } color: "#191919" // TODO: Theme! elide: Text.ElideRight - font: UM.Theme.getFont("small") // 12pt, bold + font: UM.Theme.getFont("default_bold") // 12pt, bold text: "" // FIXED-LINE-HEIGHT: diff --git a/plugins/UM3NetworkPrinting/resources/qml/MonitorPrintJobCard.qml b/plugins/UM3NetworkPrinting/resources/qml/MonitorPrintJobCard.qml index 8231870c21..5eaeff2e84 100644 --- a/plugins/UM3NetworkPrinting/resources/qml/MonitorPrintJobCard.qml +++ b/plugins/UM3NetworkPrinting/resources/qml/MonitorPrintJobCard.qml @@ -26,6 +26,7 @@ Item ExpandableCard { + borderColor: printJob.configurationChanges.length !== 0 ? "#f5a623" : "#EAEAEC" // TODO: Theme! headerItem: Row { height: 48 * screenScaleFactor // TODO: Theme! diff --git a/plugins/UM3NetworkPrinting/resources/qml/MonitorPrintJobPreview.qml b/plugins/UM3NetworkPrinting/resources/qml/MonitorPrintJobPreview.qml index ec26bbe568..2f17db0c65 100644 --- a/plugins/UM3NetworkPrinting/resources/qml/MonitorPrintJobPreview.qml +++ b/plugins/UM3NetworkPrinting/resources/qml/MonitorPrintJobPreview.qml @@ -23,7 +23,7 @@ Item anchors.fill: parent opacity: { - if (printJob && (printJob.state == "error" || !printJob.isActive)) + if (printJob && (printJob.state == "error" || printJob.configurationChanges.length > 0 || !printJob.isActive)) { return 0.5 } @@ -60,6 +60,14 @@ Item height: 0.5 * printJobPreview.height source: { + if (!printJob) + { + return "" + } + if (printJob.configurationChanges.length > 0) + { + return "../svg/warning-icon.svg" + } switch(printJob.state) { case "error": @@ -75,6 +83,7 @@ Item default: return "" } + return "" } sourceSize { diff --git a/plugins/UM3NetworkPrinting/resources/qml/MonitorPrintJobProgressBar.qml b/plugins/UM3NetworkPrinting/resources/qml/MonitorPrintJobProgressBar.qml index 88418516ed..cfb7aba84d 100644 --- a/plugins/UM3NetworkPrinting/resources/qml/MonitorPrintJobProgressBar.qml +++ b/plugins/UM3NetworkPrinting/resources/qml/MonitorPrintJobProgressBar.qml @@ -55,7 +55,7 @@ Item left: progressBar.right leftMargin: 18 * screenScaleFactor // TODO: Theme! } - text: Math.round(printJob.progress * 100) + "%" + text: printJob ? Math.round(printJob.progress * 100) + "%" : "0%" color: printJob && printJob.isActive ? "#374355" : "#babac1" // TODO: Theme! width: contentWidth font: UM.Theme.getFont("medium") // 14pt, regular @@ -88,6 +88,8 @@ Item return catalog.i18nc("@label:status", "Aborted") } return catalog.i18nc("@label:status", "Finished") + case "finished": + return catalog.i18nc("@label:status", "Finished") case "sent_to_printer": return catalog.i18nc("@label:status", "Preparing...") case "pre_print": diff --git a/plugins/UM3NetworkPrinting/resources/qml/MonitorPrinterCard.qml b/plugins/UM3NetworkPrinting/resources/qml/MonitorPrinterCard.qml index 567fff8489..1676c51edf 100644 --- a/plugins/UM3NetworkPrinting/resources/qml/MonitorPrinterCard.qml +++ b/plugins/UM3NetworkPrinting/resources/qml/MonitorPrinterCard.qml @@ -3,6 +3,7 @@ import QtQuick 2.3 import QtQuick.Controls 2.0 +import QtQuick.Dialogs 1.1 import UM 1.3 as UM /** @@ -66,7 +67,7 @@ Item { verticalCenter: parent.verticalCenter } - width: 216 * screenScaleFactor // TODO: Theme! + width: 180 * screenScaleFactor // TODO: Theme! height: printerNameLabel.height + printerFamilyPill.height + 6 * screenScaleFactor // TODO: Theme! Label @@ -150,7 +151,7 @@ Item } border { - color: "#EAEAEC" // TODO: Theme! + color: printer.activePrintJob && printer.activePrintJob.configurationChanges.length > 0 ? "#f5a623" : "#EAEAEC" // TODO: Theme! width: borderSize // TODO: Remove once themed } color: "white" // TODO: Theme! @@ -185,14 +186,15 @@ Item } if (printer && printer.state == "unreachable") { - return catalog.i18nc("@label:status", "Unreachable") + return catalog.i18nc("@label:status", "Unavailable") } - if (printer && printer.state == "idle") + if (printer && !printer.activePrintJob && printer.state == "idle") { return catalog.i18nc("@label:status", "Idle") } return "" } + visible: text !== "" } Item @@ -218,7 +220,7 @@ Item { verticalCenter: parent.verticalCenter } - width: 216 * screenScaleFactor // TODO: Theme! + width: 180 * screenScaleFactor // TODO: Theme! height: printerNameLabel.height + printerFamilyPill.height + 6 * screenScaleFactor // TODO: Theme! visible: printer.activePrintJob @@ -247,7 +249,7 @@ Item } color: printer.activePrintJob && printer.activePrintJob.isActive ? "#53657d" : "#babac1" // TODO: Theme! elide: Text.ElideRight - font: UM.Theme.getFont("very_small") // 12pt, regular + font: UM.Theme.getFont("default") // 12pt, regular text: printer.activePrintJob ? printer.activePrintJob.owner : "Anonymous" // TODO: I18N width: parent.width @@ -264,8 +266,67 @@ Item verticalCenter: parent.verticalCenter } printJob: printer.activePrintJob - visible: printer.activePrintJob + visible: printer.activePrintJob && printer.activePrintJob.configurationChanges.length === 0 + } + + Label + { + anchors + { + verticalCenter: parent.verticalCenter + } + font: UM.Theme.getFont("default") + text: "Requires configuration changes" + visible: printer.activePrintJob && printer.activePrintJob.configurationChanges.length > 0 + + // FIXED-LINE-HEIGHT: + height: 18 * screenScaleFactor // TODO: Theme! + verticalAlignment: Text.AlignVCenter } } + + Button + { + id: detailsButton + anchors + { + verticalCenter: parent.verticalCenter + right: parent.right + rightMargin: 18 * screenScaleFactor // TODO: Theme! + } + background: Rectangle + { + color: "#d8d8d8" // TODO: Theme! + radius: 2 * screenScaleFactor // Todo: Theme! + Rectangle + { + anchors.fill: parent + anchors.bottomMargin: 2 * screenScaleFactor // TODO: Theme! + color: detailsButton.hovered ? "#e4e4e4" : "#f0f0f0" // TODO: Theme! + radius: 2 * screenScaleFactor // Todo: Theme! + } + } + contentItem: Label + { + anchors.fill: parent + anchors.bottomMargin: 2 * screenScaleFactor // TODO: Theme! + color: "#1e66d7" // TODO: Theme! + font: UM.Theme.getFont("medium") // 14pt, regular + text: "Details" // TODO: I18NC! + verticalAlignment: Text.AlignVCenter + horizontalAlignment: Text.AlignHCenter + height: 18 * screenScaleFactor // TODO: Theme! + } + implicitHeight: 32 * screenScaleFactor // TODO: Theme! + implicitWidth: 96 * screenScaleFactor // TODO: Theme! + visible: printer.activePrintJob && printer.activePrintJob.configurationChanges.length > 0 + onClicked: overrideConfirmationDialog.open() + } + } + + MonitorConfigOverrideDialog + { + id: overrideConfirmationDialog + printer: base.printer } } \ No newline at end of file diff --git a/plugins/UM3NetworkPrinting/resources/qml/ClusterMonitorItem.qml b/plugins/UM3NetworkPrinting/resources/qml/MonitorStage.qml similarity index 98% rename from plugins/UM3NetworkPrinting/resources/qml/ClusterMonitorItem.qml rename to plugins/UM3NetworkPrinting/resources/qml/MonitorStage.qml index adf5ea5e1c..4d59e0eb6b 100644 --- a/plugins/UM3NetworkPrinting/resources/qml/ClusterMonitorItem.qml +++ b/plugins/UM3NetworkPrinting/resources/qml/MonitorStage.qml @@ -8,6 +8,7 @@ import UM 1.3 as UM import Cura 1.0 as Cura import QtGraphicalEffects 1.0 +// Root component for the monitor tab (stage) Component { Item @@ -130,7 +131,7 @@ Component verticalCenter: externalLinkIcon.verticalCenter } color: UM.Theme.getColor("primary") - font: UM.Theme.getFont("default") + font: UM.Theme.getFont("default") // 12pt, regular linkColor: UM.Theme.getColor("primary") text: catalog.i18nc("@label link to connect manager", "Manage queue in Cura Connect") } diff --git a/plugins/UM3NetworkPrinting/resources/qml/PrintCoreConfiguration.qml b/plugins/UM3NetworkPrinting/resources/qml/PrintCoreConfiguration.qml deleted file mode 100644 index 7bcd9ce6e4..0000000000 --- a/plugins/UM3NetworkPrinting/resources/qml/PrintCoreConfiguration.qml +++ /dev/null @@ -1,121 +0,0 @@ -// Copyright (c) 2018 Ultimaker B.V. -// Cura is released under the terms of the LGPLv3 or higher. - -import QtQuick 2.2 -import QtQuick.Controls 1.4 -import QtQuick.Controls.Styles 1.4 -import UM 1.2 as UM - -Item { - id: extruderInfo; - property var printCoreConfiguration: null; - height: childrenRect.height; - width: Math.round(parent.width / 2); - - // Extruder circle - Item { - id: extruderCircle; - height: UM.Theme.getSize("monitor_extruder_circle").height; - width: UM.Theme.getSize("monitor_extruder_circle").width; - - // Loading skeleton - Rectangle { - anchors.fill: parent; - color: UM.Theme.getColor("monitor_skeleton_fill"); - radius: Math.round(width / 2); - visible: !printCoreConfiguration; - } - - // Actual content - Rectangle { - anchors.fill: parent; - border.width: UM.Theme.getSize("monitor_thick_lining").width; - border.color: UM.Theme.getColor("monitor_lining_heavy"); - color: "transparent"; - opacity: { - if (printCoreConfiguration == null || printCoreConfiguration.activeMaterial == null || printCoreConfiguration.hotendID == null) { - return 0.5; - } - return 1; - } - radius: Math.round(width / 2); - visible: printCoreConfiguration; - - Label { - anchors.centerIn: parent; - color: UM.Theme.getColor("text"); - font: UM.Theme.getFont("default_bold"); - text: printCoreConfiguration ? printCoreConfiguration.position + 1 : 0; - } - } - } - - // Print core and material labels - Item { - id: materialLabel - anchors { - left: extruderCircle.right; - leftMargin: UM.Theme.getSize("default_margin").width; - right: parent.right; - top: parent.top; - } - height: UM.Theme.getSize("monitor_text_line").height; - - // Loading skeleton - Rectangle { - anchors.fill: parent; - color: UM.Theme.getColor("monitor_skeleton_fill"); - visible: !extruderInfo.printCoreConfiguration; - } - - // Actual content - Label { - anchors.fill: parent; - elide: Text.ElideRight; - color: UM.Theme.getColor("text"); - font: UM.Theme.getFont("default"); - text: { - if (printCoreConfiguration && printCoreConfiguration.activeMaterial != undefined) { - return printCoreConfiguration.activeMaterial.name; - } - return ""; - } - visible: extruderInfo.printCoreConfiguration; - } - } - - Item { - id: printCoreLabel; - anchors { - left: extruderCircle.right; - leftMargin: UM.Theme.getSize("default_margin").width; - right: parent.right; - top: materialLabel.bottom; - topMargin: Math.floor(UM.Theme.getSize("default_margin").height/4); - } - height: UM.Theme.getSize("monitor_text_line").height; - - // Loading skeleton - Rectangle { - color: UM.Theme.getColor("monitor_skeleton_fill"); - height: parent.height; - visible: !extruderInfo.printCoreConfiguration; - width: Math.round(parent.width / 3); - } - - // Actual content - Label { - color: UM.Theme.getColor("text"); - elide: Text.ElideRight; - font: UM.Theme.getFont("default"); - opacity: 0.6; - text: { - if (printCoreConfiguration != undefined && printCoreConfiguration.hotendID != undefined) { - return printCoreConfiguration.hotendID; - } - return ""; - } - visible: extruderInfo.printCoreConfiguration; - } - } -} diff --git a/plugins/UM3NetworkPrinting/resources/qml/PrintJobContextMenu.qml b/plugins/UM3NetworkPrinting/resources/qml/PrintJobContextMenu.qml index 02a8e7ae69..1edbf9f6a2 100644 --- a/plugins/UM3NetworkPrinting/resources/qml/PrintJobContextMenu.qml +++ b/plugins/UM3NetworkPrinting/resources/qml/PrintJobContextMenu.qml @@ -182,7 +182,7 @@ Item { abortConfirmationDialog.visible = true; popup.close(); } - text: printJob.state == "aborting" ? catalog.i18nc("@label", "Aborting...") : catalog.i18nc("@label", "Abort"); + text: printJob && printJob.state == "aborting" ? catalog.i18nc("@label", "Aborting...") : catalog.i18nc("@label", "Abort"); visible: { if (!printJob) { return false; diff --git a/plugins/UM3NetworkPrinting/resources/qml/PrintJobInfoBlock.qml b/plugins/UM3NetworkPrinting/resources/qml/PrintJobInfoBlock.qml deleted file mode 100644 index a611cb4ff6..0000000000 --- a/plugins/UM3NetworkPrinting/resources/qml/PrintJobInfoBlock.qml +++ /dev/null @@ -1,505 +0,0 @@ -// Copyright (c) 2018 Ultimaker B.V. -// Cura is released under the terms of the LGPLv3 or higher. - -import QtQuick 2.2 -import QtQuick.Dialogs 1.1 -import QtQuick.Controls 2.0 -import QtQuick.Controls.Styles 1.4 -import QtGraphicalEffects 1.0 -import QtQuick.Layouts 1.1 -import QtQuick.Dialogs 1.1 -import UM 1.3 as UM - -Item { - id: root; - property var shadowRadius: UM.Theme.getSize("monitor_shadow_radius").width; - property var shadowOffset: 2 * screenScaleFactor; - property var debug: false; - property var printJob: null; - width: parent.width; // Bubbles downward - height: childrenRect.height + shadowRadius * 2; // Bubbles upward - - UM.I18nCatalog { - id: catalog; - name: "cura"; - } - - // The actual card (white block) - Rectangle { - // 5px margin, but shifted 2px vertically because of the shadow - anchors { - bottomMargin: root.shadowRadius + root.shadowOffset; - leftMargin: root.shadowRadius; - rightMargin: root.shadowRadius; - topMargin: root.shadowRadius - root.shadowOffset; - } - color: UM.Theme.getColor("monitor_card_background"); - height: childrenRect.height; - layer.enabled: true - layer.effect: DropShadow { - radius: root.shadowRadius - verticalOffset: 2 * screenScaleFactor - color: "#3F000000" // 25% shadow - } - width: parent.width - shadowRadius * 2; - - Column { - height: childrenRect.height; - width: parent.width; - - // Main content - Item { - id: mainContent; - height: 200 * screenScaleFactor; // TODO: Theme! - width: parent.width; - - // Left content - Item { - anchors { - bottom: parent.bottom; - left: parent.left; - margins: UM.Theme.getSize("wide_margin").width; - right: parent.horizontalCenter; - top: parent.top; - } - - Item { - id: printJobName; - width: parent.width; - height: UM.Theme.getSize("monitor_text_line").height; - - Rectangle { - color: UM.Theme.getColor("monitor_skeleton_fill"); - height: parent.height; - visible: !printJob; - width: Math.round(parent.width / 3); - } - Label { - anchors.fill: parent; - color: UM.Theme.getColor("text"); - elide: Text.ElideRight; - font: UM.Theme.getFont("default_bold"); - text: printJob && printJob.name ? printJob.name : ""; // Supress QML warnings - visible: printJob; - } - } - - Item { - id: printJobOwnerName; - anchors { - top: printJobName.bottom; - topMargin: Math.floor(UM.Theme.getSize("default_margin").height / 2); - } - height: UM.Theme.getSize("monitor_text_line").height; - width: parent.width; - - Rectangle { - color: UM.Theme.getColor("monitor_skeleton_fill"); - height: parent.height; - visible: !printJob; - width: Math.round(parent.width / 2); - } - Label { - anchors.fill: parent; - color: UM.Theme.getColor("text"); - elide: Text.ElideRight; - font: UM.Theme.getFont("default"); - text: printJob ? printJob.owner : ""; // Supress QML warnings - visible: printJob; - } - } - - Item { - id: printJobPreview; - property var useUltibot: false; - anchors { - bottom: parent.bottom; - horizontalCenter: parent.horizontalCenter; - top: printJobOwnerName.bottom; - topMargin: UM.Theme.getSize("default_margin").height; - } - width: height; - - // Skeleton - Rectangle { - anchors.fill: parent; - color: UM.Theme.getColor("monitor_skeleton_fill"); - radius: UM.Theme.getSize("default_margin").width; - visible: !printJob; - } - - // Actual content - Image { - id: previewImage; - anchors.fill: parent; - opacity: printJob && printJob.state == "error" ? 0.5 : 1.0; - source: printJob ? printJob.previewImageUrl : ""; - visible: printJob; - } - - UM.RecolorImage { - id: ultiBotImage; - - anchors.centerIn: printJobPreview; - color: UM.Theme.getColor("monitor_placeholder_image"); - height: printJobPreview.height; - source: "../svg/ultibot.svg"; - sourceSize { - height: height; - width: width; - } - /* Since print jobs ALWAYS have an image url, we have to check if that image URL errors or - not in order to determine if we show the placeholder (ultibot) image instead. */ - visible: printJob && previewImage.status == Image.Error; - width: printJobPreview.width; - } - - UM.RecolorImage { - id: statusImage; - anchors.centerIn: printJobPreview; - color: UM.Theme.getColor("monitor_image_overlay"); - height: 0.5 * printJobPreview.height; - source: printJob && printJob.state == "error" ? "../svg/aborted-icon.svg" : ""; - sourceSize { - height: height; - width: width; - } - visible: source != ""; - width: 0.5 * printJobPreview.width; - } - } - - Label { - id: totalTimeLabel; - anchors { - bottom: parent.bottom; - right: parent.right; - } - color: UM.Theme.getColor("text"); - elide: Text.ElideRight; - font: UM.Theme.getFont("default"); - text: printJob ? OutputDevice.formatDuration(printJob.timeTotal) : ""; - } - } - - // Divider - Rectangle { - anchors { - horizontalCenter: parent.horizontalCenter; - verticalCenter: parent.verticalCenter; - } - color: !printJob ? UM.Theme.getColor("monitor_skeleton_fill") : UM.Theme.getColor("monitor_lining_light"); - height: parent.height - 2 * UM.Theme.getSize("default_margin").height; - width: UM.Theme.getSize("default_lining").width; - } - - // Right content - Item { - anchors { - bottom: parent.bottom; - left: parent.horizontalCenter; - margins: UM.Theme.getSize("wide_margin").width; - right: parent.right; - top: parent.top; - } - - Item { - id: targetPrinterLabel; - height: UM.Theme.getSize("monitor_text_line").height; - width: parent.width; - - Rectangle { - visible: !printJob; - color: UM.Theme.getColor("monitor_skeleton_fill"); - anchors.fill: parent; - } - - Label { - color: UM.Theme.getColor("text"); - elide: Text.ElideRight; - font: UM.Theme.getFont("default_bold"); - text: { - if (printJob !== null) { - if (printJob.assignedPrinter == null) { - if (printJob.state == "error") { - return catalog.i18nc("@label", "Waiting for: Unavailable printer"); - } - return catalog.i18nc("@label", "Waiting for: First available"); - } else { - return catalog.i18nc("@label", "Waiting for: ") + printJob.assignedPrinter.name; - } - } - return ""; - } - visible: printJob; - } - } - - PrinterInfoBlock { - anchors.bottom: parent.bottom; - printer: root.printJon && root.printJob.assignedPrinter; - printJob: root.printJob; - } - } - - PrintJobContextMenu { - id: contextButton; - anchors { - right: mainContent.right; - rightMargin: UM.Theme.getSize("default_margin").width * 3 + root.shadowRadius; - top: mainContent.top; - topMargin: UM.Theme.getSize("default_margin").height; - } - printJob: root.printJob; - visible: root.printJob; - } - } - - Item { - id: configChangesBox; - height: childrenRect.height; - visible: printJob && printJob.configurationChanges.length !== 0; - width: parent.width; - - // Config change toggle - Rectangle { - id: configChangeToggle; - color: { - if (configChangeToggleArea.containsMouse) { - return UM.Theme.getColor("viewport_background"); // TODO: Theme! - } else { - return "transparent"; - } - } - width: parent.width; - height: UM.Theme.getSize("default_margin").height * 4; // TODO: Theme! - anchors { - left: parent.left; - right: parent.right; - top: parent.top; - } - - Rectangle { - color: !printJob ? UM.Theme.getColor("monitor_skeleton_fill") : UM.Theme.getColor("monitor_lining_light"); - height: UM.Theme.getSize("default_lining").height; - width: parent.width; - } - - UM.RecolorImage { - anchors { - right: configChangeToggleLabel.left; - rightMargin: UM.Theme.getSize("default_margin").width; - verticalCenter: parent.verticalCenter; - } - color: UM.Theme.getColor("text"); - height: 23 * screenScaleFactor; // TODO: Theme! - source: "../svg/warning-icon.svg"; - sourceSize { - height: height; - width: width; - } - width: 23 * screenScaleFactor; // TODO: Theme! - } - - Label { - id: configChangeToggleLabel; - anchors { - horizontalCenter: parent.horizontalCenter; - verticalCenter: parent.verticalCenter; - } - color: UM.Theme.getColor("text"); - font: UM.Theme.getFont("default"); - text: catalog.i18nc("@label", "Configuration change"); - } - - UM.RecolorImage { - anchors { - left: configChangeToggleLabel.right; - leftMargin: UM.Theme.getSize("default_margin").width; - verticalCenter: parent.verticalCenter; - } - color: UM.Theme.getColor("text"); - height: 15 * screenScaleFactor; // TODO: Theme! - source: { - if (configChangeDetails.visible) { - return UM.Theme.getIcon("arrow_top"); - } else { - return UM.Theme.getIcon("arrow_bottom"); - } - } - sourceSize { - width: width; - height: height; - } - width: 15 * screenScaleFactor; // TODO: Theme! - } - - MouseArea { - id: configChangeToggleArea; - anchors.fill: parent; - hoverEnabled: true; - onClicked: { - configChangeDetails.visible = !configChangeDetails.visible; - } - } - } - - // Config change details - Item { - id: configChangeDetails; - anchors.top: configChangeToggle.bottom; - Behavior on height { NumberAnimation { duration: 100 } } - // In case of really massive multi-line configuration changes - height: visible ? Math.max(UM.Theme.getSize("monitor_config_override_box").height, childrenRect.height) : 0; - visible: false; - width: parent.width; - - Item { - anchors { - bottomMargin: UM.Theme.getSize("wide_margin").height; - fill: parent; - leftMargin: UM.Theme.getSize("wide_margin").height * 4; - rightMargin: UM.Theme.getSize("wide_margin").height * 4; - topMargin: UM.Theme.getSize("wide_margin").height; - } - clip: true; - - Label { - anchors.fill: parent; - elide: Text.ElideRight; - color: UM.Theme.getColor("text"); - font: UM.Theme.getFont("default"); - text: { - if (!printJob || printJob.configurationChanges.length === 0) { - return ""; - } - var topLine; - if (materialsAreKnown(printJob)) { - topLine = catalog.i18nc("@label", "The assigned printer, %1, requires the following configuration change(s):").arg(printJob.assignedPrinter.name); - } else { - topLine = catalog.i18nc("@label", "The printer %1 is assigned, but the job contains an unknown material configuration.").arg(printJob.assignedPrinter.name); - } - var result = "

" + topLine +"

"; - for (var i = 0; i < printJob.configurationChanges.length; i++) { - var change = printJob.configurationChanges[i]; - var text; - switch (change.typeOfChange) { - case "material_change": - text = catalog.i18nc("@label", "Change material %1 from %2 to %3.").arg(change.index + 1).arg(change.originName).arg(change.targetName); - break; - case "material_insert": - text = catalog.i18nc("@label", "Load %3 as material %1 (This cannot be overridden).").arg(change.index + 1).arg(change.targetName); - break; - case "print_core_change": - text = catalog.i18nc("@label", "Change print core %1 from %2 to %3.").arg(change.index + 1).arg(change.originName).arg(change.targetName); - break; - case "buildplate_change": - text = catalog.i18nc("@label", "Change build plate to %1 (This cannot be overridden).").arg(formatBuildPlateType(change.target_name)); - break; - default: - text = ""; - } - result += "

" + text + "

"; - } - return result; - } - wrapMode: Text.WordWrap; - } - - Button { - anchors { - bottom: parent.bottom; - left: parent.left; - } - background: Rectangle { - border { - color: UM.Theme.getColor("monitor_lining_heavy"); - width: UM.Theme.getSize("default_lining").width; - } - color: parent.hovered ? UM.Theme.getColor("monitor_card_background_inactive") : UM.Theme.getColor("monitor_card_background"); - implicitHeight: UM.Theme.getSize("default_margin").height * 3; - implicitWidth: UM.Theme.getSize("default_margin").height * 8; - } - contentItem: Label { - color: UM.Theme.getColor("text"); - font: UM.Theme.getFont("medium"); - horizontalAlignment: Text.AlignHCenter; - text: parent.text; - verticalAlignment: Text.AlignVCenter; - } - onClicked: { - overrideConfirmationDialog.visible = true; - } - text: catalog.i18nc("@label", "Override"); - visible: { - if (printJob && printJob.configurationChanges) { - var length = printJob.configurationChanges.length; - for (var i = 0; i < length; i++) { - var typeOfChange = printJob.configurationChanges[i].typeOfChange; - if (typeOfChange === "material_insert" || typeOfChange === "buildplate_change") { - return false; - } - } - } - return true; - } - } - } - } - - MessageDialog { - id: overrideConfirmationDialog; - Component.onCompleted: visible = false; - icon: StandardIcon.Warning; - onYes: OutputDevice.forceSendJob(printJob.key); - standardButtons: StandardButton.Yes | StandardButton.No; - text: { - if (!printJob) { - return ""; - } - var printJobName = formatPrintJobName(printJob.name); - var confirmText = catalog.i18nc("@label", "Starting a print job with an incompatible configuration could damage your 3D printer. Are you sure you want to override the configuration and print %1?").arg(printJobName); - return confirmText; - } - title: catalog.i18nc("@window:title", "Override configuration configuration and start print"); - } - } - } - } - // Utils - function formatPrintJobName(name) { - var extensions = [ ".gz", ".gcode", ".ufp" ]; - for (var i = 0; i < extensions.length; i++) { - var extension = extensions[i]; - if (name.slice(-extension.length) === extension) { - name = name.substring(0, name.length - extension.length); - } - } - return name; - } - function materialsAreKnown(job) { - var conf0 = job.configuration[0]; - if (conf0 && !conf0.material.material) { - return false; - } - var conf1 = job.configuration[1]; - if (conf1 && !conf1.material.material) { - return false; - } - return true; - } - function formatBuildPlateType(buildPlateType) { - var translationText = ""; - switch (buildPlateType) { - case "glass": - translationText = catalog.i18nc("@label", "Glass"); - break; - case "aluminum": - translationText = catalog.i18nc("@label", "Aluminum"); - break; - default: - translationText = null; - } - return translationText; - } -} diff --git a/plugins/UM3NetworkPrinting/resources/qml/PrintJobPreview.qml b/plugins/UM3NetworkPrinting/resources/qml/PrintJobPreview.qml deleted file mode 100644 index b1a73255f4..0000000000 --- a/plugins/UM3NetworkPrinting/resources/qml/PrintJobPreview.qml +++ /dev/null @@ -1,75 +0,0 @@ -// Copyright (c) 2018 Ultimaker B.V. -// Cura is released under the terms of the LGPLv3 or higher. - -import QtQuick 2.3 -import QtQuick.Dialogs 1.1 -import QtQuick.Controls 2.0 -import QtQuick.Controls.Styles 1.3 -import QtGraphicalEffects 1.0 -import QtQuick.Controls 1.4 as LegacyControls -import UM 1.3 as UM - -// Includes print job name, owner, and preview - -Item { - property var job: null; - property var useUltibot: false; - height: 100 * screenScaleFactor; - width: height; - - // Skeleton - Rectangle { - anchors.fill: parent; - color: UM.Theme.getColor("monitor_skeleton_fill"); - radius: UM.Theme.getSize("default_margin").width; - visible: !job; - } - - // Actual content - Image { - id: previewImage; - visible: job; - source: job ? job.previewImageUrl : ""; - opacity: { - if (job == null) { - return 1.0; - } - var states = ["wait_cleanup", "wait_user_action", "error", "paused"]; - if (states.indexOf(job.state) !== -1) { - return 0.5; - } - return 1.0; - } - anchors.fill: parent; - } - - UM.RecolorImage { - id: ultibotImage; - anchors.centerIn: parent; - color: UM.Theme.getColor("monitor_placeholder_image"); // TODO: Theme! - height: parent.height; - source: "../svg/ultibot.svg"; - sourceSize { - height: height; - width: width; - } - /* Since print jobs ALWAYS have an image url, we have to check if that image URL errors or - not in order to determine if we show the placeholder (ultibot) image instead. */ - visible: job && previewImage.status == Image.Error; - width: parent.width; - } - - UM.RecolorImage { - id: statusImage; - anchors.centerIn: parent; - color: "black"; // TODO: Theme! - height: Math.round(0.5 * parent.height); - source: job && job.state == "error" ? "../svg/aborted-icon.svg" : ""; - sourceSize { - height: height; - width: width; - } - visible: source != ""; - width: Math.round(0.5 * parent.width); - } -} \ No newline at end of file diff --git a/plugins/UM3NetworkPrinting/resources/qml/PrintJobTitle.qml b/plugins/UM3NetworkPrinting/resources/qml/PrintJobTitle.qml deleted file mode 100644 index f9f7b5ae87..0000000000 --- a/plugins/UM3NetworkPrinting/resources/qml/PrintJobTitle.qml +++ /dev/null @@ -1,59 +0,0 @@ -// Copyright (c) 2018 Ultimaker B.V. -// Cura is released under the terms of the LGPLv3 or higher. - -import QtQuick 2.3 -import QtQuick.Controls 2.0 -import UM 1.3 as UM - -Column { - property var job: null; - height: childrenRect.height; - spacing: Math.floor( UM.Theme.getSize("default_margin").height / 2); // TODO: Use explicit theme size - width: parent.width; - - Item { - id: jobName; - height: UM.Theme.getSize("monitor_text_line").height; - width: parent.width; - - // Skeleton loading - Rectangle { - color: UM.Theme.getColor("monitor_skeleton_fill"); - height: parent.height; - visible: !job; - width: Math.round(parent.width / 3); - } - - Label { - anchors.fill: parent; - color: UM.Theme.getColor("text"); - elide: Text.ElideRight; - font: UM.Theme.getFont("default_bold"); - text: job && job.name ? job.name : ""; - visible: job; - } - } - - Item { - id: ownerName; - height: UM.Theme.getSize("monitor_text_line").height; - width: parent.width; - - // Skeleton loading - Rectangle { - color: UM.Theme.getColor("monitor_skeleton_fill"); - height: parent.height; - visible: !job; - width: Math.round(parent.width / 2); - } - - Label { - anchors.fill: parent; - color: UM.Theme.getColor("text") - elide: Text.ElideRight; - font: UM.Theme.getFont("default"); - text: job ? job.owner : ""; - visible: job; - } - } -} \ No newline at end of file diff --git a/plugins/UM3NetworkPrinting/resources/qml/PrinterCard.qml b/plugins/UM3NetworkPrinting/resources/qml/PrinterCard.qml deleted file mode 100644 index 24beaf70fe..0000000000 --- a/plugins/UM3NetworkPrinting/resources/qml/PrinterCard.qml +++ /dev/null @@ -1,241 +0,0 @@ -// Copyright (c) 2018 Ultimaker B.V. -// Cura is released under the terms of the LGPLv3 or higher. - -import QtQuick 2.3 -import QtQuick.Dialogs 1.1 -import QtQuick.Controls 2.0 -import QtQuick.Controls.Styles 1.3 -import QtGraphicalEffects 1.0 -import UM 1.3 as UM - -Item { - id: root; - property var shadowRadius: UM.Theme.getSize("monitor_shadow_radius").width; - property var shadowOffset: UM.Theme.getSize("monitor_shadow_offset").width; - property var printer: null; - property var collapsed: true; - height: childrenRect.height + shadowRadius * 2; // Bubbles upward - width: parent.width; // Bubbles downward - - // The actual card (white block) - Rectangle { - // 5px margin, but shifted 2px vertically because of the shadow - anchors { - bottomMargin: root.shadowRadius + root.shadowOffset; - leftMargin: root.shadowRadius; - rightMargin: root.shadowRadius; - topMargin: root.shadowRadius - root.shadowOffset; - } - color: { - if (!printer) { - return UM.Theme.getColor("monitor_card_background_inactive"); - } - if (printer.state == "disabled") { - return UM.Theme.getColor("monitor_card_background_inactive"); - } else { - return UM.Theme.getColor("monitor_card_background"); - } - } - height: childrenRect.height; - layer.effect: DropShadow { - radius: root.shadowRadius; - verticalOffset: root.shadowOffset; - color: "#3F000000"; // 25% shadow - } - layer.enabled: true - width: parent.width - 2 * shadowRadius; - - Column { - id: cardContents; - height: childrenRect.height; - width: parent.width; - - // Main card - Item { - id: mainCard; - anchors { - left: parent.left; - leftMargin: UM.Theme.getSize("default_margin").width; - right: parent.right; - rightMargin: UM.Theme.getSize("default_margin").width; - } - height: 60 * screenScaleFactor + 2 * UM.Theme.getSize("default_margin").height; - width: parent.width; - - // Machine icon - Item { - id: machineIcon; - anchors.verticalCenter: parent.verticalCenter; - height: parent.height - 2 * UM.Theme.getSize("default_margin").width; - width: height; - - // Skeleton - Rectangle { - anchors.fill: parent; - color: UM.Theme.getColor("monitor_skeleton_fill_dark"); - radius: UM.Theme.getSize("default_margin").width; - visible: !printer; - } - - // Content - UM.RecolorImage { - anchors.centerIn: parent; - color: { - if (printer && printer.activePrintJob != undefined) { - return UM.Theme.getColor("monitor_printer_icon"); - } - return UM.Theme.getColor("monitor_printer_icon_inactive"); - } - height: sourceSize.height; - source: { - if (!printer) { - return ""; - } - switch(printer.type) { - case "Ultimaker 3": - return "../svg/UM3-icon.svg"; - case "Ultimaker 3 Extended": - return "../svg/UM3x-icon.svg"; - case "Ultimaker S5": - return "../svg/UMs5-icon.svg"; - } - } - visible: printer; - width: sourceSize.width; - } - } - - // Printer info - Item { - id: printerInfo; - anchors { - left: machineIcon.right; - leftMargin: UM.Theme.getSize("wide_margin").width; - right: collapseIcon.left; - verticalCenter: machineIcon.verticalCenter; - } - height: childrenRect.height; - - // Machine name - Item { - id: machineNameLabel; - height: UM.Theme.getSize("monitor_text_line").height; - width: { - var percent = printer ? 0.75 : 0.3; - return Math.round(parent.width * percent); - } - - // Skeleton - Rectangle { - anchors.fill: parent; - color: UM.Theme.getColor("monitor_skeleton_fill_dark"); - visible: !printer; - } - - // Actual content - Label { - anchors.fill: parent; - color: UM.Theme.getColor("text"); - elide: Text.ElideRight; - font: UM.Theme.getFont("default_bold"); - text: printer ? printer.name : ""; - visible: printer; - width: parent.width; - } - } - - // Job name - Item { - id: activeJobLabel; - anchors { - top: machineNameLabel.bottom; - topMargin: Math.round(UM.Theme.getSize("default_margin").height / 2); - } - height: UM.Theme.getSize("monitor_text_line").height; - width: Math.round(parent.width * 0.75); - - // Skeleton - Rectangle { - anchors.fill: parent; - color: UM.Theme.getColor("monitor_skeleton_fill_dark"); - visible: !printer; - } - - // Actual content - Label { - anchors.fill: parent; - color: UM.Theme.getColor("monitor_text_inactive"); - elide: Text.ElideRight; - font: UM.Theme.getFont("default"); - text: { - if (!printer) { - return ""; - } - if (printer.state == "disabled") { - return catalog.i18nc("@label", "Not available"); - } else if (printer.state == "unreachable") { - return catalog.i18nc("@label", "Unreachable"); - } - if (printer.activePrintJob != null && printer.activePrintJob.name) { - return printer.activePrintJob.name; - } - return catalog.i18nc("@label", "Available"); - } - visible: printer; - } - } - } - - // Collapse icon - UM.RecolorImage { - id: collapseIcon; - anchors { - right: parent.right; - rightMargin: UM.Theme.getSize("default_margin").width; - verticalCenter: parent.verticalCenter; - } - color: UM.Theme.getColor("text"); - height: 15 * screenScaleFactor; // TODO: Theme! - source: root.collapsed ? UM.Theme.getIcon("arrow_left") : UM.Theme.getIcon("arrow_bottom"); - sourceSize { - height: height; - width: width; - } - visible: printer; - width: 15 * screenScaleFactor; // TODO: Theme! - } - - MouseArea { - anchors.fill: parent; - enabled: printer; - onClicked: { - if (model && root.collapsed) { - printerList.currentIndex = model.index; - } else { - printerList.currentIndex = -1; - } - } - } - - Connections { - target: printerList; - onCurrentIndexChanged: { - root.collapsed = printerList.currentIndex != model.index; - } - } - } - // Detailed card - PrinterCardDetails { - collapsed: root.collapsed; - printer: root.printer; - visible: root.printer; - } - - // Progress bar - PrinterCardProgressBar { - visible: printer && printer.activePrintJob != null; - width: parent.width; - } - } - } -} diff --git a/plugins/UM3NetworkPrinting/resources/qml/PrinterCardDetails.qml b/plugins/UM3NetworkPrinting/resources/qml/PrinterCardDetails.qml deleted file mode 100644 index 31da388b00..0000000000 --- a/plugins/UM3NetworkPrinting/resources/qml/PrinterCardDetails.qml +++ /dev/null @@ -1,75 +0,0 @@ -// Copyright (c) 2018 Ultimaker B.V. -// Cura is released under the terms of the LGPLv3 or higher. - -import QtQuick 2.3 -import QtQuick.Dialogs 1.1 -import QtQuick.Controls 2.0 -import QtQuick.Controls.Styles 1.3 -import QtGraphicalEffects 1.0 -import QtQuick.Controls 1.4 as LegacyControls -import UM 1.3 as UM - -Item { - id: root; - property var printer: null; - property var printJob: printer ? printer.activePrintJob : null; - property var collapsed: true; - Behavior on height { NumberAnimation { duration: 100 } } - Behavior on opacity { NumberAnimation { duration: 100 } } - height: collapsed ? 0 : childrenRect.height; - opacity: collapsed ? 0 : 1; - width: parent.width; - - Column { - id: contentColumn; - anchors { - left: parent.left; - leftMargin: UM.Theme.getSize("default_margin").width; - right: parent.right; - rightMargin: UM.Theme.getSize("default_margin").width; - } - height: childrenRect.height + UM.Theme.getSize("default_margin").height; - spacing: UM.Theme.getSize("default_margin").height; - width: parent.width; - - HorizontalLine {} - - PrinterInfoBlock { - printer: root.printer; - printJob: root.printer ? root.printer.activePrintJob : null; - } - - HorizontalLine {} - - Row { - height: childrenRect.height; - visible: root.printJob; - width: parent.width; - - PrintJobTitle { - job: root.printer ? root.printer.activePrintJob : null; - } - PrintJobContextMenu { - id: contextButton; - anchors { - right: parent.right; - rightMargin: UM.Theme.getSize("wide_margin").width; - } - printJob: root.printer ? root.printer.activePrintJob : null; - visible: printJob; - } - } - - PrintJobPreview { - anchors.horizontalCenter: parent.horizontalCenter; - job: root.printer && root.printer.activePrintJob ? root.printer.activePrintJob : null; - visible: root.printJob; - } - - CameraButton { - id: showCameraButton; - iconSource: "../svg/camera-icon.svg"; - visible: root.printer; - } - } -} diff --git a/plugins/UM3NetworkPrinting/resources/qml/PrinterCardProgressBar.qml b/plugins/UM3NetworkPrinting/resources/qml/PrinterCardProgressBar.qml deleted file mode 100644 index e86c959b8c..0000000000 --- a/plugins/UM3NetworkPrinting/resources/qml/PrinterCardProgressBar.qml +++ /dev/null @@ -1,108 +0,0 @@ -// Copyright (c) 2018 Ultimaker B.V. -// Cura is released under the terms of the LGPLv3 or higher. - -import QtQuick 2.3 -import QtQuick.Controls.Styles 1.3 -import QtQuick.Controls 1.4 -import UM 1.3 as UM - -ProgressBar { - property var progress: { - if (!printer || printer.activePrintJob == null) { - return 0; - } - var result = printer.activePrintJob.timeElapsed / printer.activePrintJob.timeTotal; - if (result > 1.0) { - result = 1.0; - } - return result; - } - style: ProgressBarStyle { - property var remainingTime: { - if (!printer || printer.activePrintJob == null) { - return 0; - } - /* Sometimes total minus elapsed is less than 0. Use Math.max() to prevent remaining - time from ever being less than 0. Negative durations cause strange behavior such - as displaying "-1h -1m". */ - return Math.max(printer.activePrintJob.timeTotal - printer.activePrintJob.timeElapsed, 0); - } - property var progressText: { - if (printer === null ) { - return ""; - } - switch (printer.activePrintJob.state) { - case "wait_cleanup": - if (printer.activePrintJob.timeTotal > printer.activePrintJob.timeElapsed) { - return catalog.i18nc("@label:status", "Aborted"); - } - return catalog.i18nc("@label:status", "Finished"); - case "pre_print": - case "sent_to_printer": - return catalog.i18nc("@label:status", "Preparing"); - case "aborted": - return catalog.i18nc("@label:status", "Aborted"); - case "wait_user_action": - return catalog.i18nc("@label:status", "Aborted"); - case "pausing": - return catalog.i18nc("@label:status", "Pausing"); - case "paused": - return OutputDevice.formatDuration( remainingTime ); - case "resuming": - return catalog.i18nc("@label:status", "Resuming"); - case "queued": - return catalog.i18nc("@label:status", "Action required"); - default: - return OutputDevice.formatDuration( remainingTime ); - } - } - background: Rectangle { - color: UM.Theme.getColor("monitor_progress_background"); - implicitHeight: visible ? 24 : 0; - implicitWidth: 100; - } - progress: Rectangle { - id: progressItem; - color: { - if (! printer || !printer.activePrintJob) { - return "black"; - } - var state = printer.activePrintJob.state - var inactiveStates = [ - "pausing", - "paused", - "resuming", - "wait_cleanup" - ]; - if (inactiveStates.indexOf(state) > -1 && remainingTime > 0) { - return UM.Theme.getColor("monitor_progress_fill_inactive"); - } else { - return UM.Theme.getColor("monitor_progress_fill"); - } - } - - Label { - id: progressLabel; - anchors { - left: parent.left; - leftMargin: getTextOffset(); - } - text: progressText; - anchors.verticalCenter: parent.verticalCenter; - color: progressItem.width + progressLabel.width < control.width ? UM.Theme.getColor("text") : UM.Theme.getColor("monitor_progress_fill_text"); - width: contentWidth; - font: UM.Theme.getFont("default"); - } - - function getTextOffset() { - if (progressItem.width + progressLabel.width + 16 < control.width) { - return progressItem.width + UM.Theme.getSize("default_margin").width; - } else { - return progressItem.width - progressLabel.width - UM.Theme.getSize("default_margin").width; - } - } - } - } - value: progress; - width: parent.width; -} \ No newline at end of file diff --git a/plugins/UM3NetworkPrinting/resources/qml/PrinterFamilyPill.qml b/plugins/UM3NetworkPrinting/resources/qml/PrinterFamilyPill.qml deleted file mode 100644 index 0a88b053a8..0000000000 --- a/plugins/UM3NetworkPrinting/resources/qml/PrinterFamilyPill.qml +++ /dev/null @@ -1,32 +0,0 @@ -// Copyright (c) 2018 Ultimaker B.V. -// Cura is released under the terms of the LGPLv3 or higher. - -import QtQuick 2.2 -import QtQuick.Controls 1.4 -import UM 1.2 as UM - -Item { - property alias text: familyNameLabel.text; - property var padding: 3 * screenScaleFactor; // TODO: Theme! - implicitHeight: familyNameLabel.contentHeight + 2 * padding; // Apply the padding to top and bottom. - implicitWidth: Math.max(48 * screenScaleFactor, familyNameLabel.contentWidth + implicitHeight); // The extra height is added to ensure the radius doesn't cut something off. - - Rectangle { - id: background; - anchors { - horizontalCenter: parent.horizontalCenter; - right: parent.right; - } - color: familyNameLabel.text.length < 1 ? UM.Theme.getColor("monitor_skeleton_fill") : UM.Theme.getColor("monitor_pill_background"); - height: parent.height; - radius: 0.5 * height; - width: parent.width; - } - - Label { - id: familyNameLabel; - anchors.centerIn: parent; - color: UM.Theme.getColor("text"); - text: ""; - } -} \ No newline at end of file diff --git a/plugins/UM3NetworkPrinting/resources/qml/PrinterInfoBlock.qml b/plugins/UM3NetworkPrinting/resources/qml/PrinterInfoBlock.qml deleted file mode 100644 index 92a8f1dcb3..0000000000 --- a/plugins/UM3NetworkPrinting/resources/qml/PrinterInfoBlock.qml +++ /dev/null @@ -1,83 +0,0 @@ -// Copyright (c) 2018 Ultimaker B.V. -// Cura is released under the terms of the LGPLv3 or higher. - -import QtQuick 2.3 -import QtQuick.Dialogs 1.1 -import QtQuick.Controls 2.0 -import QtQuick.Controls.Styles 1.3 -import QtGraphicalEffects 1.0 -import QtQuick.Controls 1.4 as LegacyControls -import UM 1.3 as UM - -// Includes printer type pill and extuder configurations - -Item { - id: root; - property var printer: null; - property var printJob: null; - width: parent.width; - height: childrenRect.height; - - // Printer family pills - Row { - id: printerFamilyPills; - anchors { - left: parent.left; - right: parent.right; - } - height: childrenRect.height; - spacing: Math.round(0.5 * UM.Theme.getSize("default_margin").width); - width: parent.width; - - Repeater { - id: compatiblePills; - delegate: PrinterFamilyPill { - text: modelData; - } - model: printJob ? printJob.compatibleMachineFamilies : []; - visible: printJob; - - } - - PrinterFamilyPill { - text: printer ? printer.type : ""; - visible: !compatiblePills.visible && printer; - } - } - - // Extruder info - Row { - id: extrudersInfo; - anchors { - left: parent.left; - right: parent.right; - rightMargin: UM.Theme.getSize("default_margin").width; - top: printerFamilyPills.bottom; - topMargin: UM.Theme.getSize("default_margin").height; - } - height: childrenRect.height; - spacing: UM.Theme.getSize("default_margin").width; - width: parent.width; - - PrintCoreConfiguration { - width: Math.round(parent.width / 2) * screenScaleFactor; - printCoreConfiguration: getExtruderConfig(0); - } - - PrintCoreConfiguration { - width: Math.round(parent.width / 2) * screenScaleFactor; - printCoreConfiguration: getExtruderConfig(1); - } - } - - function getExtruderConfig( i ) { - if (root.printJob) { - // Use more-specific print job if possible - return root.printJob.configuration.extruderConfigurations[i]; - } - if (root.printer) { - return root.printer.printerConfiguration.extruderConfigurations[i]; - } - return null; - } -} \ No newline at end of file diff --git a/plugins/UM3NetworkPrinting/resources/qml/UM3InfoComponents.qml b/plugins/UM3NetworkPrinting/resources/qml/UM3InfoComponents.qml index 105143c851..643c8164a7 100644 --- a/plugins/UM3NetworkPrinting/resources/qml/UM3InfoComponents.qml +++ b/plugins/UM3NetworkPrinting/resources/qml/UM3InfoComponents.qml @@ -29,7 +29,7 @@ Item { Button { height: UM.Theme.getSize("save_button_save_to_button").height; onClicked: Cura.MachineManager.printerOutputDevices[0].requestAuthentication(); - style: UM.Theme.styles.sidebar_action_button; + style: UM.Theme.styles.print_setup_action_button; text: catalog.i18nc("@action:button", "Request Access"); tooltip: catalog.i18nc("@info:tooltip", "Send access request to the printer"); visible: printerConnected && !printerAcceptsCommands && !authenticationRequested; @@ -38,7 +38,7 @@ Item { Button { height: UM.Theme.getSize("save_button_save_to_button").height; onClicked: connectActionDialog.show(); - style: UM.Theme.styles.sidebar_action_button; + style: UM.Theme.styles.print_setup_action_button; text: catalog.i18nc("@action:button", "Connect"); tooltip: catalog.i18nc("@info:tooltip", "Connect to a printer"); visible: !printerConnected; diff --git a/plugins/UM3NetworkPrinting/src/ClusterUM3OutputDevice.py b/plugins/UM3NetworkPrinting/src/ClusterUM3OutputDevice.py index e31229680c..ef890fc4ed 100644 --- a/plugins/UM3NetworkPrinting/src/ClusterUM3OutputDevice.py +++ b/plugins/UM3NetworkPrinting/src/ClusterUM3OutputDevice.py @@ -64,7 +64,7 @@ class ClusterUM3OutputDevice(NetworkedPrinterOutputDevice): self._print_jobs = [] # type: List[UM3PrintJobOutputModel] self._received_print_jobs = False # type: bool - self._monitor_view_qml_path = os.path.join(os.path.dirname(os.path.abspath(__file__)), "../resources/qml/ClusterMonitorItem.qml") + self._monitor_view_qml_path = os.path.join(os.path.dirname(os.path.abspath(__file__)), "../resources/qml/MonitorStage.qml") # See comments about this hack with the clusterPrintersChanged signal self.printersChanged.connect(self.clusterPrintersChanged) @@ -607,17 +607,24 @@ class ClusterUM3OutputDevice(NetworkedPrinterOutputDevice): def _createMaterialOutputModel(self, material_data: Dict[str, Any]) -> "MaterialOutputModel": material_manager = CuraApplication.getInstance().getMaterialManager() - material_group_list = material_manager.getMaterialGroupListByGUID(material_data["guid"]) - # This can happen if the connected machine has no material in one or more extruders (if GUID is empty), or the - # material is unknown to Cura, so we should return an "empty" or "unknown" material model. + material_group_list = None + + # Avoid crashing if there is no "guid" field in the metadata + material_guid = material_data.get("guid") + if material_guid: + material_group_list = material_manager.getMaterialGroupListByGUID(material_guid) + + # This can happen if the connected machine has no material in one or more extruders (if GUID is empty), or the + # material is unknown to Cura, so we should return an "empty" or "unknown" material model. if material_group_list is None: - material_name = "Empty" if len(material_data["guid"]) == 0 else "Unknown" - return MaterialOutputModel(guid = material_data["guid"], - type = material_data.get("type", ""), - color = material_data.get("color", ""), - brand = material_data.get("brand", ""), - name = material_data.get("name", material_name) - ) + material_name = i18n_catalog.i18nc("@label:material", "Empty") if len(material_data.get("guid", "")) == 0 \ + else i18n_catalog.i18nc("@label:material", "Unknown") + return MaterialOutputModel(guid = material_data.get("guid", ""), + type = material_data.get("type", ""), + color = material_data.get("color", ""), + brand = material_data.get("brand", ""), + name = material_data.get("name", material_name) + ) # Sort the material groups by "is_read_only = True" first, and then the name alphabetically. read_only_material_group_list = list(filter(lambda x: x.is_read_only, material_group_list)) @@ -643,9 +650,10 @@ class ClusterUM3OutputDevice(NetworkedPrinterOutputDevice): color = material_data["color"] brand = material_data["brand"] material_type = material_data["material"] - name = "Empty" if material_data["material"] == "empty" else "Unknown" - return MaterialOutputModel(guid=material_data["guid"], type=material_type, - brand=brand, color=color, name=name) + name = i18n_catalog.i18nc("@label:material", "Empty") if material_data["material"] == "empty" \ + else i18n_catalog.i18nc("@label:material", "Unknown") + return MaterialOutputModel(guid = material_data["guid"], type = material_type, + brand = brand, color = color, name = name) def _updatePrinter(self, printer: PrinterOutputModel, data: Dict[str, Any]) -> None: # For some unknown reason the cluster wants UUID for everything, except for sending a job directly to a printer. diff --git a/plugins/USBPrinting/MonitorItem.qml b/plugins/USBPrinting/MonitorItem.qml new file mode 100644 index 0000000000..8041698ef0 --- /dev/null +++ b/plugins/USBPrinting/MonitorItem.qml @@ -0,0 +1,46 @@ +// Copyright (c) 2018 Ultimaker B.V. +// Cura is released under the terms of the LGPLv3 or higher. + +import QtQuick 2.10 +import QtQuick.Controls 2.0 +import QtQuick.Layouts 1.3 + +import UM 1.2 as UM +import Cura 1.0 as Cura +Component +{ + Item + { + Rectangle + { + anchors.right: parent.right + width: parent.width * 0.3 + anchors.top: parent.top + anchors.bottom: parent.bottom + + Cura.PrintMonitor + { + anchors.fill: parent + } + + Rectangle + { + id: footerSeparator + width: parent.width + height: UM.Theme.getSize("wide_lining").height + color: UM.Theme.getColor("wide_lining") + anchors.bottom: monitorButton.top + anchors.bottomMargin: UM.Theme.getSize("thick_margin").height + } + + // MonitorButton is actually the bottom footer panel. + Cura.MonitorButton + { + id: monitorButton + anchors.bottom: parent.bottom + anchors.left: parent.left + anchors.right: parent.right + } + } + } +} \ No newline at end of file diff --git a/plugins/USBPrinting/USBPrinterOutputDevice.py b/plugins/USBPrinting/USBPrinterOutputDevice.py index e1c39ff8fa..1d42e70366 100644 --- a/plugins/USBPrinting/USBPrinterOutputDevice.py +++ b/plugins/USBPrinting/USBPrinterOutputDevice.py @@ -1,5 +1,6 @@ # Copyright (c) 2018 Ultimaker B.V. # Cura is released under the terms of the LGPLv3 or higher. +import os from UM.Logger import Logger from UM.i18n import i18nCatalog @@ -64,7 +65,7 @@ class USBPrinterOutputDevice(PrinterOutputDevice): self._accepts_commands = True self._paused = False - self._printer_busy = False # when printer is preheating and waiting (M190/M109), or when waiting for action on the printer + self._printer_busy = False # When printer is preheating and waiting (M190/M109), or when waiting for action on the printer self.setConnectionText(catalog.i18nc("@info:status", "Connected via USB")) @@ -77,6 +78,8 @@ class USBPrinterOutputDevice(PrinterOutputDevice): self._firmware_name_requested = False self._firmware_updater = AvrFirmwareUpdater(self) + self._monitor_view_qml_path = os.path.join(os.path.dirname(os.path.abspath(__file__)), "MonitorItem.qml") + CuraApplication.getInstance().getOnExitCallbackManager().addCallback(self._checkActivePrintingUponAppExit) # This is a callback function that checks if there is any printing in progress via USB when the application tries diff --git a/plugins/UltimakerMachineActions/UMOCheckupMachineAction.qml b/plugins/UltimakerMachineActions/UMOCheckupMachineAction.qml index 4a1d42e248..2a01cfaa40 100644 --- a/plugins/UltimakerMachineActions/UMOCheckupMachineAction.qml +++ b/plugins/UltimakerMachineActions/UMOCheckupMachineAction.qml @@ -19,7 +19,7 @@ Cura.MachineAction property bool heatupBedStarted: false property bool printerConnected: Cura.MachineManager.printerConnected - UM.I18nCatalog { id: catalog; name:"cura"} + UM.I18nCatalog { id: catalog; name: "cura"} Label { id: pageTitle diff --git a/plugins/UserAgreement/UserAgreement.qml b/plugins/UserAgreement/UserAgreement.qml index 4ee03f4ad5..2e5893fc41 100644 --- a/plugins/UserAgreement/UserAgreement.qml +++ b/plugins/UserAgreement/UserAgreement.qml @@ -36,7 +36,7 @@ UM.Dialog width: parent.width anchors.bottomMargin: UM.Theme.getSize("default_margin").height - UM.I18nCatalog { id: catalog; name:"cura" } + UM.I18nCatalog { id: catalog; name: "cura" } Button { diff --git a/resources/bundled_packages/cura.json b/resources/bundled_packages/cura.json index 33c6304fc5..e1c55992f9 100644 --- a/resources/bundled_packages/cura.json +++ b/resources/bundled_packages/cura.json @@ -373,6 +373,23 @@ } } }, + "PreviewStage": { + "package_info": { + "package_id": "PreviewStage", + "package_type": "plugin", + "display_name": "Preview Stage", + "description": "Provides a preview stage in Cura.", + "package_version": "1.0.0", + "sdk_version": 5, + "website": "https://ultimaker.com", + "author": { + "author_id": "UltimakerPackages", + "display_name": "Ultimaker B.V.", + "email": "plugins@ultimaker.com", + "website": "https://ultimaker.com" + } + } + }, "RemovableDriveOutputDevice": { "package_info": { "package_id": "RemovableDriveOutputDevice", diff --git a/resources/qml/AboutDialog.qml b/resources/qml/AboutDialog.qml deleted file mode 100644 index 9a7e53260b..0000000000 --- a/resources/qml/AboutDialog.qml +++ /dev/null @@ -1,170 +0,0 @@ -// Copyright (c) 2015 Ultimaker B.V. -// Cura is released under the terms of the LGPLv3 or higher. - -import QtQuick 2.2 -import QtQuick.Controls 1.1 -import QtQuick.Window 2.1 - -import UM 1.1 as UM - -UM.Dialog -{ - id: base - - //: About dialog title - title: catalog.i18nc("@title:window","About Cura") - - minimumWidth: 500 * screenScaleFactor - minimumHeight: 650 * screenScaleFactor - width: minimumWidth - height: minimumHeight - - Rectangle - { - width: parent.width + 2 * margin // margin from Dialog.qml - height: version.y + version.height + margin - - anchors.top: parent.top - anchors.topMargin: - margin - anchors.horizontalCenter: parent.horizontalCenter - - color: UM.Theme.getColor("viewport_background") - } - - Image - { - id: logo - width: (base.minimumWidth * 0.85) | 0 - height: (width * (1/4.25)) | 0 - - source: UM.Theme.getImage("logo") - - sourceSize.width: width - sourceSize.height: height - anchors.top: parent.top - anchors.topMargin: ((base.minimumWidth - width) / 2) | 0 - anchors.horizontalCenter: parent.horizontalCenter - - UM.I18nCatalog{id: catalog; name:"cura"} - } - - Label - { - id: version - - text: catalog.i18nc("@label","version: %1").arg(UM.Application.version) - font: UM.Theme.getFont("large") - color: UM.Theme.getColor("text") - anchors.right : logo.right - anchors.top: logo.bottom - anchors.topMargin: (UM.Theme.getSize("default_margin").height / 2) | 0 - } - - Label - { - id: description - width: parent.width - - //: About dialog application description - text: catalog.i18nc("@label","End-to-end solution for fused filament 3D printing.") - font: UM.Theme.getFont("system") - wrapMode: Text.WordWrap - anchors.top: version.bottom - anchors.topMargin: UM.Theme.getSize("default_margin").height - } - - Label - { - id: creditsNotes - width: parent.width - - //: About dialog application author note - text: catalog.i18nc("@info:credit","Cura is developed by Ultimaker B.V. in cooperation with the community.\nCura proudly uses the following open source projects:") - font: UM.Theme.getFont("system") - wrapMode: Text.WordWrap - anchors.top: description.bottom - anchors.topMargin: UM.Theme.getSize("default_margin").height - } - - ScrollView - { - id: credits - anchors.top: creditsNotes.bottom - anchors.topMargin: UM.Theme.getSize("default_margin").height - - width: parent.width - height: base.height - y - (2 * UM.Theme.getSize("default_margin").height + closeButton.height) - - ListView - { - id: projectsList - - width: parent.width - - delegate: Row - { - Label - { - text: "%2".arg(model.url).arg(model.name) - width: (projectsList.width * 0.25) | 0 - elide: Text.ElideRight - onLinkActivated: Qt.openUrlExternally(link) - } - Label - { - text: model.description - elide: Text.ElideRight - width: (projectsList.width * 0.6) | 0 - } - Label - { - text: model.license - elide: Text.ElideRight - width: (projectsList.width * 0.15) | 0 - } - } - model: ListModel - { - id: projectsModel - } - Component.onCompleted: - { - projectsModel.append({ name:"Cura", description: catalog.i18nc("@label", "Graphical user interface"), license: "LGPLv3", url: "https://github.com/Ultimaker/Cura" }); - projectsModel.append({ name:"Uranium", description: catalog.i18nc("@label", "Application framework"), license: "LGPLv3", url: "https://github.com/Ultimaker/Uranium" }); - projectsModel.append({ name:"CuraEngine", description: catalog.i18nc("@label", "G-code generator"), license: "AGPLv3", url: "https://github.com/Ultimaker/CuraEngine" }); - projectsModel.append({ name:"libArcus", description: catalog.i18nc("@label", "Interprocess communication library"), license: "LGPLv3", url: "https://github.com/Ultimaker/libArcus" }); - - projectsModel.append({ name:"Python", description: catalog.i18nc("@label", "Programming language"), license: "Python", url: "http://python.org/" }); - projectsModel.append({ name:"Qt5", description: catalog.i18nc("@label", "GUI framework"), license: "LGPLv3", url: "https://www.qt.io/" }); - projectsModel.append({ name:"PyQt", description: catalog.i18nc("@label", "GUI framework bindings"), license: "GPL", url: "https://riverbankcomputing.com/software/pyqt" }); - projectsModel.append({ name:"SIP", description: catalog.i18nc("@label", "C/C++ Binding library"), license: "GPL", url: "https://riverbankcomputing.com/software/sip" }); - projectsModel.append({ name:"Protobuf", description: catalog.i18nc("@label", "Data interchange format"), license: "BSD", url: "https://developers.google.com/protocol-buffers" }); - projectsModel.append({ name:"SciPy", description: catalog.i18nc("@label", "Support library for scientific computing"), license: "BSD-new", url: "https://www.scipy.org/" }); - projectsModel.append({ name:"NumPy", description: catalog.i18nc("@label", "Support library for faster math"), license: "BSD", url: "http://www.numpy.org/" }); - projectsModel.append({ name:"NumPy-STL", description: catalog.i18nc("@label", "Support library for handling STL files"), license: "BSD", url: "https://github.com/WoLpH/numpy-stl" }); - projectsModel.append({ name:"Shapely", description: catalog.i18nc("@label", "Support library for handling planar objects"), license: "BSD", url: "https://github.com/Toblerity/Shapely" }); - projectsModel.append({ name:"Trimesh", description: catalog.i18nc("@label", "Support library for handling triangular meshes"), license: "MIT", url: "https://trimsh.org" }); - projectsModel.append({ name:"NetworkX", description: catalog.i18nc("@label", "Support library for analysis of complex networks"), license: "3-clause BSD", url: "https://networkx.github.io/" }); - projectsModel.append({ name:"libSavitar", description: catalog.i18nc("@label", "Support library for handling 3MF files"), license: "LGPLv3", url: "https://github.com/ultimaker/libsavitar" }); - projectsModel.append({ name:"libCharon", description: catalog.i18nc("@label", "Support library for file metadata and streaming"), license: "LGPLv3", url: "https://github.com/ultimaker/libcharon" }); - projectsModel.append({ name:"PySerial", description: catalog.i18nc("@label", "Serial communication library"), license: "Python", url: "http://pyserial.sourceforge.net/" }); - projectsModel.append({ name:"python-zeroconf", description: catalog.i18nc("@label", "ZeroConf discovery library"), license: "LGPL", url: "https://github.com/jstasiak/python-zeroconf" }); - projectsModel.append({ name:"Clipper", description: catalog.i18nc("@label", "Polygon clipping library"), license: "Boost", url: "http://www.angusj.com/delphi/clipper.php" }); - projectsModel.append({ name:"Requests", description: catalog.i18nc("@Label", "Python HTTP library"), license: "GPL", url: "http://docs.python-requests.org" }); - - projectsModel.append({ name:"Noto Sans", description: catalog.i18nc("@label", "Font"), license: "Apache 2.0", url: "https://www.google.com/get/noto/" }); - projectsModel.append({ name:"Font-Awesome-SVG-PNG", description: catalog.i18nc("@label", "SVG icons"), license: "SIL OFL 1.1", url: "https://github.com/encharm/Font-Awesome-SVG-PNG" }); - projectsModel.append({ name:"AppImageKit", description: catalog.i18nc("@label", "Linux cross-distribution application deployment"), license: "MIT", url: "https://github.com/AppImage/AppImageKit" }); - } - } - } - - rightButtons: Button - { - //: Close about dialog button - id: closeButton - text: catalog.i18nc("@action:button","Close"); - - onClicked: base.visible = false; - } -} diff --git a/resources/qml/Account/AccountDetails.qml b/resources/qml/Account/AccountDetails.qml new file mode 100644 index 0000000000..bfb23930c6 --- /dev/null +++ b/resources/qml/Account/AccountDetails.qml @@ -0,0 +1,69 @@ +// Copyright (c) 2018 Ultimaker B.V. +// Cura is released under the terms of the LGPLv3 or higher. + +import QtQuick 2.7 +import QtQuick.Controls 2.1 + +import UM 1.4 as UM +import Cura 1.1 as Cura + +Column +{ + property var profile: null + property var loggedIn: false + property var profileImage: "" + + padding: UM.Theme.getSize("wide_margin").height + spacing: UM.Theme.getSize("wide_margin").height + + AvatarImage + { + id: avatar + width: UM.Theme.getSize("avatar_image").width + height: UM.Theme.getSize("avatar_image").height + anchors.horizontalCenter: parent.horizontalCenter + source: + { + if(loggedIn) + { + if(profileImage) + { + return profileImage + } + return UM.Theme.getImage("avatar_no_user") + } + return UM.Theme.getImage("avatar_no_user") + } + outlineColor: loggedIn ? UM.Theme.getColor("account_widget_outline_active") : UM.Theme.getColor("lining") + } + + Label + { + id: information + anchors.horizontalCenter: parent.horizontalCenter + horizontalAlignment: Text.AlignHCenter + renderType: Text.NativeRendering + text: loggedIn ? profile["username"] : catalog.i18nc("@label", "Please log in or create an account to\nenjoy all features of Ultimaker Cura.") + font: loggedIn ? UM.Theme.getFont("large") : UM.Theme.getFont("default") + color: UM.Theme.getColor("text") + } + + Loader + { + id: accountOperations + anchors.horizontalCenter: parent.horizontalCenter + sourceComponent: loggedIn ? userOperations : generalOperations + } + + Component + { + id: userOperations + UserOperations { } + } + + Component + { + id: generalOperations + GeneralOperations { } + } +} \ No newline at end of file diff --git a/resources/qml/Account/AccountWidget.qml b/resources/qml/Account/AccountWidget.qml new file mode 100644 index 0000000000..d3bd6fd130 --- /dev/null +++ b/resources/qml/Account/AccountWidget.qml @@ -0,0 +1,76 @@ +// Copyright (c) 2018 Ultimaker B.V. +// Cura is released under the terms of the LGPLv3 or higher. + +import QtQuick 2.7 +import QtQuick.Controls 2.1 + +import UM 1.4 as UM +import Cura 1.1 as Cura + +Button +{ + id: accountWidget + property var profile: Cura.API.account.userProfile + property var loggedIn: Cura.API.account.isLoggedIn + + implicitHeight: UM.Theme.getSize("main_window_header").height + implicitWidth: UM.Theme.getSize("main_window_header").height + + background: AvatarImage + { + id: avatar + + width: Math.round(0.8 * accountWidget.width) + height: Math.round(0.8 * accountWidget.height) + anchors.verticalCenter: accountWidget.verticalCenter + anchors.horizontalCenter: accountWidget.horizontalCenter + + source: + { + if(loggedIn) + { + if(profile["profile_image_url"]) + { + return profile["profile_image_url"] + } + return UM.Theme.getImage("avatar_no_user") + } + return UM.Theme.getImage("avatar_no_user") + } + outlineColor: loggedIn ? UM.Theme.getColor("account_widget_outline_active") : UM.Theme.getColor("lining") + } + + onClicked: popup.opened ? popup.close() : popup.open() + + Popup + { + id: popup + + y: parent.height + UM.Theme.getSize("default_arrow").height + x: parent.width - width + + closePolicy: Popup.CloseOnEscape | Popup.CloseOnPressOutsideParent + + opacity: opened ? 1 : 0 + Behavior on opacity { NumberAnimation { duration: 100 } } + + contentItem: AccountDetails + { + id: panel + profile: Cura.API.account.userProfile + loggedIn: Cura.API.account.isLoggedIn + profileImage: Cura.API.account.profileImageUrl + } + + background: UM.PointingRectangle + { + color: UM.Theme.getColor("tool_panel_background") + borderColor: UM.Theme.getColor("lining") + borderWidth: UM.Theme.getSize("default_lining").width + + target: Qt.point(width - (accountWidget.width / 2), -10) + + arrowSize: UM.Theme.getSize("default_arrow").width + } + } +} diff --git a/resources/qml/Account/AvatarImage.qml b/resources/qml/Account/AvatarImage.qml new file mode 100644 index 0000000000..b76aff6990 --- /dev/null +++ b/resources/qml/Account/AvatarImage.qml @@ -0,0 +1,56 @@ +// Copyright (c) 2018 Ultimaker B.V. +// Cura is released under the terms of the LGPLv3 or higher. + +import QtQuick 2.7 +import QtQuick.Controls 2.1 +import QtGraphicalEffects 1.0 + +import UM 1.4 as UM + +Item +{ + // This item shows the provided image while applying a round mask to it. + // It also shows a round border around it. The color is defined by the outlineColor property. + + id: avatar + + property alias source: profileImage.source + property alias outlineColor: profileImageOutline.color + + Image + { + id: profileImage + anchors.fill: parent + source: UM.Theme.getImage("avatar_default") + fillMode: Image.PreserveAspectCrop + visible: false + mipmap: true + } + + Rectangle + { + id: profileImageMask + anchors.fill: parent + radius: width + } + + OpacityMask + { + anchors.fill: parent + source: profileImage + maskSource: profileImageMask + cached: true + } + + UM.RecolorImage + { + id: profileImageOutline + anchors.centerIn: parent + // Make it a bit bigger than it has to, otherwise it sometimes shows a white border. + width: parent.width + 2 + height: parent.height + 2 + source: UM.Theme.getIcon("circle_outline") + sourceSize: Qt.size(parent.width, parent.height) + color: UM.Theme.getColor("account_widget_ouline_active") + } +} \ No newline at end of file diff --git a/resources/qml/Account/GeneralOperations.qml b/resources/qml/Account/GeneralOperations.qml new file mode 100644 index 0000000000..b9f1025d5e --- /dev/null +++ b/resources/qml/Account/GeneralOperations.qml @@ -0,0 +1,31 @@ +// Copyright (c) 2018 Ultimaker B.V. +// Cura is released under the terms of the LGPLv3 or higher. + +import QtQuick 2.2 +import QtQuick.Controls 1.1 + +import UM 1.4 as UM +import Cura 1.1 as Cura + +Row +{ + spacing: UM.Theme.getSize("default_margin").width + + Cura.SecondaryButton + { + width: UM.Theme.getSize("account_button").width + height: UM.Theme.getSize("account_button").height + text: catalog.i18nc("@button", "Create account") + onClicked: Qt.openUrlExternally("https://account.ultimaker.com/app/create") + fixedWidthMode: true + } + + Cura.PrimaryButton + { + width: UM.Theme.getSize("account_button").width + height: UM.Theme.getSize("account_button").height + text: catalog.i18nc("@button", "Login") + onClicked: Cura.API.account.login() + fixedWidthMode: true + } +} \ No newline at end of file diff --git a/resources/qml/Account/UserOperations.qml b/resources/qml/Account/UserOperations.qml new file mode 100644 index 0000000000..b9ffa395d6 --- /dev/null +++ b/resources/qml/Account/UserOperations.qml @@ -0,0 +1,31 @@ +// Copyright (c) 2018 Ultimaker B.V. +// Cura is released under the terms of the LGPLv3 or higher. + +import QtQuick 2.2 +import QtQuick.Controls 1.1 + +import UM 1.4 as UM +import Cura 1.1 as Cura + +Row +{ + spacing: UM.Theme.getSize("default_margin").width + + Cura.SecondaryButton + { + width: UM.Theme.getSize("account_button").width + height: UM.Theme.getSize("account_button").height + text: catalog.i18nc("@button", "Manage account") + onClicked: Qt.openUrlExternally("https://account.ultimaker.com") + fixedWidthMode: true + } + + Cura.PrimaryButton + { + width: UM.Theme.getSize("account_button").width + height: UM.Theme.getSize("account_button").height + text: catalog.i18nc("@button", "Logout") + onClicked: Cura.API.account.logout() + fixedWidthMode: true + } +} \ No newline at end of file diff --git a/resources/qml/ActionButton.qml b/resources/qml/ActionButton.qml new file mode 100644 index 0000000000..7177120f35 --- /dev/null +++ b/resources/qml/ActionButton.qml @@ -0,0 +1,119 @@ +// Copyright (c) 2018 Ultimaker B.V. +// Cura is released under the terms of the LGPLv3 or higher. + +import QtQuick 2.7 +import QtQuick.Controls 2.1 +import QtGraphicalEffects 1.0 // For the dropshadow +import UM 1.1 as UM +import Cura 1.0 as Cura + + +Button +{ + id: button + property bool isIconOnRightSide: false + + property alias iconSource: buttonIconLeft.source + property alias textFont: buttonText.font + property alias cornerRadius: backgroundRect.radius + property alias tooltip: tooltip.text + property alias cornerSide: backgroundRect.cornerSide + + property color color: UM.Theme.getColor("primary") + property color hoverColor: UM.Theme.getColor("primary_hover") + property color disabledColor: color + property color textColor: UM.Theme.getColor("button_text") + property color textHoverColor: textColor + property color textDisabledColor: textColor + property color outlineColor: color + property color outlineHoverColor: hoverColor + property color outlineDisabledColor: outlineColor + property alias shadowColor: shadow.color + property alias shadowEnabled: shadow.visible + + // This property is used to indicate whether the button has a fixed width or the width would depend on the contents + // Be careful when using fixedWidthMode, the translated texts can be too long that they won't fit. In any case, + // we elide the text to the right so the text will be cut off with the three dots at the end. + property var fixedWidthMode: false + + leftPadding: UM.Theme.getSize("default_margin").width + rightPadding: UM.Theme.getSize("default_margin").width + height: UM.Theme.getSize("action_button").height + hoverEnabled: true + + contentItem: Row + { + //Left side icon. Only displayed if !isIconOnRightSide. + UM.RecolorImage + { + id: buttonIconLeft + source: "" + height: buttonText.height + width: visible ? height : 0 + sourceSize.width: width + sourceSize.height: height + color: button.hovered ? button.textHoverColor : button.textColor + visible: source != "" && !button.isIconOnRightSide + anchors.verticalCenter: parent.verticalCenter + } + + Label + { + id: buttonText + text: button.text + color: button.enabled ? (button.hovered ? button.textHoverColor : button.textColor): button.textDisabledColor + font: UM.Theme.getFont("action_button") + visible: text != "" + renderType: Text.NativeRendering + anchors.verticalCenter: parent.verticalCenter + width: fixedWidthMode ? button.width - button.leftPadding - button.rightPadding : undefined + horizontalAlignment: Text.AlignHCenter + elide: Text.ElideRight + } + + //Right side icon. Only displayed if isIconOnRightSide. + UM.RecolorImage + { + id: buttonIconRight + source: buttonIconLeft.source + height: buttonText.height + width: visible ? height : 0 + sourceSize.width: width + sourceSize.height: height + color: buttonIconLeft.color + visible: source != "" && button.isIconOnRightSide + anchors.verticalCenter: buttonIconLeft.verticalCenter + } + } + + background: Cura.RoundedRectangle + { + id: backgroundRect + cornerSide: Cura.RoundedRectangle.Direction.All + color: button.enabled ? (button.hovered ? button.hoverColor : button.color) : button.disabledColor + radius: UM.Theme.getSize("action_button_radius").width + border.width: UM.Theme.getSize("default_lining").width + border.color: button.enabled ? (button.hovered ? button.outlineHoverColor : button.outlineColor) : button.outlineDisabledColor + } + + DropShadow + { + id: shadow + // Don't blur the shadow + radius: 0 + anchors.fill: backgroundRect + source: backgroundRect + verticalOffset: 2 + visible: false + // Should always be drawn behind the background. + z: backgroundRect.z - 1 + } + + ToolTip + { + id: tooltip + text: "" + delay: 500 + visible: text != "" && button.hovered + } +} \ No newline at end of file diff --git a/resources/qml/ActionPanel/ActionPanelWidget.qml b/resources/qml/ActionPanel/ActionPanelWidget.qml new file mode 100644 index 0000000000..a1cd81e9e9 --- /dev/null +++ b/resources/qml/ActionPanel/ActionPanelWidget.qml @@ -0,0 +1,55 @@ +// Copyright (c) 2018 Ultimaker B.V. +// Cura is released under the terms of the LGPLv3 or higher. + +import QtQuick 2.7 +import QtQuick.Controls 2.1 +import QtQuick.Layouts 1.3 + +import UM 1.2 as UM +import Cura 1.0 as Cura + + +// This element hold all the elements needed for the user to trigger the slicing process, and later +// to get information about the printing times, material consumption and the output process (such as +// saving to a file, printing over network, ... +Rectangle +{ + id: actionPanelWidget + + width: UM.Theme.getSize("action_panel_widget").width + height: childrenRect.height + 2 * UM.Theme.getSize("thick_margin").height + + color: UM.Theme.getColor("main_background") + border.width: UM.Theme.getSize("default_lining").width + border.color: UM.Theme.getColor("lining") + radius: UM.Theme.getSize("default_radius").width + + property bool outputAvailable: UM.Backend.state == UM.Backend.Done || UM.Backend.state == UM.Backend.Disabled + + Loader + { + id: loader + anchors + { + top: parent.top + topMargin: UM.Theme.getSize("thick_margin").height + left: parent.left + leftMargin: UM.Theme.getSize("thick_margin").width + right: parent.right + rightMargin: UM.Theme.getSize("thick_margin").width + } + sourceComponent: outputAvailable ? outputProcessWidget : sliceProcessWidget + } + + Component + { + id: sliceProcessWidget + SliceProcessWidget { } + } + + Component + { + id: outputProcessWidget + OutputProcessWidget { } + } +} \ No newline at end of file diff --git a/resources/qml/ActionPanel/OutputDevicesActionButton.qml b/resources/qml/ActionPanel/OutputDevicesActionButton.qml new file mode 100644 index 0000000000..9a6c97bcff --- /dev/null +++ b/resources/qml/ActionPanel/OutputDevicesActionButton.qml @@ -0,0 +1,107 @@ +// Copyright (c) 2018 Ultimaker B.V. +// Cura is released under the terms of the LGPLv3 or higher. + +import QtQuick 2.7 +import QtQuick.Controls 2.1 +import QtQuick.Layouts 1.3 + +import UM 1.1 as UM +import Cura 1.0 as Cura + +Item +{ + id: widget + + Cura.PrimaryButton + { + id: saveToButton + height: parent.height + fixedWidthMode: true + cornerSide: deviceSelectionMenu.visible ? Cura.RoundedRectangle.Direction.Left : Cura.RoundedRectangle.Direction.All + + anchors + { + top: parent.top + left: parent.left + right: deviceSelectionMenu.visible ? deviceSelectionMenu.left : parent.right + } + + tooltip: UM.OutputDeviceManager.activeDeviceDescription + + text: UM.OutputDeviceManager.activeDeviceShortDescription + + onClicked: + { + forceActiveFocus(); + UM.OutputDeviceManager.requestWriteToDevice(UM.OutputDeviceManager.activeDevice, PrintInformation.jobName, + { "filter_by_machine": true, "preferred_mimetypes": Cura.MachineManager.activeMachine.preferred_output_file_formats }); + } + } + + Cura.ActionButton + { + id: deviceSelectionMenu + height: parent.height + + shadowEnabled: true + shadowColor: UM.Theme.getColor("primary_shadow") + cornerSide: Cura.RoundedRectangle.Direction.Right + + anchors + { + top: parent.top + right: parent.right + } + + leftPadding: UM.Theme.getSize("narrow_margin").width //Need more space than usual here for wide text. + rightPadding: UM.Theme.getSize("narrow_margin").width + tooltip: popup.opened ? "" : catalog.i18nc("@info:tooltip", "Select the active output device") + iconSource: popup.opened ? UM.Theme.getIcon("arrow_top") : UM.Theme.getIcon("arrow_bottom") + color: UM.Theme.getColor("action_panel_secondary") + visible: (devicesModel.deviceCount > 1) + + onClicked: popup.opened ? popup.close() : popup.open() + + Popup + { + id: popup + padding: 0 + + y: -height + x: parent.width - width + + closePolicy: Popup.CloseOnEscape | Popup.CloseOnPressOutsideParent + + contentItem: ColumnLayout + { + Repeater + { + model: devicesModel + + delegate: Cura.ActionButton + { + text: model.description + color: "transparent" + cornerRadius: 0 + hoverColor: UM.Theme.getColor("primary") + Layout.fillWidth: true + onClicked: + { + UM.OutputDeviceManager.setActiveDevice(model.id) + popup.close() + } + } + } + } + + background: Rectangle + { + opacity: visible ? 1 : 0 + Behavior on opacity { NumberAnimation { duration: 100 } } + color: UM.Theme.getColor("action_panel_secondary") + } + } + } + + UM.OutputDevicesModel { id: devicesModel } +} \ No newline at end of file diff --git a/resources/qml/ActionPanel/OutputProcessWidget.qml b/resources/qml/ActionPanel/OutputProcessWidget.qml new file mode 100644 index 0000000000..3f53abf28f --- /dev/null +++ b/resources/qml/ActionPanel/OutputProcessWidget.qml @@ -0,0 +1,142 @@ +// Copyright (c) 2018 Ultimaker B.V. +// Cura is released under the terms of the LGPLv3 or higher. + +import QtQuick 2.7 +import QtQuick.Controls 2.1 +import QtQuick.Layouts 1.3 + +import UM 1.1 as UM +import Cura 1.0 as Cura + + +// This element contains all the elements the user needs to visualize the data +// that is gather after the slicing process, such as printint time, material usage, ... +// There are also two buttons: one to previsualize the output layers, and the other to +// select what to do with it (such as print over network, save to file, ...) +Column +{ + id: widget + + spacing: UM.Theme.getSize("thin_margin").height + property bool preSlicedData: PrintInformation.preSliced + + UM.I18nCatalog + { + id: catalog + name: "cura" + } + + Item + { + id: information + width: parent.width + height: childrenRect.height + + Column + { + id: timeAndCostsInformation + spacing: UM.Theme.getSize("thin_margin").height + + anchors + { + left: parent.left + right: printInformationPanel.left + rightMargin: UM.Theme.getSize("thin_margin").height + } + + Cura.IconWithText + { + id: estimatedTime + width: parent.width + + text: preSlicedData ? catalog.i18nc("@label", "No time estimation available") : PrintInformation.currentPrintTime.getDisplayString(UM.DurationFormat.Long) + source: UM.Theme.getIcon("clock") + font: UM.Theme.getFont("default_bold") + } + + Cura.IconWithText + { + id: estimatedCosts + width: parent.width + + property var printMaterialLengths: PrintInformation.materialLengths + property var printMaterialWeights: PrintInformation.materialWeights + + text: + { + if (preSlicedData) + { + return catalog.i18nc("@label", "No cost estimation available") + } + var totalLengths = 0 + var totalWeights = 0 + if (printMaterialLengths) + { + for(var index = 0; index < printMaterialLengths.length; index++) + { + if(printMaterialLengths[index] > 0) + { + totalLengths += printMaterialLengths[index] + totalWeights += Math.round(printMaterialWeights[index]) + } + } + } + return totalWeights + "g ยท " + totalLengths.toFixed(2) + "m" + } + source: UM.Theme.getIcon("spool") + } + } + + PrintInformationWidget + { + id: printInformationPanel + visible: !preSlicedData + + anchors + { + right: parent.right + verticalCenter: timeAndCostsInformation.verticalCenter + } + } + } + + Item + { + id: buttonRow + anchors.right: parent.right + anchors.left: parent.left + height: UM.Theme.getSize("action_button").height + + Cura.SecondaryButton + { + id: previewStageShortcut + + anchors + { + left: parent.left + right: outputDevicesButton.left + rightMargin: UM.Theme.getSize("default_margin").width + } + + height: UM.Theme.getSize("action_button").height + leftPadding: UM.Theme.getSize("default_margin").width + rightPadding: UM.Theme.getSize("default_margin").width + text: catalog.i18nc("@button", "Preview") + + onClicked: UM.Controller.setActiveStage("PreviewStage") + visible: UM.Controller.activeStage != null && UM.Controller.activeStage.stageId != "PreviewStage" + + shadowEnabled: true + shadowColor: UM.Theme.getColor("action_button_disabled_shadow") + } + + Cura.OutputDevicesActionButton + { + id: outputDevicesButton + + anchors.right: parent.right + width: previewStageShortcut.visible ? UM.Theme.getSize("action_button").width : parent.width + height: UM.Theme.getSize("action_button").height + } + } +} \ No newline at end of file diff --git a/resources/qml/ActionPanel/PrintInformationWidget.qml b/resources/qml/ActionPanel/PrintInformationWidget.qml new file mode 100644 index 0000000000..554273a818 --- /dev/null +++ b/resources/qml/ActionPanel/PrintInformationWidget.qml @@ -0,0 +1,58 @@ +// Copyright (c) 2018 Ultimaker B.V. +// Cura is released under the terms of the LGPLv3 or higher. + +import QtQuick 2.7 +import QtQuick.Controls 2.1 + +import UM 1.1 as UM +import Cura 1.0 as Cura + +UM.RecolorImage +{ + id: widget + + source: UM.Theme.getIcon("info") + width: UM.Theme.getSize("section_icon").width + height: UM.Theme.getSize("section_icon").height + + color: popup.opened ? UM.Theme.getColor("primary") : UM.Theme.getColor("text_medium") + + MouseArea + { + anchors.fill: parent + hoverEnabled: true + onEntered: popup.open() + onExited: popup.close() + } + + Popup + { + id: popup + + y: -(height + UM.Theme.getSize("default_arrow").height + UM.Theme.getSize("thin_margin").height) + x: parent.width - width + UM.Theme.getSize("thin_margin").width + + closePolicy: Popup.CloseOnEscape | Popup.CloseOnPressOutsideParent + + opacity: opened ? 1 : 0 + Behavior on opacity { NumberAnimation { duration: 100 } } + + contentItem: PrintJobInformation + { + id: printJobInformation + width: UM.Theme.getSize("action_panel_information_widget").width + } + + background: UM.PointingRectangle + { + color: UM.Theme.getColor("tool_panel_background") + borderColor: UM.Theme.getColor("lining") + borderWidth: UM.Theme.getSize("default_lining").width + + target: Qt.point(width - (widget.width / 2) - UM.Theme.getSize("thin_margin").width, + height + UM.Theme.getSize("default_arrow").height - UM.Theme.getSize("thin_margin").height) + + arrowSize: UM.Theme.getSize("default_arrow").width + } + } +} \ No newline at end of file diff --git a/resources/qml/ActionPanel/PrintJobInformation.qml b/resources/qml/ActionPanel/PrintJobInformation.qml new file mode 100644 index 0000000000..8bd5d5a0d3 --- /dev/null +++ b/resources/qml/ActionPanel/PrintJobInformation.qml @@ -0,0 +1,159 @@ +// Copyright (c) 2018 Ultimaker B.V. +// Cura is released under the terms of the LGPLv3 or higher. + +import QtQuick 2.7 +import QtQuick.Controls 2.1 + +import UM 1.1 as UM +import Cura 1.0 as Cura + +Column +{ + id: base + spacing: UM.Theme.getSize("default_margin").width + + UM.I18nCatalog + { + id: catalog + name: "cura" + } + + Column + { + id: timeSpecification + width: parent.width + topPadding: UM.Theme.getSize("default_margin").height + leftPadding: UM.Theme.getSize("default_margin").width + rightPadding: UM.Theme.getSize("default_margin").width + + Label + { + text: catalog.i18nc("@label", "Time specification").toUpperCase() + color: UM.Theme.getColor("primary") + font: UM.Theme.getFont("default_bold") + renderType: Text.NativeRendering + } + + Label + { + property var printDuration: PrintInformation.currentPrintTime + + text: + { + // All the time information for the different features is achieved + var printTime = PrintInformation.getFeaturePrintTimes() + var totalSeconds = parseInt(printDuration.getDisplayString(UM.DurationFormat.Seconds)) + + // A message is created and displayed when the user hover the time label + var text = "" + for(var feature in printTime) + { + if(!printTime[feature].isTotalDurationZero) + { + text += "" + + "".arg(printTime[feature].getDisplayString(UM.DurationFormat.ISO8601).slice(0,-3)) + + "".arg(Math.round(100 * parseInt(printTime[feature].getDisplayString(UM.DurationFormat.Seconds)) / totalSeconds)) + + "" + } + } + text += "
" + feature + ":  %1  %1%
" + return text + } + width: parent.width - 2 * UM.Theme.getSize("default_margin").width + color: UM.Theme.getColor("text") + font: UM.Theme.getFont("default") + renderType: Text.NativeRendering + textFormat: Text.RichText + } + } + + Column + { + id: materialSpecification + width: parent.width + bottomPadding: UM.Theme.getSize("default_margin").height + leftPadding: UM.Theme.getSize("default_margin").width + rightPadding: UM.Theme.getSize("default_margin").width + + Label + { + text: catalog.i18nc("@label", "Material specification").toUpperCase() + color: UM.Theme.getColor("primary") + font: UM.Theme.getFont("default_bold") + renderType: Text.NativeRendering + } + + Label + { + property var printMaterialLengths: PrintInformation.materialLengths + property var printMaterialWeights: PrintInformation.materialWeights + property var printMaterialCosts: PrintInformation.materialCosts + property var printMaterialNames: PrintInformation.materialNames + + function formatRow(items) + { + var rowHTML = "" + for(var item = 0; item < items.length; item++) + { + if (item == 0) + { + rowHTML += "%1".arg(items[item]) + } + else + { + rowHTML += "  %1".arg(items[item]) + } + } + rowHTML += "" + return rowHTML + } + + text: + { + var lengths = [] + var weights = [] + var costs = [] + var names = [] + if(printMaterialLengths) + { + for(var index = 0; index < printMaterialLengths.length; index++) + { + if(printMaterialLengths[index] > 0) + { + names.push(printMaterialNames[index]) + lengths.push(printMaterialLengths[index].toFixed(2)) + weights.push(String(Math.round(printMaterialWeights[index]))) + var cost = printMaterialCosts[index] == undefined ? 0 : printMaterialCosts[index].toFixed(2) + costs.push(cost) + } + } + } + if(lengths.length == 0) + { + lengths = ["0.00"] + weights = ["0"] + costs = ["0.00"] + } + + var text = "" + for(var index = 0; index < lengths.length; index++) + { + text += formatRow([ + "%1:".arg(names[index]), + catalog.i18nc("@label m for meter", "%1m").arg(lengths[index]), + catalog.i18nc("@label g for grams", "%1g").arg(weights[index]), + "%1 %2".arg(UM.Preferences.getValue("cura/currency")).arg(costs[index]), + ]) + } + text += "
" + + return text + } + width: parent.width - 2 * UM.Theme.getSize("default_margin").width + color: UM.Theme.getColor("text") + font: UM.Theme.getFont("default") + renderType: Text.NativeRendering + textFormat: Text.RichText + } + } +} \ No newline at end of file diff --git a/resources/qml/ActionPanel/SliceProcessWidget.qml b/resources/qml/ActionPanel/SliceProcessWidget.qml new file mode 100644 index 0000000000..18caeafb40 --- /dev/null +++ b/resources/qml/ActionPanel/SliceProcessWidget.qml @@ -0,0 +1,157 @@ +// Copyright (c) 2018 Ultimaker B.V. +// Cura is released under the terms of the LGPLv3 or higher. + +import QtQuick 2.7 +import QtQuick.Controls 2.1 +import QtQuick.Layouts 1.3 +import QtQuick.Controls 1.4 as Controls1 + +import UM 1.1 as UM +import Cura 1.0 as Cura + + +// This element contains all the elements the user needs to create a printjob from the +// model(s) that is(are) on the buildplate. Mainly the button to start/stop the slicing +// process and a progress bar to see the progress of the process. +Column +{ + id: widget + + spacing: UM.Theme.getSize("thin_margin").height + + UM.I18nCatalog + { + id: catalog + name: "cura" + } + + property real progress: UM.Backend.progress + property int backendState: UM.Backend.state + + function sliceOrStopSlicing() + { + if (widget.backendState == UM.Backend.NotStarted) + { + CuraApplication.backend.forceSlice() + } + else + { + CuraApplication.backend.stopSlicing() + } + } + + Label + { + id: autoSlicingLabel + width: parent.width + visible: prepareButtons.autoSlice && (widget.backendState == UM.Backend.Processing || widget.backendState == UM.Backend.NotStarted) + + text: catalog.i18nc("@label:PrintjobStatus", "Auto slicing...") + color: UM.Theme.getColor("text") + font: UM.Theme.getFont("default") + renderType: Text.NativeRendering + } + + Cura.IconWithText + { + id: unableToSliceMessage + width: parent.width + visible: widget.backendState == UM.Backend.Error + + text: catalog.i18nc("@label:PrintjobStatus", "Unable to Slice") + source: UM.Theme.getIcon("warning") + color: UM.Theme.getColor("warning") + } + + // Progress bar, only visible when the backend is in the process of slice the printjob + ProgressBar + { + id: progressBar + width: parent.width + height: UM.Theme.getSize("progressbar").height + value: progress + indeterminate: widget.backendState == UM.Backend.NotStarted + visible: (widget.backendState == UM.Backend.Processing || (prepareButtons.autoSlice && widget.backendState == UM.Backend.NotStarted)) + + background: Rectangle + { + anchors.fill: parent + radius: UM.Theme.getSize("progressbar_radius").width + color: UM.Theme.getColor("progressbar_background") + } + + contentItem: Item + { + anchors.fill: parent + Rectangle + { + width: progressBar.visualPosition * parent.width + height: parent.height + radius: UM.Theme.getSize("progressbar_radius").width + color: UM.Theme.getColor("progressbar_control") + } + } + } + + Item + { + id: prepareButtons + // Get the current value from the preferences + property bool autoSlice: UM.Preferences.getValue("general/auto_slice") + // Disable the slice process when + + width: parent.width + height: UM.Theme.getSize("action_button").height + visible: !autoSlice + Cura.PrimaryButton + { + id: sliceButton + fixedWidthMode: true + anchors.fill: parent + text: catalog.i18nc("@button", "Slice") + enabled: widget.backendState != UM.Backend.Error + visible: widget.backendState == UM.Backend.NotStarted || widget.backendState == UM.Backend.Error + onClicked: sliceOrStopSlicing() + } + + Cura.SecondaryButton + { + id: cancelButton + fixedWidthMode: true + anchors.fill: parent + text: catalog.i18nc("@button", "Cancel") + enabled: sliceButton.enabled + visible: !sliceButton.visible + onClicked: sliceOrStopSlicing() + } + } + + + // React when the user changes the preference of having the auto slice enabled + Connections + { + target: UM.Preferences + onPreferenceChanged: + { + var autoSlice = UM.Preferences.getValue("general/auto_slice") + prepareButtons.autoSlice = autoSlice + if(autoSlice) + { + CuraApplication.backend.forceSlice() + } + } + } + + // Shortcut for "slice/stop" + Controls1.Action + { + shortcut: "Ctrl+P" + onTriggered: + { + if (prepareButton.enabled) + { + sliceOrStopSlicing() + } + } + } +} diff --git a/resources/qml/Actions.qml b/resources/qml/Actions.qml index bd7b15a1c7..a1077f5fb7 100644 --- a/resources/qml/Actions.qml +++ b/resources/qml/Actions.qml @@ -1,4 +1,4 @@ -// Copyright (c) 2015 Ultimaker B.V. +// Copyright (c) 2018 Ultimaker B.V. // Cura is released under the terms of the LGPLv3 or higher. pragma Singleton @@ -23,8 +23,6 @@ Item property alias viewLeftSideCamera: viewLeftSideCameraAction; property alias viewRightSideCamera: viewRightSideCameraAction; - property alias expandSidebar: expandSidebarAction; - property alias deleteSelection: deleteSelectionAction; property alias centerSelection: centerSelectionAction; property alias multiplySelection: multiplySelectionAction; @@ -58,7 +56,6 @@ Item property alias preferences: preferencesAction; - property alias showEngineLog: showEngineLogAction; property alias showProfileFolder: showProfileFolderAction; property alias documentation: documentationAction; property alias reportBug: reportBugAction; @@ -70,7 +67,7 @@ Item property alias browsePackages: browsePackagesAction - UM.I18nCatalog{id: catalog; name:"cura"} + UM.I18nCatalog{id: catalog; name: "cura"} Action { @@ -398,14 +395,6 @@ Item shortcut: StandardKey.New } - Action - { - id: showEngineLogAction; - text: catalog.i18nc("@action:inmenu menubar:help","Show Engine &Log..."); - iconName: "view-list-text"; - shortcut: StandardKey.WhatsThis; - } - Action { id: showProfileFolderAction; @@ -426,11 +415,4 @@ Item text: catalog.i18nc("@action:menu", "&Marketplace") iconName: "plugins_browse" } - - Action - { - id: expandSidebarAction; - text: catalog.i18nc("@action:inmenu menubar:view","Expand/Collapse Sidebar"); - shortcut: "Ctrl+E"; - } } diff --git a/resources/qml/BorderGroup.qml b/resources/qml/BorderGroup.qml new file mode 100644 index 0000000000..38ad9fadff --- /dev/null +++ b/resources/qml/BorderGroup.qml @@ -0,0 +1,10 @@ +// Copyright (c) 2018 Ultimaker B.V. +// Cura is released under the terms of the LGPLv3 or higher. + +import QtQuick 2.0 + +QtObject +{ + property real width: 0 + property color color: "black" +} diff --git a/resources/qml/Cura.qml b/resources/qml/Cura.qml index 029149f1d0..a4faa27b67 100644 --- a/resources/qml/Cura.qml +++ b/resources/qml/Cura.qml @@ -1,4 +1,4 @@ -// Copyright (c) 2017 Ultimaker B.V. +// Copyright (c) 2018 Ultimaker B.V. // Cura is released under the terms of the LGPLv3 or higher. import QtQuick 2.7 @@ -6,53 +6,42 @@ import QtQuick.Controls 1.4 import QtQuick.Controls.Styles 1.4 import QtQuick.Layouts 1.1 import QtQuick.Dialogs 1.2 +import QtGraphicalEffects 1.0 import UM 1.3 as UM import Cura 1.1 as Cura +import "Dialogs" import "Menus" +import "MainWindow" UM.MainWindow { id: base - //: Cura application window title - title: catalog.i18nc("@title:window","Ultimaker Cura"); - viewportRect: Qt.rect(0, 0, (base.width - sidebar.width) / base.width, 1.0) - property bool showPrintMonitor: false + // Cura application window title + title: catalog.i18nc("@title:window", "Ultimaker Cura") backgroundColor: UM.Theme.getColor("viewport_background") - // This connection is here to support legacy printer output devices that use the showPrintMonitor signal on Application to switch to the monitor stage - // It should be phased out in newer plugin versions. - Connections + + UM.I18nCatalog { - target: CuraApplication - onShowPrintMonitor: { - if (show) { - UM.Controller.setActiveStage("MonitorStage") - } else { - UM.Controller.setActiveStage("PrepareStage") - } - } + id: catalog + name: "cura" } - onWidthChanged: + function showTooltip(item, position, text) { - // If slidebar is collapsed then it should be invisible - // otherwise after the main_window resize the sidebar will be fully re-drawn - if (sidebar.collapsed){ - if (sidebar.visible == true){ - sidebar.visible = false - sidebar.initialWidth = 0 - } - } - else{ - if (sidebar.visible == false){ - sidebar.visible = true - sidebar.initialWidth = UM.Theme.getSize("sidebar").width - } - } + tooltip.text = text; + position = item.mapToItem(backgroundItem, position.x - UM.Theme.getSize("default_arrow").width, position.y); + tooltip.show(position); } + function hideTooltip() + { + tooltip.hide(); + } + + Component.onCompleted: { CuraApplication.setMinimumWindowSize(UM.Theme.getSize("window_minimum_size")) @@ -72,12 +61,12 @@ UM.MainWindow Item { - id: backgroundItem; - anchors.fill: parent; - UM.I18nCatalog{id: catalog; name:"cura"} + id: backgroundItem + anchors.fill: parent signal hasMesh(string name) //this signal sends the filebase name so it can be used for the JobSpecs.qml - function getMeshName(path){ + function getMeshName(path) + { //takes the path the complete path of the meshname and returns only the filebase var fileName = path.slice(path.lastIndexOf("/") + 1) var fileBase = fileName.slice(0, fileName.indexOf(".")) @@ -85,253 +74,86 @@ UM.MainWindow } //DeleteSelection on the keypress backspace event - Keys.onPressed: { + Keys.onPressed: + { if (event.key == Qt.Key_Backspace) { Cura.Actions.deleteSelection.trigger() } } - UM.ApplicationMenu + ApplicationMenu { - id: menu + id: applicationMenu window: base - - Menu - { - id: fileMenu - title: catalog.i18nc("@title:menu menubar:toplevel","&File"); - MenuItem - { - id: newProjectMenu - action: Cura.Actions.newProject; - } - - MenuItem - { - id: openMenu - action: Cura.Actions.open; - } - - RecentFilesMenu { } - - MenuItem - { - id: saveWorkspaceMenu - text: catalog.i18nc("@title:menu menubar:file","&Save...") - onTriggered: - { - var args = { "filter_by_machine": false, "file_type": "workspace", "preferred_mimetypes": "application/vnd.ms-package.3dmanufacturing-3dmodel+xml" }; - if(UM.Preferences.getValue("cura/dialog_on_project_save")) - { - saveWorkspaceDialog.args = args; - saveWorkspaceDialog.open() - } - else - { - UM.OutputDeviceManager.requestWriteToDevice("local_file", PrintInformation.jobName, args) - } - } - } - - MenuSeparator { } - - MenuItem - { - id: saveAsMenu - text: catalog.i18nc("@title:menu menubar:file", "&Export...") - onTriggered: - { - var localDeviceId = "local_file"; - UM.OutputDeviceManager.requestWriteToDevice(localDeviceId, PrintInformation.jobName, { "filter_by_machine": false, "preferred_mimetypes": "application/vnd.ms-package.3dmanufacturing-3dmodel+xml"}); - } - } - - MenuItem - { - id: exportSelectionMenu - text: catalog.i18nc("@action:inmenu menubar:file", "Export Selection..."); - enabled: UM.Selection.hasSelection; - iconName: "document-save-as"; - onTriggered: UM.OutputDeviceManager.requestWriteSelectionToDevice("local_file", PrintInformation.jobName, { "filter_by_machine": false, "preferred_mimetypes": "application/vnd.ms-package.3dmanufacturing-3dmodel+xml"}); - } - - MenuSeparator { } - - MenuItem - { - id: reloadAllMenu - action: Cura.Actions.reloadAll; - } - - MenuSeparator { } - - MenuItem { action: Cura.Actions.quit; } - } - - Menu - { - title: catalog.i18nc("@title:menu menubar:toplevel","&Edit"); - - MenuItem { action: Cura.Actions.undo; } - MenuItem { action: Cura.Actions.redo; } - MenuSeparator { } - MenuItem { action: Cura.Actions.selectAll; } - MenuItem { action: Cura.Actions.arrangeAll; } - MenuItem { action: Cura.Actions.deleteSelection; } - MenuItem { action: Cura.Actions.deleteAll; } - MenuItem { action: Cura.Actions.resetAllTranslation; } - MenuItem { action: Cura.Actions.resetAll; } - MenuSeparator { } - MenuItem { action: Cura.Actions.groupObjects;} - MenuItem { action: Cura.Actions.mergeObjects;} - MenuItem { action: Cura.Actions.unGroupObjects;} - } - - ViewMenu { title: catalog.i18nc("@title:menu", "&View") } - - Menu - { - id: settingsMenu - title: catalog.i18nc("@title:menu", "&Settings") - - PrinterMenu { title: catalog.i18nc("@title:menu menubar:settings", "&Printer") } - - Instantiator - { - model: Cura.ExtrudersModel { simpleNames: true } - Menu { - title: model.name - - NozzleMenu { title: Cura.MachineManager.activeDefinitionVariantsName; visible: Cura.MachineManager.hasVariants; extruderIndex: index } - MaterialMenu { title: catalog.i18nc("@title:menu", "&Material"); visible: Cura.MachineManager.hasMaterials; extruderIndex: index } - - MenuSeparator - { - visible: Cura.MachineManager.hasVariants || Cura.MachineManager.hasMaterials - } - - MenuItem - { - text: catalog.i18nc("@action:inmenu", "Set as Active Extruder") - onTriggered: Cura.MachineManager.setExtruderIndex(model.index) - } - - MenuItem - { - text: catalog.i18nc("@action:inmenu", "Enable Extruder") - onTriggered: Cura.MachineManager.setExtruderEnabled(model.index, true) - visible: !Cura.MachineManager.getExtruder(model.index).isEnabled - } - - MenuItem - { - text: catalog.i18nc("@action:inmenu", "Disable Extruder") - onTriggered: Cura.MachineManager.setExtruderEnabled(model.index, false) - visible: Cura.MachineManager.getExtruder(model.index).isEnabled - enabled: Cura.MachineManager.numberExtrudersEnabled > 1 - } - - } - onObjectAdded: settingsMenu.insertItem(index, object) - onObjectRemoved: settingsMenu.removeItem(object) - } - - // TODO Only show in dev mode. Remove check when feature ready - BuildplateMenu { title: catalog.i18nc("@title:menu", "&Build plate"); visible: CuraSDKVersion == "dev" ? Cura.MachineManager.hasVariantBuildplates : false } - ProfileMenu { title: catalog.i18nc("@title:settings", "&Profile"); } - - MenuSeparator { } - - MenuItem { action: Cura.Actions.configureSettingVisibility } - } - - Menu - { - id: extension_menu - title: catalog.i18nc("@title:menu menubar:toplevel","E&xtensions"); - - Instantiator - { - id: extensions - model: UM.ExtensionModel { } - - Menu - { - id: sub_menu - title: model.name; - visible: actions != null - enabled: actions != null - Instantiator - { - model: actions - MenuItem - { - text: model.text - onTriggered: extensions.model.subMenuTriggered(name, model.text) - } - onObjectAdded: sub_menu.insertItem(index, object) - onObjectRemoved: sub_menu.removeItem(object) - } - } - - onObjectAdded: extension_menu.insertItem(index, object) - onObjectRemoved: extension_menu.removeItem(object) - } - } - - Menu - { - id: plugin_menu - title: catalog.i18nc("@title:menu menubar:toplevel", "&Marketplace") - - MenuItem { action: Cura.Actions.browsePackages } - } - - Menu - { - id: preferencesMenu - title: catalog.i18nc("@title:menu menubar:toplevel","P&references"); - - MenuItem { action: Cura.Actions.preferences; } - } - - Menu - { - id: helpMenu - title: catalog.i18nc("@title:menu menubar:toplevel","&Help"); - - MenuItem { action: Cura.Actions.showProfileFolder; } - MenuItem { action: Cura.Actions.documentation; } - MenuItem { action: Cura.Actions.reportBug; } - MenuSeparator { } - MenuItem { action: Cura.Actions.about; } - } - } - - UM.SettingPropertyProvider - { - id: machineExtruderCount - - containerStack: Cura.MachineManager.activeMachine - key: "machine_extruder_count" - watchedProperties: [ "value" ] - storeIndex: 0 } Item { - id: contentItem; + id: headerBackground + anchors + { + top: applicationMenu.bottom + left: parent.left + right: parent.right + } + height: stageMenu.source != "" ? Math.round(mainWindowHeader.height + stageMenu.height / 2) : mainWindowHeader.height - y: menu.height - width: parent.width; - height: parent.height - menu.height; + LinearGradient + { + anchors.fill: parent + start: Qt.point(0, 0) + end: Qt.point(parent.width, 0) + gradient: Gradient + { + GradientStop + { + position: 0.0 + color: UM.Theme.getColor("main_window_header_background") + } + GradientStop + { + position: 0.5 + color: UM.Theme.getColor("main_window_header_background_gradient") + } + GradientStop + { + position: 1.0 + color: UM.Theme.getColor("main_window_header_background") + } + } + } + } - Keys.forwardTo: menu + MainWindowHeader + { + id: mainWindowHeader + anchors + { + left: parent.left + right: parent.right + top: applicationMenu.bottom + } + } + + Item + { + id: contentItem + + anchors + { + top: mainWindowHeader.bottom + bottom: parent.bottom + left: parent.left + right: parent.right + } + + Keys.forwardTo: applicationMenu DropArea { - anchors.fill: parent; + // The drop area is here to handle files being dropped onto Cura. + anchors.fill: parent onDropped: { if (drop.urls.length > 0) @@ -359,156 +181,110 @@ UM.MainWindow } } - JobSpecs - { - id: jobSpecs - anchors - { - bottom: parent.bottom; - right: sidebar.left; - bottomMargin: UM.Theme.getSize("default_margin").height; - rightMargin: UM.Theme.getSize("default_margin").width; - } - } - - Button - { - id: openFileButton; - text: catalog.i18nc("@action:button","Open File"); - iconSource: UM.Theme.getIcon("load") - style: UM.Theme.styles.tool_button - tooltip: "" - anchors - { - top: topbar.bottom; - topMargin: UM.Theme.getSize("default_margin").height; - left: parent.left; - } - action: Cura.Actions.open; - } - Toolbar { - id: toolbar; + // The toolbar is the left bar that is populated by all the tools (which are dynamicly populated by + // plugins) + id: toolbar property int mouseX: base.mouseX property int mouseY: base.mouseY - anchors { - top: openFileButton.bottom; - topMargin: UM.Theme.getSize("window_margin").height; - left: parent.left; + anchors + { + verticalCenter: parent.verticalCenter + left: parent.left } + visible: CuraApplication.platformActivity && !PrintInformation.preSliced } ObjectsList { - id: objectsList; - visible: UM.Preferences.getValue("cura/use_multi_build_plate"); + id: objectsList + visible: UM.Preferences.getValue("cura/use_multi_build_plate") anchors { - bottom: parent.bottom; - left: parent.left; + bottom: viewOrientationControls.top + left: toolbar.right + margins: UM.Theme.getSize("default_margin").width } - } - Topbar + JobSpecs + { + id: jobSpecs + visible: CuraApplication.platformActivity + anchors + { + left: parent.left + bottom: viewOrientationControls.top + margins: UM.Theme.getSize("default_margin").width + bottomMargin: UM.Theme.getSize("thin_margin").width + } + } + + ViewOrientationControls + { + id: viewOrientationControls + + anchors + { + left: parent.left + bottom: parent.bottom + margins: UM.Theme.getSize("default_margin").width + } + } + + Cura.ActionPanelWidget { - id: topbar - anchors.left: parent.left anchors.right: parent.right - anchors.top: parent.top + anchors.bottom: parent.bottom + anchors.rightMargin: UM.Theme.getSize("thick_margin").width + anchors.bottomMargin: UM.Theme.getSize("thick_margin").height + visible: CuraApplication.platformActivity } Loader { + // A stage can control this area. If nothing is set, it will therefore show the 3D view. id: main anchors { - top: topbar.bottom - bottom: parent.bottom + // Align to the top of the stageMenu since the stageMenu may not exist + top: parent.top left: parent.left - right: sidebar.left + right: parent.right + bottom: parent.bottom } - MouseArea - { - visible: UM.Controller.activeStage.mainComponent != "" - anchors.fill: parent - acceptedButtons: Qt.AllButtons - onWheel: wheel.accepted = true - } - - source: UM.Controller.activeStage.mainComponent + source: UM.Controller.activeStage != null ? UM.Controller.activeStage.mainComponent : "" } Loader { - id: sidebar - - property bool collapsed: false; - property var initialWidth: UM.Theme.getSize("sidebar").width; - - function callExpandOrCollapse() { - if (collapsed) { - sidebar.visible = true; - sidebar.initialWidth = UM.Theme.getSize("sidebar").width; - viewportRect = Qt.rect(0, 0, (base.width - sidebar.width) / base.width, 1.0); - expandSidebarAnimation.start(); - } else { - viewportRect = Qt.rect(0, 0, 1, 1.0); - collapseSidebarAnimation.start(); - } - collapsed = !collapsed; - UM.Preferences.setValue("cura/sidebar_collapsed", collapsed); - } + // The stage menu is, as the name implies, a menu that is defined by the active stage. + // Note that this menu does not need to be set at all! It's perfectly acceptable to have a stage + // without this menu! + id: stageMenu anchors { - top: topbar.top - bottom: parent.bottom + left: parent.left + right: parent.right + top: parent.top } - width: initialWidth - x: base.width - sidebar.width - source: UM.Controller.activeStage.sidebarComponent + height: UM.Theme.getSize("stage_menu").height + source: UM.Controller.activeStage != null ? UM.Controller.activeStage.stageMenuComponent : "" - NumberAnimation { - id: collapseSidebarAnimation - target: sidebar - properties: "x" - to: base.width - duration: 100 - } - - NumberAnimation { - id: expandSidebarAnimation - target: sidebar - properties: "x" - to: base.width - sidebar.width - duration: 100 - } - - Component.onCompleted: + // The printSetupSelector is defined here so that the setting list doesn't need to get re-instantiated + // Every time the stage is changed. + property var printSetupSelector: Cura.PrintSetupSelector { - var sidebar_collapsed = UM.Preferences.getValue("cura/sidebar_collapsed"); - - if (sidebar_collapsed) - { - sidebar.collapsed = true; - viewportRect = Qt.rect(0, 0, 1, 1.0) - collapseSidebarAnimation.start(); - } - } - - MouseArea - { - visible: UM.Controller.activeStage.sidebarComponent != "" - anchors.fill: parent - acceptedButtons: Qt.AllButtons - onWheel: wheel.accepted = true + width: UM.Theme.getSize("print_setup_widget").width + height: UM.Theme.getSize("stage_menu").height + headerCornerSide: RoundedRectangle.Direction.Right } } @@ -517,20 +293,17 @@ UM.MainWindow anchors { horizontalCenter: parent.horizontalCenter - horizontalCenterOffset: -(Math.round(UM.Theme.getSize("sidebar").width / 2)) - top: parent.verticalCenter; - bottom: parent.bottom; + top: parent.verticalCenter + bottom: parent.bottom bottomMargin: UM.Theme.getSize("default_margin").height } } } - } - // Expand or collapse sidebar - Connections - { - target: Cura.Actions.expandSidebar - onTriggered: sidebar.callExpandOrCollapse() + PrintSetupTooltip + { + id: tooltip + } } UM.PreferencesDialog @@ -567,13 +340,6 @@ UM.MainWindow } } - WorkspaceSummaryDialog - { - id: saveWorkspaceDialog - property var args - onYes: UM.OutputDeviceManager.requestWriteToDevice("local_file", PrintInformation.jobName, args) - } - Connections { target: Cura.Actions.preferences @@ -586,33 +352,6 @@ UM.MainWindow onShowPreferencesWindow: preferences.visible = true } - MessageDialog - { - id: newProjectDialog - modality: Qt.ApplicationModal - title: catalog.i18nc("@title:window", "New project") - text: catalog.i18nc("@info:question", "Are you sure you want to start a new project? This will clear the build plate and any unsaved settings.") - standardButtons: StandardButton.Yes | StandardButton.No - icon: StandardIcon.Question - onYes: - { - CuraApplication.deleteAll(); - Cura.Actions.resetProfile.trigger(); - } - } - - Connections - { - target: Cura.Actions.newProject - onTriggered: - { - if(Printer.platformActivity || Cura.MachineManager.hasUserSettings) - { - newProjectDialog.visible = true - } - } - } - Connections { target: Cura.Actions.addProfile @@ -670,19 +409,6 @@ UM.MainWindow } } - UM.ExtensionModel { - id: curaExtensions - } - - // show the plugin browser dialog - Connections - { - target: Cura.Actions.browsePackages - onTriggered: { - curaExtensions.callExtensionMethod("Toolbox", "browsePackages") - } - } - Timer { id: createProfileTimer @@ -703,7 +429,8 @@ UM.MainWindow } } - ContextMenu { + ContextMenu + { id: contextMenu } @@ -870,7 +597,8 @@ UM.MainWindow modality: Qt.ApplicationModal } - MessageDialog { + MessageDialog + { id: infoMultipleFilesWithGcodeDialog title: catalog.i18nc("@title:window", "Open File(s)") icon: StandardIcon.Information @@ -914,11 +642,6 @@ UM.MainWindow } } - EngineLog - { - id: engineLog; - } - Connections { target: Cura.Actions.showProfileFolder diff --git a/resources/qml/Dialogs/AboutDialog.qml b/resources/qml/Dialogs/AboutDialog.qml new file mode 100644 index 0000000000..add84614e0 --- /dev/null +++ b/resources/qml/Dialogs/AboutDialog.qml @@ -0,0 +1,168 @@ +// Copyright (c) 2018 Ultimaker B.V. +// Cura is released under the terms of the LGPLv3 or higher. + +import QtQuick 2.2 +import QtQuick.Controls 1.1 +import QtQuick.Window 2.1 + +import UM 1.1 as UM + +UM.Dialog +{ + id: base + + //: About dialog title + title: catalog.i18nc("@title:window","About Cura") + + minimumWidth: 500 * screenScaleFactor + minimumHeight: 650 * screenScaleFactor + width: minimumWidth + height: minimumHeight + + Rectangle + { + width: parent.width + 2 * margin // margin from Dialog.qml + height: version.y + version.height + margin + + anchors.top: parent.top + anchors.topMargin: - margin + anchors.horizontalCenter: parent.horizontalCenter + + color: UM.Theme.getColor("viewport_background") + } + + Image + { + id: logo + width: (base.minimumWidth * 0.85) | 0 + height: (width * (UM.Theme.getSize("logo").height / UM.Theme.getSize("logo").width)) | 0 + + source: UM.Theme.getImage("logo_about") + + anchors.top: parent.top + anchors.topMargin: ((base.minimumWidth - width) / 2) | 0 + anchors.horizontalCenter: parent.horizontalCenter + + UM.I18nCatalog{id: catalog; name: "cura"} + } + + Label + { + id: version + + text: catalog.i18nc("@label","version: %1").arg(UM.Application.version) + font: UM.Theme.getFont("large") + color: UM.Theme.getColor("text") + anchors.right : logo.right + anchors.top: logo.bottom + anchors.topMargin: (UM.Theme.getSize("default_margin").height / 2) | 0 + } + + Label + { + id: description + width: parent.width + + //: About dialog application description + text: catalog.i18nc("@label","End-to-end solution for fused filament 3D printing.") + font: UM.Theme.getFont("system") + wrapMode: Text.WordWrap + anchors.top: version.bottom + anchors.topMargin: UM.Theme.getSize("default_margin").height + } + + Label + { + id: creditsNotes + width: parent.width + + //: About dialog application author note + text: catalog.i18nc("@info:credit","Cura is developed by Ultimaker B.V. in cooperation with the community.\nCura proudly uses the following open source projects:") + font: UM.Theme.getFont("system") + wrapMode: Text.WordWrap + anchors.top: description.bottom + anchors.topMargin: UM.Theme.getSize("default_margin").height + } + + ScrollView + { + id: credits + anchors.top: creditsNotes.bottom + anchors.topMargin: UM.Theme.getSize("default_margin").height + + width: parent.width + height: base.height - y - (2 * UM.Theme.getSize("default_margin").height + closeButton.height) + + ListView + { + id: projectsList + + width: parent.width + + delegate: Row + { + Label + { + text: "%2".arg(model.url).arg(model.name) + width: (projectsList.width * 0.25) | 0 + elide: Text.ElideRight + onLinkActivated: Qt.openUrlExternally(link) + } + Label + { + text: model.description + elide: Text.ElideRight + width: (projectsList.width * 0.6) | 0 + } + Label + { + text: model.license + elide: Text.ElideRight + width: (projectsList.width * 0.15) | 0 + } + } + model: ListModel + { + id: projectsModel + } + Component.onCompleted: + { + projectsModel.append({ name: "Cura", description: catalog.i18nc("@label", "Graphical user interface"), license: "LGPLv3", url: "https://github.com/Ultimaker/Cura" }); + projectsModel.append({ name: "Uranium", description: catalog.i18nc("@label", "Application framework"), license: "LGPLv3", url: "https://github.com/Ultimaker/Uranium" }); + projectsModel.append({ name: "CuraEngine", description: catalog.i18nc("@label", "G-code generator"), license: "AGPLv3", url: "https://github.com/Ultimaker/CuraEngine" }); + projectsModel.append({ name: "libArcus", description: catalog.i18nc("@label", "Interprocess communication library"), license: "LGPLv3", url: "https://github.com/Ultimaker/libArcus" }); + + projectsModel.append({ name: "Python", description: catalog.i18nc("@label", "Programming language"), license: "Python", url: "http://python.org/" }); + projectsModel.append({ name: "Qt5", description: catalog.i18nc("@label", "GUI framework"), license: "LGPLv3", url: "https://www.qt.io/" }); + projectsModel.append({ name: "PyQt", description: catalog.i18nc("@label", "GUI framework bindings"), license: "GPL", url: "https://riverbankcomputing.com/software/pyqt" }); + projectsModel.append({ name: "SIP", description: catalog.i18nc("@label", "C/C++ Binding library"), license: "GPL", url: "https://riverbankcomputing.com/software/sip" }); + projectsModel.append({ name: "Protobuf", description: catalog.i18nc("@label", "Data interchange format"), license: "BSD", url: "https://developers.google.com/protocol-buffers" }); + projectsModel.append({ name: "SciPy", description: catalog.i18nc("@label", "Support library for scientific computing"), license: "BSD-new", url: "https://www.scipy.org/" }); + projectsModel.append({ name: "NumPy", description: catalog.i18nc("@label", "Support library for faster math"), license: "BSD", url: "http://www.numpy.org/" }); + projectsModel.append({ name: "NumPy-STL", description: catalog.i18nc("@label", "Support library for handling STL files"), license: "BSD", url: "https://github.com/WoLpH/numpy-stl" }); + projectsModel.append({ name: "Shapely", description: catalog.i18nc("@label", "Support library for handling planar objects"), license: "BSD", url: "https://github.com/Toblerity/Shapely" }); + projectsModel.append({ name: "Trimesh", description: catalog.i18nc("@label", "Support library for handling triangular meshes"), license: "MIT", url: "https://trimsh.org" }); + projectsModel.append({ name: "NetworkX", description: catalog.i18nc("@label", "Support library for analysis of complex networks"), license: "3-clause BSD", url: "https://networkx.github.io/" }); + projectsModel.append({ name: "libSavitar", description: catalog.i18nc("@label", "Support library for handling 3MF files"), license: "LGPLv3", url: "https://github.com/ultimaker/libsavitar" }); + projectsModel.append({ name: "libCharon", description: catalog.i18nc("@label", "Support library for file metadata and streaming"), license: "LGPLv3", url: "https://github.com/ultimaker/libcharon" }); + projectsModel.append({ name: "PySerial", description: catalog.i18nc("@label", "Serial communication library"), license: "Python", url: "http://pyserial.sourceforge.net/" }); + projectsModel.append({ name: "python-zeroconf", description: catalog.i18nc("@label", "ZeroConf discovery library"), license: "LGPL", url: "https://github.com/jstasiak/python-zeroconf" }); + projectsModel.append({ name: "Clipper", description: catalog.i18nc("@label", "Polygon clipping library"), license: "Boost", url: "http://www.angusj.com/delphi/clipper.php" }); + projectsModel.append({ name: "Requests", description: catalog.i18nc("@Label", "Python HTTP library"), license: "GPL", url: "http://docs.python-requests.org" }); + + projectsModel.append({ name: "Noto Sans", description: catalog.i18nc("@label", "Font"), license: "Apache 2.0", url: "https://www.google.com/get/noto/" }); + projectsModel.append({ name: "Font-Awesome-SVG-PNG", description: catalog.i18nc("@label", "SVG icons"), license: "SIL OFL 1.1", url: "https://github.com/encharm/Font-Awesome-SVG-PNG" }); + projectsModel.append({ name: "AppImageKit", description: catalog.i18nc("@label", "Linux cross-distribution application deployment"), license: "MIT", url: "https://github.com/AppImage/AppImageKit" }); + } + } + } + + rightButtons: Button + { + //: Close about dialog button + id: closeButton + text: catalog.i18nc("@action:button","Close"); + + onClicked: base.visible = false; + } +} diff --git a/resources/qml/AddMachineDialog.qml b/resources/qml/Dialogs/AddMachineDialog.qml similarity index 97% rename from resources/qml/AddMachineDialog.qml rename to resources/qml/Dialogs/AddMachineDialog.qml index 2bbdba319c..f00359869c 100644 --- a/resources/qml/AddMachineDialog.qml +++ b/resources/qml/Dialogs/AddMachineDialog.qml @@ -1,4 +1,4 @@ -// Copyright (c) 2017 Ultimaker B.V. +// Copyright (c) 2018 Ultimaker B.V. // Cura is released under the terms of the LGPLv3 or higher. import QtQuick 2.2 @@ -156,7 +156,6 @@ UM.Dialog anchors.rightMargin: UM.Theme.getSize("default_margin").width width: UM.Theme.getSize("standard_arrow").width height: UM.Theme.getSize("standard_arrow").height - sourceSize.width: width sourceSize.height: width color: palette.windowText source: base.activeCategory == section ? UM.Theme.getIcon("arrow_bottom") : UM.Theme.getIcon("arrow_right") @@ -170,7 +169,7 @@ UM.Dialog if (machineList.model.getItem(machineList.currentIndex).section != section) { // Find the first machine from this section - for(var i = 0; i < machineList.model.rowCount(); i++) + for(var i = 0; i < machineList.model.count; i++) { var item = machineList.model.getItem(i); if (item.section == section) @@ -276,7 +275,6 @@ UM.Dialog id: machineName text: getMachineName() width: Math.floor(parent.width * 0.75) - implicitWidth: UM.Theme.getSize("standard_list_input").width maximumLength: 40 //validator: Cura.MachineNameValidator { } //TODO: Gives a segfault in PyQt5.6. For now, we must use a signal on text changed. validator: RegExpValidator diff --git a/resources/qml/AskOpenAsProjectOrModelsDialog.qml b/resources/qml/Dialogs/AskOpenAsProjectOrModelsDialog.qml similarity index 100% rename from resources/qml/AskOpenAsProjectOrModelsDialog.qml rename to resources/qml/Dialogs/AskOpenAsProjectOrModelsDialog.qml diff --git a/resources/qml/DiscardOrKeepProfileChangesDialog.qml b/resources/qml/Dialogs/DiscardOrKeepProfileChangesDialog.qml similarity index 100% rename from resources/qml/DiscardOrKeepProfileChangesDialog.qml rename to resources/qml/Dialogs/DiscardOrKeepProfileChangesDialog.qml diff --git a/resources/qml/OpenFilesIncludingProjectsDialog.qml b/resources/qml/Dialogs/OpenFilesIncludingProjectsDialog.qml similarity index 100% rename from resources/qml/OpenFilesIncludingProjectsDialog.qml rename to resources/qml/Dialogs/OpenFilesIncludingProjectsDialog.qml diff --git a/resources/qml/WorkspaceSummaryDialog.qml b/resources/qml/Dialogs/WorkspaceSummaryDialog.qml similarity index 99% rename from resources/qml/WorkspaceSummaryDialog.qml rename to resources/qml/Dialogs/WorkspaceSummaryDialog.qml index 1b3a7aac55..35630bd19b 100644 --- a/resources/qml/WorkspaceSummaryDialog.qml +++ b/resources/qml/Dialogs/WorkspaceSummaryDialog.qml @@ -11,6 +11,7 @@ import Cura 1.0 as Cura UM.Dialog { + id: base title: catalog.i18nc("@title:window", "Save Project") minimumWidth: 500 * screenScaleFactor @@ -49,7 +50,7 @@ UM.Dialog UM.SettingDefinitionsModel { id: definitionsModel - containerId: Cura.MachineManager.activeDefinitionId + containerId: base.visible ? Cura.MachineManager.activeDefinitionId: "" showAll: true exclude: ["command_line_settings"] showAncestors: true diff --git a/resources/qml/EngineLog.qml b/resources/qml/EngineLog.qml deleted file mode 100644 index 965587b59e..0000000000 --- a/resources/qml/EngineLog.qml +++ /dev/null @@ -1,53 +0,0 @@ -// Copyright (c) 2015 Ultimaker B.V. -// Cura is released under the terms of the LGPLv3 or higher. - -import QtQuick 2.2 -import QtQuick.Controls 1.1 -import QtQuick.Layouts 1.1 - -import UM 1.1 as UM - -UM.Dialog -{ - id: dialog; - - //: Engine Log dialog title - title: catalog.i18nc("@title:window","Engine Log"); - - modality: Qt.NonModal; - - TextArea - { - id: textArea - anchors.fill: parent; - - Timer - { - id: updateTimer; - interval: 1000; - running: false; - repeat: true; - onTriggered: textArea.text = CuraApplication.getEngineLog(); - } - UM.I18nCatalog{id: catalog; name:"cura"} - } - - rightButtons: Button - { - //: Close engine log button - text: catalog.i18nc("@action:button","Close"); - onClicked: dialog.visible = false; - } - - onVisibleChanged: - { - if(visible) - { - textArea.text = CuraApplication.getEngineLog(); - updateTimer.start(); - } else - { - updateTimer.stop(); - } - } -} diff --git a/resources/qml/ExpandableComponent.qml b/resources/qml/ExpandableComponent.qml new file mode 100644 index 0000000000..afe15bcb1d --- /dev/null +++ b/resources/qml/ExpandableComponent.qml @@ -0,0 +1,262 @@ +// Copyright (c) 2018 Ultimaker B.V. +// Cura is released under the terms of the LGPLv3 or higher. + +import QtQuick 2.7 +import QtQuick.Controls 2.3 + +import UM 1.2 as UM +import Cura 1.0 as Cura + +import QtGraphicalEffects 1.0 // For the dropshadow + +// The expandable component has 2 major sub components: +// * The headerItem; Always visible and should hold some info about what happens if the component is expanded +// * The contentItem; The content that needs to be shown if the component is expanded. +Item +{ + id: base + + // Enumeration with the different possible alignments of the content with respect of the headerItem + enum ContentAlignment + { + AlignLeft, + AlignRight + } + + // The headerItem holds the QML item that is always displayed. + property alias headerItem: headerItemLoader.sourceComponent + + // The contentItem holds the QML item that is shown when the "open" button is pressed + property alias contentItem: content.contentItem + + property color contentBackgroundColor: UM.Theme.getColor("action_button") + + property color headerBackgroundColor: UM.Theme.getColor("action_button") + property color headerActiveColor: UM.Theme.getColor("secondary") + property color headerHoverColor: UM.Theme.getColor("action_button_hovered") + + property alias enabled: mouseArea.enabled + + // Text to show when this component is disabled + property alias disabledText: disabledLabel.text + + // Defines the alignment of the content with respect of the headerItem, by default to the right + property int contentAlignment: ExpandableComponent.ContentAlignment.AlignRight + + // How much spacing is needed around the contentItem + property alias contentPadding: content.padding + + // Adds a title to the content item + property alias contentHeaderTitle: contentHeader.headerTitle + + // How much spacing is needed for the contentItem by Y coordinate + property var contentSpacingY: UM.Theme.getSize("narrow_margin").width + + // How much padding is needed around the header & button + property alias headerPadding: background.padding + + // What icon should be displayed on the right. + property alias iconSource: collapseButton.source + + property alias iconColor: collapseButton.color + + // The icon size (it's always drawn as a square) + property alias iconSize: collapseButton.height + + // Is the "drawer" open? + readonly property alias expanded: contentContainer.visible + + // What should the radius of the header be. This is also influenced by the headerCornerSide + property alias headerRadius: background.radius + + // On what side should the header corners be shown? 1 is down, 2 is left, 3 is up and 4 is right. + property alias headerCornerSide: background.cornerSide + + property alias headerShadowColor: shadow.color + + property alias enableHeaderShadow: shadow.visible + + property int shadowOffset: 2 + + function toggleContent() + { + contentContainer.visible = !expanded + } + + // Add this binding since the background color is not updated otherwise + Binding + { + target: background + property: "color" + value: + { + return base.enabled ? (expanded ? headerActiveColor : headerBackgroundColor) : UM.Theme.getColor("disabled") + } + } + + // The panel needs to close when it becomes disabled + Connections + { + target: base + onEnabledChanged: + { + if (!base.enabled && expanded) + { + toggleContent() + } + } + } + + implicitHeight: 100 * screenScaleFactor + implicitWidth: 400 * screenScaleFactor + + RoundedRectangle + { + id: background + property real padding: UM.Theme.getSize("default_margin").width + + color: base.enabled ? (base.expanded ? headerActiveColor : headerBackgroundColor) : UM.Theme.getColor("disabled") + anchors.fill: parent + + Label + { + id: disabledLabel + visible: !base.enabled + anchors.fill: parent + leftPadding: background.padding + rightPadding: background.padding + text: "" + font: UM.Theme.getFont("default") + renderType: Text.NativeRendering + verticalAlignment: Text.AlignVCenter + color: UM.Theme.getColor("text") + wrapMode: Text.WordWrap + } + + Item + { + anchors.fill: parent + visible: base.enabled + + Loader + { + id: headerItemLoader + anchors + { + left: parent.left + right: collapseButton.visible ? collapseButton.left : parent.right + top: parent.top + bottom: parent.bottom + margins: background.padding + } + } + + UM.RecolorImage + { + id: collapseButton + anchors + { + right: parent.right + verticalCenter: parent.verticalCenter + margins: background.padding + } + source: UM.Theme.getIcon("pencil") + visible: source != "" + width: UM.Theme.getSize("standard_arrow").width + height: UM.Theme.getSize("standard_arrow").height + color: UM.Theme.getColor("small_button_text") + } + } + + MouseArea + { + id: mouseArea + anchors.fill: parent + onClicked: toggleContent() + hoverEnabled: true + onEntered: background.color = headerHoverColor + onExited: background.color = base.enabled ? (base.expanded ? headerActiveColor : headerBackgroundColor) : UM.Theme.getColor("disabled") + } + } + + DropShadow + { + id: shadow + // Don't blur the shadow + radius: 0 + anchors.fill: background + source: background + verticalOffset: base.shadowOffset + visible: true + color: UM.Theme.getColor("action_button_shadow") + // Should always be drawn behind the background. + z: background.z - 1 + } + + Cura.RoundedRectangle + { + id: contentContainer + + visible: false + width: childrenRect.width + height: childrenRect.height + + // Ensure that the content is located directly below the headerItem + y: background.height + base.shadowOffset + base.contentSpacingY + + // Make the content aligned with the rest, using the property contentAlignment to decide whether is right or left. + // In case of right alignment, the 3x padding is due to left, right and padding between the button & text. + x: contentAlignment == ExpandableComponent.ContentAlignment.AlignRight ? -width + collapseButton.width + headerItemLoader.width + 3 * background.padding : 0 + + cornerSide: Cura.RoundedRectangle.Direction.All + color: contentBackgroundColor + border.width: UM.Theme.getSize("default_lining").width + border.color: UM.Theme.getColor("lining") + radius: UM.Theme.getSize("default_radius").width + + ExpandableComponentHeader + { + id: contentHeader + headerTitle: "" + anchors + { + top: parent.top + right: parent.right + left: parent.left + } + + } + + Control + { + id: content + + anchors.top: contentHeader.bottom + padding: UM.Theme.getSize("default_margin").width + + contentItem: Item {} + + onContentItemChanged: + { + // Since we want the size of the content to be set by the size of the content, + // we need to do it like this. + content.width = contentItem.width + 2 * content.padding + content.height = contentItem.height + 2 * content.padding + } + } + } + + // DO NOT MOVE UP IN THE CODE: This connection has to be here, after the definition of the content item. + // Apparently the order in which these are handled matters and so the height is correctly updated if this is here. + Connections + { + // Since it could be that the content is dynamically populated, we should also take these changes into account. + target: content.contentItem + onWidthChanged: content.width = content.contentItem.width + 2 * content.padding + onHeightChanged: + { + content.height = content.contentItem.height + 2 * content.padding + contentContainer.height = contentHeader.height + content.height + } + } +} diff --git a/resources/qml/ExpandableComponentHeader.qml b/resources/qml/ExpandableComponentHeader.qml new file mode 100644 index 0000000000..09ea262c82 --- /dev/null +++ b/resources/qml/ExpandableComponentHeader.qml @@ -0,0 +1,68 @@ +// Copyright (c) 2018 Ultimaker B.V. +// Cura is released under the terms of the LGPLv3 or higher. + +import QtQuick 2.7 +import QtQuick.Controls 2.3 + +import UM 1.2 as UM +import Cura 1.0 as Cura + +// Header of the popup +Cura.RoundedRectangle +{ + id: header + + property alias headerTitle: headerLabel.text + + height: UM.Theme.getSize("expandable_component_content_header").height + color: UM.Theme.getColor("secondary") + cornerSide: Cura.RoundedRectangle.Direction.Up + border.width: UM.Theme.getSize("default_lining").width + border.color: UM.Theme.getColor("lining") + radius: UM.Theme.getSize("default_radius").width + + Label + { + id: headerLabel + text: "" + font: UM.Theme.getFont("default") + renderType: Text.NativeRendering + verticalAlignment: Text.AlignVCenter + color: UM.Theme.getColor("small_button_text") + height: parent.height + + anchors + { + topMargin: UM.Theme.getSize("default_margin").height + left: parent.left + leftMargin: UM.Theme.getSize("default_margin").height + } + } + + Button + { + id: closeButton + width: UM.Theme.getSize("message_close").width + height: UM.Theme.getSize("message_close").height + hoverEnabled: true + + anchors + { + right: parent.right + rightMargin: UM.Theme.getSize("default_margin").width + verticalCenter: parent.verticalCenter + } + + contentItem: UM.RecolorImage + { + anchors.fill: parent + sourceSize.width: width + color: closeButton.hovered ? UM.Theme.getColor("small_button_text_hover") : UM.Theme.getColor("small_button_text") + source: UM.Theme.getIcon("cross1") + } + + background: Item {} + + onClicked: toggleContent() // Will hide the popup item + } +} \ No newline at end of file diff --git a/resources/qml/ExpandablePopup.qml b/resources/qml/ExpandablePopup.qml new file mode 100644 index 0000000000..2d2665373e --- /dev/null +++ b/resources/qml/ExpandablePopup.qml @@ -0,0 +1,250 @@ +// Copyright (c) 2018 Ultimaker B.V. +// Cura is released under the terms of the LGPLv3 or higher. + +import QtQuick 2.7 +import QtQuick.Controls 2.3 + +import UM 1.2 as UM +import Cura 1.0 as Cura + +import QtGraphicalEffects 1.0 // For the dropshadow + +// The expandable component has 2 major sub components: +// * The headerItem; Always visible and should hold some info about what happens if the component is expanded +// * The contentItem; The content that needs to be shown if the component is expanded. +Item +{ + id: base + + // Enumeration with the different possible alignments of the content with respect of the headerItem + enum ContentAlignment + { + AlignLeft, + AlignRight + } + + // The headerItem holds the QML item that is always displayed. + property alias headerItem: headerItemLoader.sourceComponent + + // The contentItem holds the QML item that is shown when the "open" button is pressed + property alias contentItem: content.contentItem + + property color contentBackgroundColor: UM.Theme.getColor("action_button") + + property color headerBackgroundColor: UM.Theme.getColor("action_button") + property color headerActiveColor: UM.Theme.getColor("secondary") + property color headerHoverColor: UM.Theme.getColor("action_button_hovered") + + property alias enabled: mouseArea.enabled + + // Text to show when this component is disabled + property alias disabledText: disabledLabel.text + + // Defines the alignment of the content with respect of the headerItem, by default to the right + property int contentAlignment: ExpandablePopup.ContentAlignment.AlignRight + + // How much spacing is needed around the contentItem + property alias contentPadding: content.padding + + // How much padding is needed around the header & button + property alias headerPadding: background.padding + + // What icon should be displayed on the right. + property alias iconSource: collapseButton.source + + property alias iconColor: collapseButton.color + + // The icon size (it's always drawn as a square) + property alias iconSize: collapseButton.height + + // Is the "drawer" open? + readonly property alias expanded: content.visible + + property alias expandedHighlightColor: expandedHighlight.color + + // What should the radius of the header be. This is also influenced by the headerCornerSide + property alias headerRadius: background.radius + + // On what side should the header corners be shown? 1 is down, 2 is left, 3 is up and 4 is right. + property alias headerCornerSide: background.cornerSide + + // Change the contentItem close behaviour + property alias contentClosePolicy : content.closePolicy + + property alias headerShadowColor: shadow.color + + property alias enableHeaderShadow: shadow.visible + + property int shadowOffset: 2 + + function toggleContent() + { + if (content.visible) + { + content.close() + } + else + { + content.open() + } + } + + // Add this binding since the background color is not updated otherwise + Binding + { + target: background + property: "color" + value: base.enabled ? headerBackgroundColor : UM.Theme.getColor("disabled") + } + + // The panel needs to close when it becomes disabled + Connections + { + target: base + onEnabledChanged: + { + if (!base.enabled && expanded) + { + toggleContent() + } + } + } + + implicitHeight: 100 * screenScaleFactor + implicitWidth: 400 * screenScaleFactor + + RoundedRectangle + { + id: background + property real padding: UM.Theme.getSize("default_margin").width + + color: base.enabled ? headerBackgroundColor : UM.Theme.getColor("disabled") + anchors.fill: parent + + Label + { + id: disabledLabel + visible: !base.enabled + leftPadding: background.padding + text: "" + font: UM.Theme.getFont("default") + renderType: Text.NativeRendering + verticalAlignment: Text.AlignVCenter + color: UM.Theme.getColor("text") + height: parent.height + } + + Item + { + anchors.fill: parent + visible: base.enabled + + Loader + { + id: headerItemLoader + anchors + { + left: parent.left + right: collapseButton.visible ? collapseButton.left : parent.right + top: parent.top + bottom: parent.bottom + margins: background.padding + } + } + + // A highlight that is shown when the content is expanded + Rectangle + { + id: expandedHighlight + width: parent.width + height: UM.Theme.getSize("thick_lining").height + color: UM.Theme.getColor("primary") + visible: expanded + anchors.bottom: parent.bottom + } + + UM.RecolorImage + { + id: collapseButton + anchors + { + right: parent.right + verticalCenter: parent.verticalCenter + margins: background.padding + } + source: expanded ? UM.Theme.getIcon("arrow_bottom") : UM.Theme.getIcon("arrow_left") + visible: source != "" + width: UM.Theme.getSize("standard_arrow").width + height: UM.Theme.getSize("standard_arrow").height + color: UM.Theme.getColor("small_button_text") + } + } + + MouseArea + { + id: mouseArea + anchors.fill: parent + onClicked: toggleContent() + hoverEnabled: true + onEntered: background.color = headerHoverColor + onExited: background.color = base.enabled ? headerBackgroundColor : UM.Theme.getColor("disabled") + } + } + + DropShadow + { + id: shadow + // Don't blur the shadow + radius: 0 + anchors.fill: background + source: background + verticalOffset: base.shadowOffset + visible: true + color: UM.Theme.getColor("action_button_shadow") + // Should always be drawn behind the background. + z: background.z - 1 + } + + Popup + { + id: content + + // Ensure that the content is located directly below the headerItem + y: background.height + base.shadowOffset + + // Make the content aligned with the rest, using the property contentAlignment to decide whether is right or left. + // In case of right alignment, the 3x padding is due to left, right and padding between the button & text. + x: contentAlignment == ExpandablePopup.ContentAlignment.AlignRight ? -width + collapseButton.width + headerItemLoader.width + 3 * background.padding : 0 + padding: UM.Theme.getSize("default_margin").width + closePolicy: Popup.CloseOnPressOutsideParent + + background: Cura.RoundedRectangle + { + cornerSide: Cura.RoundedRectangle.Direction.Down + color: contentBackgroundColor + border.width: UM.Theme.getSize("default_lining").width + border.color: UM.Theme.getColor("lining") + radius: UM.Theme.getSize("default_radius").width + } + + contentItem: Item {} + + onContentItemChanged: + { + // Since we want the size of the content to be set by the size of the content, + // we need to do it like this. + content.width = contentItem.width + 2 * content.padding + content.height = contentItem.height + 2 * content.padding + } + } + + // DO NOT MOVE UP IN THE CODE: This connection has to be here, after the definition of the content item. + // Apparently the order in which these are handled matters and so the height is correctly updated if this is here. + Connections + { + // Since it could be that the content is dynamically populated, we should also take these changes into account. + target: content.contentItem + onWidthChanged: content.width = content.contentItem.width + 2 * content.padding + onHeightChanged: content.height = content.contentItem.height + 2 * content.padding + } +} diff --git a/resources/qml/ExtruderButton.qml b/resources/qml/ExtruderButton.qml index 2c1b80047e..feb399d528 100644 --- a/resources/qml/ExtruderButton.qml +++ b/resources/qml/ExtruderButton.qml @@ -2,80 +2,32 @@ // Cura is released under the terms of the LGPLv3 or higher. import QtQuick 2.2 -import QtQuick.Controls 1.1 +import QtQuick.Controls 2.0 import UM 1.2 as UM import Cura 1.0 as Cura -Button +Cura.ToolbarButton { id: base - property var extruder; + property var extruder text: catalog.i18ncp("@label %1 is filled in with the name of an extruder", "Print Selected Model with %1", "Print Selected Models with %1", UM.Selection.selectionCount).arg(extruder.name) - style: UM.Theme.styles.tool_button; - iconSource: UM.Theme.getIcon("extruder_button") - checked: Cura.ExtruderManager.selectedObjectExtruders.indexOf(extruder.id) != -1 enabled: UM.Selection.hasSelection && extruder.stack.isEnabled - property color customColor: base.hovered ? UM.Theme.getColor("button_hover") : UM.Theme.getColor("button"); - - Rectangle + toolItem: ExtruderIcon { - anchors.fill: parent - anchors.margins: UM.Theme.getSize("default_lining").width; - - color: "transparent" - - border.width: base.checked ? UM.Theme.getSize("default_lining").width : 0; - border.color: UM.Theme.getColor("button_text") - } - - Item - { - anchors.centerIn: parent - width: UM.Theme.getSize("default_margin").width - height: UM.Theme.getSize("default_margin").height - - Label - { - anchors.centerIn: parent; - text: index + 1; - color: parent.enabled ? UM.Theme.getColor("button_text") : UM.Theme.getColor("button_disabled_text") - font: UM.Theme.getFont("default_bold"); - } - } - - // Material colour circle - // Only draw the filling colour of the material inside the SVG border. - Rectangle - { - anchors - { - right: parent.right - top: parent.top - rightMargin: UM.Theme.getSize("extruder_button_material_margin").width - topMargin: UM.Theme.getSize("extruder_button_material_margin").height - } - - color: model.color - - width: UM.Theme.getSize("extruder_button_material").width - height: UM.Theme.getSize("extruder_button_material").height - radius: Math.round(width / 2) - - border.width: UM.Theme.getSize("default_lining").width - border.color: UM.Theme.getColor("extruder_button_material_border") - - opacity: !base.enabled ? 0.2 : 1.0 + materialColor: extruder.color + extruderEnabled: extruder.stack.isEnabled + property int index: extruder.index } onClicked: { forceActiveFocus() //First grab focus, so all the text fields are updated - CuraActions.setExtruderForSelection(extruder.id); + CuraActions.setExtruderForSelection(extruder.id) } } diff --git a/resources/qml/ExtruderIcon.qml b/resources/qml/ExtruderIcon.qml new file mode 100644 index 0000000000..bb0b347b7e --- /dev/null +++ b/resources/qml/ExtruderIcon.qml @@ -0,0 +1,71 @@ +// Copyright (c) 2018 Ultimaker B.V. +// Cura is released under the terms of the LGPLv3 or higher. + +import QtQuick 2.7 +import QtQuick.Controls 1.1 +import UM 1.2 as UM + +Item +{ + id: extruderIconItem + + implicitWidth: UM.Theme.getSize("extruder_icon").width + implicitHeight: UM.Theme.getSize("extruder_icon").height + + property bool checked: true + property color materialColor + property alias textColor: extruderNumberText.color + property bool extruderEnabled: true + + UM.RecolorImage + { + id: mainIcon + anchors.fill: parent + + source: UM.Theme.getIcon("extruder_button") + color: extruderEnabled ? materialColor: UM.Theme.getColor("disabled") + } + + Rectangle + { + id: extruderNumberCircle + + width: height + height: Math.round(parent.height / 2) + radius: Math.round(width / 2) + color: UM.Theme.getColor("toolbar_background") + + anchors + { + horizontalCenter: parent.horizontalCenter + top: parent.top + // The circle needs to be slightly off center (so it sits in the middle of the square bit of the icon) + topMargin: (parent.height - height) / 2 - 0.1 * parent.height + } + + Label + { + id: extruderNumberText + anchors.centerIn: parent + text: index + 1 + font: UM.Theme.getFont("very_small") + width: contentWidth + height: contentHeight + visible: extruderEnabled + renderType: Text.NativeRendering + horizontalAlignment: Text.AlignHCenter + verticalAlignment: Text.AlignVCenter + } + + UM.RecolorImage + { + id: disabledIcon + anchors.fill: parent + anchors.margins: UM.Theme.getSize("thick_lining").width + sourceSize.height: width + source: UM.Theme.getIcon("cross1") + visible: !extruderEnabled + color: "black" + } + } +} \ No newline at end of file diff --git a/resources/qml/IconWithText.qml b/resources/qml/IconWithText.qml new file mode 100644 index 0000000000..5530740040 --- /dev/null +++ b/resources/qml/IconWithText.qml @@ -0,0 +1,70 @@ +// Copyright (c) 2018 Ultimaker B.V. +// Cura is released under the terms of the LGPLv3 or higher. + +import QtQuick 2.7 +import QtQuick.Controls 2.0 +import QtQuick.Layouts 1.3 + +import UM 1.2 as UM +import Cura 1.0 as Cura + +// Reusable component that holds an (re-colorable) icon on the left with some text on the right. +// This component is also designed to be used with layouts. It will use the width of the text + icon as preferred width +// It sets the icon size + half of the content as its minium width (in which case it will elide the text) +Item +{ + property alias source: icon.source + property alias iconSize: icon.width + property alias color: label.color + property alias text: label.text + property alias font: label.font + + property real margin: UM.Theme.getSize("narrow_margin").width + + // These properties can be used in combination with layouts. + readonly property real contentWidth: icon.width + margin + label.contentWidth + readonly property real minContentWidth: Math.round(icon.width + margin + 0.5 * label.contentWidth) + + Layout.minimumWidth: minContentWidth + Layout.preferredWidth: contentWidth + Layout.fillHeight: true + Layout.fillWidth: true + + implicitWidth: icon.width + 100 + implicitHeight: icon.height + + UM.RecolorImage + { + id: icon + width: UM.Theme.getSize("section_icon").width + height: UM.Theme.getSize("section_icon").height + + color: label.color + + anchors + { + left: parent.left + verticalCenter: parent.verticalCenter + } + } + + Label + { + id: label + font: UM.Theme.getFont("default") + color: UM.Theme.getColor("text") + renderType: Text.NativeRendering + elide: Text.ElideRight + verticalAlignment: Text.AlignVCenter + + anchors + { + left: icon.right + right: parent.right + top: parent.top + bottom: parent.bottom + rightMargin: 0 + margins: margin + } + } +} \ No newline at end of file diff --git a/resources/qml/JobSpecs.qml b/resources/qml/JobSpecs.qml index 1a5b604886..c7f82b8876 100644 --- a/resources/qml/JobSpecs.qml +++ b/resources/qml/JobSpecs.qml @@ -1,4 +1,4 @@ -// Copyright (c) 2017 Ultimaker B.V. +// Copyright (c) 2018 Ultimaker B.V. // Cura is released under the terms of the LGPLv3 or higher. import QtQuick 2.2 @@ -9,141 +9,145 @@ import QtQuick.Layouts 1.1 import UM 1.1 as UM import Cura 1.0 as Cura -Item { +Item +{ id: base property bool activity: CuraApplication.platformActivity property string fileBaseName: PrintInformation.baseName - UM.I18nCatalog { id: catalog; name:"cura"} + UM.I18nCatalog + { + id: catalog + name: "cura" + } + width: childrenRect.width height: childrenRect.height - onActivityChanged: { - if (activity == false) { + onActivityChanged: + { + if (!activity) + { //When there is no mesh in the buildplate; the printJobTextField is set to an empty string so it doesn't set an empty string as a jobName (which is later used for saving the file) - PrintInformation.baseName = '' + PrintInformation.baseName = "" } } - Rectangle + Item { id: jobNameRow anchors.top: parent.top - anchors.right: parent.right + anchors.left: parent.left height: UM.Theme.getSize("jobspecs_line").height - visible: base.activity - Item + Button { - width: parent.width - height: parent.height + id: printJobPencilIcon + anchors.left: parent.left + anchors.verticalCenter: parent.verticalCenter + width: UM.Theme.getSize("save_button_specs_icons").width + height: UM.Theme.getSize("save_button_specs_icons").height - Button + onClicked: { - id: printJobPencilIcon - anchors.right: parent.right - anchors.verticalCenter: parent.verticalCenter - width: UM.Theme.getSize("save_button_specs_icons").width - height: UM.Theme.getSize("save_button_specs_icons").height - - onClicked: - { - printJobTextfield.selectAll(); - printJobTextfield.focus = true; - } - style: ButtonStyle - { - background: Item - { - UM.RecolorImage - { - width: UM.Theme.getSize("save_button_specs_icons").width; - height: UM.Theme.getSize("save_button_specs_icons").height; - sourceSize.width: width; - sourceSize.height: width; - color: control.hovered ? UM.Theme.getColor("text_scene_hover") : UM.Theme.getColor("text_scene"); - source: UM.Theme.getIcon("pencil"); - } - } - } + printJobTextfield.selectAll() + printJobTextfield.focus = true } - TextField + style: ButtonStyle { - id: printJobTextfield - anchors.right: printJobPencilIcon.left - anchors.rightMargin: Math.round(UM.Theme.getSize("default_margin").width / 2) - height: UM.Theme.getSize("jobspecs_line").height - width: Math.max(__contentWidth + UM.Theme.getSize("default_margin").width, 50) - maximumLength: 120 - property int unremovableSpacing: 5 - text: PrintInformation.jobName - horizontalAlignment: TextInput.AlignRight - onEditingFinished: { - var new_name = text == "" ? catalog.i18nc("@text Print job name", "Untitled") : text; - PrintInformation.setJobName(new_name, true); - printJobTextfield.focus = false; - } - validator: RegExpValidator { - regExp: /^[^\\\/\*\?\|\[\]]*$/ - } - style: TextFieldStyle{ - textColor: UM.Theme.getColor("text_scene"); - font: UM.Theme.getFont("default_bold"); - background: Rectangle { - opacity: 0 - border.width: 0 + background: Item + { + UM.RecolorImage + { + width: UM.Theme.getSize("save_button_specs_icons").width + height: UM.Theme.getSize("save_button_specs_icons").height + sourceSize.width: width + sourceSize.height: width + color: control.hovered ? UM.Theme.getColor("text_scene_hover") : UM.Theme.getColor("text_scene") + source: UM.Theme.getIcon("pencil") } } } } - } - Row { - id: additionalComponentsRow - anchors.top: jobNameRow.bottom - anchors.right: parent.right + TextField + { + id: printJobTextfield + anchors.left: printJobPencilIcon.right + anchors.leftMargin: UM.Theme.getSize("narrow_margin").width + height: UM.Theme.getSize("jobspecs_line").height + width: Math.max(__contentWidth + UM.Theme.getSize("default_margin").width, 50) + maximumLength: 120 + text: PrintInformation.jobName + horizontalAlignment: TextInput.AlignLeft + + onEditingFinished: + { + var new_name = text == "" ? catalog.i18nc("@text Print job name", "Untitled") : text + PrintInformation.setJobName(new_name, true) + printJobTextfield.focus = false + } + + validator: RegExpValidator { + regExp: /^[^\\\/\*\?\|\[\]]*$/ + } + + style: TextFieldStyle + { + textColor: UM.Theme.getColor("text_scene") + font: UM.Theme.getFont("default_bold") + background: Rectangle + { + opacity: 0 + border.width: 0 + } + } + } } Label { id: boundingSpec anchors.top: jobNameRow.bottom - anchors.right: additionalComponentsRow.left - anchors.rightMargin: - { - if (additionalComponentsRow.width > 0) - { - return UM.Theme.getSize("default_margin").width - } - else - { - return 0; - } - } + anchors.left: parent.left + height: UM.Theme.getSize("jobspecs_line").height verticalAlignment: Text.AlignVCenter - font: UM.Theme.getFont("small") + font: UM.Theme.getFont("default_bold") color: UM.Theme.getColor("text_scene") text: CuraApplication.getSceneBoundingBoxString } - Component.onCompleted: { + Row + { + id: additionalComponentsRow + anchors.top: boundingSpec.top + anchors.bottom: boundingSpec.bottom + anchors.left: boundingSpec.right + anchors.leftMargin: UM.Theme.getSize("default_margin").width + } + + Component.onCompleted: + { base.addAdditionalComponents("jobSpecsButton") } - Connections { + Connections + { target: CuraApplication onAdditionalComponentsChanged: base.addAdditionalComponents("jobSpecsButton") } - function addAdditionalComponents (areaId) { - if(areaId == "jobSpecsButton") { - for (var component in CuraApplication.additionalComponents["jobSpecsButton"]) { + function addAdditionalComponents(areaId) + { + if (areaId == "jobSpecsButton") + { + for (var component in CuraApplication.additionalComponents["jobSpecsButton"]) + { CuraApplication.additionalComponents["jobSpecsButton"][component].parent = additionalComponentsRow } } } - } diff --git a/resources/qml/MachineSelection.qml b/resources/qml/MachineSelection.qml deleted file mode 100644 index 7a8a6b476b..0000000000 --- a/resources/qml/MachineSelection.qml +++ /dev/null @@ -1,86 +0,0 @@ -// Copyright (c) 2017 Ultimaker B.V. -// Cura is released under the terms of the LGPLv3 or higher. - -import QtQuick 2.2 -import QtQuick.Controls 1.1 -import QtQuick.Controls.Styles 1.1 -import QtQuick.Layouts 1.1 - -import UM 1.2 as UM -import Cura 1.0 as Cura -import "Menus" - -ToolButton -{ - id: base - property bool isNetworkPrinter: Cura.MachineManager.activeMachineNetworkKey != "" - property bool printerConnected: Cura.MachineManager.printerConnected - property var printerStatus: Cura.MachineManager.printerConnected ? "connected" : "disconnected" - text: isNetworkPrinter ? Cura.MachineManager.activeMachineNetworkGroupName : Cura.MachineManager.activeMachineName - - tooltip: Cura.MachineManager.activeMachineName - - style: ButtonStyle - { - background: Rectangle - { - color: - { - if (control.pressed) { - return UM.Theme.getColor("sidebar_header_active"); - } - else if (control.hovered) { - return UM.Theme.getColor("sidebar_header_hover"); - } - else { - return UM.Theme.getColor("sidebar_header_bar"); - } - } - Behavior on color { ColorAnimation { duration: 50; } } - - UM.RecolorImage - { - id: downArrow - anchors.verticalCenter: parent.verticalCenter - anchors.right: parent.right - anchors.rightMargin: UM.Theme.getSize("default_margin").width - width: UM.Theme.getSize("standard_arrow").width - height: UM.Theme.getSize("standard_arrow").height - sourceSize.width: width - sourceSize.height: width - color: UM.Theme.getColor("text_emphasis") - source: UM.Theme.getIcon("arrow_bottom") - } - - PrinterStatusIcon - { - id: printerStatusIcon - visible: printerConnected || isNetworkPrinter - status: printerStatus - anchors - { - verticalCenter: parent.verticalCenter - left: parent.left - leftMargin: UM.Theme.getSize("sidebar_margin").width - } - } - - Label - { - id: sidebarComboBoxLabel - color: UM.Theme.getColor("sidebar_header_text_active") - text: control.text; - elide: Text.ElideRight; - anchors.left: printerStatusIcon.visible ? printerStatusIcon.right : parent.left; - anchors.leftMargin: printerStatusIcon.visible ? UM.Theme.getSize("sidebar_lining").width : UM.Theme.getSize("sidebar_margin").width - anchors.right: downArrow.left; - anchors.rightMargin: control.rightMargin; - anchors.verticalCenter: parent.verticalCenter; - font: UM.Theme.getFont("medium_bold") - } - } - label: Label {} - } - - menu: PrinterMenu { } -} diff --git a/resources/qml/MainWindow/ApplicationMenu.qml b/resources/qml/MainWindow/ApplicationMenu.qml new file mode 100644 index 0000000000..04c068cb54 --- /dev/null +++ b/resources/qml/MainWindow/ApplicationMenu.qml @@ -0,0 +1,171 @@ +// Copyright (c) 2018 Ultimaker B.V. +// Cura is released under the terms of the LGPLv3 or higher. + +import QtQuick 2.7 +import QtQuick.Controls 1.4 +import QtQuick.Controls.Styles 1.4 +import QtQuick.Layouts 1.1 +import QtQuick.Dialogs 1.2 + +import UM 1.3 as UM +import Cura 1.1 as Cura + +import "../Menus" +import "../Dialogs" + +Item +{ + id: menu + width: applicationMenu.width + height: applicationMenu.height + property alias window: applicationMenu.window + + UM.ApplicationMenu + { + id: applicationMenu + + FileMenu { title: catalog.i18nc("@title:menu menubar:toplevel", "&File") } + + Menu + { + title: catalog.i18nc("@title:menu menubar:toplevel", "&Edit") + + MenuItem { action: Cura.Actions.undo } + MenuItem { action: Cura.Actions.redo } + MenuSeparator { } + MenuItem { action: Cura.Actions.selectAll } + MenuItem { action: Cura.Actions.arrangeAll } + MenuItem { action: Cura.Actions.deleteSelection } + MenuItem { action: Cura.Actions.deleteAll } + MenuItem { action: Cura.Actions.resetAllTranslation } + MenuItem { action: Cura.Actions.resetAll } + MenuSeparator { } + MenuItem { action: Cura.Actions.groupObjects } + MenuItem { action: Cura.Actions.mergeObjects } + MenuItem { action: Cura.Actions.unGroupObjects } + } + + ViewMenu { title: catalog.i18nc("@title:menu menubar:toplevel", "&View") } + + SettingsMenu { title: catalog.i18nc("@title:menu menubar:toplevel", "&Settings") } + + Menu + { + id: extensionMenu + title: catalog.i18nc("@title:menu menubar:toplevel", "E&xtensions") + + Instantiator + { + id: extensions + model: UM.ExtensionModel { } + + Menu + { + id: sub_menu + title: model.name; + visible: actions != null + enabled: actions != null + Instantiator + { + model: actions + MenuItem + { + text: model.text + onTriggered: extensions.model.subMenuTriggered(name, model.text) + } + onObjectAdded: sub_menu.insertItem(index, object) + onObjectRemoved: sub_menu.removeItem(object) + } + } + + onObjectAdded: extensionMenu.insertItem(index, object) + onObjectRemoved: extensionMenu.removeItem(object) + } + } + + Menu + { + id: plugin_menu + title: catalog.i18nc("@title:menu menubar:toplevel", "&Marketplace") + + MenuItem { action: Cura.Actions.browsePackages } + } + + Menu + { + id: preferencesMenu + title: catalog.i18nc("@title:menu menubar:toplevel", "P&references") + + MenuItem { action: Cura.Actions.preferences } + } + + Menu + { + id: helpMenu + title: catalog.i18nc("@title:menu menubar:toplevel", "&Help") + + MenuItem { action: Cura.Actions.showProfileFolder } + MenuItem { action: Cura.Actions.documentation } + MenuItem { action: Cura.Actions.reportBug } + MenuSeparator { } + MenuItem { action: Cura.Actions.about } + } + } + + // ############################################################################################### + // Definition of other components that are linked to the menus + // ############################################################################################### + + WorkspaceSummaryDialog + { + id: saveWorkspaceDialog + property var args + onYes: UM.OutputDeviceManager.requestWriteToDevice("local_file", PrintInformation.jobName, args) + } + + MessageDialog + { + id: newProjectDialog + modality: Qt.ApplicationModal + title: catalog.i18nc("@title:window", "New project") + text: catalog.i18nc("@info:question", "Are you sure you want to start a new project? This will clear the build plate and any unsaved settings.") + standardButtons: StandardButton.Yes | StandardButton.No + icon: StandardIcon.Question + onYes: + { + CuraApplication.deleteAll(); + Cura.Actions.resetProfile.trigger(); + } + } + + UM.ExtensionModel + { + id: curaExtensions + } + + // ############################################################################################### + // Definition of all the connections + // ############################################################################################### + + Connections + { + target: Cura.Actions.newProject + onTriggered: + { + if(Printer.platformActivity || Cura.MachineManager.hasUserSettings) + { + newProjectDialog.visible = true + } + } + } + + // show the plugin browser dialog + Connections + { + target: Cura.Actions.browsePackages + onTriggered: + { + curaExtensions.callExtensionMethod("Toolbox", "browsePackages") + } + } +} \ No newline at end of file diff --git a/resources/qml/MainWindow/MainWindowHeader.qml b/resources/qml/MainWindow/MainWindowHeader.qml new file mode 100644 index 0000000000..ae1c13d9c3 --- /dev/null +++ b/resources/qml/MainWindow/MainWindowHeader.qml @@ -0,0 +1,118 @@ +// Copyright (c) 2018 Ultimaker B.V. +// Cura is released under the terms of the LGPLv3 or higher. + +import QtQuick 2.7 +import QtQuick.Controls 2.0 as Controls2 +import QtQuick.Controls 1.4 +import QtQuick.Controls.Styles 1.1 + +import UM 1.4 as UM +import Cura 1.0 as Cura +import QtGraphicalEffects 1.0 + +import "../Account" + +Item +{ + id: base + + implicitHeight: UM.Theme.getSize("main_window_header").height + implicitWidth: UM.Theme.getSize("main_window_header").width + + Image + { + id: logo + anchors.left: parent.left + anchors.leftMargin: UM.Theme.getSize("default_margin").width + anchors.verticalCenter: parent.verticalCenter + + source: UM.Theme.getImage("logo") + width: UM.Theme.getSize("logo").width + height: UM.Theme.getSize("logo").height + } + + Row + { + id: stagesListContainer + spacing: Math.round(UM.Theme.getSize("default_margin").width / 2) + + anchors + { + horizontalCenter: parent.horizontalCenter + verticalCenter: parent.verticalCenter + leftMargin: UM.Theme.getSize("default_margin").width + } + + // The main window header is dynamically filled with all available stages + Repeater + { + id: stagesHeader + + model: UM.StageModel { } + + delegate: Button + { + text: model.name.toUpperCase() + checkable: true + checked: model.active + anchors.verticalCenter: parent.verticalCenter + exclusiveGroup: mainWindowHeaderMenuGroup + style: UM.Theme.styles.main_window_header_tab + height: UM.Theme.getSize("main_window_header_button").height + onClicked: UM.Controller.setActiveStage(model.id) + iconSource: model.stage.iconSource + + property color overlayColor: "transparent" + property string overlayIconSource: "" + } + } + + ExclusiveGroup { id: mainWindowHeaderMenuGroup } + } + + // Shortcut button to quick access the Toolbox + Controls2.Button + { + id: marketplaceButton + text: catalog.i18nc("@action:button", "Marketplace") + height: Math.round(0.5 * UM.Theme.getSize("main_window_header").height) + onClicked: Cura.Actions.browsePackages.trigger() + + hoverEnabled: true + + background: Rectangle + { + radius: UM.Theme.getSize("action_button_radius").width + color: marketplaceButton.hovered ? UM.Theme.getColor("primary_text") : UM.Theme.getColor("main_window_header_background") + border.width: UM.Theme.getSize("default_lining").width + border.color: UM.Theme.getColor("primary_text") + } + + contentItem: Label + { + id: label + text: marketplaceButton.text + color: marketplaceButton.hovered ? UM.Theme.getColor("main_window_header_background") : UM.Theme.getColor("primary_text") + width: contentWidth + verticalAlignment: Text.AlignVCenter + renderType: Text.NativeRendering + } + + anchors + { + right: accountWidget.left + rightMargin: UM.Theme.getSize("default_margin").width + verticalCenter: parent.verticalCenter + } + } + + AccountWidget + { + id: accountWidget + anchors + { + right: parent.right + rightMargin: UM.Theme.getSize("default_margin").width + } + } +} diff --git a/resources/qml/Menus/ConfigurationMenu/AutoConfiguration.qml b/resources/qml/Menus/ConfigurationMenu/AutoConfiguration.qml new file mode 100644 index 0000000000..68c56c7c4b --- /dev/null +++ b/resources/qml/Menus/ConfigurationMenu/AutoConfiguration.qml @@ -0,0 +1,39 @@ +// Copyright (c) 2018 Ultimaker B.V. +// Cura is released under the terms of the LGPLv3 or higher. + +import QtQuick 2.7 +import QtQuick.Controls 2.0 + +import UM 1.3 as UM +import Cura 1.0 as Cura + +Item +{ + width: parent.width + height: childrenRect.height + + Label + { + id: header + text: catalog.i18nc("@header", "Configurations") + font: UM.Theme.getFont("large") + color: UM.Theme.getColor("text") + height: contentHeight + renderType: Text.NativeRendering + + anchors + { + left: parent.left + right: parent.right + } + } + + ConfigurationListView + { + anchors.top: header.bottom + anchors.topMargin: UM.Theme.getSize("default_margin").width + width: parent.width + + outputDevice: Cura.MachineManager.printerOutputDevices.length >= 1 ? Cura.MachineManager.printerOutputDevices[0] : null + } +} \ No newline at end of file diff --git a/resources/qml/Menus/ConfigurationMenu/ConfigurationItem.qml b/resources/qml/Menus/ConfigurationMenu/ConfigurationItem.qml index 942dd81d9c..728a0cbe9a 100644 --- a/resources/qml/Menus/ConfigurationMenu/ConfigurationItem.qml +++ b/resources/qml/Menus/ConfigurationMenu/ConfigurationItem.qml @@ -7,143 +7,129 @@ import QtQuick.Controls 2.0 import UM 1.2 as UM import Cura 1.0 as Cura -Rectangle +Button { id: configurationItem property var configuration: null - property var selected: false - signal activateConfiguration() + hoverEnabled: true - height: childrenRect.height - border.width: UM.Theme.getSize("default_lining").width - border.color: updateBorderColor() - color: selected ? UM.Theme.getColor("configuration_item_active") : UM.Theme.getColor("configuration_item") - property var textColor: selected ? UM.Theme.getColor("configuration_item_text_active") : UM.Theme.getColor("configuration_item_text") + height: background.height - function updateBorderColor() + background: Rectangle { - border.color = selected ? UM.Theme.getColor("configuration_item_border_active") : UM.Theme.getColor("configuration_item_border") - } + height: childrenRect.height + color: parent.hovered ? UM.Theme.getColor("action_button_hovered") : UM.Theme.getColor("action_button") + border.color: (parent.checked || parent.hovered) ? UM.Theme.getColor("primary") : UM.Theme.getColor("lining") + border.width: parent.checked ? UM.Theme.getSize("thick_lining").width : UM.Theme.getSize("default_lining").width + radius: UM.Theme.getSize("default_radius").width - Column - { - id: contentColumn - width: parent.width - padding: UM.Theme.getSize("default_margin").width - spacing: Math.round(UM.Theme.getSize("default_margin").height / 2) - - Row + Column { - id: extruderRow + id: contentColumn + width: parent.width + padding: UM.Theme.getSize("wide_margin").width + spacing: UM.Theme.getSize("narrow_margin").height - width: parent.width - 2 * parent.padding - height: childrenRect.height - - spacing: UM.Theme.getSize("default_margin").width - - Repeater + Row { - id: repeater - height: childrenRect.height - model: configuration.extruderConfigurations - delegate: PrintCoreConfiguration + id: extruderRow + + anchors { - width: Math.round(parent.width / 2) - printCoreConfiguration: modelData - mainColor: textColor + left: parent.left + leftMargin: parent.padding + right: parent.right + rightMargin: parent.padding + } + height: childrenRect.height + + spacing: UM.Theme.getSize("default_margin").width + + Repeater + { + id: repeater + height: childrenRect.height + model: configuration.extruderConfigurations + delegate: PrintCoreConfiguration + { + width: Math.round(parent.width / 2) + printCoreConfiguration: modelData + } + } + } + + //Buildplate row separator + Rectangle + { + id: separator + + visible: buildplateInformation.visible + anchors + { + left: parent.left + leftMargin: parent.padding + right: parent.right + rightMargin: parent.padding + } + height: visible ? Math.round(UM.Theme.getSize("default_lining").height / 2) : 0 + color: UM.Theme.getColor("lining") + } + + Item + { + id: buildplateInformation + + anchors + { + left: parent.left + leftMargin: parent.padding + right: parent.right + rightMargin: parent.padding + } + height: childrenRect.height + visible: configuration.buildplateConfiguration != "" + + UM.RecolorImage + { + id: buildplateIcon + anchors.left: parent.left + width: UM.Theme.getSize("main_window_header_button_icon").width + height: UM.Theme.getSize("main_window_header_button_icon").height + source: UM.Theme.getIcon("buildplate") + color: UM.Theme.getColor("text") + } + + Label + { + id: buildplateLabel + anchors.left: buildplateIcon.right + anchors.verticalCenter: buildplateIcon.verticalCenter + anchors.leftMargin: Math.round(UM.Theme.getSize("default_margin").height / 2) + text: configuration.buildplateConfiguration + renderType: Text.NativeRendering + color: UM.Theme.getColor("text") } } } - //Buildplate row separator - Rectangle + Connections { - id: separator - - visible: buildplateInformation.visible - width: parent.width - 2 * parent.padding - height: visible ? Math.round(UM.Theme.getSize("sidebar_lining_thin").height / 2) : 0 - color: textColor - } - - Item - { - id: buildplateInformation - width: parent.width - 2 * parent.padding - height: childrenRect.height - visible: configuration.buildplateConfiguration != "" - - UM.RecolorImage { - id: buildplateIcon - anchors.left: parent.left - width: UM.Theme.getSize("topbar_button_icon").width - height: UM.Theme.getSize("topbar_button_icon").height - sourceSize.width: width - sourceSize.height: height - source: UM.Theme.getIcon("buildplate") - color: textColor - } - - Label + target: Cura.MachineManager + onCurrentConfigurationChanged: { - id: buildplateLabel - anchors.left: buildplateIcon.right - anchors.verticalCenter: buildplateIcon.verticalCenter - anchors.leftMargin: Math.round(UM.Theme.getSize("default_margin").height / 2) - text: configuration.buildplateConfiguration - renderType: Text.NativeRendering - color: textColor + configurationItem.checked = Cura.MachineManager.matchesConfiguration(configuration) } } - } - MouseArea - { - id: mouse - anchors.fill: parent - onClicked: activateConfiguration() - cursorShape: Qt.PointingHandCursor - hoverEnabled: true - onEntered: + Component.onCompleted: { - parent.border.color = UM.Theme.getColor("configuration_item_border_hover") - if (configurationItem.selected == false) - { - configurationItem.color = UM.Theme.getColor("sidebar_lining") - } - } - onExited: - { - updateBorderColor() - if (configurationItem.selected == false) - { - configurationItem.color = UM.Theme.getColor("configuration_item") - } + configurationItem.checked = Cura.MachineManager.matchesConfiguration(configuration) } } - Connections + onClicked: { - target: Cura.MachineManager - onCurrentConfigurationChanged: { - configurationItem.selected = Cura.MachineManager.matchesConfiguration(configuration) - updateBorderColor() - } - } - - Component.onCompleted: - { - configurationItem.selected = Cura.MachineManager.matchesConfiguration(configuration) - updateBorderColor() - } - - onVisibleChanged: - { - if(visible) - { - // I cannot trigger function updateBorderColor() after visibility change - color = selected ? UM.Theme.getColor("configuration_item_active") : UM.Theme.getColor("configuration_item") - } + Cura.MachineManager.applyRemoteConfiguration(configuration) } } \ No newline at end of file diff --git a/resources/qml/Menus/ConfigurationMenu/ConfigurationListView.qml b/resources/qml/Menus/ConfigurationMenu/ConfigurationListView.qml index 7aaf87b4df..3cc0754284 100644 --- a/resources/qml/Menus/ConfigurationMenu/ConfigurationListView.qml +++ b/resources/qml/Menus/ConfigurationMenu/ConfigurationListView.qml @@ -2,8 +2,7 @@ // Cura is released under the terms of the LGPLv3 or higher. import QtQuick 2.7 -import QtQuick.Controls 1.4 -import QtQuick.Controls.Styles 1.4 +import QtQuick.Controls 2.3 import UM 1.2 as UM import Cura 1.0 as Cura @@ -12,75 +11,74 @@ Column { id: base property var outputDevice: null - property var computedHeight: container.height + configurationListHeading.height + 3 * padding height: childrenRect.height + 2 * padding - padding: UM.Theme.getSize("default_margin").width - spacing: Math.round(UM.Theme.getSize("default_margin").height / 2) + spacing: UM.Theme.getSize("narrow_margin").height function forceModelUpdate() { // FIXME For now the model should be removed and then created again, otherwise changes in the printer don't automatically update the UI configurationList.model = [] - if(outputDevice) + if (outputDevice) { configurationList.model = outputDevice.uniqueConfigurations } } - Label - { - id: configurationListHeading - text: catalog.i18nc("@label:header configurations", "Available configurations") - font: UM.Theme.getFont("large") - width: parent.width - 2 * parent.padding - color: UM.Theme.getColor("configuration_item_text") - } - - Component - { - id: sectionHeading - Rectangle - { - height: childrenRect.height + UM.Theme.getSize("default_margin").height - Label - { - text: section - font: UM.Theme.getFont("default_bold") - color: UM.Theme.getColor("configuration_item_text") - } - } - } - ScrollView { id: container - width: parent.width - parent.padding - height: Math.min(configurationList.contentHeight, 350 * screenScaleFactor) + width: parent.width + readonly property int maximumHeight: 350 * screenScaleFactor + height: Math.round(Math.min(configurationList.height, maximumHeight)) + contentHeight: configurationList.height + clip: true - style: UM.Theme.styles.scrollview - __wheelAreaScrollSpeed: 75 // Scroll three lines in one scroll event + ScrollBar.vertical.policy: (configurationList.height > maximumHeight) ? ScrollBar.AlwaysOn : ScrollBar.AlwaysOff //The AsNeeded policy also hides it when the cursor is away, and we don't want that. + ScrollBar.vertical.background: Rectangle + { + implicitWidth: UM.Theme.getSize("scrollbar").width + radius: width / 2 + color: UM.Theme.getColor("scrollbar_background") + } + ScrollBar.vertical.contentItem: Rectangle + { + implicitWidth: UM.Theme.getSize("scrollbar").width + radius: width / 2 + color: UM.Theme.getColor(parent.pressed ? "scrollbar_handle_down" : parent.hovered ? "scrollbar_handle_hover" : "scrollbar_handle") + } + + ButtonGroup + { + buttons: configurationList.children + } ListView { id: configurationList - spacing: Math.round(UM.Theme.getSize("default_margin").height / 2) - width: container.width + spacing: UM.Theme.getSize("narrow_margin").height + width: container.width - ((height > container.maximumHeight) ? container.ScrollBar.vertical.background.width : 0) //Make room for scroll bar if there is any. contentHeight: childrenRect.height + height: childrenRect.height section.property: "modelData.printerType" section.criteria: ViewSection.FullString - section.delegate: sectionHeading + section.delegate: Item + { + height: printerTypeLabel.height + UM.Theme.getSize("wide_margin").height //Causes a default margin above the label and a default margin below the label. + Cura.PrinterTypeLabel + { + id: printerTypeLabel + text: Cura.MachineManager.getAbbreviatedMachineName(section) + anchors.verticalCenter: parent.verticalCenter //One default margin above and one below. + } + } model: (outputDevice != null) ? outputDevice.uniqueConfigurations : [] + delegate: ConfigurationItem { - width: parent.width - UM.Theme.getSize("default_margin").width + width: parent.width configuration: modelData - onActivateConfiguration: - { - switchPopupState() - Cura.MachineManager.applyRemoteConfiguration(configuration) - } } } } diff --git a/resources/qml/Menus/ConfigurationMenu/ConfigurationMenu.qml b/resources/qml/Menus/ConfigurationMenu/ConfigurationMenu.qml new file mode 100644 index 0000000000..33a317b42b --- /dev/null +++ b/resources/qml/Menus/ConfigurationMenu/ConfigurationMenu.qml @@ -0,0 +1,218 @@ +// Copyright (c) 2018 Ultimaker B.V. +// Cura is released under the terms of the LGPLv3 or higher. + +import QtQuick 2.7 +import QtQuick.Controls 2.0 +import QtQuick.Controls.Styles 1.4 + +import UM 1.2 as UM +import Cura 1.0 as Cura + + +/** + * Menu that allows you to select the configuration of the current printer, such + * as the nozzle sizes and materials in each extruder. + */ +Cura.ExpandablePopup +{ + id: base + + Cura.ExtrudersModel + { + id: extrudersModel + } + + UM.I18nCatalog + { + id: catalog + name: "cura" + } + + enum ConfigurationMethod + { + Auto, + Custom + } + + enabled: Cura.MachineManager.hasMaterials || Cura.MachineManager.hasVariants || Cura.MachineManager.hasVariantBuildplates; //Only let it drop down if there is any configuration that you could change. + + headerItem: Item + { + // Horizontal list that shows the extruders and their materials + ListView + { + id: extrudersList + + orientation: ListView.Horizontal + anchors.fill: parent + model: extrudersModel + visible: Cura.MachineManager.hasMaterials + + delegate: Item + { + height: parent.height + width: Math.round(ListView.view.width / extrudersModel.count) + + // Extruder icon. Shows extruder index and has the same color as the active material. + Cura.ExtruderIcon + { + id: extruderIcon + materialColor: model.color + extruderEnabled: model.enabled + height: parent.height + width: height + } + + // Label for the brand of the material + Label + { + id: brandNameLabel + + text: model.material_brand + elide: Text.ElideRight + font: UM.Theme.getFont("default") + color: UM.Theme.getColor("text_inactive") + renderType: Text.NativeRendering + + anchors + { + left: extruderIcon.right + leftMargin: UM.Theme.getSize("default_margin").width + right: parent.right + rightMargin: UM.Theme.getSize("default_margin").width + } + } + + // Label that shows the name of the material + Label + { + text: model.material + elide: Text.ElideRight + font: UM.Theme.getFont("default") + color: UM.Theme.getColor("text") + renderType: Text.NativeRendering + + anchors + { + left: extruderIcon.right + leftMargin: UM.Theme.getSize("default_margin").width + right: parent.right + rightMargin: UM.Theme.getSize("default_margin").width + top: brandNameLabel.bottom + } + } + } + } + + //Placeholder text if there is a configuration to select but no materials (so we can't show the materials per extruder). + Label + { + text: catalog.i18nc("@label", "Select configuration") + elide: Text.ElideRight + font: UM.Theme.getFont("default") + color: UM.Theme.getColor("text") + renderType: Text.NativeRendering + + visible: !Cura.MachineManager.hasMaterials && (Cura.MachineManager.hasVariants || Cura.MachineManager.hasVariantBuildplates) + + anchors + { + left: parent.left + leftMargin: UM.Theme.getSize("default_margin").width + verticalCenter: parent.verticalCenter + } + } + } + + contentItem: Column + { + id: popupItem + width: base.width - 2 * UM.Theme.getSize("default_margin").width + height: implicitHeight //Required because ExpandableComponent will try to use this to determine the size of the background of the pop-up. + spacing: UM.Theme.getSize("default_margin").height + + property bool is_connected: false //If current machine is connected to a printer. Only evaluated upon making popup visible. + onVisibleChanged: + { + is_connected = Cura.MachineManager.activeMachineNetworkKey !== "" && Cura.MachineManager.printerConnected //Re-evaluate. + } + + property int configuration_method: is_connected ? ConfigurationMenu.ConfigurationMethod.Auto : ConfigurationMenu.ConfigurationMethod.Custom //Auto if connected to a printer at start-up, or Custom if not. + + Item + { + width: parent.width + height: + { + var height = 0; + if(autoConfiguration.visible) + { + height += autoConfiguration.height; + } + if(customConfiguration.visible) + { + height += customConfiguration.height; + } + return height; + } + AutoConfiguration + { + id: autoConfiguration + visible: popupItem.configuration_method == ConfigurationMenu.ConfigurationMethod.Auto + } + + CustomConfiguration + { + id: customConfiguration + visible: popupItem.configuration_method == ConfigurationMenu.ConfigurationMethod.Custom + } + } + + Rectangle + { + id: separator + visible: buttonBar.visible + x: -contentPadding + + width: base.width + height: UM.Theme.getSize("default_lining").height + + color: UM.Theme.getColor("lining") + } + + //Allow switching between custom and auto. + Item + { + id: buttonBar + visible: popupItem.is_connected //Switching only makes sense if the "auto" part is possible. + + width: parent.width + height: childrenRect.height + + Cura.SecondaryButton + { + id: goToCustom + visible: popupItem.configuration_method == ConfigurationMenu.ConfigurationMethod.Auto + text: catalog.i18nc("@label", "Custom") + + anchors.right: parent.right + + iconSource: UM.Theme.getIcon("arrow_right") + isIconOnRightSide: true + + onClicked: popupItem.configuration_method = ConfigurationMenu.ConfigurationMethod.Custom + } + + Cura.SecondaryButton + { + id: goToAuto + visible: popupItem.configuration_method == ConfigurationMenu.ConfigurationMethod.Custom + text: catalog.i18nc("@label", "Configurations") + + iconSource: UM.Theme.getIcon("arrow_left") + + onClicked: popupItem.configuration_method = ConfigurationMenu.ConfigurationMethod.Auto + } + } + } +} diff --git a/resources/qml/Menus/ConfigurationMenu/ConfigurationSelection.qml b/resources/qml/Menus/ConfigurationMenu/ConfigurationSelection.qml deleted file mode 100644 index d7ee2c68ee..0000000000 --- a/resources/qml/Menus/ConfigurationMenu/ConfigurationSelection.qml +++ /dev/null @@ -1,65 +0,0 @@ -// Copyright (c) 2018 Ultimaker B.V. -// Cura is released under the terms of the LGPLv3 or higher. - -import QtQuick 2.7 -import QtQuick.Controls 2.0 -import QtQuick.Controls.Styles 1.4 - -import UM 1.2 as UM -import Cura 1.0 as Cura - -Item -{ - id: configurationSelector - property var connectedDevice: Cura.MachineManager.printerOutputDevices.length >= 1 ? Cura.MachineManager.printerOutputDevices[0] : null - property var panelWidth: control.width - - function switchPopupState() - { - popup.visible ? popup.close() : popup.open() - } - - SyncButton - { - id: syncButton - onClicked: switchPopupState() - outputDevice: connectedDevice - } - - Popup - { - // TODO Change once updating to Qt5.10 - The 'opened' property is in 5.10 but the behavior is now implemented with the visible property - id: popup - clip: true - closePolicy: Popup.CloseOnPressOutsideParent - y: configurationSelector.height - UM.Theme.getSize("default_lining").height - x: configurationSelector.width - width - width: panelWidth - visible: false - padding: UM.Theme.getSize("default_lining").width - transformOrigin: Popup.Top - contentItem: ConfigurationListView - { - id: configList - width: panelWidth - 2 * popup.padding - outputDevice: connectedDevice - } - background: Rectangle - { - color: UM.Theme.getColor("setting_control") - border.color: UM.Theme.getColor("setting_control_border") - } - exit: Transition - { - // This applies a default NumberAnimation to any changes a state change makes to x or y properties - NumberAnimation { property: "visible"; duration: 75; } - } - enter: Transition - { - // This applies a default NumberAnimation to any changes a state change makes to x or y properties - NumberAnimation { property: "visible"; duration: 75; } - } - onClosed: visible = false - onOpened: visible = true - } -} \ No newline at end of file diff --git a/resources/qml/Menus/ConfigurationMenu/CustomConfiguration.qml b/resources/qml/Menus/ConfigurationMenu/CustomConfiguration.qml new file mode 100644 index 0000000000..8429e2c093 --- /dev/null +++ b/resources/qml/Menus/ConfigurationMenu/CustomConfiguration.qml @@ -0,0 +1,295 @@ +// Copyright (c) 2018 Ultimaker B.V. +// Cura is released under the terms of the LGPLv3 or higher. + +import QtQuick 2.6 +import QtQuick.Controls 2.0 +import QtQuick.Controls 1.1 as OldControls + +import Cura 1.0 as Cura +import UM 1.3 as UM + +Item +{ + UM.I18nCatalog + { + id: catalog + name: "cura" + } + + width: parent.width + height: childrenRect.height + + Label + { + id: header + text: catalog.i18nc("@header", "Custom") + font: UM.Theme.getFont("large") + color: UM.Theme.getColor("text") + height: contentHeight + renderType: Text.NativeRendering + + anchors + { + top: parent.top + left: parent.left + right: parent.right + } + } + + //Printer type selector. + Item + { + id: printerTypeSelectorRow + visible: + { + return Cura.MachineManager.printerOutputDevices.length >= 1 //If connected... + && Cura.MachineManager.printerOutputDevices[0].connectedPrintersTypeCount != null //...and we have configuration information... + && Cura.MachineManager.printerOutputDevices[0].connectedPrintersTypeCount.length > 1; //...and there is more than one type of printer in the configuration list. + } + height: visible ? childrenRect.height : 0 + + anchors + { + left: parent.left + leftMargin: UM.Theme.getSize("default_margin").width + right: parent.right + rightMargin: UM.Theme.getSize("default_margin").width + top: header.bottom + topMargin: visible ? UM.Theme.getSize("default_margin").height : 0 + } + + Label + { + text: catalog.i18nc("@label", "Printer") + width: Math.round(parent.width * 0.3) - UM.Theme.getSize("default_margin").width + height: contentHeight + font: UM.Theme.getFont("default") + color: UM.Theme.getColor("text") + anchors.verticalCenter: printerTypeSelector.verticalCenter + anchors.left: parent.left + } + + OldControls.ToolButton + { + id: printerTypeSelector + text: Cura.MachineManager.activeMachineDefinitionName + tooltip: Cura.MachineManager.activeMachineDefinitionName + height: UM.Theme.getSize("setting_control").height + width: Math.round(parent.width * 0.7) + UM.Theme.getSize("default_margin").width + anchors.right: parent.right + style: UM.Theme.styles.print_setup_header_button + + menu: Cura.PrinterTypeMenu { } + } + } + + UM.TabRow + { + id: tabBar + anchors.top: printerTypeSelectorRow.bottom + anchors.topMargin: UM.Theme.getSize("default_margin").height + visible: extrudersModel.count > 1 + + Repeater + { + id: repeater + model: extrudersModel + delegate: UM.TabRowButton + { + contentItem: Item + { + Cura.ExtruderIcon + { + anchors.horizontalCenter: parent.horizontalCenter + materialColor: model.color + extruderEnabled: model.enabled + width: parent.height + height: parent.height + } + } + onClicked: + { + Cura.ExtruderManager.setActiveExtruderIndex(tabBar.currentIndex) + } + } + } + + //When active extruder changes for some other reason, switch tabs. + //Don't directly link currentIndex to Cura.ExtruderManager.activeExtruderIndex! + //This causes a segfault in Qt 5.11. Something with VisualItemModel removing index -1. We have to use setCurrentIndex instead. + Connections + { + target: Cura.ExtruderManager + onActiveExtruderChanged: + { + tabBar.setCurrentIndex(Cura.ExtruderManager.activeExtruderIndex); + } + } + + //When the model of the extruders is rebuilt, the list of extruders is briefly emptied and rebuilt. + //This causes the currentIndex of the tab to be in an invalid position which resets it to 0. + //Therefore we need to change it back to what it was: The active extruder index. + Connections + { + target: repeater.model + onModelChanged: + { + tabBar.setCurrentIndex(Cura.ExtruderManager.activeExtruderIndex) + } + } + } + + Rectangle + { + width: parent.width + height: childrenRect.height + anchors.top: tabBar.bottom + + radius: tabBar.visible ? UM.Theme.getSize("default_radius").width : 0 + border.width: tabBar.visible ? UM.Theme.getSize("default_lining").width : 0 + border.color: UM.Theme.getColor("lining") + color: UM.Theme.getColor("main_background") + + //Remove rounding and lining at the top. + Rectangle + { + width: parent.width + height: parent.radius + anchors.top: parent.top + color: UM.Theme.getColor("lining") + visible: tabBar.visible + Rectangle + { + anchors + { + left: parent.left + leftMargin: parent.parent.border.width + right: parent.right + rightMargin: parent.parent.border.width + top: parent.top + } + height: parent.parent.radius + color: parent.parent.color + } + } + + Column + { + id: selectors + padding: UM.Theme.getSize("default_margin").width + spacing: UM.Theme.getSize("default_margin").height + + property var model: extrudersModel.items[tabBar.currentIndex] + + readonly property real paddedWidth: parent.width - padding * 2 + property real textWidth: Math.round(paddedWidth * 0.3) + property real controlWidth: paddedWidth - textWidth + + Row + { + height: UM.Theme.getSize("print_setup_item").height + visible: extrudersModel.count > 1 // If there is only one extruder, there is no point to enable/disable that. + + Label + { + text: catalog.i18nc("@label", "Enabled") + verticalAlignment: Text.AlignVCenter + font: UM.Theme.getFont("default") + color: UM.Theme.getColor("text") + height: parent.height + width: selectors.textWidth + renderType: Text.NativeRendering + } + + OldControls.CheckBox + { + checked: Cura.MachineManager.activeStack != null ? Cura.MachineManager.activeStack.isEnabled : false + enabled: !checked || Cura.MachineManager.numberExtrudersEnabled > 1 //Disable if it's the last enabled extruder. + height: UM.Theme.getSize("setting_control").height + style: UM.Theme.styles.checkbox + + /* Use a MouseArea to process the click on this checkbox. + This is necessary because actually clicking the checkbox + causes the "checked" property to be overwritten. After + it's been overwritten, the original link that made it + depend on the active extruder stack is broken. */ + MouseArea + { + anchors.fill: parent + onClicked: Cura.MachineManager.setExtruderEnabled(Cura.ExtruderManager.activeExtruderIndex, !parent.checked) + enabled: parent.enabled + } + } + } + + Row + { + height: UM.Theme.getSize("print_setup_item").height + visible: Cura.MachineManager.hasMaterials + + Label + { + text: catalog.i18nc("@label", "Material") + verticalAlignment: Text.AlignVCenter + font: UM.Theme.getFont("default") + color: UM.Theme.getColor("text") + height: parent.height + width: selectors.textWidth + renderType: Text.NativeRendering + } + + OldControls.ToolButton + { + id: materialSelection + + property bool valueError: Cura.MachineManager.activeStack != null ? Cura.ContainerManager.getContainerMetaDataEntry(Cura.MachineManager.activeStack.material.id, "compatible", "") != "True" : true + property bool valueWarning: !Cura.MachineManager.isActiveQualitySupported + + text: Cura.MachineManager.activeStack != null ? Cura.MachineManager.activeStack.material.name : "" + tooltip: text + + height: UM.Theme.getSize("setting_control").height + width: selectors.controlWidth + + style: UM.Theme.styles.print_setup_header_button + activeFocusOnPress: true + menu: Cura.MaterialMenu + { + extruderIndex: Cura.ExtruderManager.activeExtruderIndex + } + } + } + + Row + { + height: UM.Theme.getSize("print_setup_item").height + visible: Cura.MachineManager.hasVariants + + Label + { + text: Cura.MachineManager.activeDefinitionVariantsName + verticalAlignment: Text.AlignVCenter + font: UM.Theme.getFont("default") + color: UM.Theme.getColor("text") + height: parent.height + width: selectors.textWidth + renderType: Text.NativeRendering + } + + OldControls.ToolButton + { + id: variantSelection + text: Cura.MachineManager.activeVariantName + tooltip: Cura.MachineManager.activeVariantName + + height: UM.Theme.getSize("setting_control").height + width: selectors.controlWidth + style: UM.Theme.styles.print_setup_header_button + activeFocusOnPress: true; + + menu: Cura.NozzleMenu { extruderIndex: Cura.ExtruderManager.activeExtruderIndex } + } + } + } + } +} diff --git a/resources/qml/Menus/ConfigurationMenu/PrintCoreConfiguration.qml b/resources/qml/Menus/ConfigurationMenu/PrintCoreConfiguration.qml index 97b5bee745..a344e31d4f 100644 --- a/resources/qml/Menus/ConfigurationMenu/PrintCoreConfiguration.qml +++ b/resources/qml/Menus/ConfigurationMenu/PrintCoreConfiguration.qml @@ -5,87 +5,50 @@ import QtQuick 2.7 import QtQuick.Controls 2.0 import UM 1.2 as UM +import Cura 1.0 as Cura - -Column +Row { id: extruderInfo property var printCoreConfiguration - property var mainColor: "black" - spacing: Math.round(UM.Theme.getSize("default_margin").height / 2) - height: childrenRect.height + height: information.height + spacing: UM.Theme.getSize("default_margin").width - Item + //Extruder icon. + Cura.ExtruderIcon { - id: extruder - width: parent.width - height: childrenRect.height + materialColor: printCoreConfiguration.material.color + anchors.verticalCenter: parent.verticalCenter + extruderEnabled: printCoreConfiguration.material.brand !== "" && printCoreConfiguration.hotendID !== "" + } + Column + { + id: information Label { - id: extruderLabel - text: catalog.i18nc("@label:extruder label", "Extruder") + text: printCoreConfiguration.material.brand ? printCoreConfiguration.material.brand : " " //Use space so that the height is still correct. renderType: Text.NativeRendering elide: Text.ElideRight - anchors.left: parent.left font: UM.Theme.getFont("default") - color: mainColor + color: UM.Theme.getColor("text_inactive") } - - // Rounded item to show the extruder number - Item + Label { - id: extruderIconItem - anchors.verticalCenter: extruderLabel.verticalCenter - anchors.left: extruderLabel.right - anchors.leftMargin: Math.round(UM.Theme.getSize("default_margin").width / 2) - - width: UM.Theme.getSize("section_icon").width - height: UM.Theme.getSize("section_icon").height - - UM.RecolorImage { - id: mainCircle - anchors.fill: parent - - anchors.centerIn: parent - sourceSize.width: parent.width - sourceSize.height: parent.height - source: UM.Theme.getIcon("extruder_button") - color: mainColor - } - - Label - { - id: extruderNumberText - anchors.centerIn: parent - text: printCoreConfiguration.position + 1 - renderType: Text.NativeRendering - font: UM.Theme.getFont("default") - color: mainColor - } + text: printCoreConfiguration.material.brand ? printCoreConfiguration.material.name : " " //Use space so that the height is still correct. + renderType: Text.NativeRendering + elide: Text.ElideRight + font: UM.Theme.getFont("default") + color: UM.Theme.getColor("text") + } + Label + { + text: printCoreConfiguration.hotendID ? printCoreConfiguration.hotendID : " " //Use space so that the height is still correct. + renderType: Text.NativeRendering + elide: Text.ElideRight + font: UM.Theme.getFont("default") + color: UM.Theme.getColor("text_inactive") } - } - - Label - { - id: materialLabel - text: printCoreConfiguration.material.name - renderType: Text.NativeRendering - elide: Text.ElideRight - width: parent.width - font: UM.Theme.getFont("default_bold") - color: mainColor - } - - Label - { - id: printCoreTypeLabel - text: printCoreConfiguration.hotendID - renderType: Text.NativeRendering - elide: Text.ElideRight - width: parent.width - font: UM.Theme.getFont("default") - color: mainColor } } diff --git a/resources/qml/Menus/ConfigurationMenu/SyncButton.qml b/resources/qml/Menus/ConfigurationMenu/SyncButton.qml deleted file mode 100644 index 3099d684c1..0000000000 --- a/resources/qml/Menus/ConfigurationMenu/SyncButton.qml +++ /dev/null @@ -1,102 +0,0 @@ -// Copyright (c) 2018 Ultimaker B.V. -// Cura is released under the terms of the LGPLv3 or higher. - -import QtQuick 2.7 -import QtQuick.Controls 1.4 -import QtQuick.Controls.Styles 1.4 - -import UM 1.2 as UM -import Cura 1.0 as Cura - -Button -{ - id: base - property var outputDevice: null - property var matched: updateOnSync() - text: matched == true ? catalog.i18nc("@label:extruder label", "Yes") : catalog.i18nc("@label:extruder label", "No") - width: parent.width - height: parent.height - - function updateOnSync() - { - if (outputDevice != undefined) - { - for (var index in outputDevice.uniqueConfigurations) - { - var configuration = outputDevice.uniqueConfigurations[index] - if (Cura.MachineManager.matchesConfiguration(configuration)) - { - base.matched = true; - return; - } - } - } - base.matched = false; - } - - style: ButtonStyle - { - background: Rectangle - { - color: - { - if(control.pressed) - { - return UM.Theme.getColor("sidebar_header_active"); - } - else if(control.hovered) - { - return UM.Theme.getColor("sidebar_header_hover"); - } - else - { - return UM.Theme.getColor("sidebar_header_bar"); - } - } - Behavior on color { ColorAnimation { duration: 50; } } - - UM.RecolorImage - { - id: downArrow - anchors.verticalCenter: parent.verticalCenter - anchors.right: parent.right - anchors.rightMargin: UM.Theme.getSize("default_margin").width - width: UM.Theme.getSize("standard_arrow").width - height: UM.Theme.getSize("standard_arrow").height - sourceSize.width: width - sourceSize.height: height - color: UM.Theme.getColor("text_emphasis") - source: UM.Theme.getIcon("arrow_bottom") - } - UM.RecolorImage - { - id: sidebarComboBoxLabel - anchors.left: parent.left - anchors.leftMargin: UM.Theme.getSize("default_margin").width - anchors.verticalCenter: parent.verticalCenter; - - width: UM.Theme.getSize("printer_sync_icon").width - height: UM.Theme.getSize("printer_sync_icon").height - - color: control.matched ? UM.Theme.getColor("printer_config_matched") : UM.Theme.getColor("printer_config_mismatch") - source: UM.Theme.getIcon("tab_status_connected") - sourceSize.width: width - sourceSize.height: height - } - } - label: Label {} - } - - Connections - { - target: outputDevice - onUniqueConfigurationsChanged: updateOnSync() - } - - Connections - { - target: Cura.MachineManager - onCurrentConfigurationChanged: updateOnSync() - onOutputDevicesChanged: updateOnSync() - } -} \ No newline at end of file diff --git a/resources/qml/Menus/FileMenu.qml b/resources/qml/Menus/FileMenu.qml new file mode 100644 index 0000000000..955ac89693 --- /dev/null +++ b/resources/qml/Menus/FileMenu.qml @@ -0,0 +1,81 @@ +// Copyright (c) 2018 Ultimaker B.V. +// Cura is released under the terms of the LGPLv3 or higher. + +import QtQuick 2.2 +import QtQuick.Controls 1.1 + +import UM 1.2 as UM +import Cura 1.0 as Cura + +Menu +{ + id: base + title: catalog.i18nc("@title:menu menubar:toplevel", "&File") + + MenuItem + { + id: newProjectMenu + action: Cura.Actions.newProject + } + + MenuItem + { + id: openMenu + action: Cura.Actions.open + } + + RecentFilesMenu { } + + MenuItem + { + id: saveWorkspaceMenu + text: catalog.i18nc("@title:menu menubar:file", "&Save...") + onTriggered: + { + var args = { "filter_by_machine": false, "file_type": "workspace", "preferred_mimetypes": "application/vnd.ms-package.3dmanufacturing-3dmodel+xml" }; + if(UM.Preferences.getValue("cura/dialog_on_project_save")) + { + saveWorkspaceDialog.args = args + saveWorkspaceDialog.open() + } + else + { + UM.OutputDeviceManager.requestWriteToDevice("local_file", PrintInformation.jobName, args) + } + } + } + + MenuSeparator { } + + MenuItem + { + id: saveAsMenu + text: catalog.i18nc("@title:menu menubar:file", "&Export...") + onTriggered: + { + var localDeviceId = "local_file" + UM.OutputDeviceManager.requestWriteToDevice(localDeviceId, PrintInformation.jobName, { "filter_by_machine": false, "preferred_mimetypes": "application/vnd.ms-package.3dmanufacturing-3dmodel+xml"}) + } + } + + MenuItem + { + id: exportSelectionMenu + text: catalog.i18nc("@action:inmenu menubar:file", "Export Selection...") + enabled: UM.Selection.hasSelection + iconName: "document-save-as" + onTriggered: UM.OutputDeviceManager.requestWriteSelectionToDevice("local_file", PrintInformation.jobName, { "filter_by_machine": false, "preferred_mimetypes": "application/vnd.ms-package.3dmanufacturing-3dmodel+xml"}) + } + + MenuSeparator { } + + MenuItem + { + id: reloadAllMenu + action: Cura.Actions.reloadAll + } + + MenuSeparator { } + + MenuItem { action: Cura.Actions.quit } +} \ No newline at end of file diff --git a/resources/qml/Menus/PrinterStatusIcon.qml b/resources/qml/Menus/PrinterStatusIcon.qml deleted file mode 100644 index 6ff6b07af8..0000000000 --- a/resources/qml/Menus/PrinterStatusIcon.qml +++ /dev/null @@ -1,27 +0,0 @@ -// Copyright (c) 2017 Ultimaker B.V. -// Cura is released under the terms of the LGPLv3 or higher. - -import QtQuick 2.2 - -import UM 1.2 as UM -import Cura 1.0 as Cura - -Item -{ - property var status: "disconnected" - width: childrenRect.width - height: childrenRect.height - UM.RecolorImage - { - id: statusIcon - width: UM.Theme.getSize("printer_status_icon").width - height: UM.Theme.getSize("printer_status_icon").height - sourceSize.width: width - sourceSize.height: width - color: UM.Theme.getColor("tab_status_" + parent.status) - source: UM.Theme.getIcon(parent.status) - } -} - - - diff --git a/resources/qml/Menus/ProfileMenu.qml b/resources/qml/Menus/ProfileMenu.qml index fd46d2ef72..bf950aa409 100644 --- a/resources/qml/Menus/ProfileMenu.qml +++ b/resources/qml/Menus/ProfileMenu.qml @@ -37,7 +37,7 @@ Menu MenuSeparator { id: customSeparator - visible: Cura.CustomQualityProfilesDropDownMenuModel.rowCount > 0 + visible: Cura.CustomQualityProfilesDropDownMenuModel.count > 0 } Instantiator @@ -48,7 +48,7 @@ Menu Connections { target: Cura.CustomQualityProfilesDropDownMenuModel - onModelReset: customSeparator.visible = Cura.CustomQualityProfilesDropDownMenuModel.rowCount() > 0 + onModelReset: customSeparator.visible = Cura.CustomQualityProfilesDropDownMenuModel.count > 0 } MenuItem @@ -62,12 +62,12 @@ Menu onObjectAdded: { - customSeparator.visible = model.rowCount() > 0; + customSeparator.visible = model.count > 0; menu.insertItem(index, object); } onObjectRemoved: { - customSeparator.visible = model.rowCount() > 0; + customSeparator.visible = model.count > 0; menu.removeItem(object); } } diff --git a/resources/qml/Menus/RecentFilesMenu.qml b/resources/qml/Menus/RecentFilesMenu.qml index 12f53fb517..0f1f67b6fa 100644 --- a/resources/qml/Menus/RecentFilesMenu.qml +++ b/resources/qml/Menus/RecentFilesMenu.qml @@ -7,6 +7,8 @@ import QtQuick.Controls 1.1 import UM 1.3 as UM import Cura 1.0 as Cura +import "../Dialogs" + Menu { id: menu diff --git a/resources/qml/Menus/SettingsMenu.qml b/resources/qml/Menus/SettingsMenu.qml new file mode 100644 index 0000000000..4ea3a4d71a --- /dev/null +++ b/resources/qml/Menus/SettingsMenu.qml @@ -0,0 +1,70 @@ +// Copyright (c) 2018 Ultimaker B.V. +// Cura is released under the terms of the LGPLv3 or higher. + +import QtQuick 2.2 +import QtQuick.Controls 1.1 + +import UM 1.2 as UM +import Cura 1.0 as Cura + +Menu +{ + id: base + title: catalog.i18nc("@title:menu menubar:toplevel", "&Settings") + + PrinterMenu { title: catalog.i18nc("@title:menu menubar:settings", "&Printer") } + + Instantiator + { + model: Cura.MachineManager.activeMachine.extruderList + + Menu + { + title: modelData.name + + NozzleMenu { title: Cura.MachineManager.activeDefinitionVariantsName; visible: Cura.MachineManager.hasVariants; extruderIndex: index } + MaterialMenu { title: catalog.i18nc("@title:menu", "&Material"); visible: Cura.MachineManager.hasMaterials; extruderIndex: index } + + MenuSeparator + { + visible: Cura.MachineManager.hasVariants || Cura.MachineManager.hasMaterials + } + + MenuItem + { + text: catalog.i18nc("@action:inmenu", "Set as Active Extruder") + onTriggered: Cura.MachineManager.setExtruderIndex(model.index) + } + + MenuItem + { + text: catalog.i18nc("@action:inmenu", "Enable Extruder") + onTriggered: Cura.MachineManager.setExtruderEnabled(model.index, true) + visible: !Cura.MachineManager.getExtruder(model.index).isEnabled + } + + MenuItem + { + text: catalog.i18nc("@action:inmenu", "Disable Extruder") + onTriggered: Cura.MachineManager.setExtruderEnabled(model.index, false) + visible: Cura.MachineManager.getExtruder(model.index).isEnabled + enabled: Cura.MachineManager.numberExtrudersEnabled > 1 + } + + } + onObjectAdded: base.insertItem(index, object) + onObjectRemoved: base.removeItem(object) + } + + // TODO Only show in dev mode. Remove check when feature ready + BuildplateMenu + { + title: catalog.i18nc("@title:menu", "&Build plate") + visible: CuraSDKVersion == "dev" && Cura.MachineManager.hasVariantBuildplates + } + ProfileMenu { title: catalog.i18nc("@title:settings", "&Profile") } + + MenuSeparator { } + + MenuItem { action: Cura.Actions.configureSettingVisibility } +} \ No newline at end of file diff --git a/resources/qml/Menus/ViewMenu.qml b/resources/qml/Menus/ViewMenu.qml index 12d4ffd7dd..217975c803 100644 --- a/resources/qml/Menus/ViewMenu.qml +++ b/resources/qml/Menus/ViewMenu.qml @@ -11,32 +11,10 @@ Menu { title: catalog.i18nc("@title:menu menubar:toplevel", "&View") id: base + enabled: !PrintInformation.preSliced property var multiBuildPlateModel: CuraApplication.getMultiBuildPlateModel() - // main views - Instantiator - { - model: UM.ViewModel{} - MenuItem - { - text: model.name - checkable: true - checked: model.active - exclusiveGroup: group - onTriggered: UM.Controller.setActiveView(model.id) - enabled: !PrintInformation.preSliced - } - onObjectAdded: base.insertItem(index, object) - onObjectRemoved: base.removeItem(object) - } - ExclusiveGroup - { - id: group - } - - MenuSeparator {} - Menu { title: catalog.i18nc("@action:inmenu menubar:view","&Camera position"); @@ -80,12 +58,6 @@ Menu MenuSeparator {} - MenuItem - { - action: Cura.Actions.expandSidebar - } - - MenuSeparator {} MenuItem { action: Cura.Actions.toggleFullScreen diff --git a/resources/qml/MonitorButton.qml b/resources/qml/MonitorButton.qml index aa40de11e4..fd7d2287c4 100644 --- a/resources/qml/MonitorButton.qml +++ b/resources/qml/MonitorButton.qml @@ -13,9 +13,9 @@ import Cura 1.0 as Cura Item { id: base; - UM.I18nCatalog { id: catalog; name:"cura"} + UM.I18nCatalog { id: catalog; name: "cura"} - height: childrenRect.height + UM.Theme.getSize("sidebar_margin").height + height: childrenRect.height + UM.Theme.getSize("thick_margin").height property bool printerConnected: Cura.MachineManager.printerConnected property bool printerAcceptsCommands: printerConnected && Cura.MachineManager.printerOutputDevices[0].acceptsCommands @@ -162,10 +162,10 @@ Item Label { id: statusLabel - width: parent.width - 2 * UM.Theme.getSize("sidebar_margin").width + width: parent.width - 2 * UM.Theme.getSize("thick_margin").width anchors.top: parent.top anchors.left: parent.left - anchors.leftMargin: UM.Theme.getSize("sidebar_margin").width + anchors.leftMargin: UM.Theme.getSize("thick_margin").width color: base.statusColor font: UM.Theme.getFont("large") @@ -224,12 +224,12 @@ Item property string backgroundColor: UM.Theme.getColor("progressbar_background"); property string controlColor: base.statusColor; - width: parent.width - 2 * UM.Theme.getSize("sidebar_margin").width; + width: parent.width - 2 * UM.Theme.getSize("thick_margin").width; height: UM.Theme.getSize("progressbar").height; anchors.top: statusLabel.bottom; - anchors.topMargin: Math.round(UM.Theme.getSize("sidebar_margin").height / 4); + anchors.topMargin: Math.round(UM.Theme.getSize("thick_margin").height / 4); anchors.left: parent.left; - anchors.leftMargin: UM.Theme.getSize("sidebar_margin").width; + anchors.leftMargin: UM.Theme.getSize("thick_margin").width; } Row @@ -237,9 +237,9 @@ Item id: buttonsRow height: abortButton.height anchors.top: progressBar.bottom - anchors.topMargin: UM.Theme.getSize("sidebar_margin").height + anchors.topMargin: UM.Theme.getSize("thick_margin").height anchors.right: parent.right - anchors.rightMargin: UM.Theme.getSize("sidebar_margin").width + anchors.rightMargin: UM.Theme.getSize("thick_margin").width spacing: UM.Theme.getSize("default_margin").width Row @@ -309,7 +309,7 @@ Item } } - style: UM.Theme.styles.sidebar_action_button + style: UM.Theme.styles.print_setup_action_button } Button @@ -325,7 +325,7 @@ Item text: catalog.i18nc("@label", "Abort Print") onClicked: confirmationDialog.visible = true - style: UM.Theme.styles.sidebar_action_button + style: UM.Theme.styles.print_setup_action_button } MessageDialog diff --git a/resources/qml/MonitorSidebar.qml b/resources/qml/MonitorSidebar.qml index 80bd5c1a2e..669bdbfb8f 100644 --- a/resources/qml/MonitorSidebar.qml +++ b/resources/qml/MonitorSidebar.qml @@ -1,15 +1,17 @@ -// Copyright (c) 2017 Ultimaker B.V. +// Copyright (c) 2018 Ultimaker B.V. // Cura is released under the terms of the LGPLv3 or higher. -import QtQuick 2.7 +import QtQuick 2.10 import QtQuick.Controls 2.0 import QtQuick.Layouts 1.3 import UM 1.2 as UM import Cura 1.0 as Cura + import "Menus" import "Menus/ConfigurationMenu" + Rectangle { id: base @@ -30,8 +32,8 @@ Rectangle property variant printMaterialCosts: PrintInformation.materialCosts property variant printMaterialNames: PrintInformation.materialNames - color: UM.Theme.getColor("sidebar") - UM.I18nCatalog { id: catalog; name:"cura"} + color: UM.Theme.getColor("main_background") + UM.I18nCatalog { id: catalog; name: "cura"} Timer { id: tooltipDelayTimer @@ -70,7 +72,7 @@ Rectangle time -= minutes * 60 var seconds = Math.floor(time); - var finalTime = strPadLeft(hours, "0", 2) + ':' + strPadLeft(minutes,'0',2)+ ':' + strPadLeft(seconds,'0',2); + var finalTime = strPadLeft(hours, "0", 2) + ":" + strPadLeft(minutes, "0", 2) + ":" + strPadLeft(seconds, "0", 2); return finalTime; } @@ -85,11 +87,11 @@ Rectangle } } - MachineSelection + MachineSelector { id: machineSelection width: base.width - configSelection.width - separator.width - height: UM.Theme.getSize("sidebar_header").height + height: UM.Theme.getSize("stage_menu").height anchors.top: base.top anchors.left: parent.left } @@ -98,21 +100,20 @@ Rectangle { id: separator visible: configSelection.visible - width: visible ? Math.round(UM.Theme.getSize("sidebar_lining_thin").height / 2) : 0 - height: UM.Theme.getSize("sidebar_header").height - color: UM.Theme.getColor("sidebar_lining_thin") + width: visible ? Math.round(UM.Theme.getSize("thick_lining").height / 2) : 0 + height: UM.Theme.getSize("stage_menu").height + color: UM.Theme.getColor("thick_lining") anchors.left: machineSelection.right } - ConfigurationSelection + CustomConfigurationSelector { id: configSelection visible: isNetworkPrinter && printerConnected width: visible ? Math.round(base.width * 0.15) : 0 - height: UM.Theme.getSize("sidebar_header").height + height: UM.Theme.getSize("stage_menu").height anchors.top: base.top anchors.right: parent.right - panelWidth: base.width } Loader @@ -158,10 +159,10 @@ Rectangle { id: footerSeparator width: parent.width - height: UM.Theme.getSize("sidebar_lining").height - color: UM.Theme.getColor("sidebar_lining") + height: UM.Theme.getSize("wide_lining").height + color: UM.Theme.getColor("wide_lining") anchors.bottom: monitorButton.top - anchors.bottomMargin: UM.Theme.getSize("sidebar_margin").height + anchors.bottomMargin: UM.Theme.getSize("thick_margin").height } // MonitorButton is actually the bottom footer panel. @@ -172,7 +173,7 @@ Rectangle anchors.bottom: parent.bottom } - SidebarTooltip + PrintSetupTooltip { id: tooltip } diff --git a/resources/qml/ObjectsList.qml b/resources/qml/ObjectsList.qml index 8c8eaa16ae..fd5175fce2 100644 --- a/resources/qml/ObjectsList.qml +++ b/resources/qml/ObjectsList.qml @@ -1,4 +1,4 @@ -// Copyright (c) 2017 Ultimaker B.V. +// Copyright (c) 2018 Ultimaker B.V. // Cura is released under the terms of the LGPLv3 or higher. import QtQuick 2.2 @@ -55,7 +55,6 @@ Rectangle { width: control.width height: control.height - sourceSize.width: width sourceSize.height: width color: UM.Theme.getColor("setting_control_text") source: collapsed ? UM.Theme.getIcon("arrow_left") : UM.Theme.getIcon("arrow_bottom") @@ -225,7 +224,7 @@ Rectangle { id: arrangeAllBuildPlatesButton; text: catalog.i18nc("@action:button","Arrange to all build plates"); - style: UM.Theme.styles.sidebar_action_button + style: UM.Theme.styles.print_setup_action_button height: UM.Theme.getSize("objects_menu_button").height; tooltip: ''; anchors @@ -245,7 +244,7 @@ Rectangle { id: arrangeBuildPlateButton; text: catalog.i18nc("@action:button","Arrange current build plate"); - style: UM.Theme.styles.sidebar_action_button + style: UM.Theme.styles.print_setup_action_button height: UM.Theme.getSize("objects_menu_button").height; tooltip: ''; anchors diff --git a/resources/qml/Preferences/GeneralPage.qml b/resources/qml/Preferences/GeneralPage.qml index 5006ae2777..5ff5f567ea 100644 --- a/resources/qml/Preferences/GeneralPage.qml +++ b/resources/qml/Preferences/GeneralPage.qml @@ -1,4 +1,4 @@ -// Copyright (c) 2017 Ultimaker B.V. +// Copyright (c) 2018 Ultimaker B.V. // Cura is released under the terms of the LGPLv3 or higher. import QtQuick 2.1 @@ -134,7 +134,7 @@ UM.PreferencesPage UM.PluginsModel { id: plugins } //: Language selection label - UM.I18nCatalog{id: catalog; name:"cura"} + UM.I18nCatalog{id: catalog; name: "cura"} Label { diff --git a/resources/qml/Preferences/MachinesPage.qml b/resources/qml/Preferences/MachinesPage.qml index 4dc5465dc6..bc75b9bc72 100644 --- a/resources/qml/Preferences/MachinesPage.qml +++ b/resources/qml/Preferences/MachinesPage.qml @@ -21,8 +21,10 @@ UM.ManagementPage function activeMachineIndex() { - for(var i = 0; i < model.rowCount(); i++) { - if (model.getItem(i).id == Cura.MachineManager.activeMachineId) { + for(var i = 0; i < model.count; i++) + { + if (model.getItem(i).id == Cura.MachineManager.activeMachineId) + { return i; } } @@ -47,7 +49,7 @@ UM.ManagementPage { text: catalog.i18nc("@action:button", "Remove"); iconName: "list-remove"; - enabled: base.currentItem != null && model.rowCount() > 1 + enabled: base.currentItem != null && model.count > 1 onClicked: confirmDialog.open(); }, Button diff --git a/resources/qml/Preferences/Materials/MaterialsBrandSection.qml b/resources/qml/Preferences/Materials/MaterialsBrandSection.qml index c8f391dfb0..a3a0e4708f 100644 --- a/resources/qml/Preferences/Materials/MaterialsBrandSection.qml +++ b/resources/qml/Preferences/Materials/MaterialsBrandSection.qml @@ -55,7 +55,8 @@ Rectangle text: "" implicitWidth: UM.Theme.getSize("favorites_button").width implicitHeight: UM.Theme.getSize("favorites_button").height - UM.RecolorImage { + UM.RecolorImage + { anchors { verticalCenter: parent.verticalCenter @@ -63,8 +64,6 @@ Rectangle } width: UM.Theme.getSize("standard_arrow").width height: UM.Theme.getSize("standard_arrow").height - sourceSize.width: width - sourceSize.height: height color: "black" source: brand_section.expanded ? UM.Theme.getIcon("arrow_bottom") : UM.Theme.getIcon("arrow_left") } diff --git a/resources/qml/Preferences/Materials/MaterialsList.qml b/resources/qml/Preferences/Materials/MaterialsList.qml index 00bead9650..61f92db84c 100644 --- a/resources/qml/Preferences/Materials/MaterialsList.qml +++ b/resources/qml/Preferences/Materials/MaterialsList.qml @@ -57,7 +57,7 @@ Item var currentItemId = base.currentItem == null ? "" : base.currentItem.root_material_id search_root_id = currentItemId } - for (var material_idx = 0; material_idx < genericMaterialsModel.rowCount(); material_idx++) + for (var material_idx = 0; material_idx < genericMaterialsModel.count; material_idx++) { var material = genericMaterialsModel.getItem(material_idx) if (material.root_material_id == search_root_id) @@ -72,15 +72,15 @@ Item return true } } - for (var brand_idx = 0; brand_idx < materialsModel.rowCount(); brand_idx++) + for (var brand_idx = 0; brand_idx < materialsModel.count; brand_idx++) { var brand = materialsModel.getItem(brand_idx) var types_model = brand.material_types - for (var type_idx = 0; type_idx < types_model.rowCount(); type_idx++) + for (var type_idx = 0; type_idx < types_model.count; type_idx++) { var type = types_model.getItem(type_idx) var colors_model = type.colors - for (var material_idx = 0; material_idx < colors_model.rowCount(); material_idx++) + for (var material_idx = 0; material_idx < colors_model.count; material_idx++) { var material = colors_model.getItem(material_idx) if (material.root_material_id == search_root_id) diff --git a/resources/qml/Preferences/Materials/MaterialsSlot.qml b/resources/qml/Preferences/Materials/MaterialsSlot.qml index a5af17f47a..a706aaf2b9 100644 --- a/resources/qml/Preferences/Materials/MaterialsSlot.qml +++ b/resources/qml/Preferences/Materials/MaterialsSlot.qml @@ -95,8 +95,6 @@ Rectangle } width: UM.Theme.getSize("favorites_button_icon").width height: UM.Theme.getSize("favorites_button_icon").height - sourceSize.width: width - sourceSize.height: height color: { if (favorite_button.hovered) diff --git a/resources/qml/Preferences/Materials/MaterialsTypeSection.qml b/resources/qml/Preferences/Materials/MaterialsTypeSection.qml index f62fc4ee16..f98c19e0b3 100644 --- a/resources/qml/Preferences/Materials/MaterialsTypeSection.qml +++ b/resources/qml/Preferences/Materials/MaterialsTypeSection.qml @@ -74,8 +74,6 @@ Rectangle } width: UM.Theme.getSize("standard_arrow").width height: UM.Theme.getSize("standard_arrow").height - sourceSize.width: width - sourceSize.height: height color: "black" source: material_type_section.expanded ? UM.Theme.getIcon("arrow_bottom") : UM.Theme.getIcon("arrow_left") } diff --git a/resources/qml/Preferences/ProfilesPage.qml b/resources/qml/Preferences/ProfilesPage.qml index ba0c2848a5..d7ffbb3152 100644 --- a/resources/qml/Preferences/ProfilesPage.qml +++ b/resources/qml/Preferences/ProfilesPage.qml @@ -188,21 +188,27 @@ Item Connections { target: qualitiesModel - onItemsChanged: { + onItemsChanged: + { var toSelectItemName = base.currentItem == null ? "" : base.currentItem.name; - if (newQualityNameToSelect != "") { + if (newQualityNameToSelect != "") + { toSelectItemName = newQualityNameToSelect; } var newIdx = -1; // Default to nothing if nothing can be found - if (toSelectItemName != "") { + if (toSelectItemName != "") + { // Select the required quality name if given - for (var idx = 0; idx < qualitiesModel.rowCount(); ++idx) { + for (var idx = 0; idx < qualitiesModel.count; ++idx) + { var item = qualitiesModel.getItem(idx); - if (item.name == toSelectItemName) { + if (item.name == toSelectItemName) + { // Switch to the newly created profile if needed newIdx = idx; - if (base.toActivateNewQuality) { + if (base.toActivateNewQuality) + { // Activate this custom quality if required Cura.MachineManager.setQualityChangesGroup(item.quality_changes_group); } @@ -382,9 +388,11 @@ Item var selectedItemName = Cura.MachineManager.activeQualityOrQualityChangesName; // Select the required quality name if given - for (var idx = 0; idx < qualitiesModel.rowCount(); idx++) { + for (var idx = 0; idx < qualitiesModel.count; idx++) + { var item = qualitiesModel.getItem(idx); - if (item.name == selectedItemName) { + if (item.name == selectedItemName) + { currentIndex = idx; break; } diff --git a/resources/qml/Preferences/SettingVisibilityPage.qml b/resources/qml/Preferences/SettingVisibilityPage.qml index 2edbeee960..3f7571a170 100644 --- a/resources/qml/Preferences/SettingVisibilityPage.qml +++ b/resources/qml/Preferences/SettingVisibilityPage.qml @@ -50,7 +50,7 @@ UM.PreferencesPage { return Qt.Unchecked } - else if(definitionsModel.visibleCount == definitionsModel.rowCount(null)) + else if(definitionsModel.visibleCount == definitionsModel.count) { return Qt.Checked } diff --git a/resources/qml/PrepareSidebar.qml b/resources/qml/PrepareSidebar.qml deleted file mode 100644 index fe0fb033f7..0000000000 --- a/resources/qml/PrepareSidebar.qml +++ /dev/null @@ -1,616 +0,0 @@ -// Copyright (c) 2017 Ultimaker B.V. -// Cura is released under the terms of the LGPLv3 or higher. - -import QtQuick 2.7 -import QtQuick.Controls 2.0 -import QtQuick.Layouts 1.3 - -import UM 1.2 as UM -import Cura 1.0 as Cura -import "Menus" -import "Menus/ConfigurationMenu" - -Rectangle -{ - id: base - - property int currentModeIndex: -1 - property bool hideSettings: PrintInformation.preSliced - property bool hideView: Cura.MachineManager.activeMachineName == "" - - // Is there an output device for this printer? - property bool isNetworkPrinter: Cura.MachineManager.activeMachineNetworkKey != "" - property bool printerConnected: Cura.MachineManager.printerConnected - property bool printerAcceptsCommands: printerConnected && Cura.MachineManager.printerOutputDevices[0].acceptsCommands - property var connectedPrinter: Cura.MachineManager.printerOutputDevices.length >= 1 ? Cura.MachineManager.printerOutputDevices[0] : null - - property variant printDuration: PrintInformation.currentPrintTime - property variant printMaterialLengths: PrintInformation.materialLengths - property variant printMaterialWeights: PrintInformation.materialWeights - property variant printMaterialCosts: PrintInformation.materialCosts - property variant printMaterialNames: PrintInformation.materialNames - - color: UM.Theme.getColor("sidebar") - UM.I18nCatalog { id: catalog; name:"cura"} - - Timer { - id: tooltipDelayTimer - interval: 500 - repeat: false - property var item - property string text - - onTriggered: - { - base.showTooltip(base, {x: 0, y: item.y}, text); - } - } - - function showTooltip(item, position, text) - { - tooltip.text = text; - position = item.mapToItem(base, position.x - UM.Theme.getSize("default_arrow").width, position.y); - tooltip.show(position); - } - - function hideTooltip() - { - tooltip.hide(); - } - - function strPadLeft(string, pad, length) { - return (new Array(length + 1).join(pad) + string).slice(-length); - } - - 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; - } - - MouseArea - { - anchors.fill: parent - acceptedButtons: Qt.AllButtons - - onWheel: - { - wheel.accepted = true; - } - } - - MachineSelection - { - id: machineSelection - width: base.width - configSelection.width - separator.width - height: UM.Theme.getSize("sidebar_header").height - anchors.top: base.top - anchors.left: parent.left - } - - Rectangle - { - id: separator - visible: configSelection.visible - width: visible ? Math.round(UM.Theme.getSize("sidebar_lining_thin").height / 2) : 0 - height: UM.Theme.getSize("sidebar_header").height - color: UM.Theme.getColor("sidebar_lining_thin") - anchors.left: machineSelection.right - } - - ConfigurationSelection - { - id: configSelection - visible: isNetworkPrinter && printerConnected - width: visible ? Math.round(base.width * 0.15) : 0 - height: UM.Theme.getSize("sidebar_header").height - anchors.top: base.top - anchors.right: parent.right - panelWidth: base.width - } - - SidebarHeader { - id: header - width: parent.width - visible: !hideSettings && (machineExtruderCount.properties.value > 1 || Cura.MachineManager.hasMaterials || Cura.MachineManager.hasVariants) - anchors.top: machineSelection.bottom - - onShowTooltip: base.showTooltip(item, location, text) - onHideTooltip: base.hideTooltip() - } - - Rectangle { - id: headerSeparator - width: parent.width - visible: settingsModeSelection.visible && header.visible - height: visible ? UM.Theme.getSize("sidebar_lining").height : 0 - color: UM.Theme.getColor("sidebar_lining") - anchors.top: header.bottom - anchors.topMargin: visible ? UM.Theme.getSize("sidebar_margin").height : 0 - } - - onCurrentModeIndexChanged: - { - UM.Preferences.setValue("cura/active_mode", currentModeIndex); - if(modesListModel.count > base.currentModeIndex) - { - sidebarContents.replace(modesListModel.get(base.currentModeIndex).item, { "replace": true }) - } - } - - Label - { - id: settingsModeLabel - text: !hideSettings ? catalog.i18nc("@label:listbox", "Print Setup") : catalog.i18nc("@label:listbox", "Print Setup disabled\nG-code files cannot be modified") - renderType: Text.NativeRendering - anchors.left: parent.left - anchors.leftMargin: UM.Theme.getSize("sidebar_margin").width - anchors.top: hideSettings ? machineSelection.bottom : headerSeparator.bottom - anchors.topMargin: UM.Theme.getSize("sidebar_margin").height - width: Math.round(parent.width * 0.45) - font: UM.Theme.getFont("large") - color: UM.Theme.getColor("text") - visible: !hideView - } - - // Settings mode selection toggle - Rectangle - { - id: settingsModeSelection - color: "transparent" - - width: Math.round(parent.width * 0.55) - height: UM.Theme.getSize("sidebar_header_mode_toggle").height - - anchors.right: parent.right - anchors.rightMargin: UM.Theme.getSize("sidebar_margin").width - anchors.topMargin: UM.Theme.getSize("sidebar_margin").height - anchors.top: - { - if (settingsModeLabel.contentWidth >= parent.width - width - UM.Theme.getSize("sidebar_margin").width * 2) - { - return settingsModeLabel.bottom; - } - else - { - return headerSeparator.bottom; - } - } - - visible: !hideSettings && !hideView - - Component - { - id: wizardDelegate - - Button - { - id: control - - height: settingsModeSelection.height - width: Math.round(parent.width / 2) - - anchors.left: parent.left - anchors.leftMargin: model.index * Math.round(settingsModeSelection.width / 2) - anchors.verticalCenter: parent.verticalCenter - - ButtonGroup.group: modeMenuGroup - - checkable: true - checked: base.currentModeIndex == index - onClicked: base.currentModeIndex = index - - onHoveredChanged: - { - if (hovered) - { - tooltipDelayTimer.item = settingsModeSelection - tooltipDelayTimer.text = model.tooltipText - tooltipDelayTimer.start() - } - else - { - tooltipDelayTimer.stop() - base.hideTooltip() - } - } - - background: Rectangle - { - border.width: control.checked ? UM.Theme.getSize("default_lining").width * 2 : UM.Theme.getSize("default_lining").width - border.color: (control.checked || control.pressed) ? UM.Theme.getColor("action_button_active_border") : control.hovered ? UM.Theme.getColor("action_button_hovered_border"): UM.Theme.getColor("action_button_border") - - // for some reason, QtQuick decided to use the color of the background property as text color for the contentItem, so here it is - color: (control.checked || control.pressed) ? UM.Theme.getColor("action_button_active") : control.hovered ? UM.Theme.getColor("action_button_hovered") : UM.Theme.getColor("action_button") - } - - contentItem: Label - { - text: model.text - font: UM.Theme.getFont("default") - horizontalAlignment: Text.AlignHCenter - verticalAlignment: Text.AlignVCenter - renderType: Text.NativeRendering - elide: Text.ElideRight - color: - { - if(control.pressed) - { - return UM.Theme.getColor("action_button_active_text"); - } - else if(control.hovered) - { - return UM.Theme.getColor("action_button_hovered_text"); - } - return UM.Theme.getColor("action_button_text"); - } - } - } - } - - ButtonGroup - { - id: modeMenuGroup - } - - ListView - { - id: modesList - model: modesListModel - delegate: wizardDelegate - anchors.top: parent.top - anchors.left: parent.left - width: parent.width - } - } - - StackView - { - id: sidebarContents - - anchors.bottom: footerSeparator.top - anchors.top: settingsModeSelection.bottom - anchors.topMargin: UM.Theme.getSize("sidebar_margin").height - anchors.left: base.left - anchors.right: base.right - visible: !hideSettings - - replaceEnter: Transition { - PropertyAnimation { - property: "opacity" - from: 0 - to:1 - duration: 100 - } - } - - replaceExit: Transition { - PropertyAnimation { - property: "opacity" - from: 1 - to:0 - duration: 100 - } - } - } - - Loader - { - anchors.bottom: footerSeparator.top - anchors.top: headerSeparator.bottom - anchors.left: base.left - anchors.right: base.right - source: "SidebarContents.qml" - } - - Rectangle - { - id: footerSeparator - width: parent.width - height: UM.Theme.getSize("sidebar_lining").height - color: UM.Theme.getColor("sidebar_lining") - anchors.bottom: printSpecs.top - anchors.bottomMargin: Math.round(UM.Theme.getSize("sidebar_margin").height * 2 + UM.Theme.getSize("progressbar").height + UM.Theme.getFont("default_bold").pixelSize) - } - - Item - { - id: printSpecs - anchors.left: parent.left - anchors.bottom: parent.bottom - anchors.leftMargin: UM.Theme.getSize("sidebar_margin").width - anchors.bottomMargin: UM.Theme.getSize("sidebar_margin").height - height: timeDetails.height + costSpec.height - width: base.width - (saveButton.buttonRowWidth + UM.Theme.getSize("sidebar_margin").width) - clip: true - - Label - { - id: timeDetails - anchors.left: parent.left - anchors.bottom: costSpec.top - font: UM.Theme.getFont("large") - color: UM.Theme.getColor("text_subtext") - text: (!base.printDuration || !base.printDuration.valid) ? catalog.i18nc("@label Hours and minutes", "00h 00min") : base.printDuration.getDisplayString(UM.DurationFormat.Short) - renderType: Text.NativeRendering - - MouseArea - { - id: timeDetailsMouseArea - anchors.fill: parent - hoverEnabled: true - - onEntered: - { - if(base.printDuration.valid && !base.printDuration.isTotalDurationZero) - { - // All the time information for the different features is achieved - var print_time = PrintInformation.getFeaturePrintTimes(); - var total_seconds = parseInt(base.printDuration.getDisplayString(UM.DurationFormat.Seconds)) - - // A message is created and displayed when the user hover the time label - var tooltip_html = "%1
".arg(catalog.i18nc("@tooltip", "Time specification")); - for(var feature in print_time) - { - if(!print_time[feature].isTotalDurationZero) - { - tooltip_html += "" + - "".arg(print_time[feature].getDisplayString(UM.DurationFormat.ISO8601).slice(0,-3)) + - "".arg(Math.round(100 * parseInt(print_time[feature].getDisplayString(UM.DurationFormat.Seconds)) / total_seconds)) + - ""; - } - } - tooltip_html += "
" + feature + ":  %1  %1%
"; - - base.showTooltip(parent, Qt.point(-UM.Theme.getSize("sidebar_margin").width, 0), tooltip_html); - } - } - onExited: - { - base.hideTooltip(); - } - } - } - - Label - { - function formatRow(items) - { - var row_html = ""; - for(var item = 0; item < items.length; item++) - { - if (item == 0) - { - row_html += "%1".arg(items[item]); - } - else - { - row_html += "  %1".arg(items[item]); - } - } - row_html += ""; - return row_html; - } - - function getSpecsData() - { - var lengths = []; - var total_length = 0; - var weights = []; - var total_weight = 0; - var costs = []; - var total_cost = 0; - var some_costs_known = false; - var names = []; - if(base.printMaterialLengths) - { - for(var index = 0; index < base.printMaterialLengths.length; index++) - { - if(base.printMaterialLengths[index] > 0) - { - names.push(base.printMaterialNames[index]); - lengths.push(base.printMaterialLengths[index].toFixed(2)); - weights.push(String(Math.round(base.printMaterialWeights[index]))); - var cost = base.printMaterialCosts[index] == undefined ? 0 : base.printMaterialCosts[index].toFixed(2); - costs.push(cost); - if(cost > 0) - { - some_costs_known = true; - } - - total_length += base.printMaterialLengths[index]; - total_weight += base.printMaterialWeights[index]; - total_cost += base.printMaterialCosts[index]; - } - } - } - if(lengths.length == 0) - { - lengths = ["0.00"]; - weights = ["0"]; - costs = ["0.00"]; - } - - var tooltip_html = "%1
".arg(catalog.i18nc("@label", "Cost specification")); - for(var index = 0; index < lengths.length; index++) - { - tooltip_html += formatRow([ - "%1:".arg(names[index]), - catalog.i18nc("@label m for meter", "%1m").arg(lengths[index]), - catalog.i18nc("@label g for grams", "%1g").arg(weights[index]), - "%1 %2".arg(UM.Preferences.getValue("cura/currency")).arg(costs[index]), - ]); - } - if(lengths.length > 1) - { - tooltip_html += formatRow([ - catalog.i18nc("@label", "Total:"), - catalog.i18nc("@label m for meter", "%1m").arg(total_length.toFixed(2)), - catalog.i18nc("@label g for grams", "%1g").arg(Math.round(total_weight)), - "%1 %2".arg(UM.Preferences.getValue("cura/currency")).arg(total_cost.toFixed(2)), - ]); - } - tooltip_html += "
"; - tooltipText = tooltip_html; - - return tooltipText - } - - id: costSpec - anchors.left: parent.left - anchors.bottom: parent.bottom - font: UM.Theme.getFont("very_small") - renderType: Text.NativeRendering - color: UM.Theme.getColor("text_subtext") - elide: Text.ElideMiddle - width: parent.width - property string tooltipText - text: - { - var lengths = []; - var weights = []; - var costs = []; - var someCostsKnown = false; - if(base.printMaterialLengths) { - for(var index = 0; index < base.printMaterialLengths.length; index++) - { - if(base.printMaterialLengths[index] > 0) - { - lengths.push(base.printMaterialLengths[index].toFixed(2)); - weights.push(String(Math.round(base.printMaterialWeights[index]))); - var cost = base.printMaterialCosts[index] == undefined ? 0 : base.printMaterialCosts[index].toFixed(2); - costs.push(cost); - if(cost > 0) - { - someCostsKnown = true; - } - } - } - } - if(lengths.length == 0) - { - lengths = ["0.00"]; - weights = ["0"]; - costs = ["0.00"]; - } - var result = lengths.join(" + ") + "m / ~ " + weights.join(" + ") + "g"; - if(someCostsKnown) - { - result += " / ~ " + costs.join(" + ") + " " + UM.Preferences.getValue("cura/currency"); - } - return result; - } - MouseArea - { - id: costSpecMouseArea - anchors.fill: parent - hoverEnabled: true - - onEntered: - { - - if(base.printDuration.valid && !base.printDuration.isTotalDurationZero) - { - var show_data = costSpec.getSpecsData() - - base.showTooltip(parent, Qt.point(-UM.Theme.getSize("sidebar_margin").width, 0), show_data); - } - } - onExited: - { - base.hideTooltip(); - } - } - } - } - - // SaveButton is actually the bottom footer panel. - SaveButton - { - id: saveButton - implicitWidth: base.width - anchors.top: footerSeparator.bottom - anchors.topMargin: UM.Theme.getSize("sidebar_margin").height - anchors.bottom: parent.bottom - } - - SidebarTooltip - { - id: tooltip - } - - // Setting mode: Recommended or Custom - ListModel - { - id: modesListModel - } - - SidebarSimple - { - id: sidebarSimple - visible: false - - onShowTooltip: base.showTooltip(item, location, text) - onHideTooltip: base.hideTooltip() - } - - SidebarAdvanced - { - id: sidebarAdvanced - visible: false - - onShowTooltip: base.showTooltip(item, location, text) - onHideTooltip: base.hideTooltip() - } - - Component.onCompleted: - { - modesListModel.append({ - text: catalog.i18nc("@title:tab", "Recommended"), - tooltipText: catalog.i18nc("@tooltip", "Recommended Print Setup

Print with the recommended settings for the selected printer, material and quality."), - item: sidebarSimple - }) - modesListModel.append({ - text: catalog.i18nc("@title:tab", "Custom"), - tooltipText: catalog.i18nc("@tooltip", "Custom Print Setup

Print with finegrained control over every last bit of the slicing process."), - item: sidebarAdvanced - }) - - var index = Math.round(UM.Preferences.getValue("cura/active_mode")) - - if(index != null && !isNaN(index)) - { - currentModeIndex = index; - } - else - { - currentModeIndex = 0; - } - } - - UM.SettingPropertyProvider - { - id: machineExtruderCount - - containerStack: Cura.MachineManager.activeMachine - key: "machine_extruder_count" - watchedProperties: [ "value" ] - storeIndex: 0 - } - - UM.SettingPropertyProvider - { - id: machineHeatedBed - - containerStack: Cura.MachineManager.activeMachine - key: "machine_heated_bed" - watchedProperties: [ "value" ] - storeIndex: 0 - } -} diff --git a/resources/qml/PrimaryButton.qml b/resources/qml/PrimaryButton.qml new file mode 100644 index 0000000000..fca63d2cdb --- /dev/null +++ b/resources/qml/PrimaryButton.qml @@ -0,0 +1,20 @@ +// Copyright (c) 2018 Ultimaker B.V. +// Cura is released under the terms of the LGPLv3 or higher. + +import QtQuick 2.2 + +import UM 1.4 as UM +import Cura 1.1 as Cura + + +Cura.ActionButton +{ + shadowEnabled: true + shadowColor: enabled ? UM.Theme.getColor("primary_button_shadow"): UM.Theme.getColor("action_button_disabled_shadow") + color: UM.Theme.getColor("primary_button") + textColor: UM.Theme.getColor("primary_button_text") + outlineColor: "transparent" + disabledColor: UM.Theme.getColor("action_button_disabled") + textDisabledColor: UM.Theme.getColor("action_button_disabled_text") + hoverColor: UM.Theme.getColor("primary_button_hover") +} \ No newline at end of file diff --git a/resources/qml/PrintMonitor.qml b/resources/qml/PrintMonitor.qml index 12e95d1e89..4ed8daa55c 100644 --- a/resources/qml/PrintMonitor.qml +++ b/resources/qml/PrintMonitor.qml @@ -11,136 +11,180 @@ import Cura 1.0 as Cura import "PrinterOutput" -Column + +Rectangle { - id: printMonitor + id: base + UM.I18nCatalog { id: catalog; name: "cura"} + + function showTooltip(item, position, text) + { + tooltip.text = text; + position = item.mapToItem(base, position.x - UM.Theme.getSize("default_arrow").width, position.y); + tooltip.show(position); + } + + function hideTooltip() + { + tooltip.hide(); + } + + function strPadLeft(string, pad, length) { + return (new Array(length + 1).join(pad) + string).slice(-length); + } + + 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; + } + property var connectedDevice: Cura.MachineManager.printerOutputDevices.length >= 1 ? Cura.MachineManager.printerOutputDevices[0] : null property var activePrinter: connectedDevice != null ? connectedDevice.activePrinter : null property var activePrintJob: activePrinter != null ? activePrinter.activePrintJob: null - Cura.ExtrudersModel + PrintSetupTooltip { - id: extrudersModel - simpleNames: true + id: tooltip } - OutputDeviceHeader + Column { - outputDevice: connectedDevice - } + id: printMonitor - Rectangle - { - color: UM.Theme.getColor("sidebar_lining") - width: parent.width - height: childrenRect.height + anchors.fill: parent - Flow + Cura.ExtrudersModel { - id: extrudersGrid - spacing: UM.Theme.getSize("sidebar_lining_thin").width + id: extrudersModel + simpleNames: true + } + + OutputDeviceHeader + { + outputDevice: connectedDevice + } + + Rectangle + { + color: UM.Theme.getColor("wide_lining") width: parent.width + height: childrenRect.height - Repeater + Flow { - id: extrudersRepeater - model: activePrinter != null ? activePrinter.extruders : null + id: extrudersGrid + spacing: UM.Theme.getSize("thick_lining").width + width: parent.width - ExtruderBox + Repeater { - color: UM.Theme.getColor("sidebar") - width: index == machineExtruderCount.properties.value - 1 && index % 2 == 0 ? extrudersGrid.width : Math.round(extrudersGrid.width / 2 - UM.Theme.getSize("sidebar_lining_thin").width / 2) - extruderModel: modelData + id: extrudersRepeater + model: activePrinter != null ? activePrinter.extruders : null + + ExtruderBox + { + color: UM.Theme.getColor("main_background") + width: index == machineExtruderCount.properties.value - 1 && index % 2 == 0 ? extrudersGrid.width : Math.round(extrudersGrid.width / 2 - UM.Theme.getSize("thick_lining").width / 2) + extruderModel: modelData + } } } } - } - Rectangle - { - color: UM.Theme.getColor("sidebar_lining") - width: parent.width - height: UM.Theme.getSize("sidebar_lining_thin").width - } - - HeatedBedBox - { - visible: { - if(activePrinter != null && activePrinter.bedTemperature != -1) - { - return true - } - return false - } - printerModel: activePrinter - } - - UM.SettingPropertyProvider - { - id: bedTemperature - containerStack: Cura.MachineManager.activeMachine - key: "material_bed_temperature" - watchedProperties: ["value", "minimum_value", "maximum_value", "resolve"] - storeIndex: 0 - - property var resolve: Cura.MachineManager.activeStack != Cura.MachineManager.activeMachine ? properties.resolve : "None" - } - - UM.SettingPropertyProvider - { - id: machineExtruderCount - containerStack: Cura.MachineManager.activeMachine - key: "machine_extruder_count" - watchedProperties: ["value"] - } - - ManualPrinterControl - { - printerModel: activePrinter - visible: activePrinter != null ? activePrinter.canControlManually : false - } - - - MonitorSection - { - label: catalog.i18nc("@label", "Active print") - width: base.width - visible: activePrinter != null - } - - - MonitorItem - { - label: catalog.i18nc("@label", "Job Name") - value: activePrintJob != null ? activePrintJob.name : "" - width: base.width - visible: activePrinter != null - } - - MonitorItem - { - label: catalog.i18nc("@label", "Printing Time") - value: activePrintJob != null ? getPrettyTime(activePrintJob.timeTotal) : "" - width: base.width - visible: activePrinter != null - } - - MonitorItem - { - label: catalog.i18nc("@label", "Estimated time left") - value: activePrintJob != null ? getPrettyTime(activePrintJob.timeTotal - activePrintJob.timeElapsed) : "" - visible: + Rectangle { - if(activePrintJob == null) + color: UM.Theme.getColor("wide_lining") + width: parent.width + height: UM.Theme.getSize("thick_lining").width + } + + HeatedBedBox + { + visible: { + if(activePrinter != null && activePrinter.bedTemperature != -1) + { + return true + } return false } - - return (activePrintJob.state == "printing" || - activePrintJob.state == "resuming" || - activePrintJob.state == "pausing" || - activePrintJob.state == "paused") + printerModel: activePrinter + } + + UM.SettingPropertyProvider + { + id: bedTemperature + containerStack: Cura.MachineManager.activeMachine + key: "material_bed_temperature" + watchedProperties: ["value", "minimum_value", "maximum_value", "resolve"] + storeIndex: 0 + + property var resolve: Cura.MachineManager.activeStack != Cura.MachineManager.activeMachine ? properties.resolve : "None" + } + + UM.SettingPropertyProvider + { + id: machineExtruderCount + containerStack: Cura.MachineManager.activeMachine + key: "machine_extruder_count" + watchedProperties: ["value"] + } + + ManualPrinterControl + { + printerModel: activePrinter + visible: activePrinter != null ? activePrinter.canControlManually : false + } + + + MonitorSection + { + label: catalog.i18nc("@label", "Active print") + width: base.width + visible: activePrinter != null + } + + + MonitorItem + { + label: catalog.i18nc("@label", "Job Name") + value: activePrintJob != null ? activePrintJob.name : "" + width: base.width + visible: activePrinter != null + } + + MonitorItem + { + label: catalog.i18nc("@label", "Printing Time") + value: activePrintJob != null ? getPrettyTime(activePrintJob.timeTotal) : "" + width: base.width + visible: activePrinter != null + } + + MonitorItem + { + label: catalog.i18nc("@label", "Estimated time left") + value: activePrintJob != null ? getPrettyTime(activePrintJob.timeTotal - activePrintJob.timeElapsed) : "" + visible: + { + if(activePrintJob == null) + { + return false + } + + return (activePrintJob.state == "printing" || + activePrintJob.state == "resuming" || + activePrintJob.state == "pausing" || + activePrintJob.state == "paused") + } + width: base.width } - width: base.width } -} +} \ No newline at end of file diff --git a/resources/qml/PrintSetupSelector/Custom/CustomPrintSetup.qml b/resources/qml/PrintSetupSelector/Custom/CustomPrintSetup.qml new file mode 100644 index 0000000000..b28c9ceb46 --- /dev/null +++ b/resources/qml/PrintSetupSelector/Custom/CustomPrintSetup.qml @@ -0,0 +1,133 @@ +// Copyright (c) 2018 Ultimaker B.V. +// Cura is released under the terms of the LGPLv3 or higher. + +import QtQuick 2.7 +import QtQuick.Controls 2.0 + +import UM 1.3 as UM +import Cura 1.0 as Cura + + +Item +{ + id: customPrintSetup + height: childrenRect.height + padding + + property real padding: UM.Theme.getSize("default_margin").width + property bool multipleExtruders: extrudersModel.count > 1 + + Cura.ExtrudersModel + { + id: extrudersModel + } + + // Profile selector row + GlobalProfileSelector + { + id: globalProfileRow + anchors + { + top: parent.top + topMargin: parent.padding + left: parent.left + leftMargin: parent.padding + right: parent.right + rightMargin: parent.padding + } + } + + UM.TabRow + { + id: tabBar + + visible: multipleExtruders // The tab row is only visible when there are more than 1 extruder + + anchors + { + top: globalProfileRow.bottom + topMargin: UM.Theme.getSize("default_margin").height + left: parent.left + leftMargin: parent.padding + right: parent.right + rightMargin: parent.padding + } + + Repeater + { + id: repeater + model: extrudersModel + delegate: UM.TabRowButton + { + contentItem: Item + { + Cura.ExtruderIcon + { + anchors.horizontalCenter: parent.horizontalCenter + materialColor: model.color + extruderEnabled: model.enabled + } + } + onClicked: + { + Cura.ExtruderManager.setActiveExtruderIndex(tabBar.currentIndex) + } + } + } + + //When active extruder changes for some other reason, switch tabs. + //Don't directly link currentIndex to Cura.ExtruderManager.activeExtruderIndex! + //This causes a segfault in Qt 5.11. Something with VisualItemModel removing index -1. We have to use setCurrentIndex instead. + Connections + { + target: Cura.ExtruderManager + onActiveExtruderChanged: + { + tabBar.setCurrentIndex(Cura.ExtruderManager.activeExtruderIndex); + } + } + + //When the model of the extruders is rebuilt, the list of extruders is briefly emptied and rebuilt. + //This causes the currentIndex of the tab to be in an invalid position which resets it to 0. + //Therefore we need to change it back to what it was: The active extruder index. + Connections + { + target: repeater.model + onModelChanged: + { + tabBar.setCurrentIndex(Cura.ExtruderManager.activeExtruderIndex) + } + } + } + + Rectangle + { + height: UM.Theme.getSize("print_setup_widget").height + anchors + { + top: tabBar.visible ? tabBar.bottom : globalProfileRow.bottom + left: parent.left + leftMargin: parent.padding + right: parent.right + rightMargin: parent.padding + topMargin: -UM.Theme.getSize("default_lining").width + } + z: tabBar.z - 1 + // Don't show the border when only one extruder + border.color: tabBar.visible ? UM.Theme.getColor("lining") : "transparent" + border.width: UM.Theme.getSize("default_lining").width + + Cura.SettingView + { + anchors + { + fill: parent + topMargin: UM.Theme.getSize("default_margin").height + leftMargin: UM.Theme.getSize("default_margin").width + // Small space for the scrollbar + rightMargin: UM.Theme.getSize("narrow_margin").width + // Compensate for the negative margin in the parent + bottomMargin: UM.Theme.getSize("default_lining").width + } + } + } +} diff --git a/resources/qml/PrintSetupSelector/Custom/GlobalProfileSelector.qml b/resources/qml/PrintSetupSelector/Custom/GlobalProfileSelector.qml new file mode 100644 index 0000000000..8baaf9a7ae --- /dev/null +++ b/resources/qml/PrintSetupSelector/Custom/GlobalProfileSelector.qml @@ -0,0 +1,100 @@ +// Copyright (c) 2018 Ultimaker B.V. +// Cura is released under the terms of the LGPLv3 or higher. + +import QtQuick 2.7 +import QtQuick.Controls 1.1 +import QtQuick.Controls.Styles 1.1 +import QtQuick.Layouts 1.2 + +import UM 1.2 as UM +import Cura 1.0 as Cura + +Item +{ + id: globalProfileRow + height: childrenRect.height + + Label + { + id: globalProfileLabel + anchors + { + top: parent.top + bottom: parent.bottom + left: parent.left + right: globalProfileSelection.left + } + text: catalog.i18nc("@label", "Profile") + font: UM.Theme.getFont("default") + color: UM.Theme.getColor("text") + verticalAlignment: Text.AlignVCenter + } + + ToolButton + { + id: globalProfileSelection + + text: generateActiveQualityText() + width: UM.Theme.getSize("print_setup_big_item").width + height: UM.Theme.getSize("print_setup_big_item").height + anchors + { + top: parent.top + right: parent.right + } + tooltip: Cura.MachineManager.activeQualityOrQualityChangesName + style: UM.Theme.styles.print_setup_header_button + activeFocusOnPress: true + menu: Cura.ProfileMenu { } + + function generateActiveQualityText() + { + var result = Cura.MachineManager.activeQualityOrQualityChangesName + if (Cura.MachineManager.isActiveQualityExperimental) + { + result += " (Experimental)" + } + + if (Cura.MachineManager.isActiveQualitySupported) + { + if (Cura.MachineManager.activeQualityLayerHeight > 0) + { + result += " " + result += " - " + result += Cura.MachineManager.activeQualityLayerHeight + "mm" + result += "" + } + } + + return result + } + + UM.SimpleButton + { + id: customisedSettings + + visible: Cura.MachineManager.hasUserSettings + width: UM.Theme.getSize("print_setup_icon").width + height: UM.Theme.getSize("print_setup_icon").height + + anchors.verticalCenter: parent.verticalCenter + anchors.right: parent.right + anchors.rightMargin: Math.round(UM.Theme.getSize("setting_preferences_button_margin").width - UM.Theme.getSize("thick_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("default_margin").width, 0), content) + } + onExited: base.hideTooltip() + } + } +} \ No newline at end of file diff --git a/resources/qml/PrintSetupSelector/PrintSetupSelector.qml b/resources/qml/PrintSetupSelector/PrintSetupSelector.qml new file mode 100644 index 0000000000..599eac957e --- /dev/null +++ b/resources/qml/PrintSetupSelector/PrintSetupSelector.qml @@ -0,0 +1,35 @@ +// Copyright (c) 2018 Ultimaker B.V. +// Cura is released under the terms of the LGPLv3 or higher. + +import QtQuick 2.7 +import QtQuick.Controls 2.0 + +import UM 1.3 as UM +import Cura 1.0 as Cura + +Cura.ExpandableComponent +{ + id: printSetupSelector + + property bool preSlicedData: PrintInformation.preSliced + + contentPadding: UM.Theme.getSize("default_lining").width + contentHeaderTitle: catalog.i18nc("@label", "Print settings") + enabled: !preSlicedData + disabledText: catalog.i18nc("@label shown when we load a Gcode file", "Print setup disabled. G code file can not be modified.") + + UM.I18nCatalog + { + id: catalog + name: "cura" + } + + headerItem: PrintSetupSelectorHeader {} + + Cura.ExtrudersModel + { + id: extrudersModel + } + + contentItem: PrintSetupSelectorContents {} +} \ No newline at end of file diff --git a/resources/qml/PrintSetupSelector/PrintSetupSelectorContents.qml b/resources/qml/PrintSetupSelector/PrintSetupSelectorContents.qml new file mode 100644 index 0000000000..6c678f7ce5 --- /dev/null +++ b/resources/qml/PrintSetupSelector/PrintSetupSelectorContents.qml @@ -0,0 +1,129 @@ +// Copyright (c) 2018 Ultimaker B.V. +// Cura is released under the terms of the LGPLv3 or higher. + +import QtQuick 2.7 +import QtQuick.Controls 2.3 + +import UM 1.3 as UM +import Cura 1.0 as Cura + +import "Recommended" +import "Custom" + +Item +{ + id: content + + width: UM.Theme.getSize("print_setup_widget").width - 2 * UM.Theme.getSize("default_margin").width + height: childrenRect.height + + enum Mode + { + Recommended = 0, + Custom = 1 + } + + // Set the current mode index to the value that is stored in the preferences or Recommended mode otherwise. + property int currentModeIndex: + { + var index = Math.round(UM.Preferences.getValue("cura/active_mode")) + + if (index != null && !isNaN(index)) + { + return index + } + return PrintSetupSelectorContents.Mode.Recommended + } + onCurrentModeIndexChanged: UM.Preferences.setValue("cura/active_mode", currentModeIndex) + + Item + { + id: contents + // Use the visible property instead of checking the currentModeIndex. That creates a binding that + // evaluates the new height every time the visible property changes. + height: recommendedPrintSetup.visible ? recommendedPrintSetup.height : customPrintSetup.height + + anchors + { + top: parent.top + left: parent.left + right: parent.right + } + + RecommendedPrintSetup + { + id: recommendedPrintSetup + anchors + { + left: parent.left + right: parent.right + top: parent.top + } + visible: currentModeIndex == PrintSetupSelectorContents.Mode.Recommended + } + + CustomPrintSetup + { + id: customPrintSetup + anchors + { + left: parent.left + right: parent.right + top: parent.top + } + visible: currentModeIndex == PrintSetupSelectorContents.Mode.Custom + } + } + + Rectangle + { + id: buttonsSeparator + + // The buttonsSeparator is inside the contents. This is to avoid a double line in the bottom + anchors.bottom: contents.bottom + width: parent.width + height: UM.Theme.getSize("default_lining").height + color: UM.Theme.getColor("lining") + } + + Item + { + id: buttonRow + property real padding: UM.Theme.getSize("default_margin").width + height: childrenRect.height + 2 * padding + + anchors + { + top: buttonsSeparator.bottom + left: parent.left + right: parent.right + } + + Cura.SecondaryButton + { + anchors.top: parent.top + anchors.left: parent.left + anchors.margins: parent.padding + leftPadding: UM.Theme.getSize("default_margin").width + rightPadding: UM.Theme.getSize("default_margin").width + text: catalog.i18nc("@button", "Recommended") + iconSource: UM.Theme.getIcon("arrow_left") + visible: currentModeIndex == PrintSetupSelectorContents.Mode.Custom + onClicked: currentModeIndex = PrintSetupSelectorContents.Mode.Recommended + } + + Cura.SecondaryButton + { + anchors.top: parent.top + anchors.right: parent.right + anchors.margins: UM.Theme.getSize("default_margin").width + leftPadding: UM.Theme.getSize("default_margin").width + rightPadding: UM.Theme.getSize("default_margin").width + text: catalog.i18nc("@button", "Custom") + iconSource: UM.Theme.getIcon("arrow_right") + isIconOnRightSide: true + visible: currentModeIndex == PrintSetupSelectorContents.Mode.Recommended + onClicked: currentModeIndex = PrintSetupSelectorContents.Mode.Custom + } + } +} \ No newline at end of file diff --git a/resources/qml/PrintSetupSelector/PrintSetupSelectorHeader.qml b/resources/qml/PrintSetupSelector/PrintSetupSelectorHeader.qml new file mode 100644 index 0000000000..94da5bdd6f --- /dev/null +++ b/resources/qml/PrintSetupSelector/PrintSetupSelectorHeader.qml @@ -0,0 +1,83 @@ +// Copyright (c) 2018 Ultimaker B.V. +// Cura is released under the terms of the LGPLv3 or higher. + +import QtQuick 2.7 +import QtQuick.Controls 2.3 +import QtQuick.Layouts 1.3 + +import UM 1.3 as UM +import Cura 1.0 as Cura + +RowLayout +{ + property string enabledText: catalog.i18nc("@label:Should be short", "On") + property string disabledText: catalog.i18nc("@label:Should be short", "Off") + + Cura.IconWithText + { + source: UM.Theme.getIcon("category_layer_height") + text: + { + if (Cura.MachineManager.activeStack) + { + var text = Cura.MachineManager.activeQualityOrQualityChangesName + if (!Cura.MachineManager.hasNotSupportedQuality) + { + text += " " + layerHeight.properties.value + "mm" + } + return text + } + return "" + } + + UM.SettingPropertyProvider + { + id: layerHeight + containerStack: Cura.MachineManager.activeStack + key: "layer_height" + watchedProperties: ["value"] + } + } + + Cura.IconWithText + { + source: UM.Theme.getIcon("category_infill") + text: Cura.MachineManager.activeStack ? parseInt(infillDensity.properties.value) + "%" : "0%" + + UM.SettingPropertyProvider + { + id: infillDensity + containerStack: Cura.MachineManager.activeStack + key: "infill_sparse_density" + watchedProperties: ["value"] + } + } + + Cura.IconWithText + { + source: UM.Theme.getIcon("category_support") + text: supportEnabled.properties.value == "True" ? enabledText : disabledText + + UM.SettingPropertyProvider + { + id: supportEnabled + containerStack: Cura.MachineManager.activeMachine + key: "support_enable" + watchedProperties: ["value"] + } + } + + Cura.IconWithText + { + source: UM.Theme.getIcon("category_adhesion") + text: platformAdhesionType.properties.value != "skirt" && platformAdhesionType.properties.value != "none" ? enabledText : disabledText + + UM.SettingPropertyProvider + { + id: platformAdhesionType + containerStack: Cura.MachineManager.activeMachine + key: "adhesion_type" + watchedProperties: [ "value"] + } + } +} \ No newline at end of file diff --git a/resources/qml/PrintSetupSelector/Recommended/RecommendedAdhesionSelector.qml b/resources/qml/PrintSetupSelector/Recommended/RecommendedAdhesionSelector.qml new file mode 100644 index 0000000000..a5f35f333b --- /dev/null +++ b/resources/qml/PrintSetupSelector/Recommended/RecommendedAdhesionSelector.qml @@ -0,0 +1,100 @@ +// Copyright (c) 2018 Ultimaker B.V. +// Cura is released under the terms of the LGPLv3 or higher. + +import QtQuick 2.7 +import QtQuick.Controls 1.4 +import QtQuick.Controls.Styles 1.4 + +import UM 1.2 as UM +import Cura 1.0 as Cura + + +// +// Adhesion +// +Item +{ + id: enableAdhesionRow + height: childrenRect.height + + property real labelColumnWidth: Math.round(width / 3) + + Cura.IconWithText + { + id: enableAdhesionRowTitle + anchors.top: parent.top + anchors.left: parent.left + source: UM.Theme.getIcon("category_adhesion") + text: catalog.i18nc("@label", "Adhesion") + width: labelColumnWidth + } + + Item + { + id: enableAdhesionContainer + height: enableAdhesionCheckBox.height + + anchors + { + left: enableAdhesionRowTitle.right + right: parent.right + verticalCenter: enableAdhesionRowTitle.verticalCenter + } + + CheckBox + { + id: enableAdhesionCheckBox + anchors.verticalCenter: parent.verticalCenter + + property alias _hovered: adhesionMouseArea.containsMouse + + //: Setting enable printing build-plate adhesion helper checkbox + style: UM.Theme.styles.checkbox + enabled: recommendedPrintSetup.settingsEnabled + + visible: platformAdhesionType.properties.enabled == "True" + checked: platformAdhesionType.properties.value != "skirt" && platformAdhesionType.properties.value != "none" + + MouseArea + { + id: adhesionMouseArea + anchors.fill: parent + hoverEnabled: true + + onClicked: + { + var adhesionType = "skirt" + if (!parent.checked) + { + // Remove the "user" setting to see if the rest of the stack prescribes a brim or a raft + platformAdhesionType.removeFromContainer(0) + adhesionType = platformAdhesionType.properties.value + if(adhesionType == "skirt" || adhesionType == "none") + { + // If the rest of the stack doesn't prescribe an adhesion-type, default to a brim + adhesionType = "brim" + } + } + platformAdhesionType.setPropertyValue("value", adhesionType) + } + + onEntered: + { + base.showTooltip(enableAdhesionCheckBox, Qt.point(-enableAdhesionContainer.x - UM.Theme.getSize("thick_margin").width, 0), + catalog.i18nc("@label", "Enable printing a brim or raft. This will add a flat area around or under your object which is easy to cut off afterwards.")); + } + onExited: base.hideTooltip() + } + } + } + + UM.SettingPropertyProvider + { + id: platformAdhesionType + containerStack: Cura.MachineManager.activeMachine + removeUnusedValue: false //Doesn't work with settings that are resolved. + key: "adhesion_type" + watchedProperties: [ "value", "enabled" ] + storeIndex: 0 + } +} \ No newline at end of file diff --git a/resources/qml/PrintSetupSelector/Recommended/RecommendedInfillDensitySelector.qml b/resources/qml/PrintSetupSelector/Recommended/RecommendedInfillDensitySelector.qml new file mode 100644 index 0000000000..2971415948 --- /dev/null +++ b/resources/qml/PrintSetupSelector/Recommended/RecommendedInfillDensitySelector.qml @@ -0,0 +1,252 @@ +// Copyright (c) 2018 Ultimaker B.V. +// Cura is released under the terms of the LGPLv3 or higher. + +import QtQuick 2.7 +import QtQuick.Controls 1.4 +import QtQuick.Controls.Styles 1.4 + +import UM 1.2 as UM +import Cura 1.0 as Cura + + +// +// Infill +// +Item +{ + id: infillRow + height: childrenRect.height + + property real labelColumnWidth: Math.round(width / 3) + + // Create a binding to update the icon when the infill density changes + Binding + { + target: infillRowTitle + property: "source" + value: + { + var density = parseInt(infillDensity.properties.value) + if (parseInt(infillSteps.properties.value) != 0) + { + return UM.Theme.getIcon("gradual") + } + if (density <= 0) + { + return UM.Theme.getIcon("hollow") + } + if (density < 40) + { + return UM.Theme.getIcon("sparse") + } + if (density < 90) + { + return UM.Theme.getIcon("dense") + } + return UM.Theme.getIcon("solid") + } + } + + // We use a binding to make sure that after manually setting infillSlider.value it is still bound to the property provider + Binding + { + target: infillSlider + property: "value" + value: parseInt(infillDensity.properties.value) + } + + // Here are the elements that are shown in the left column + Cura.IconWithText + { + id: infillRowTitle + anchors.top: parent.top + anchors.left: parent.left + source: UM.Theme.getIcon("category_infill") + text: catalog.i18nc("@label", "Infill") + " (%)" + width: labelColumnWidth + } + + Item + { + id: infillSliderContainer + height: childrenRect.height + + anchors + { + left: infillRowTitle.right + right: parent.right + verticalCenter: infillRowTitle.verticalCenter + } + + Slider + { + id: infillSlider + + width: parent.width + height: UM.Theme.getSize("print_setup_slider_handle").height // The handle is the widest element of the slider + + minimumValue: 0 + maximumValue: 100 + stepSize: 1 + tickmarksEnabled: true + + // disable slider when gradual support is enabled + enabled: parseInt(infillSteps.properties.value) == 0 + + // set initial value from stack + value: parseInt(infillDensity.properties.value) + + style: SliderStyle + { + //Draw line + groove: Item + { + Rectangle + { + height: UM.Theme.getSize("print_setup_slider_groove").height + width: control.width - UM.Theme.getSize("print_setup_slider_handle").width + anchors.horizontalCenter: parent.horizontalCenter + anchors.verticalCenter: parent.verticalCenter + color: control.enabled ? UM.Theme.getColor("quality_slider_available") : UM.Theme.getColor("quality_slider_unavailable") + } + } + + handle: Rectangle + { + id: handleButton + color: control.enabled ? UM.Theme.getColor("primary") : UM.Theme.getColor("quality_slider_unavailable") + implicitWidth: UM.Theme.getSize("print_setup_slider_handle").width + implicitHeight: implicitWidth + radius: Math.round(implicitWidth / 2) + } + + tickmarks: Repeater + { + id: repeater + model: control.maximumValue / control.stepSize + 1 + + Rectangle + { + color: control.enabled ? UM.Theme.getColor("quality_slider_available") : UM.Theme.getColor("quality_slider_unavailable") + implicitWidth: UM.Theme.getSize("print_setup_slider_tickmarks").width + implicitHeight: UM.Theme.getSize("print_setup_slider_tickmarks").height + anchors.verticalCenter: parent.verticalCenter + + // Do not use Math.round otherwise the tickmarks won't be aligned + x: ((styleData.handleWidth / 2) - (implicitWidth / 2) + (index * ((repeater.width - styleData.handleWidth) / (repeater.count-1)))) + radius: Math.round(implicitWidth / 2) + visible: (index % 10) == 0 // Only show steps of 10% + + Label + { + text: index + visible: (index % 20) == 0 // Only show steps of 20% + anchors.horizontalCenter: parent.horizontalCenter + y: UM.Theme.getSize("thin_margin").height + renderType: Text.NativeRendering + } + } + } + } + + onValueChanged: + { + // Don't round the value if it's already the same + if (parseInt(infillDensity.properties.value) == infillSlider.value) + { + return + } + + // Round the slider value to the nearest multiple of 10 (simulate step size of 10) + var roundedSliderValue = Math.round(infillSlider.value / 10) * 10 + + // Update the slider value to represent the rounded value + infillSlider.value = roundedSliderValue + + // Update value only if the Recomended mode is Active, + // Otherwise if I change the value in the Custom mode the Recomended view will try to repeat + // same operation + var active_mode = UM.Preferences.getValue("cura/active_mode") + + if (active_mode == 0 || active_mode == "simple") + { + Cura.MachineManager.setSettingForAllExtruders("infill_sparse_density", "value", roundedSliderValue) + Cura.MachineManager.resetSettingForAllExtruders("infill_line_distance") + } + } + } + } + + // Gradual Support Infill Checkbox + CheckBox + { + id: enableGradualInfillCheckBox + property alias _hovered: enableGradualInfillMouseArea.containsMouse + + anchors.top: infillSliderContainer.bottom + anchors.topMargin: UM.Theme.getSize("wide_margin").height + anchors.left: infillSliderContainer.left + + text: catalog.i18nc("@label", "Gradual infill") + style: UM.Theme.styles.checkbox + enabled: recommendedPrintSetup.settingsEnabled + visible: infillSteps.properties.enabled == "True" + checked: parseInt(infillSteps.properties.value) > 0 + + MouseArea + { + id: enableGradualInfillMouseArea + + anchors.fill: parent + hoverEnabled: true + enabled: true + + property var previousInfillDensity: parseInt(infillDensity.properties.value) + + onClicked: + { + // Set to 90% only when enabling gradual infill + var newInfillDensity; + if (parseInt(infillSteps.properties.value) == 0) + { + previousInfillDensity = parseInt(infillDensity.properties.value) + newInfillDensity = 90 + } else { + newInfillDensity = previousInfillDensity + } + Cura.MachineManager.setSettingForAllExtruders("infill_sparse_density", "value", String(newInfillDensity)) + + var infill_steps_value = 0 + if (parseInt(infillSteps.properties.value) == 0) + { + infill_steps_value = 5 + } + + Cura.MachineManager.setSettingForAllExtruders("gradual_infill_steps", "value", infill_steps_value) + } + + onEntered: base.showTooltip(enableGradualInfillCheckBox, Qt.point(-infillSliderContainer.x - UM.Theme.getSize("thick_margin").width, 0), + catalog.i18nc("@label", "Gradual infill will gradually increase the amount of infill towards the top.")) + + onExited: base.hideTooltip() + } + } + + UM.SettingPropertyProvider + { + id: infillDensity + containerStackId: Cura.MachineManager.activeStackId + key: "infill_sparse_density" + watchedProperties: [ "value" ] + storeIndex: 0 + } + + UM.SettingPropertyProvider + { + id: infillSteps + containerStackId: Cura.MachineManager.activeStackId + key: "gradual_infill_steps" + watchedProperties: ["value", "enabled"] + storeIndex: 0 + } +} \ No newline at end of file diff --git a/resources/qml/PrintSetupSelector/Recommended/RecommendedPrintSetup.qml b/resources/qml/PrintSetupSelector/Recommended/RecommendedPrintSetup.qml new file mode 100644 index 0000000000..6885f8c041 --- /dev/null +++ b/resources/qml/PrintSetupSelector/Recommended/RecommendedPrintSetup.qml @@ -0,0 +1,81 @@ +// Copyright (c) 2018 Ultimaker B.V. +// Cura is released under the terms of the LGPLv3 or higher. + +import QtQuick 2.7 +import QtQuick.Controls 1.4 +import QtQuick.Controls.Styles 1.4 + +import UM 1.2 as UM +import Cura 1.0 as Cura + +Item +{ + id: recommendedPrintSetup + + height: childrenRect.height + 2 * padding + + property Action configureSettings + + property bool settingsEnabled: Cura.ExtruderManager.activeExtruderStackId || extrudersEnabledCount.properties.value == 1 + property real padding: UM.Theme.getSize("thick_margin").width + + UM.I18nCatalog + { + id: catalog + name: "cura" + } + + Column + { + width: parent.width - 2 * parent.padding + spacing: UM.Theme.getSize("wide_margin").height + + anchors + { + left: parent.left + right: parent.right + top: parent.top + margins: parent.padding + } + + // TODO + property real firstColumnWidth: Math.round(width / 3) + + RecommendedQualityProfileSelector + { + width: parent.width + // TODO Create a reusable component with these properties to not define them separately for each component + labelColumnWidth: parent.firstColumnWidth + } + + RecommendedInfillDensitySelector + { + width: parent.width + // TODO Create a reusable component with these properties to not define them separately for each component + labelColumnWidth: parent.firstColumnWidth + } + + RecommendedSupportSelector + { + width: parent.width + // TODO Create a reusable component with these properties to not define them separately for each component + labelColumnWidth: parent.firstColumnWidth + } + + RecommendedAdhesionSelector + { + width: parent.width + // TODO Create a reusable component with these properties to not define them separately for each component + labelColumnWidth: parent.firstColumnWidth + } + } + + UM.SettingPropertyProvider + { + id: extrudersEnabledCount + containerStack: Cura.MachineManager.activeMachine + key: "extruders_enabled_count" + watchedProperties: [ "value" ] + storeIndex: 0 + } +} diff --git a/resources/qml/PrintSetupSelector/Recommended/RecommendedQualityProfileSelector.qml b/resources/qml/PrintSetupSelector/Recommended/RecommendedQualityProfileSelector.qml new file mode 100644 index 0000000000..15d40f545a --- /dev/null +++ b/resources/qml/PrintSetupSelector/Recommended/RecommendedQualityProfileSelector.qml @@ -0,0 +1,453 @@ +// Copyright (c) 2018 Ultimaker B.V. +// Cura is released under the terms of the LGPLv3 or higher. + +import QtQuick 2.7 +import QtQuick.Controls 1.4 +import QtQuick.Controls.Styles 1.4 + +import UM 1.2 as UM +import Cura 1.0 as Cura + + +// +// Quality profile +// +Item +{ + id: qualityRow + height: childrenRect.height + + property real labelColumnWidth: Math.round(width / 3) + property real settingsColumnWidth: width - labelColumnWidth + + Timer + { + id: qualitySliderChangeTimer + interval: 50 + running: false + repeat: false + onTriggered: + { + var item = Cura.QualityProfilesDropDownMenuModel.getItem(qualitySlider.value); + Cura.MachineManager.activeQualityGroup = item.quality_group; + } + } + + Component.onCompleted: qualityModel.update() + + Connections + { + target: Cura.QualityProfilesDropDownMenuModel + onItemsChanged: qualityModel.update() + } + + Connections { + target: base + onVisibleChanged: + { + // update needs to be called when the widgets are visible, otherwise the step width calculation + // will fail because the width of an invisible item is 0. + if (visible) + { + qualityModel.update(); + } + } + } + + ListModel + { + id: qualityModel + + property var totalTicks: 0 + property var availableTotalTicks: 0 + property var existingQualityProfile: 0 + + property var qualitySliderActiveIndex: 0 + property var qualitySliderStepWidth: 0 + property var qualitySliderAvailableMin: 0 + property var qualitySliderAvailableMax: 0 + property var qualitySliderMarginRight: 0 + + function update () + { + reset() + + var availableMin = -1 + var availableMax = -1 + + for (var i = 0; i < Cura.QualityProfilesDropDownMenuModel.rowCount(); i++) + { + var qualityItem = Cura.QualityProfilesDropDownMenuModel.getItem(i) + + // Add each quality item to the UI quality model + qualityModel.append(qualityItem) + + // Set selected value + if (Cura.MachineManager.activeQualityType == qualityItem.quality_type) + { + // set to -1 when switching to user created profile so all ticks are clickable + if (Cura.SimpleModeSettingsManager.isProfileUserCreated) + { + qualityModel.qualitySliderActiveIndex = -1 + } + else + { + qualityModel.qualitySliderActiveIndex = i + } + + qualityModel.existingQualityProfile = 1 + } + + // Set min available + if (qualityItem.available && availableMin == -1) + { + availableMin = i + } + + // Set max available + if (qualityItem.available) + { + availableMax = i + } + } + + // Set total available ticks for active slider part + if (availableMin != -1) + { + qualityModel.availableTotalTicks = availableMax - availableMin + 1 + } + + // Calculate slider values + calculateSliderStepWidth(qualityModel.totalTicks) + calculateSliderMargins(availableMin, availableMax, qualityModel.totalTicks) + + qualityModel.qualitySliderAvailableMin = availableMin + qualityModel.qualitySliderAvailableMax = availableMax + } + + function calculateSliderStepWidth (totalTicks) + { + // Do not use Math.round otherwise the tickmarks won't be aligned + qualityModel.qualitySliderStepWidth = totalTicks != 0 ? + ((settingsColumnWidth - UM.Theme.getSize("print_setup_slider_handle").width) / (totalTicks)) : 0 + } + + function calculateSliderMargins (availableMin, availableMax, totalTicks) + { + if (availableMin == -1 || (availableMin == 0 && availableMax == 0)) + { + // Do not use Math.round otherwise the tickmarks won't be aligned + qualityModel.qualitySliderMarginRight = settingsColumnWidth + } + else if (availableMin == availableMax) + { + // Do not use Math.round otherwise the tickmarks won't be aligned + qualityModel.qualitySliderMarginRight = (totalTicks - availableMin) * qualitySliderStepWidth + } + else + { + // Do not use Math.round otherwise the tickmarks won't be aligned + qualityModel.qualitySliderMarginRight = (totalTicks - availableMax) * qualitySliderStepWidth + } + } + + function reset () { + qualityModel.clear() + qualityModel.availableTotalTicks = 0 + qualityModel.existingQualityProfile = 0 + + // check, the ticks count cannot be less than zero + qualityModel.totalTicks = Math.max(0, Cura.QualityProfilesDropDownMenuModel.rowCount() - 1) + } + } + + // Here are the elements that are shown in the left column + Item + { + id: titleRow + width: labelColumnWidth + height: childrenRect.height + + Cura.IconWithText + { + id: qualityRowTitle + source: UM.Theme.getIcon("category_layer_height") + text: catalog.i18nc("@label", "Layer Height") + anchors.left: parent.left + anchors.right: customisedSettings.left + } + + UM.SimpleButton + { + id: customisedSettings + + visible: Cura.SimpleModeSettingsManager.isProfileCustomized || Cura.SimpleModeSettingsManager.isProfileUserCreated + height: visible ? UM.Theme.getSize("print_setup_icon").height : 0 + width: height + anchors + { + right: parent.right + rightMargin: UM.Theme.getSize("default_margin").width + leftMargin: UM.Theme.getSize("default_margin").width + verticalCenter: parent.verticalCenter + } + + color: hovered ? UM.Theme.getColor("setting_control_button_hover") : UM.Theme.getColor("setting_control_button") + iconSource: UM.Theme.getIcon("reset") + + onClicked: + { + // if the current profile is user-created, switch to a built-in quality + Cura.MachineManager.resetToUseDefaultQuality() + } + onEntered: + { + var tooltipContent = catalog.i18nc("@tooltip","You have modified some profile settings. If you want to change these go to custom mode.") + base.showTooltip(qualityRow, Qt.point(-UM.Theme.getSize("thick_margin").width, 0), tooltipContent) + } + onExited: base.hideTooltip() + } + } + + // Show titles for the each quality slider ticks + Item + { + anchors.left: speedSlider.left + anchors.top: speedSlider.bottom + height: childrenRect.height + + Repeater + { + model: qualityModel + + Label + { + anchors.verticalCenter: parent.verticalCenter + anchors.top: parent.top + // The height has to be set manually, otherwise it's not automatically calculated in the repeater + height: UM.Theme.getSize("default_margin").height + color: (Cura.MachineManager.activeMachine != null && Cura.QualityProfilesDropDownMenuModel.getItem(index).available) ? UM.Theme.getColor("quality_slider_available") : UM.Theme.getColor("quality_slider_unavailable") + text: + { + var result = "" + if(Cura.MachineManager.activeMachine != null) + { + result = Cura.QualityProfilesDropDownMenuModel.getItem(index).layer_height + + if(result == undefined) + { + result = ""; + } + else + { + result = Number(Math.round(result + "e+2") + "e-2"); //Round to 2 decimals. Javascript makes this difficult... + if (result == undefined || result != result) //Parse failure. + { + result = ""; + } + } + } + return result + } + + x: + { + // Make sure the text aligns correctly with each tick + if (qualityModel.totalTicks == 0) + { + // If there is only one tick, align it centrally + return Math.round(((settingsColumnWidth) - width) / 2) + } + else if (index == 0) + { + return Math.round(settingsColumnWidth / qualityModel.totalTicks) * index + } + else if (index == qualityModel.totalTicks) + { + return Math.round(settingsColumnWidth / qualityModel.totalTicks) * index - width + } + else + { + return Math.round((settingsColumnWidth / qualityModel.totalTicks) * index - (width / 2)) + } + } + } + } + } + + // Print speed slider + // Two sliders are created, one at the bottom with the unavailable qualities + // and the other at the top with the available quality profiles and so the handle to select them. + Item + { + id: speedSlider + height: childrenRect.height + + anchors + { + left: titleRow.right + right: parent.right + verticalCenter: titleRow.verticalCenter + } + + // Draw unavailable slider + Slider + { + id: unavailableSlider + + width: parent.width + height: qualitySlider.height // Same height as the slider that is on top + updateValueWhileDragging : false + tickmarksEnabled: true + + minimumValue: 0 + // maximumValue must be greater than minimumValue to be able to see the handle. While the value is strictly + // speaking not always correct, it seems to have the correct behavior (switching from 0 available to 1 available) + maximumValue: qualityModel.totalTicks + stepSize: 1 + + style: SliderStyle + { + //Draw Unvailable line + groove: Item + { + Rectangle + { + height: UM.Theme.getSize("print_setup_slider_groove").height + width: control.width - UM.Theme.getSize("print_setup_slider_handle").width + anchors.horizontalCenter: parent.horizontalCenter + anchors.verticalCenter: parent.verticalCenter + color: UM.Theme.getColor("quality_slider_unavailable") + } + } + + handle: Item {} + + tickmarks: Repeater + { + id: qualityRepeater + model: qualityModel.totalTicks > 0 ? qualityModel : 0 + + Rectangle + { + color: Cura.QualityProfilesDropDownMenuModel.getItem(index).available ? UM.Theme.getColor("quality_slider_available") : UM.Theme.getColor("quality_slider_unavailable") + implicitWidth: UM.Theme.getSize("print_setup_slider_tickmarks").width + implicitHeight: UM.Theme.getSize("print_setup_slider_tickmarks").height + anchors.verticalCenter: parent.verticalCenter + + // Do not use Math.round otherwise the tickmarks won't be aligned + x: ((UM.Theme.getSize("print_setup_slider_handle").width / 2) - (implicitWidth / 2) + (qualityModel.qualitySliderStepWidth * index)) + radius: Math.round(implicitWidth / 2) + } + } + } + + // Create a mouse area on top of the unavailable profiles to show a specific tooltip + MouseArea + { + anchors.fill: parent + hoverEnabled: true + enabled: !Cura.SimpleModeSettingsManager.isProfileUserCreated + onEntered: + { + var tooltipContent = catalog.i18nc("@tooltip", "This quality profile is not available for your current material and nozzle configuration. Please change these to enable this quality profile") + base.showTooltip(qualityRow, Qt.point(-UM.Theme.getSize("thick_margin").width, customisedSettings.height), tooltipContent) + } + onExited: base.hideTooltip() + } + } + + // Draw available slider + Slider + { + id: qualitySlider + + width: qualityModel.qualitySliderStepWidth * (qualityModel.availableTotalTicks - 1) + UM.Theme.getSize("print_setup_slider_handle").width + height: UM.Theme.getSize("print_setup_slider_handle").height // The handle is the widest element of the slider + enabled: qualityModel.totalTicks > 0 && !Cura.SimpleModeSettingsManager.isProfileCustomized + visible: qualityModel.availableTotalTicks > 0 + updateValueWhileDragging : false + + anchors + { + right: parent.right + rightMargin: qualityModel.qualitySliderMarginRight + } + + minimumValue: qualityModel.qualitySliderAvailableMin >= 0 ? qualityModel.qualitySliderAvailableMin : 0 + // maximumValue must be greater than minimumValue to be able to see the handle. While the value is strictly + // speaking not always correct, it seems to have the correct behavior (switching from 0 available to 1 available) + maximumValue: qualityModel.qualitySliderAvailableMax >= 1 ? qualityModel.qualitySliderAvailableMax : 1 + stepSize: 1 + + value: qualityModel.qualitySliderActiveIndex + + style: SliderStyle + { + // Draw Available line + groove: Item + { + Rectangle + { + height: UM.Theme.getSize("print_setup_slider_groove").height + width: control.width - UM.Theme.getSize("print_setup_slider_handle").width + anchors.verticalCenter: parent.verticalCenter + + // Do not use Math.round otherwise the tickmarks won't be aligned + x: UM.Theme.getSize("print_setup_slider_handle").width / 2 + color: UM.Theme.getColor("quality_slider_available") + } + } + + handle: Rectangle + { + id: qualityhandleButton + color: UM.Theme.getColor("primary") + implicitWidth: UM.Theme.getSize("print_setup_slider_handle").width + implicitHeight: implicitWidth + radius: Math.round(implicitWidth / 2) + visible: !Cura.SimpleModeSettingsManager.isProfileCustomized && !Cura.SimpleModeSettingsManager.isProfileUserCreated && qualityModel.existingQualityProfile + } + } + + onValueChanged: + { + // 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.qualitySliderActiveIndex && qualityModel.qualitySliderActiveIndex != -1) + { + // start updating with short delay + qualitySliderChangeTimer.start() + } + } + } + + // This mouse area is only used to capture the onHover state and don't propagate it to the unavailable mouse area + MouseArea + { + anchors.fill: parent + hoverEnabled: true + acceptedButtons: Qt.NoButton + enabled: !Cura.SimpleModeSettingsManager.isProfileUserCreated + } + } + + // This mouse area will only take the mouse events and show a tooltip when the profile in use is + // a user created profile + MouseArea + { + anchors.fill: parent + hoverEnabled: true + visible: Cura.SimpleModeSettingsManager.isProfileUserCreated + + onEntered: + { + var tooltipContent = catalog.i18nc("@tooltip", "A custom profile is currently active. To enable the quality slider, choose a default quality profile in Custom tab") + base.showTooltip(qualityRow, Qt.point(-UM.Theme.getSize("thick_margin").width, customisedSettings.height), tooltipContent) + } + onExited: base.hideTooltip() + } + } +} \ No newline at end of file diff --git a/resources/qml/PrintSetupSelector/Recommended/RecommendedSupportSelector.qml b/resources/qml/PrintSetupSelector/Recommended/RecommendedSupportSelector.qml new file mode 100644 index 0000000000..57e0c8ce6b --- /dev/null +++ b/resources/qml/PrintSetupSelector/Recommended/RecommendedSupportSelector.qml @@ -0,0 +1,204 @@ +// Copyright (c) 2018 Ultimaker B.V. +// Cura is released under the terms of the LGPLv3 or higher. + +import QtQuick 2.7 +import QtQuick.Controls 1.4 +import QtQuick.Controls.Styles 1.4 + +import UM 1.2 as UM +import Cura 1.0 as Cura + + +// +// Enable support +// +Item +{ + id: enableSupportRow + height: childrenRect.height + + property real labelColumnWidth: Math.round(width / 3) + + Cura.IconWithText + { + id: enableSupportRowTitle + anchors.top: parent.top + anchors.left: parent.left + visible: enableSupportCheckBox.visible + source: UM.Theme.getIcon("category_support") + text: catalog.i18nc("@label", "Support") + width: labelColumnWidth + } + + Item + { + id: enableSupportContainer + height: enableSupportCheckBox.height + + anchors + { + left: enableSupportRowTitle.right + right: parent.right + verticalCenter: enableSupportRowTitle.verticalCenter + } + + CheckBox + { + id: enableSupportCheckBox + anchors.verticalCenter: parent.verticalCenter + + property alias _hovered: enableSupportMouseArea.containsMouse + + style: UM.Theme.styles.checkbox + enabled: recommendedPrintSetup.settingsEnabled + + visible: supportEnabled.properties.enabled == "True" + checked: supportEnabled.properties.value == "True" + + MouseArea + { + id: enableSupportMouseArea + anchors.fill: parent + hoverEnabled: true + + onClicked: supportEnabled.setPropertyValue("value", supportEnabled.properties.value != "True") + + onEntered: + { + base.showTooltip(enableSupportCheckBox, Qt.point(-enableSupportContainer.x - UM.Theme.getSize("thick_margin").width, 0), + catalog.i18nc("@label", "Generate structures to support parts of the model which have overhangs. Without these structures, such parts would collapse during printing.")) + } + onExited: base.hideTooltip() + } + } + + ComboBox + { + id: supportExtruderCombobox + + height: UM.Theme.getSize("print_setup_big_item").height + anchors + { + left: enableSupportCheckBox.right + right: parent.right + leftMargin: UM.Theme.getSize("thick_margin").width + rightMargin: UM.Theme.getSize("thick_margin").width + verticalCenter: parent.verticalCenter + } + + style: UM.Theme.styles.combobox_color + enabled: recommendedPrintSetup.settingsEnabled + visible: enableSupportCheckBox.visible && (supportEnabled.properties.value == "True") && (extrudersEnabledCount.properties.value > 1) + textRole: "text" // this solves that the combobox isn't populated in the first time Cura is started + + model: extruderModel + + property alias _hovered: supportExtruderMouseArea.containsMouse + property string color_override: "" // for manually setting values + property string color: // is evaluated automatically, but the first time is before extruderModel being filled + { + var current_extruder = extruderModel.get(currentIndex) + color_override = "" + if (current_extruder === undefined) return "" + return (current_extruder.color) ? current_extruder.color : "" + } + + currentIndex: + { + if (supportExtruderNr.properties == null) + { + return Cura.MachineManager.defaultExtruderPosition + } + else + { + var extruder = parseInt(supportExtruderNr.properties.value) + if ( extruder === -1) + { + return Cura.MachineManager.defaultExtruderPosition + } + return extruder; + } + } + + onActivated: supportExtruderNr.setPropertyValue("value", String(index)) + + MouseArea + { + id: supportExtruderMouseArea + anchors.fill: parent + hoverEnabled: true + enabled: recommendedPrintSetup.settingsEnabled + acceptedButtons: Qt.NoButton + onEntered: + { + base.showTooltip(supportExtruderCombobox, Qt.point(-enableSupportContainer.x - supportExtruderCombobox.x - UM.Theme.getSize("thick_margin").width, 0), + catalog.i18nc("@label", "Select which extruder to use for support. This will build up supporting structures below the model to prevent the model from sagging or printing in mid air.")); + } + onExited: base.hideTooltip() + + } + + function updateCurrentColor() + { + var current_extruder = extruderModel.get(currentIndex) + if (current_extruder !== undefined) + { + supportExtruderCombobox.color_override = current_extruder.color + } + } + } + } + + ListModel + { + id: extruderModel + Component.onCompleted: populateExtruderModel() + } + + //: Model used to populate the extrudelModel + Cura.ExtrudersModel + { + id: extruders + onModelChanged: populateExtruderModel() + } + + UM.SettingPropertyProvider + { + id: supportEnabled + containerStack: Cura.MachineManager.activeMachine + key: "support_enable" + watchedProperties: [ "value", "enabled", "description" ] + storeIndex: 0 + } + + UM.SettingPropertyProvider + { + id: supportExtruderNr + containerStack: Cura.MachineManager.activeMachine + key: "support_extruder_nr" + watchedProperties: [ "value" ] + storeIndex: 0 + } + + UM.SettingPropertyProvider + { + id: machineExtruderCount + containerStack: Cura.MachineManager.activeMachine + key: "machine_extruder_count" + watchedProperties: ["value"] + storeIndex: 0 + } + + function populateExtruderModel() + { + extruderModel.clear() + for (var extruderNumber = 0; extruderNumber < extruders.rowCount(); extruderNumber++) + { + extruderModel.append({ + text: extruders.getItem(extruderNumber).name, + color: extruders.getItem(extruderNumber).color + }) + } + supportExtruderCombobox.updateCurrentColor() + } +} \ No newline at end of file diff --git a/resources/qml/SidebarTooltip.qml b/resources/qml/PrintSetupTooltip.qml similarity index 93% rename from resources/qml/SidebarTooltip.qml rename to resources/qml/PrintSetupTooltip.qml index 29199481f6..4fa4ef9dd7 100644 --- a/resources/qml/SidebarTooltip.qml +++ b/resources/qml/PrintSetupTooltip.qml @@ -36,7 +36,7 @@ UM.PointingRectangle { } } base.opacity = 1; - target = Qt.point(40 , position.y + Math.round(UM.Theme.getSize("tooltip_arrow_margins").height / 2)) + target = Qt.point(position.x + 1, position.y + Math.round(UM.Theme.getSize("tooltip_arrow_margins").height / 2)) } function hide() { diff --git a/resources/qml/PrinterOutput/ExtruderBox.qml b/resources/qml/PrinterOutput/ExtruderBox.qml index f0abd4cd6c..247bb3a27d 100644 --- a/resources/qml/PrinterOutput/ExtruderBox.qml +++ b/resources/qml/PrinterOutput/ExtruderBox.qml @@ -12,8 +12,10 @@ Item property alias color: background.color property var extruderModel property var position: index + property var connectedPrinter: Cura.MachineManager.printerOutputDevices.length >= 1 ? Cura.MachineManager.printerOutputDevices[0] : null + implicitWidth: parent.width - implicitHeight: UM.Theme.getSize("sidebar_extruder_box").height + implicitHeight: UM.Theme.getSize("print_setup_extruder_box").height UM.SettingPropertyProvider { @@ -45,7 +47,7 @@ Item { id: extruderTargetTemperature text: Math.round(extruderModel.targetHotendTemperature) + "ยฐC" - font: UM.Theme.getFont("small") + font: UM.Theme.getFont("default_bold") color: UM.Theme.getColor("text_inactive") anchors.right: parent.right anchors.rightMargin: UM.Theme.getSize("default_margin").width diff --git a/resources/qml/PrinterOutput/HeatedBedBox.qml b/resources/qml/PrinterOutput/HeatedBedBox.qml index 9de66ad0be..33cf5cd1e2 100644 --- a/resources/qml/PrinterOutput/HeatedBedBox.qml +++ b/resources/qml/PrinterOutput/HeatedBedBox.qml @@ -1,10 +1,10 @@ // Copyright (c) 2017 Ultimaker B.V. // Cura is released under the terms of the LGPLv3 or higher. -import QtQuick 2.2 -import QtQuick.Controls 1.1 -import QtQuick.Controls.Styles 1.1 -import QtQuick.Layouts 1.1 +import QtQuick 2.10 +import QtQuick.Controls 1.4 +import QtQuick.Controls.Styles 1.4 +import QtQuick.Layouts 1.3 import UM 1.2 as UM import Cura 1.0 as Cura @@ -12,12 +12,13 @@ import Cura 1.0 as Cura Item { implicitWidth: parent.width - height: visible ? UM.Theme.getSize("sidebar_extruder_box").height : 0 + height: visible ? UM.Theme.getSize("print_setup_extruder_box").height : 0 property var printerModel + property var connectedPrinter: Cura.MachineManager.printerOutputDevices.length >= 1 ? Cura.MachineManager.printerOutputDevices[0] : null Rectangle { - color: UM.Theme.getColor("sidebar") + color: UM.Theme.getColor("main_background") anchors.fill: parent Label //Build plate label. @@ -34,7 +35,7 @@ Item { id: bedTargetTemperature text: printerModel != null ? printerModel.targetBedTemperature + "ยฐC" : "" - font: UM.Theme.getFont("small") + font: UM.Theme.getFont("default_bold") color: UM.Theme.getColor("text_inactive") anchors.right: parent.right anchors.rightMargin: UM.Theme.getSize("default_margin").width @@ -114,7 +115,7 @@ Item { return false; //Can't preheat if not connected. } - if (!connectedPrinter.acceptsCommands) + if (connectedPrinter == null || !connectedPrinter.acceptsCommands) { return false; //Not allowed to do anything. } diff --git a/resources/qml/PrinterOutput/ManualPrinterControl.qml b/resources/qml/PrinterOutput/ManualPrinterControl.qml index 70961a2eb2..106ae7db03 100644 --- a/resources/qml/PrinterOutput/ManualPrinterControl.qml +++ b/resources/qml/PrinterOutput/ManualPrinterControl.qml @@ -1,103 +1,26 @@ // Copyright (c) 2017 Ultimaker B.V. // Cura is released under the terms of the LGPLv3 or higher. -import QtQuick 2.2 -import QtQuick.Controls 1.1 -import QtQuick.Controls.Styles 1.1 -import QtQuick.Layouts 1.1 +import QtQuick 2.10 +import QtQuick.Controls 1.4 +import QtQuick.Controls.Styles 1.4 +import QtQuick.Layouts 1.3 -import UM 1.2 as UM +import UM 1.3 as UM import Cura 1.0 as Cura +import "." + + Item { - property var printerModel + property var printerModel: null property var activePrintJob: printerModel != null ? printerModel.activePrintJob : null + property var connectedPrinter: Cura.MachineManager.printerOutputDevices.length >= 1 ? Cura.MachineManager.printerOutputDevices[0] : null + implicitWidth: parent.width implicitHeight: childrenRect.height - Component - { - id: monitorButtonStyle - - 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("action_button_active_border"); - } - else if(control.hovered) - { - return UM.Theme.getColor("action_button_hovered_border"); - } - return UM.Theme.getColor("action_button_border"); - } - color: - { - if(!control.enabled) - { - return UM.Theme.getColor("action_button_disabled"); - } - else if(control.pressed) - { - return UM.Theme.getColor("action_button_active"); - } - else if(control.hovered) - { - return UM.Theme.getColor("action_button_hovered"); - } - return UM.Theme.getColor("action_button"); - } - Behavior on color - { - ColorAnimation - { - duration: 50 - } - } - } - - label: Item - { - UM.RecolorImage - { - anchors.verticalCenter: parent.verticalCenter - anchors.horizontalCenter: parent.horizontalCenter - width: Math.floor(control.width / 2) - height: Math.floor(control.height / 2) - sourceSize.width: width - sourceSize.height: width - color: - { - if(!control.enabled) - { - return UM.Theme.getColor("action_button_disabled_text"); - } - else if(control.pressed) - { - return UM.Theme.getColor("action_button_active_text"); - } - else if(control.hovered) - { - return UM.Theme.getColor("action_button_hovered_text"); - } - return UM.Theme.getColor("action_button_text"); - } - source: control.iconSource - } - } - } - } - Column { enabled: @@ -180,7 +103,7 @@ Item Layout.preferredWidth: width Layout.preferredHeight: height iconSource: UM.Theme.getIcon("arrow_top"); - style: monitorButtonStyle + style: UM.Theme.styles.monitor_button_style width: height height: UM.Theme.getSize("setting_control").height @@ -197,7 +120,7 @@ Item Layout.preferredWidth: width Layout.preferredHeight: height iconSource: UM.Theme.getIcon("arrow_left"); - style: monitorButtonStyle + style: UM.Theme.styles.monitor_button_style width: height height: UM.Theme.getSize("setting_control").height @@ -214,7 +137,7 @@ Item Layout.preferredWidth: width Layout.preferredHeight: height iconSource: UM.Theme.getIcon("arrow_right"); - style: monitorButtonStyle + style: UM.Theme.styles.monitor_button_style width: height height: UM.Theme.getSize("setting_control").height @@ -231,7 +154,7 @@ Item Layout.preferredWidth: width Layout.preferredHeight: height iconSource: UM.Theme.getIcon("arrow_bottom"); - style: monitorButtonStyle + style: UM.Theme.styles.monitor_button_style width: height height: UM.Theme.getSize("setting_control").height @@ -248,7 +171,7 @@ Item Layout.preferredWidth: width Layout.preferredHeight: height iconSource: UM.Theme.getIcon("home"); - style: monitorButtonStyle + style: UM.Theme.styles.monitor_button_style width: height height: UM.Theme.getSize("setting_control").height @@ -278,7 +201,7 @@ Item Button { iconSource: UM.Theme.getIcon("arrow_top"); - style: monitorButtonStyle + style: UM.Theme.styles.monitor_button_style width: height height: UM.Theme.getSize("setting_control").height @@ -291,7 +214,7 @@ Item Button { iconSource: UM.Theme.getIcon("home"); - style: monitorButtonStyle + style: UM.Theme.styles.monitor_button_style width: height height: UM.Theme.getSize("setting_control").height @@ -304,7 +227,7 @@ Item Button { iconSource: UM.Theme.getIcon("arrow_bottom"); - style: monitorButtonStyle + style: UM.Theme.styles.monitor_button_style width: height height: UM.Theme.getSize("setting_control").height @@ -356,72 +279,7 @@ Item checked: distancesRow.currentDistance == model.value onClicked: distancesRow.currentDistance = model.value - style: ButtonStyle { - background: Rectangle { - border.width: control.checked ? UM.Theme.getSize("default_lining").width * 2 : UM.Theme.getSize("default_lining").width - border.color: - { - if(!control.enabled) - { - return UM.Theme.getColor("action_button_disabled_border"); - } - else if (control.checked || control.pressed) - { - return UM.Theme.getColor("action_button_active_border"); - } - else if(control.hovered) - { - return UM.Theme.getColor("action_button_hovered_border"); - } - return UM.Theme.getColor("action_button_border"); - } - color: - { - if(!control.enabled) - { - return UM.Theme.getColor("action_button_disabled"); - } - else if (control.checked || control.pressed) - { - return UM.Theme.getColor("action_button_active"); - } - else if (control.hovered) - { - return UM.Theme.getColor("action_button_hovered"); - } - return UM.Theme.getColor("action_button"); - } - Behavior on color { ColorAnimation { duration: 50; } } - Label { - anchors.left: parent.left - anchors.right: parent.right - anchors.verticalCenter: parent.verticalCenter - anchors.leftMargin: UM.Theme.getSize("default_lining").width * 2 - anchors.rightMargin: UM.Theme.getSize("default_lining").width * 2 - color: - { - if(!control.enabled) - { - return UM.Theme.getColor("action_button_disabled_text"); - } - else if (control.checked || control.pressed) - { - return UM.Theme.getColor("action_button_active_text"); - } - else if (control.hovered) - { - return UM.Theme.getColor("action_button_hovered_text"); - } - return UM.Theme.getColor("action_button_text"); - } - font: UM.Theme.getFont("default") - text: control.text - horizontalAlignment: Text.AlignHCenter - elide: Text.ElideMiddle - } - } - label: Item { } - } + style: UM.Theme.styles.monitor_checkable_button_style } } } @@ -462,7 +320,7 @@ Item if (printerModel == null) { return false // Can't send custom commands if not connected. } - if (!connectedPrinter.acceptsCommands) { + if (connectedPrinter == null || !connectedPrinter.acceptsCommands) { return false // Not allowed to do anything } if (connectedPrinter.jobState == "printing" || connectedPrinter.jobState == "pre_print" || connectedPrinter.jobState == "resuming" || connectedPrinter.jobState == "pausing" || connectedPrinter.jobState == "paused" || connectedPrinter.jobState == "error" || connectedPrinter.jobState == "offline") { @@ -551,4 +409,4 @@ Item } ExclusiveGroup { id: distanceGroup } } -} \ No newline at end of file +} diff --git a/resources/qml/PrinterOutput/MonitorItem.qml b/resources/qml/PrinterOutput/MonitorItem.qml index cad8d2f7f3..a26ec20f64 100644 --- a/resources/qml/PrinterOutput/MonitorItem.qml +++ b/resources/qml/PrinterOutput/MonitorItem.qml @@ -15,6 +15,8 @@ Item property string value: "" height: childrenRect.height; + property var connectedPrinter: Cura.MachineManager.printerOutputDevices.length >= 1 ? Cura.MachineManager.printerOutputDevices[0] : null + Row { height: UM.Theme.getSize("setting_control").height diff --git a/resources/qml/PrinterOutput/MonitorSection.qml b/resources/qml/PrinterOutput/MonitorSection.qml index 6ed762362d..7ef89dabf7 100644 --- a/resources/qml/PrinterOutput/MonitorSection.qml +++ b/resources/qml/PrinterOutput/MonitorSection.qml @@ -1,10 +1,10 @@ // Copyright (c) 2017 Ultimaker B.V. // Cura is released under the terms of the LGPLv3 or higher. -import QtQuick 2.2 -import QtQuick.Controls 1.1 -import QtQuick.Controls.Styles 1.1 -import QtQuick.Layouts 1.1 +import QtQuick 2.10 +import QtQuick.Controls 1.4 +import QtQuick.Controls.Styles 1.4 +import QtQuick.Layouts 1.3 import UM 1.2 as UM import Cura 1.0 as Cura @@ -13,7 +13,8 @@ Item { id: base property string label - height: childrenRect.height; + height: childrenRect.height + Rectangle { color: UM.Theme.getColor("setting_category") @@ -30,4 +31,4 @@ Item color: UM.Theme.getColor("setting_category_text") } } -} \ No newline at end of file +} diff --git a/resources/qml/PrinterOutput/OutputDeviceHeader.qml b/resources/qml/PrinterOutput/OutputDeviceHeader.qml index b5ed1b7b4e..16280eab5f 100644 --- a/resources/qml/PrinterOutput/OutputDeviceHeader.qml +++ b/resources/qml/PrinterOutput/OutputDeviceHeader.qml @@ -43,10 +43,10 @@ Item { id: outputDeviceAddressLabel text: (outputDevice != null && outputDevice.address != null) ? outputDevice.address : "" - font: UM.Theme.getFont("small") + font: UM.Theme.getFont("default_bold") color: UM.Theme.getColor("text_inactive") - anchors.top: parent.top - anchors.right: parent.right + anchors.top: outputDeviceNameLabel.bottom + anchors.left: parent.left anchors.margins: UM.Theme.getSize("default_margin").width } @@ -54,7 +54,7 @@ Item { text: outputDevice != null ? "" : catalog.i18nc("@info:status", "The printer is not connected.") color: outputDevice != null && outputDevice.acceptsCommands ? UM.Theme.getColor("setting_control_text") : UM.Theme.getColor("setting_control_disabled_text") - font: UM.Theme.getFont("very_small") + font: UM.Theme.getFont("default") wrapMode: Text.WordWrap anchors.left: parent.left anchors.leftMargin: UM.Theme.getSize("default_margin").width diff --git a/resources/qml/PrinterSelector/MachineSelector.qml b/resources/qml/PrinterSelector/MachineSelector.qml new file mode 100644 index 0000000000..7cda4f1d2e --- /dev/null +++ b/resources/qml/PrinterSelector/MachineSelector.qml @@ -0,0 +1,174 @@ +// Copyright (c) 2018 Ultimaker B.V. +// Cura is released under the terms of the LGPLv3 or higher. + +import QtQuick 2.7 +import QtQuick.Controls 2.3 + +import UM 1.2 as UM +import Cura 1.0 as Cura + +Cura.ExpandablePopup +{ + id: machineSelector + + property bool isNetworkPrinter: Cura.MachineManager.activeMachineNetworkKey != "" + property bool isPrinterConnected: Cura.MachineManager.printerConnected + property var outputDevice: Cura.MachineManager.printerOutputDevices.length >= 1 ? Cura.MachineManager.printerOutputDevices[0] : null + + contentPadding: UM.Theme.getSize("default_lining").width + contentAlignment: Cura.ExpandablePopup.ContentAlignment.AlignLeft + + UM.I18nCatalog + { + id: catalog + name: "cura" + } + + headerItem: Item + { + implicitHeight: icon.height + + UM.RecolorImage + { + id: icon + + anchors.left: parent.left + anchors.verticalCenter: parent.verticalCenter + + source: + { + if (isNetworkPrinter) + { + if (machineSelector.outputDevice != null && machineSelector.outputDevice.clusterSize > 1) + { + return UM.Theme.getIcon("printer_group") + } + return UM.Theme.getIcon("printer_single") + } + return "" + } + width: UM.Theme.getSize("machine_selector_icon").width + height: width + + color: UM.Theme.getColor("machine_selector_printer_icon") + visible: source != "" + } + + Label + { + id: label + anchors.left: icon.visible ? icon.right : parent.left + anchors.right: parent.right + anchors.leftMargin: UM.Theme.getSize("thin_margin").width + anchors.verticalCenter: icon.verticalCenter + text: isNetworkPrinter ? Cura.MachineManager.activeMachineNetworkGroupName : Cura.MachineManager.activeMachineName + elide: Text.ElideRight + color: UM.Theme.getColor("text") + font: UM.Theme.getFont("medium") + renderType: Text.NativeRendering + } + + UM.RecolorImage + { + anchors + { + bottom: parent.bottom + left: parent.left + leftMargin: UM.Theme.getSize("thick_margin").width + } + + source: UM.Theme.getIcon("printer_connected") + width: UM.Theme.getSize("printer_status_icon").width + height: UM.Theme.getSize("printer_status_icon").height + + color: UM.Theme.getColor("primary") + visible: isNetworkPrinter && isPrinterConnected + + // Make a themable circle in the background so we can change it in other themes + Rectangle + { + id: iconBackground + anchors.centerIn: parent + // Make it a bit bigger so there is an outline + width: parent.width + 2 * UM.Theme.getSize("default_lining").width + height: parent.height + 2 * UM.Theme.getSize("default_lining").height + radius: Math.round(width / 2) + color: UM.Theme.getColor("main_background") + z: parent.z - 1 + } + } + } + + contentItem: Item + { + id: popup + width: UM.Theme.getSize("machine_selector_widget_content").width + + ScrollView + { + id: scroll + width: parent.width + clip: true + leftPadding: UM.Theme.getSize("default_lining").width + rightPadding: UM.Theme.getSize("default_lining").width + + MachineSelectorList + { + // Can't use parent.width since the parent is the flickable component and not the ScrollView + width: scroll.width - scroll.leftPadding - scroll.rightPadding + property real maximumHeight: UM.Theme.getSize("machine_selector_widget_content").height - buttonRow.height + + onHeightChanged: + { + scroll.height = Math.min(height, maximumHeight) + popup.height = scroll.height + buttonRow.height + } + } + } + + Rectangle + { + id: separator + + anchors.top: scroll.bottom + width: parent.width + height: UM.Theme.getSize("default_lining").height + color: UM.Theme.getColor("lining") + } + + Row + { + id: buttonRow + + // The separator is inside the buttonRow. This is to avoid some weird behaviours with the scroll bar. + anchors.top: separator.top + anchors.horizontalCenter: parent.horizontalCenter + padding: UM.Theme.getSize("default_margin").width + spacing: UM.Theme.getSize("default_margin").width + + Cura.SecondaryButton + { + leftPadding: UM.Theme.getSize("default_margin").width + rightPadding: UM.Theme.getSize("default_margin").width + text: catalog.i18nc("@button", "Add printer") + onClicked: + { + toggleContent() + Cura.Actions.addMachine.trigger() + } + } + + Cura.SecondaryButton + { + leftPadding: UM.Theme.getSize("default_margin").width + rightPadding: UM.Theme.getSize("default_margin").width + text: catalog.i18nc("@button", "Manage printers") + onClicked: + { + toggleContent() + Cura.Actions.configureMachines.trigger() + } + } + } + } +} diff --git a/resources/qml/PrinterSelector/MachineSelectorButton.qml b/resources/qml/PrinterSelector/MachineSelectorButton.qml new file mode 100644 index 0000000000..b88af35f82 --- /dev/null +++ b/resources/qml/PrinterSelector/MachineSelectorButton.qml @@ -0,0 +1,103 @@ +// Copyright (c) 2018 Ultimaker B.V. +// Cura is released under the terms of the LGPLv3 or higher. + +import QtQuick 2.7 +import QtQuick.Controls 2.1 + +import UM 1.1 as UM +import Cura 1.0 as Cura + +Button +{ + id: machineSelectorButton + + width: parent.width + height: UM.Theme.getSize("action_button").height + leftPadding: UM.Theme.getSize("thick_margin").width + rightPadding: UM.Theme.getSize("thick_margin").width + checkable: true + hoverEnabled: true + + property var outputDevice: null + property var printerTypesList: [] + + function updatePrinterTypesList() + { + printerTypesList = (checked && (outputDevice != null)) ? outputDevice.uniquePrinterTypes : [] + } + + contentItem: Item + { + width: machineSelectorButton.width - machineSelectorButton.leftPadding + height: UM.Theme.getSize("action_button").height + + Label + { + id: buttonText + anchors + { + left: parent.left + right: printerTypes.left + verticalCenter: parent.verticalCenter + } + text: machineSelectorButton.text + color: UM.Theme.getColor("text") + font: UM.Theme.getFont("action_button") + visible: text != "" + renderType: Text.NativeRendering + verticalAlignment: Text.AlignVCenter + elide: Text.ElideRight + } + + Row + { + id: printerTypes + width: childrenRect.width + + anchors + { + right: parent.right + verticalCenter: parent.verticalCenter + } + spacing: UM.Theme.getSize("narrow_margin").width + + Repeater + { + model: printerTypesList + delegate: Cura.PrinterTypeLabel + { + text: Cura.MachineManager.getAbbreviatedMachineName(modelData) + } + } + } + } + + background: Rectangle + { + id: backgroundRect + color: machineSelectorButton.hovered ? UM.Theme.getColor("action_button_hovered") : "transparent" + radius: UM.Theme.getSize("action_button_radius").width + border.width: UM.Theme.getSize("default_lining").width + border.color: machineSelectorButton.checked ? UM.Theme.getColor("primary") : "transparent" + } + + onClicked: + { + toggleContent() + Cura.MachineManager.setActiveMachine(model.id) + } + + Connections + { + target: outputDevice + onUniqueConfigurationsChanged: updatePrinterTypesList() + } + + Connections + { + target: Cura.MachineManager + onOutputDevicesChanged: updatePrinterTypesList() + } + + Component.onCompleted: updatePrinterTypesList() +} diff --git a/resources/qml/PrinterSelector/MachineSelectorList.qml b/resources/qml/PrinterSelector/MachineSelectorList.qml new file mode 100644 index 0000000000..54d766a6e0 --- /dev/null +++ b/resources/qml/PrinterSelector/MachineSelectorList.qml @@ -0,0 +1,84 @@ +// Copyright (c) 2018 Ultimaker B.V. +// Cura is released under the terms of the LGPLv3 or higher. + +import QtQuick 2.7 +import QtQuick.Controls 2.3 + +import UM 1.2 as UM +import Cura 1.0 as Cura + +Column +{ + id: machineSelectorList + + Label + { + text: catalog.i18nc("@label", "Connected printers") + visible: networkedPrintersModel.items.length > 0 + leftPadding: UM.Theme.getSize("default_margin").width + height: visible ? contentHeight + 2 * UM.Theme.getSize("default_margin").height : 0 + renderType: Text.NativeRendering + font: UM.Theme.getFont("medium") + color: UM.Theme.getColor("text_medium") + verticalAlignment: Text.AlignVCenter + } + + Repeater + { + id: networkedPrinters + + model: UM.ContainerStacksModel + { + id: networkedPrintersModel + filter: + { + "type": "machine", "um_network_key": "*", "hidden": "False" + } + } + + delegate: MachineSelectorButton + { + text: model.metadata["connect_group_name"] + checked: Cura.MachineManager.activeMachineNetworkGroupName == model.metadata["connect_group_name"] + outputDevice: Cura.MachineManager.printerOutputDevices.length >= 1 ? Cura.MachineManager.printerOutputDevices[0] : null + + Connections + { + target: Cura.MachineManager + onActiveMachineNetworkGroupNameChanged: checked = Cura.MachineManager.activeMachineNetworkGroupName == model.metadata["connect_group_name"] + } + } + } + + Label + { + text: catalog.i18nc("@label", "Preset printers") + visible: virtualPrintersModel.items.length > 0 + leftPadding: UM.Theme.getSize("default_margin").width + height: visible ? contentHeight + 2 * UM.Theme.getSize("default_margin").height : 0 + renderType: Text.NativeRendering + font: UM.Theme.getFont("medium") + color: UM.Theme.getColor("text_medium") + verticalAlignment: Text.AlignVCenter + } + + Repeater + { + id: virtualPrinters + + model: UM.ContainerStacksModel + { + id: virtualPrintersModel + filter: + { + "type": "machine", "um_network_key": null + } + } + + delegate: MachineSelectorButton + { + text: model.name + checked: Cura.MachineManager.activeMachineId == model.id + } + } +} \ No newline at end of file diff --git a/resources/qml/PrinterTypeLabel.qml b/resources/qml/PrinterTypeLabel.qml new file mode 100644 index 0000000000..7feae32e16 --- /dev/null +++ b/resources/qml/PrinterTypeLabel.qml @@ -0,0 +1,34 @@ +// Copyright (c) 2018 Ultimaker B.V. +// Cura is released under the terms of the LGPLv3 or higher. + +import QtQuick 2.7 +import QtQuick.Controls 2.1 + +import UM 1.1 as UM + +// This component creates a label with the abbreviated name of a printer, with a rectangle surrounding the label. +// It is created in a separated place in order to be reused whenever needed. +Item +{ + property alias text: printerTypeLabel.text + + width: UM.Theme.getSize("printer_type_label").width + height: UM.Theme.getSize("printer_type_label").height + + Rectangle + { + anchors.fill: parent + color: UM.Theme.getColor("printer_type_label_background") + } + + Label + { + id: printerTypeLabel + text: "CFFFP" // As an abbreviated name of the Custom FFF Printer + anchors.verticalCenter: parent.verticalCenter + anchors.horizontalCenter: parent.horizontalCenter + renderType: Text.NativeRendering + font: UM.Theme.getFont("default") + color: UM.Theme.getColor("text") + } +} \ No newline at end of file diff --git a/resources/qml/RoundedRectangle.qml b/resources/qml/RoundedRectangle.qml new file mode 100644 index 0000000000..3ca05e2125 --- /dev/null +++ b/resources/qml/RoundedRectangle.qml @@ -0,0 +1,72 @@ +import QtQuick 2.7 + +import UM 1.2 as UM + +// The rounded rectangle works mostly like a regular rectangle, but provides the option to have rounded corners on only one side of the rectangle. +Item +{ + id: roundedRectangle + // As per the regular rectangle + property color color: "transparent" + + // As per regular rectangle + property int radius: UM.Theme.getSize("default_radius").width + + // On what side should the corners be shown 5 can be used if no radius is needed. + // 1 is down, 2 is left, 3 is up and 4 is right. + property int cornerSide: RoundedRectangle.Direction.None + + // Simple object to ensure that border.width and border.color work + property BorderGroup border: BorderGroup {} + + enum Direction + { + None = 0, + Down = 1, + Left = 2, + Up = 3, + Right = 4, + All = 5 + } + + Rectangle + { + id: background + anchors.fill: parent + radius: cornerSide != RoundedRectangle.Direction.None ? parent.radius : 0 + color: parent.color + border.width: parent.border.width + border.color: parent.border.color + } + + // The item that covers 2 of the corners to make them not rounded. + Rectangle + { + visible: cornerSide != RoundedRectangle.Direction.None && cornerSide != RoundedRectangle.Direction.All + height: cornerSide % 2 ? parent.radius: parent.height + width: cornerSide % 2 ? parent.width : parent.radius + color: parent.color + anchors + { + right: cornerSide == RoundedRectangle.Direction.Left ? parent.right: undefined + bottom: cornerSide == RoundedRectangle.Direction.Up ? parent.bottom: undefined + } + + border.width: parent.border.width + border.color: parent.border.color + + Rectangle + { + color: roundedRectangle.color + height: cornerSide % 2 ? roundedRectangle.border.width: roundedRectangle.height - 2 * roundedRectangle.border.width + width: cornerSide % 2 ? roundedRectangle.width - 2 * roundedRectangle.border.width: roundedRectangle.border.width + anchors + { + right: cornerSide == RoundedRectangle.Direction.Right ? parent.right : undefined + bottom: cornerSide == RoundedRectangle.Direction.Down ? parent.bottom: undefined + horizontalCenter: cornerSide % 2 ? parent.horizontalCenter: undefined + verticalCenter: cornerSide % 2 ? undefined: parent.verticalCenter + } + } + } +} diff --git a/resources/qml/SaveButton.qml b/resources/qml/SaveButton.qml deleted file mode 100644 index 2a0a523026..0000000000 --- a/resources/qml/SaveButton.qml +++ /dev/null @@ -1,409 +0,0 @@ -// Copyright (c) 2018 Ultimaker B.V. -// Cura is released under the terms of the LGPLv3 or higher. - -import QtQuick 2.7 -import QtQuick.Controls 1.1 -import QtQuick.Controls.Styles 1.1 -import QtQuick.Layouts 1.1 - -import UM 1.1 as UM -import Cura 1.0 as Cura - -Item { - id: base; - UM.I18nCatalog { id: catalog; name:"cura"} - - property real progress: UM.Backend.progress - property int backendState: UM.Backend.state - property bool activity: CuraApplication.platformActivity - - property alias buttonRowWidth: saveRow.width - - property string fileBaseName - property string statusText: - { - if(!activity) - { - return catalog.i18nc("@label:PrintjobStatus", "Please load a 3D model"); - } - - if (base.backendState == "undefined") { - return "" - } - - switch(base.backendState) - { - case 1: - return catalog.i18nc("@label:PrintjobStatus", "Ready to slice"); - case 2: - return catalog.i18nc("@label:PrintjobStatus", "Slicing..."); - case 3: - return catalog.i18nc("@label:PrintjobStatus %1 is target operation","Ready to %1").arg(UM.OutputDeviceManager.activeDeviceShortDescription); - case 4: - return catalog.i18nc("@label:PrintjobStatus", "Unable to Slice"); - case 5: - return catalog.i18nc("@label:PrintjobStatus", "Slicing unavailable"); - default: - return ""; - } - } - - function sliceOrStopSlicing() { - try { - if ([1, 5].indexOf(base.backendState) != -1) { - CuraApplication.backend.forceSlice(); - } else { - CuraApplication.backend.stopSlicing(); - } - } catch (e) { - console.log('Could not start or stop slicing', e) - } - } - - Label { - id: statusLabel - width: parent.width - 2 * UM.Theme.getSize("sidebar_margin").width - anchors.top: parent.top - anchors.left: parent.left - anchors.leftMargin: UM.Theme.getSize("sidebar_margin").width - - color: UM.Theme.getColor("text") - font: UM.Theme.getFont("default_bold") - text: statusText; - } - - Rectangle { - id: progressBar - width: parent.width - 2 * UM.Theme.getSize("sidebar_margin").width - height: UM.Theme.getSize("progressbar").height - anchors.top: statusLabel.bottom - anchors.topMargin: Math.round(UM.Theme.getSize("sidebar_margin").height / 4) - anchors.left: parent.left - anchors.leftMargin: UM.Theme.getSize("sidebar_margin").width - radius: UM.Theme.getSize("progressbar_radius").width - color: UM.Theme.getColor("progressbar_background") - - Rectangle { - width: Math.max(parent.width * base.progress) - height: parent.height - color: UM.Theme.getColor("progressbar_control") - radius: UM.Theme.getSize("progressbar_radius").width - visible: (base.backendState != "undefined" && base.backendState == 2) ? true : false - } - } - - // Shortcut for "save as/print/..." - Action { - shortcut: "Ctrl+P" - onTriggered: - { - // only work when the button is enabled - if (saveToButton.enabled) { - saveToButton.clicked(); - } - // prepare button - if (prepareButton.enabled) { - sliceOrStopSlicing(); - } - } - } - - Item { - id: saveRow - width: { - // using childrenRect.width directly causes a binding loop, because setting the width affects the childrenRect - var children_width = UM.Theme.getSize("default_margin").width; - for (var index in children) - { - var child = children[index]; - if(child.visible) - { - children_width += child.width + child.anchors.rightMargin; - } - } - return Math.min(children_width, base.width - UM.Theme.getSize("sidebar_margin").width); - } - height: saveToButton.height - anchors.bottom: parent.bottom - anchors.bottomMargin: UM.Theme.getSize("sidebar_margin").height - anchors.right: parent.right - clip: true - - Row { - id: additionalComponentsRow - anchors.top: parent.top - anchors.right: saveToButton.visible ? saveToButton.left : (prepareButton.visible ? prepareButton.left : parent.right) - anchors.rightMargin: UM.Theme.getSize("default_margin").width - - spacing: UM.Theme.getSize("default_margin").width - } - - Component.onCompleted: { - saveRow.addAdditionalComponents("saveButton") - } - - Connections { - target: CuraApplication - onAdditionalComponentsChanged: saveRow.addAdditionalComponents("saveButton") - } - - function addAdditionalComponents (areaId) { - if(areaId == "saveButton") { - for (var component in CuraApplication.additionalComponents["saveButton"]) { - CuraApplication.additionalComponents["saveButton"][component].parent = additionalComponentsRow - } - } - } - - Connections { - target: UM.Preferences - onPreferenceChanged: - { - var autoSlice = UM.Preferences.getValue("general/auto_slice"); - prepareButton.autoSlice = autoSlice; - saveToButton.autoSlice = autoSlice; - } - } - - // Prepare button, only shows if auto_slice is off - Button { - id: prepareButton - - tooltip: [1, 5].indexOf(base.backendState) != -1 ? catalog.i18nc("@info:tooltip","Slice current printjob") : catalog.i18nc("@info:tooltip","Cancel slicing process") - // 1 = not started, 2 = Processing - enabled: base.backendState != "undefined" && ([1, 2].indexOf(base.backendState) != -1) && base.activity - visible: base.backendState != "undefined" && !autoSlice && ([1, 2, 4].indexOf(base.backendState) != -1) && base.activity - property bool autoSlice - height: UM.Theme.getSize("save_button_save_to_button").height - - anchors.top: parent.top - anchors.right: parent.right - anchors.rightMargin: UM.Theme.getSize("sidebar_margin").width - - // 1 = not started, 4 = error, 5 = disabled - text: [1, 4, 5].indexOf(base.backendState) != -1 ? catalog.i18nc("@label:Printjob", "Prepare") : catalog.i18nc("@label:Printjob", "Cancel") - onClicked: - { - sliceOrStopSlicing(); - } - - 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("action_button_active_border"); - else if(control.hovered) - return UM.Theme.getColor("action_button_hovered_border"); - else - return UM.Theme.getColor("action_button_border"); - } - color: - { - if(!control.enabled) - return UM.Theme.getColor("action_button_disabled"); - else if(control.pressed) - return UM.Theme.getColor("action_button_active"); - else if(control.hovered) - return UM.Theme.getColor("action_button_hovered"); - else - return UM.Theme.getColor("action_button"); - } - - 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("action_button_active_text"); - else if(control.hovered) - return UM.Theme.getColor("action_button_hovered_text"); - else - return UM.Theme.getColor("action_button_text"); - } - font: UM.Theme.getFont("action_button") - text: control.text; - } - } - label: Item { } - } - } - - Button { - id: saveToButton - - tooltip: UM.OutputDeviceManager.activeDeviceDescription; - // 3 = done, 5 = disabled - enabled: base.backendState != "undefined" && (base.backendState == 3 || base.backendState == 5) && base.activity == true - visible: base.backendState != "undefined" && autoSlice || ((base.backendState == 3 || base.backendState == 5) && base.activity == true) - property bool autoSlice - height: UM.Theme.getSize("save_button_save_to_button").height - - anchors.top: parent.top - anchors.right: deviceSelectionMenu.visible ? deviceSelectionMenu.left : parent.right - anchors.rightMargin: deviceSelectionMenu.visible ? -3 * UM.Theme.getSize("default_lining").width : UM.Theme.getSize("sidebar_margin").width - - text: UM.OutputDeviceManager.activeDeviceShortDescription - onClicked: - { - forceActiveFocus(); - UM.OutputDeviceManager.requestWriteToDevice(UM.OutputDeviceManager.activeDevice, PrintInformation.jobName, - { "filter_by_machine": true, "preferred_mimetypes": Cura.MachineManager.activeMachine.preferred_output_file_formats }); - } - - 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 { } - } - } - - Button { - id: deviceSelectionMenu - tooltip: catalog.i18nc("@info:tooltip","Select the active output device"); - anchors.top: parent.top - anchors.right: parent.right - - anchors.rightMargin: UM.Theme.getSize("sidebar_margin").width - width: UM.Theme.getSize("save_button_save_to_button").height - height: UM.Theme.getSize("save_button_save_to_button").height - // 3 = Done, 5 = Disabled - enabled: base.backendState != "undefined" && (base.backendState == 3 || base.backendState == 5) && base.activity == true - visible: base.backendState != "undefined" && (devicesModel.deviceCount > 1) && (base.backendState == 3 || base.backendState == 5) && base.activity == true - - - style: ButtonStyle { - background: Rectangle { - id: deviceSelectionIcon - 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; } } - anchors.left: parent.left - anchors.leftMargin: Math.round(UM.Theme.getSize("save_button_text_margin").width / 2); - width: parent.height - height: parent.height - - UM.RecolorImage { - anchors.verticalCenter: parent.verticalCenter - anchors.horizontalCenter: parent.horizontalCenter - width: UM.Theme.getSize("standard_arrow").width - height: UM.Theme.getSize("standard_arrow").height - sourceSize.width: width - sourceSize.height: height - 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"); - } - source: UM.Theme.getIcon("arrow_bottom"); - } - } - label: Label{ } - } - - menu: Menu { - id: devicesMenu; - Instantiator { - model: devicesModel; - MenuItem { - text: model.description - checkable: true; - checked: model.id == UM.OutputDeviceManager.activeDevice; - exclusiveGroup: devicesMenuGroup; - onTriggered: { - UM.OutputDeviceManager.setActiveDevice(model.id); - } - } - onObjectAdded: devicesMenu.insertItem(index, object) - onObjectRemoved: devicesMenu.removeItem(object) - } - ExclusiveGroup { id: devicesMenuGroup; } - } - } - UM.OutputDevicesModel { id: devicesModel; } - } -} diff --git a/resources/qml/SecondaryButton.qml b/resources/qml/SecondaryButton.qml new file mode 100644 index 0000000000..f03d8acdfa --- /dev/null +++ b/resources/qml/SecondaryButton.qml @@ -0,0 +1,20 @@ +// Copyright (c) 2018 Ultimaker B.V. +// Cura is released under the terms of the LGPLv3 or higher. + +import QtQuick 2.2 + +import UM 1.4 as UM +import Cura 1.1 as Cura + + +Cura.ActionButton +{ + shadowEnabled: true + shadowColor: enabled ? UM.Theme.getColor("secondary_button_shadow"): UM.Theme.getColor("action_button_disabled_shadow") + color: UM.Theme.getColor("secondary_button") + textColor: UM.Theme.getColor("secondary_button_text") + outlineColor: "transparent" + disabledColor: UM.Theme.getColor("action_button_disabled") + textDisabledColor: UM.Theme.getColor("action_button_disabled_text") + hoverColor: UM.Theme.getColor("secondary_button_hover") +} \ No newline at end of file diff --git a/resources/qml/Settings/SettingCategory.qml b/resources/qml/Settings/SettingCategory.qml index e3202323eb..5676bcedf9 100644 --- a/resources/qml/Settings/SettingCategory.qml +++ b/resources/qml/Settings/SettingCategory.qml @@ -12,48 +12,39 @@ Button id: base anchors.left: parent.left anchors.right: parent.right - anchors.leftMargin: UM.Theme.getSize("sidebar_margin").width - anchors.rightMargin: UM.Theme.getSize("sidebar_margin").width + // To avoid overlaping with the scrollBars + anchors.rightMargin: 2 * UM.Theme.getSize("thin_margin").width + hoverEnabled: true + background: Rectangle { id: backgroundRectangle implicitHeight: UM.Theme.getSize("section").height - color: { - if (base.color) { - return base.color; - } else if (!base.enabled) { - return UM.Theme.getColor("setting_category_disabled"); - } else if (base.hovered && base.checkable && base.checked) { - return UM.Theme.getColor("setting_category_active_hover"); - } else if (base.pressed || (base.checkable && base.checked)) { - return UM.Theme.getColor("setting_category_active"); - } else if (base.hovered) { - return UM.Theme.getColor("setting_category_hover"); - } else { - return UM.Theme.getColor("setting_category"); + color: + { + if (base.color) + { + return base.color } + else if (!base.enabled) + { + return UM.Theme.getColor("setting_category_disabled") + } + else if (base.hovered && base.checkable && base.checked) + { + return UM.Theme.getColor("setting_category_active_hover") + } + else if (base.pressed || (base.checkable && base.checked)) + { + return UM.Theme.getColor("setting_category_active") + } + else if (base.hovered) + { + return UM.Theme.getColor("setting_category_hover") + } + return UM.Theme.getColor("setting_category") } Behavior on color { ColorAnimation { duration: 50; } } - Rectangle - { - id: backgroundLiningRectangle - height: UM.Theme.getSize("default_lining").height - width: parent.width - anchors.bottom: parent.bottom - color: { - if (!base.enabled) { - return UM.Theme.getColor("setting_category_disabled_border"); - } else if ((base.hovered || base.activeFocus) && base.checkable && base.checked) { - return UM.Theme.getColor("setting_category_active_hover_border"); - } else if (base.pressed || (base.checkable && base.checked)) { - return UM.Theme.getColor("setting_category_active_border"); - } else if (base.hovered || base.activeFocus) { - return UM.Theme.getColor("setting_category_hover_border"); - } else { - return UM.Theme.getColor("setting_category_border"); - } - } - } } signal showTooltip(string text) @@ -65,18 +56,19 @@ Button property var focusItem: base - contentItem: Item { + contentItem: Item + { anchors.fill: parent - anchors.left: parent.left - Label { + Label + { id: settingNameLabel anchors { left: parent.left leftMargin: 2 * UM.Theme.getSize("default_margin").width + UM.Theme.getSize("section_icon").width - right: parent.right; - verticalCenter: parent.verticalCenter; + right: parent.right + verticalCenter: parent.verticalCenter } text: definition.label textFormat: Text.PlainText @@ -84,21 +76,27 @@ Button font: UM.Theme.getFont("setting_category") color: { - if (!base.enabled) { - return UM.Theme.getColor("setting_category_disabled_text"); - } else if ((base.hovered || base.activeFocus) && base.checkable && base.checked) { - return UM.Theme.getColor("setting_category_active_hover_text"); - } else if (base.pressed || (base.checkable && base.checked)) { - return UM.Theme.getColor("setting_category_active_text"); - } else if (base.hovered || base.activeFocus) { - return UM.Theme.getColor("setting_category_hover_text"); - } else { - return UM.Theme.getColor("setting_category_text"); + if (!base.enabled) + { + return UM.Theme.getColor("setting_category_disabled_text") + } else if ((base.hovered || base.activeFocus) && base.checkable && base.checked) + { + return UM.Theme.getColor("setting_category_active_hover_text") + } else if (base.pressed || (base.checkable && base.checked)) + { + return UM.Theme.getColor("setting_category_active_text") + } else if (base.hovered || base.activeFocus) + { + return UM.Theme.getColor("setting_category_hover_text") + } else + { + return UM.Theme.getColor("setting_category_text") } } fontSizeMode: Text.HorizontalFit minimumPointSize: 8 } + UM.RecolorImage { id: category_arrow @@ -107,21 +105,26 @@ Button anchors.rightMargin: UM.Theme.getSize("default_margin").width width: UM.Theme.getSize("standard_arrow").width height: UM.Theme.getSize("standard_arrow").height - sourceSize.width: width sourceSize.height: width color: { - if (!base.enabled) { - return UM.Theme.getColor("setting_category_disabled_text"); - } else if ((base.hovered || base.activeFocus) && base.checkable && base.checked) { - return UM.Theme.getColor("setting_category_active_hover_text"); - } else if (base.pressed || (base.checkable && base.checked)) { - return UM.Theme.getColor("setting_category_active_text"); - } else if (base.hovered || base.activeFocus) { - return UM.Theme.getColor("setting_category_hover_text"); - } else { - return UM.Theme.getColor("setting_category_text"); + if (!base.enabled) + { + return UM.Theme.getColor("setting_category_disabled_text") } + else if ((base.hovered || base.activeFocus) && base.checkable && base.checked) + { + return UM.Theme.getColor("setting_category_active_hover_text") + } + else if (base.pressed || (base.checkable && base.checked)) + { + return UM.Theme.getColor("setting_category_active_text") + } + else if (base.hovered || base.activeFocus) + { + return UM.Theme.getColor("setting_category_hover_text") + } + return UM.Theme.getColor("setting_category_text") } source: base.checked ? UM.Theme.getIcon("arrow_bottom") : UM.Theme.getIcon("arrow_left") } @@ -132,24 +135,30 @@ Button id: icon anchors.verticalCenter: parent.verticalCenter anchors.left: parent.left - anchors.leftMargin: UM.Theme.getSize("default_margin").width + anchors.leftMargin: UM.Theme.getSize("thin_margin").width color: { - if (!base.enabled) { - return UM.Theme.getColor("setting_category_disabled_text"); - } else if((base.hovered || base.activeFocus) && base.checkable && base.checked) { - return UM.Theme.getColor("setting_category_active_hover_text"); - } else if(base.pressed || (base.checkable && base.checked)) { - return UM.Theme.getColor("setting_category_active_text"); - } else if(base.hovered || base.activeFocus) { - return UM.Theme.getColor("setting_category_hover_text"); - } else { - return UM.Theme.getColor("setting_category_text"); + if (!base.enabled) + { + return UM.Theme.getColor("setting_category_disabled_text") } + else if((base.hovered || base.activeFocus) && base.checkable && base.checked) + { + return UM.Theme.getColor("setting_category_active_hover_text") + } + else if(base.pressed || (base.checkable && base.checked)) + { + return UM.Theme.getColor("setting_category_active_text") + } + else if(base.hovered || base.activeFocus) + { + return UM.Theme.getColor("setting_category_hover_text") + } + return UM.Theme.getColor("setting_category_text") } source: UM.Theme.getIcon(definition.icon) - width: UM.Theme.getSize("section_icon").width; - height: UM.Theme.getSize("section_icon").height; + width: UM.Theme.getSize("section_icon").width + height: UM.Theme.getSize("section_icon").height sourceSize.width: width + 15 * screenScaleFactor sourceSize.height: width + 15 * screenScaleFactor } @@ -159,31 +168,28 @@ Button onClicked: { - if (definition.expanded) { - settingDefinitionsModel.collapse(definition.key); - } else { - settingDefinitionsModel.expandRecursive(definition.key); + if (definition.expanded) + { + settingDefinitionsModel.collapse(definition.key) + } + else + { + settingDefinitionsModel.expandRecursive(definition.key) } //Set focus so that tab navigation continues from this point on. //NB: This must be set AFTER collapsing/expanding the category so that the scroll position is correct. - forceActiveFocus(); + forceActiveFocus() } onActiveFocusChanged: { - if(activeFocus) + if (activeFocus) { - base.focusReceived(); + base.focusReceived() } } - Keys.onTabPressed: - { - base.setActiveFocusToNextSetting(true) - } - Keys.onBacktabPressed: - { - base.setActiveFocusToNextSetting(false) - } + Keys.onTabPressed: base.setActiveFocusToNextSetting(true) + Keys.onBacktabPressed: base.setActiveFocusToNextSetting(false) UM.SimpleButton { @@ -193,9 +199,10 @@ Button height: Math.round(base.height * 0.6) width: Math.round(base.height * 0.6) - anchors { + anchors + { right: inheritButton.visible ? inheritButton.left : parent.right - // use 1.9 as the factor because there is a 0.1 difference between the settings and inheritance warning icons + // Use 1.9 as the factor because there is a 0.1 difference between the settings and inheritance warning icons rightMargin: inheritButton.visible ? Math.round(UM.Theme.getSize("default_margin").width / 2) : category_arrow.width + Math.round(UM.Theme.getSize("default_margin").width * 1.9) verticalCenter: parent.verticalCenter } @@ -204,9 +211,7 @@ Button hoverColor: UM.Theme.getColor("setting_control_button_hover") iconSource: UM.Theme.getIcon("settings") - onClicked: { - Cura.Actions.configureSettingVisibility.trigger(definition) - } + onClicked: Cura.Actions.configureSettingVisibility.trigger(definition) } UM.SimpleButton @@ -239,24 +244,18 @@ Button onClicked: { - settingDefinitionsModel.expandRecursive(definition.key); - base.checked = true; - base.showAllHiddenInheritedSettings(definition.key); + settingDefinitionsModel.expandRecursive(definition.key) + base.checked = true + base.showAllHiddenInheritedSettings(definition.key) } color: UM.Theme.getColor("setting_control_button") hoverColor: UM.Theme.getColor("setting_control_button_hover") iconSource: UM.Theme.getIcon("notice") - onEntered: - { - base.showTooltip(catalog.i18nc("@label","Some hidden settings use values different from their normal calculated value.\n\nClick to make these settings visible.")) - } + onEntered: base.showTooltip(catalog.i18nc("@label","Some hidden settings use values different from their normal calculated value.\n\nClick to make these settings visible.")) - onExited: - { - base.hideTooltip(); - } + onExited: base.hideTooltip() UM.I18nCatalog { id: catalog; name: "cura" } } diff --git a/resources/qml/Settings/SettingCheckBox.qml b/resources/qml/Settings/SettingCheckBox.qml index d37754d27c..0c7321d08a 100644 --- a/resources/qml/Settings/SettingCheckBox.qml +++ b/resources/qml/Settings/SettingCheckBox.qml @@ -28,37 +28,40 @@ SettingItem // 3: material -> user changed material in materials page // 4: variant // 5: machine - var value; - if ((base.resolve != "None") && (stackLevel != 0) && (stackLevel != 1)) { + var value + if ((base.resolve != "None") && (stackLevel != 0) && (stackLevel != 1)) + { // We have a resolve function. Indicates that the setting is not settable per extruder and that // we have to choose between the resolved value (default) and the global value // (if user has explicitly set this). - value = base.resolve; - } else { - value = propertyProvider.properties.value; + value = base.resolve + } + else + { + value = propertyProvider.properties.value } switch(value) { case "True": - return true; + return true case "False": - return false; + return false default: - return value; + return value } } Keys.onSpacePressed: { - forceActiveFocus(); - propertyProvider.setPropertyValue("value", !checked); + forceActiveFocus() + propertyProvider.setPropertyValue("value", !checked) } onClicked: { - forceActiveFocus(); - propertyProvider.setPropertyValue("value", !checked); + forceActiveFocus() + propertyProvider.setPropertyValue("value", !checked) } Keys.onTabPressed: @@ -72,9 +75,9 @@ SettingItem onActiveFocusChanged: { - if(activeFocus) + if (activeFocus) { - base.focusReceived(); + base.focusReceived() } } @@ -90,37 +93,38 @@ SettingItem color: { - if(!enabled) + if (!enabled) { return UM.Theme.getColor("setting_control_disabled") } - if(control.containsMouse || control.activeFocus) + if (control.containsMouse || control.activeFocus) { return UM.Theme.getColor("setting_control_highlight") } return UM.Theme.getColor("setting_control") } + radius: UM.Theme.getSize("setting_control_radius").width border.width: UM.Theme.getSize("default_lining").width border.color: { - if(!enabled) + if (!enabled) { return UM.Theme.getColor("setting_control_disabled_border") } - if(control.containsMouse || control.activeFocus) + if (control.containsMouse || control.activeFocus) { return UM.Theme.getColor("setting_control_border_highlight") } return UM.Theme.getColor("setting_control_border") } - UM.RecolorImage { + UM.RecolorImage + { anchors.verticalCenter: parent.verticalCenter anchors.horizontalCenter: parent.horizontalCenter width: Math.round(parent.width / 2.5) height: Math.round(parent.height / 2.5) - sourceSize.width: width sourceSize.height: width color: !enabled ? UM.Theme.getColor("setting_control_disabled_text") : UM.Theme.getColor("setting_control_text"); source: UM.Theme.getIcon("check") diff --git a/resources/qml/Settings/SettingComboBox.qml b/resources/qml/Settings/SettingComboBox.qml index 76d458e427..13d2a0eb8f 100644 --- a/resources/qml/Settings/SettingComboBox.qml +++ b/resources/qml/Settings/SettingComboBox.qml @@ -35,6 +35,7 @@ SettingItem return UM.Theme.getColor("setting_control") } + radius: UM.Theme.getSize("setting_control_radius").width border.width: UM.Theme.getSize("default_lining").width border.color: { diff --git a/resources/qml/Settings/SettingExtruder.qml b/resources/qml/Settings/SettingExtruder.qml index a9427f863a..e1fedd9274 100644 --- a/resources/qml/Settings/SettingExtruder.qml +++ b/resources/qml/Settings/SettingExtruder.qml @@ -19,8 +19,9 @@ SettingItem model: Cura.ExtrudersModel { - onModelChanged: { - control.color = getItem(control.currentIndex).color; + onModelChanged: + { + control.color = getItem(control.currentIndex).color } } @@ -113,14 +114,15 @@ SettingItem { if (!enabled) { - return UM.Theme.getColor("setting_control_disabled"); + return UM.Theme.getColor("setting_control_disabled") } if (control.hovered || base.activeFocus) { - return UM.Theme.getColor("setting_control_highlight"); + return UM.Theme.getColor("setting_control_highlight") } - return UM.Theme.getColor("setting_control"); + return UM.Theme.getColor("setting_control") } + radius: UM.Theme.getSize("setting_control_radius").width border.width: UM.Theme.getSize("default_lining").width border.color: { @@ -153,20 +155,18 @@ SettingItem elide: Text.ElideLeft verticalAlignment: Text.AlignVCenter - background: Rectangle + background: UM.RecolorImage { id: swatch - height: Math.round(UM.Theme.getSize("setting_control").height / 2) + height: Math.round(parent.height / 2) width: height - anchors.right: parent.right anchors.verticalCenter: parent.verticalCenter - anchors.margins: Math.round(UM.Theme.getSize("default_margin").width / 4) - - border.width: UM.Theme.getSize("default_lining").width - border.color: enabled ? UM.Theme.getColor("setting_control_border") : UM.Theme.getColor("setting_control_disabled_border") - radius: Math.round(width / 2) + anchors.rightMargin: UM.Theme.getSize("thin_margin").width + sourceSize.width: width + sourceSize.height: height + source: UM.Theme.getIcon("extruder_button") color: control.color } } @@ -219,20 +219,18 @@ SettingItem verticalAlignment: Text.AlignVCenter rightPadding: swatch.width + UM.Theme.getSize("setting_unit_margin").width - background: Rectangle + background: UM.RecolorImage { id: swatch - height: Math.round(UM.Theme.getSize("setting_control").height / 2) + height: Math.round(parent.height / 2) width: height - anchors.right: parent.right anchors.verticalCenter: parent.verticalCenter - anchors.margins: Math.round(UM.Theme.getSize("default_margin").width / 4) - - border.width: UM.Theme.getSize("default_lining").width - border.color: enabled ? UM.Theme.getColor("setting_control_border") : UM.Theme.getColor("setting_control_disabled_border") - radius: Math.round(width / 2) + anchors.rightMargin: UM.Theme.getSize("thin_margin").width + sourceSize.width: width + sourceSize.height: height + source: UM.Theme.getIcon("extruder_button") color: control.model.getItem(index).color } } diff --git a/resources/qml/Settings/SettingItem.qml b/resources/qml/Settings/SettingItem.qml index 785562cff5..4dd53f8663 100644 --- a/resources/qml/Settings/SettingItem.qml +++ b/resources/qml/Settings/SettingItem.qml @@ -10,10 +10,15 @@ import Cura 1.0 as Cura import "." -Item { - id: base; +Item +{ + id: base height: UM.Theme.getSize("section").height + anchors.left: parent.left + anchors.right: parent.right + // To avoid overlaping with the scrollBars + anchors.rightMargin: 2 * UM.Theme.getSize("thin_margin").width property alias contents: controlContainer.children property alias hovered: mouse.containsMouse @@ -43,25 +48,25 @@ Item { var affected_by = settingDefinitionsModel.getRequires(definition.key, "value") var affected_by_list = "" - for(var i in affected_by) + for (var i in affected_by) { affected_by_list += "
  • %1
  • \n".arg(affected_by[i].label) } var affects_list = "" - for(var i in affects) + for (var i in affects) { affects_list += "
  • %1
  • \n".arg(affects[i].label) } var tooltip = "%1\n

    %2

    ".arg(definition.label).arg(definition.description) - if(affects_list != "") + if (affects_list != "") { tooltip += "
    %1\n".arg(catalog.i18nc("@label Header for list of settings.", "Affects")).arg(affects_list) } - if(affected_by_list != "") + if (affected_by_list != "") { tooltip += "
    %1\n".arg(catalog.i18nc("@label Header for list of settings.", "Affected By")).arg(affected_by_list) } @@ -71,53 +76,57 @@ Item { MouseArea { - id: mouse; + id: mouse - anchors.fill: parent; + anchors.fill: parent - acceptedButtons: Qt.RightButton; + acceptedButtons: Qt.RightButton hoverEnabled: true; - onClicked: base.contextMenuRequested(); + onClicked: base.contextMenuRequested() - onEntered: { - hoverTimer.start(); + onEntered: + { + hoverTimer.start() } - onExited: { - if(controlContainer.item && controlContainer.item.hovered) { - return; + onExited: + { + if (controlContainer.item && controlContainer.item.hovered) + { + return } - hoverTimer.stop(); - base.hideTooltip(); + hoverTimer.stop() + base.hideTooltip() } - Timer { - id: hoverTimer; - interval: 500; - repeat: false; + Timer + { + id: hoverTimer + interval: 500 + repeat: false onTriggered: { - base.showTooltip(base.tooltipText); + base.showTooltip(base.tooltipText) } } Label { - id: label; + id: label - anchors.left: parent.left; - anchors.leftMargin: doDepthIndentation ? Math.round((UM.Theme.getSize("section_icon_column").width + 5) + ((definition.depth - 1) * UM.Theme.getSize("setting_control_depth_margin").width)) : 0 - anchors.right: settingControls.left; + anchors.left: parent.left + anchors.leftMargin: doDepthIndentation ? Math.round(UM.Theme.getSize("thin_margin").width + ((definition.depth - 1) * UM.Theme.getSize("setting_control_depth_margin").width)) : 0 + anchors.right: settingControls.left anchors.verticalCenter: parent.verticalCenter text: definition.label - elide: Text.ElideMiddle; + elide: Text.ElideMiddle renderType: Text.NativeRendering textFormat: Text.PlainText - color: UM.Theme.getColor("setting_control_text"); + color: UM.Theme.getColor("setting_control_text") opacity: (definition.visible) ? 1 : 0.5 // emphasize the setting if it has a value in the user or quality profile font: base.doQualityUserSettingEmphasis && base.stackLevel != undefined && base.stackLevel <= 1 ? UM.Theme.getFont("default_italic") : UM.Theme.getFont("default") @@ -128,11 +137,12 @@ Item { id: settingControls height: Math.round(parent.height / 2) - spacing: Math.round(UM.Theme.getSize("sidebar_margin").height / 2) + spacing: Math.round(UM.Theme.getSize("thick_margin").height / 2) - anchors { + anchors + { right: controlContainer.left - rightMargin: Math.round(UM.Theme.getSize("sidebar_margin").width / 2) + rightMargin: Math.round(UM.Theme.getSize("thick_margin").width / 2) verticalCenter: parent.verticalCenter } @@ -150,112 +160,123 @@ Item { iconSource: UM.Theme.getIcon("link") - onEntered: { - hoverTimer.stop(); - var tooltipText = catalog.i18nc("@label", "This setting is always shared between all extruders. Changing it here will change the value for all extruders."); - if ((resolve != "None") && (stackLevel != 0)) { + onEntered: + { + hoverTimer.stop() + var tooltipText = catalog.i18nc("@label", "This setting is always shared between all extruders. Changing it here will change the value for all extruders.") + if ((resolve != "None") && (stackLevel != 0)) + { // We come here if a setting has a resolve and the setting is not manually edited. - tooltipText += " " + catalog.i18nc("@label", "The value is resolved from per-extruder values ") + "[" + Cura.ExtruderManager.getInstanceExtruderValues(definition.key) + "]."; + tooltipText += " " + catalog.i18nc("@label", "The value is resolved from per-extruder values ") + "[" + Cura.ExtruderManager.getInstanceExtruderValues(definition.key) + "]." } - base.showTooltip(tooltipText); + base.showTooltip(tooltipText) } - onExited: base.showTooltip(base.tooltipText); + onExited: base.showTooltip(base.tooltipText) } UM.SimpleButton { - id: revertButton; + id: revertButton visible: base.stackLevel == 0 && base.showRevertButton - height: parent.height; - width: height; + height: parent.height + width: height color: UM.Theme.getColor("setting_control_button") hoverColor: UM.Theme.getColor("setting_control_button_hover") iconSource: UM.Theme.getIcon("reset") - onClicked: { + onClicked: + { revertButton.focus = true - if (externalResetHandler) { + if (externalResetHandler) + { externalResetHandler(propertyProvider.key) - } else { + } + else + { Cura.MachineManager.clearUserSettingAllCurrentStacks(propertyProvider.key) } } - onEntered: { hoverTimer.stop(); base.showTooltip(catalog.i18nc("@label", "This setting has a value that is different from the profile.\n\nClick to restore the value of the profile.")) } - onExited: base.showTooltip(base.tooltipText); + onEntered: + { + hoverTimer.stop() + base.showTooltip(catalog.i18nc("@label", "This setting has a value that is different from the profile.\n\nClick to restore the value of the profile.")) + } + onExited: base.showTooltip(base.tooltipText) } UM.SimpleButton { // This button shows when the setting has an inherited function, but is overriden by profile. - id: inheritButton; + id: inheritButton // Inherit button needs to be visible if; // - User made changes that override any loaded settings // - This setting item uses inherit button at all // - The type of the value of any deeper container is an "object" (eg; is a function) visible: { - if(!base.showInheritButton) + if (!base.showInheritButton) { - return false; + return false } - if(!propertyProvider.properties.enabled) + if (!propertyProvider.properties.enabled) { // Note: This is not strictly necessary since a disabled setting is hidden anyway. // But this will cause the binding to be re-evaluated when the enabled property changes. - return false; + return false } // There are no settings with any warning. - if(Cura.SettingInheritanceManager.settingsWithInheritanceWarning.length == 0) + if (Cura.SettingInheritanceManager.settingsWithInheritanceWarning.length == 0) { - return false; + return false } // This setting has a resolve value, so an inheritance warning doesn't do anything. - if(resolve != "None") + if (resolve != "None") { return false } // If the setting does not have a limit_to_extruder property (or is -1), use the active stack. - if(globalPropertyProvider.properties.limit_to_extruder == null || String(globalPropertyProvider.properties.limit_to_extruder) == "-1") + if (globalPropertyProvider.properties.limit_to_extruder == null || String(globalPropertyProvider.properties.limit_to_extruder) == "-1") { - return Cura.SettingInheritanceManager.settingsWithInheritanceWarning.indexOf(definition.key) >= 0; + return Cura.SettingInheritanceManager.settingsWithInheritanceWarning.indexOf(definition.key) >= 0 } // Setting does have a limit_to_extruder property, so use that one instead. if (definition.key === undefined) { // Observed when loading workspace, probably when SettingItems are removed. - return false; + return false } - return Cura.SettingInheritanceManager.getOverridesForExtruder(definition.key, String(globalPropertyProvider.properties.limit_to_extruder)).indexOf(definition.key) >= 0; + return Cura.SettingInheritanceManager.getOverridesForExtruder(definition.key, String(globalPropertyProvider.properties.limit_to_extruder)).indexOf(definition.key) >= 0 } - height: parent.height; - width: height; + height: parent.height + width: height - onClicked: { - focus = true; + onClicked: + { + focus = true // Get the most shallow function value (eg not a number) that we can find. var last_entry = propertyProvider.stackLevels[propertyProvider.stackLevels.length - 1] for (var i = 1; i < base.stackLevels.length; i++) { - var has_setting_function = typeof(propertyProvider.getPropertyValue("value", base.stackLevels[i])) == "object"; + var has_setting_function = typeof(propertyProvider.getPropertyValue("value", base.stackLevels[i])) == "object" if(has_setting_function) { last_entry = propertyProvider.stackLevels[i] - break; + break } } - if((last_entry == 4 || last_entry == 11) && base.stackLevel == 0 && base.stackLevels.length == 2) + if ((last_entry == 4 || last_entry == 11) && base.stackLevel == 0 && base.stackLevels.length == 2) { // Special case of the inherit reset. If only the definition (4th or 11th) container) and the first // entry (user container) are set, we can simply remove the container. @@ -276,23 +297,22 @@ Item { color: UM.Theme.getColor("setting_control_button") hoverColor: UM.Theme.getColor("setting_control_button_hover") - iconSource: UM.Theme.getIcon("formula"); + iconSource: UM.Theme.getIcon("formula") onEntered: { hoverTimer.stop(); base.showTooltip(catalog.i18nc("@label", "This setting is normally calculated, but it currently has an absolute value set.\n\nClick to restore the calculated value.")) } - onExited: base.showTooltip(base.tooltipText); + onExited: base.showTooltip(base.tooltipText) } } Item { - id: controlContainer; + id: controlContainer enabled: propertyProvider.isValueUsed - anchors.right: parent.right; - anchors.rightMargin: UM.Theme.getSize("sidebar_margin").width - anchors.verticalCenter: parent.verticalCenter; - width: UM.Theme.getSize("setting_control").width; + anchors.right: parent.right + anchors.verticalCenter: parent.verticalCenter + width: UM.Theme.getSize("setting_control").width height: UM.Theme.getSize("setting_control").height } } diff --git a/resources/qml/Settings/SettingOptionalExtruder.qml b/resources/qml/Settings/SettingOptionalExtruder.qml index a3c1422b30..200a3f64f1 100644 --- a/resources/qml/Settings/SettingOptionalExtruder.qml +++ b/resources/qml/Settings/SettingOptionalExtruder.qml @@ -1,5 +1,5 @@ -// Copyright (c) 2016 Ultimaker B.V. -// Uranium is released under the terms of the LGPLv3 or higher. +// Copyright (c) 2018 Ultimaker B.V. +// Cura is released under the terms of the LGPLv3 or higher. import QtQuick 2.7 import QtQuick.Controls 2.0 @@ -31,12 +31,15 @@ SettingItem { forceActiveFocus(); propertyProvider.setPropertyValue("value", model.getItem(index).index); - } else + } + else { if (propertyProvider.properties.value == -1) { - control.currentIndex = model.rowCount() - 1; // we know the last item is "Not overriden" - } else { + control.currentIndex = model.count - 1; // we know the last item is "Not overriden" + } + else + { control.currentIndex = propertyProvider.properties.value; // revert to the old value } } @@ -116,6 +119,7 @@ SettingItem } return UM.Theme.getColor("setting_control"); } + radius: UM.Theme.getSize("setting_control_radius").width border.width: UM.Theme.getSize("default_lining").width border.color: { @@ -148,20 +152,18 @@ SettingItem elide: Text.ElideRight verticalAlignment: Text.AlignVCenter - background: Rectangle + background: UM.RecolorImage { id: swatch - height: Math.round(UM.Theme.getSize("setting_control").height / 2) + height: Math.round(parent.height / 2) width: height - anchors.right: parent.right anchors.verticalCenter: parent.verticalCenter - anchors.margins: Math.round(UM.Theme.getSize("default_margin").width / 4) - - border.width: UM.Theme.getSize("default_lining").width - border.color: enabled ? UM.Theme.getColor("setting_control_border") : UM.Theme.getColor("setting_control_disabled_border") - radius: Math.round(width / 2) + anchors.rightMargin: UM.Theme.getSize("thin_margin").width + sourceSize.width: width + sourceSize.height: height + source: UM.Theme.getIcon("extruder_button") color: control.color } } @@ -215,20 +217,18 @@ SettingItem verticalAlignment: Text.AlignVCenter rightPadding: swatch.width + UM.Theme.getSize("setting_unit_margin").width - background: Rectangle + background: UM.RecolorImage { id: swatch - height: Math.round(UM.Theme.getSize("setting_control").height / 2) + height: Math.round(parent.height / 2) width: height - anchors.right: parent.right anchors.verticalCenter: parent.verticalCenter - anchors.margins: Math.round(UM.Theme.getSize("default_margin").width / 4) - - border.width: UM.Theme.getSize("default_lining").width - border.color: enabled ? UM.Theme.getColor("setting_control_border") : UM.Theme.getColor("setting_control_disabled_border") - radius: Math.round(width / 2) + anchors.rightMargin: UM.Theme.getSize("thin_margin").width + sourceSize.width: width + sourceSize.height: height + source: UM.Theme.getIcon("extruder_button") color: control.model.getItem(index).color } } diff --git a/resources/qml/Settings/SettingTextField.qml b/resources/qml/Settings/SettingTextField.qml index 9ec9338316..770ef53900 100644 --- a/resources/qml/Settings/SettingTextField.qml +++ b/resources/qml/Settings/SettingTextField.qml @@ -32,6 +32,7 @@ SettingItem anchors.fill: parent + radius: UM.Theme.getSize("setting_control_radius").width border.width: Math.round(UM.Theme.getSize("default_lining").width) border.color: { @@ -81,10 +82,10 @@ SettingItem Rectangle { - anchors.fill: parent; - anchors.margins: Math.round(UM.Theme.getSize("default_lining").width); + anchors.fill: parent + anchors.margins: Math.round(UM.Theme.getSize("default_lining").width) color: UM.Theme.getColor("setting_control_highlight") - opacity: !control.hovered ? 0 : propertyProvider.properties.validationState == "ValidatorState.Valid" ? 1.0 : 0.35; + opacity: !control.hovered ? 0 : propertyProvider.properties.validationState == "ValidatorState.Valid" ? 1.0 : 0.35 } Label @@ -145,11 +146,11 @@ SettingItem } color: !enabled ? UM.Theme.getColor("setting_control_disabled_text") : UM.Theme.getColor("setting_control_text") - font: UM.Theme.getFont("default"); + font: UM.Theme.getFont("default") - selectByMouse: true; + selectByMouse: true - maximumLength: (definition.type == "str" || definition.type == "[int]") ? -1 : 10; + maximumLength: (definition.type == "str" || definition.type == "[int]") ? -1 : 10 clip: true; //Hide any text that exceeds the width of the text box. validator: RegExpValidator { regExp: (definition.type == "[int]") ? /^\[?(\s*-?[0-9]{0,9}\s*,)*(\s*-?[0-9]{0,9})\s*\]?$/ : (definition.type == "int") ? /^-?[0-9]{0,10}$/ : (definition.type == "float") ? /^-?[0-9]{0,9}[.,]?[0-9]{0,3}$/ : /^.*$/ } // definition.type property from parent loader used to disallow fractional number entry @@ -158,7 +159,8 @@ SettingItem { target: input property: "text" - value: { + value: + { // Stacklevels // 0: user -> unsaved change // 1: quality changes -> saved change @@ -167,13 +169,15 @@ SettingItem // 4: variant // 5: machine_changes // 6: machine - if ((base.resolve != "None" && base.resolve) && (stackLevel != 0) && (stackLevel != 1)) { + if ((base.resolve != "None" && base.resolve) && (stackLevel != 0) && (stackLevel != 1)) + { // We have a resolve function. Indicates that the setting is not settable per extruder and that // we have to choose between the resolved value (default) and the global value // (if user has explicitly set this). - return base.resolve; - } else { - return propertyProvider.properties.value; + return base.resolve + } + else { + return propertyProvider.properties.value } } when: !input.activeFocus @@ -182,16 +186,17 @@ SettingItem MouseArea { id: mouseArea - anchors.fill: parent; + anchors.fill: parent cursorShape: Qt.IBeamCursor onPressed: { - if(!input.activeFocus) { - base.focusGainedByClick = true; - input.forceActiveFocus(); + if (!input.activeFocus) + { + base.focusGainedByClick = true + input.forceActiveFocus() } - mouse.accepted = false; + mouse.accepted = false } } } diff --git a/resources/qml/Settings/SettingView.qml b/resources/qml/Settings/SettingView.qml index 5d79eef249..c1b4b28d1d 100644 --- a/resources/qml/Settings/SettingView.qml +++ b/resources/qml/Settings/SettingView.qml @@ -1,5 +1,5 @@ -// Copyright (c) 2017 Ultimaker B.V. -// Uranium is released under the terms of the LGPLv3 or higher. +// Copyright (c) 2018 Ultimaker B.V. +// Cura is released under the terms of the LGPLv3 or higher. import QtQuick 2.7 import QtQuick.Controls 1.1 @@ -13,163 +13,28 @@ import "../Menus" Item { - id: base; + id: settingsView property QtObject settingVisibilityPresetsModel: CuraApplication.getSettingVisibilityPresetsModel() property Action configureSettings property bool findingSettings - signal showTooltip(Item item, point location, string text) - signal hideTooltip() - - Item - { - id: globalProfileRow - height: UM.Theme.getSize("sidebar_setup").height - visible: !sidebar.hideSettings - - anchors - { - top: parent.top - left: parent.left - leftMargin: Math.round(UM.Theme.getSize("sidebar_margin").width) - right: parent.right - rightMargin: Math.round(UM.Theme.getSize("sidebar_margin").width) - } - - Label - { - id: globalProfileLabel - text: catalog.i18nc("@label","Profile:") - textFormat: Text.PlainText - width: Math.round(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: generateActiveQualityText() - enabled: !header.currentExtruderVisible || header.currentExtruderIndex > -1 - width: Math.round(parent.width * 0.55) - height: UM.Theme.getSize("setting_control").height - anchors.left: globalProfileLabel.right - anchors.right: parent.right - tooltip: Cura.MachineManager.activeQualityOrQualityChangesName - style: UM.Theme.styles.sidebar_header_button - activeFocusOnPress: true - menu: ProfileMenu { } - - function generateActiveQualityText () - { - var result = Cura.MachineManager.activeQualityOrQualityChangesName - if (Cura.MachineManager.isActiveQualityExperimental) - { - result += " (Experimental)" - } - - if (Cura.MachineManager.isActiveQualitySupported) - { - if (Cura.MachineManager.activeQualityLayerHeight > 0) - { - result += " " - result += " - " - result += Cura.MachineManager.activeQualityLayerHeight + "mm" - result += "" - } - } - - return result - } - - UM.SimpleButton - { - id: customisedSettings - - visible: Cura.MachineManager.hasUserSettings - height: Math.round(parent.height * 0.6) - width: Math.round(parent.height * 0.6) - - anchors.verticalCenter: parent.verticalCenter - anchors.right: parent.right - anchors.rightMargin: Math.round(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() - } - } - } - - ToolButton - { - id: settingVisibilityMenu - - width: height - height: UM.Theme.getSize("setting_control").height - anchors - { - top: globalProfileRow.bottom - topMargin: UM.Theme.getSize("sidebar_margin").height - right: parent.right - rightMargin: UM.Theme.getSize("sidebar_margin").width - } - style: ButtonStyle - { - background: Item { - UM.RecolorImage { - anchors.verticalCenter: parent.verticalCenter - anchors.horizontalCenter: parent.horizontalCenter - width: UM.Theme.getSize("standard_arrow").width - height: UM.Theme.getSize("standard_arrow").height - sourceSize.width: width - sourceSize.height: width - color: control.enabled ? UM.Theme.getColor("setting_category_text") : UM.Theme.getColor("setting_category_disabled_text") - source: UM.Theme.getIcon("menu") - } - } - label: Label{} - } - menu: SettingVisibilityPresetsMenu - { - onShowAllSettings: - { - definitionsModel.setAllVisible(true); - filter.updateDefinitionModel(); - } - } - } Rectangle { id: filterContainer visible: true + radius: UM.Theme.getSize("setting_control_radius").width border.width: Math.round(UM.Theme.getSize("default_lining").width) border.color: { - if(hoverMouseArea.containsMouse || clearFilterButton.containsMouse) + if (hoverMouseArea.containsMouse || clearFilterButton.containsMouse) { - return UM.Theme.getColor("setting_control_border_highlight"); + return UM.Theme.getColor("setting_control_border_highlight") } else { - return UM.Theme.getColor("setting_control_border"); + return UM.Theme.getColor("setting_control_border") } } @@ -177,16 +42,12 @@ Item anchors { - top: globalProfileRow.bottom - topMargin: UM.Theme.getSize("sidebar_margin").height + top: parent.top left: parent.left - leftMargin: UM.Theme.getSize("sidebar_margin").width right: settingVisibilityMenu.left - rightMargin: Math.floor(UM.Theme.getSize("default_margin").width / 2) + rightMargin: UM.Theme.getSize("default_margin").width } - height: visible ? UM.Theme.getSize("setting_control").height : 0 - Behavior on height { NumberAnimation { duration: 100 } } - + height: UM.Theme.getSize("print_setup_big_item").height Timer { id: settingsSearchTimer @@ -198,19 +59,19 @@ Item TextField { - id: filter; + id: filter height: parent.height anchors.left: parent.left anchors.right: clearFilterButton.left - anchors.rightMargin: Math.round(UM.Theme.getSize("sidebar_margin").width) + anchors.rightMargin: Math.round(UM.Theme.getSize("thick_margin").width) - placeholderText: catalog.i18nc("@label:textbox", "Search...") + placeholderText: "" + "
    " + catalog.i18nc("@label:textbox", "search settings") style: TextFieldStyle { - textColor: UM.Theme.getColor("setting_control_text"); - placeholderTextColor: UM.Theme.getColor("setting_control_text") - font: UM.Theme.getFont("default"); + textColor: UM.Theme.getColor("setting_control_text") + placeholderTextColor: UM.Theme.getColor("setting_filter_field") + font: UM.Theme.getFont("default_italic") background: Item {} } @@ -224,38 +85,38 @@ Item onEditingFinished: { - definitionsModel.filter = {"i18n_label": "*" + text}; - findingSettings = (text.length > 0); - if(findingSettings != lastFindingSettings) + definitionsModel.filter = {"i18n_label": "*" + text} + findingSettings = (text.length > 0) + if (findingSettings != lastFindingSettings) { - updateDefinitionModel(); - lastFindingSettings = findingSettings; + updateDefinitionModel() + lastFindingSettings = findingSettings } } Keys.onEscapePressed: { - filter.text = ""; + filter.text = "" } function updateDefinitionModel() { - if(findingSettings) + if (findingSettings) { - expandedCategories = definitionsModel.expanded.slice(); - definitionsModel.expanded = [""]; // keep categories closed while to prevent render while making settings visible one by one - definitionsModel.showAncestors = true; - definitionsModel.showAll = true; - definitionsModel.expanded = ["*"]; + expandedCategories = definitionsModel.expanded.slice() + definitionsModel.expanded = [""] // keep categories closed while to prevent render while making settings visible one by one + definitionsModel.showAncestors = true + definitionsModel.showAll = true + definitionsModel.expanded = ["*"] } else { - if(expandedCategories) + if (expandedCategories) { - definitionsModel.expanded = expandedCategories; + definitionsModel.expanded = expandedCategories } - definitionsModel.showAncestors = false; - definitionsModel.showAll = false; + definitionsModel.showAncestors = false + definitionsModel.showAll = false } } } @@ -287,41 +148,93 @@ Item onClicked: { - filter.text = ""; - filter.forceActiveFocus(); + filter.text = "" + filter.forceActiveFocus() } } } + ToolButton + { + id: settingVisibilityMenu + + anchors + { + top: filterContainer.top + bottom: filterContainer.bottom + right: parent.right + rightMargin: UM.Theme.getSize("wide_margin").width + } + + style: ButtonStyle + { + background: Item + { + UM.RecolorImage + { + anchors.verticalCenter: parent.verticalCenter + anchors.horizontalCenter: parent.horizontalCenter + width: UM.Theme.getSize("standard_arrow").width + height: UM.Theme.getSize("standard_arrow").height + sourceSize.width: width + sourceSize.height: height + color: control.hovered ? UM.Theme.getColor("small_button_text_hover") : UM.Theme.getColor("small_button_text") + source: UM.Theme.getIcon("menu") + } + } + label: Label {} + } + + menu: SettingVisibilityPresetsMenu + { + onShowAllSettings: + { + definitionsModel.setAllVisible(true) + filter.updateDefinitionModel() + } + } + } + + // Mouse area that gathers the scroll events to not propagate it to the main view. + MouseArea + { + anchors.fill: scrollView + acceptedButtons: Qt.AllButtons + onWheel: wheel.accepted = true + } + ScrollView { - anchors.top: filterContainer.bottom; - anchors.bottom: parent.bottom; - anchors.right: parent.right; - anchors.left: parent.left; - anchors.topMargin: filterContainer.visible ? UM.Theme.getSize("sidebar_margin").height : 0 - Behavior on anchors.topMargin { NumberAnimation { duration: 100 } } + id: scrollView + anchors + { + top: filterContainer.bottom + topMargin: UM.Theme.getSize("default_margin").height + bottom: parent.bottom + right: parent.right + left: parent.left + } - style: UM.Theme.styles.scrollview; - flickableItem.flickableDirection: Flickable.VerticalFlick; - __wheelAreaScrollSpeed: 75; // Scroll three lines in one scroll event + style: UM.Theme.styles.scrollview + flickableItem.flickableDirection: Flickable.VerticalFlick + __wheelAreaScrollSpeed: 75 // Scroll three lines in one scroll event ListView { id: contents - spacing: Math.round(UM.Theme.getSize("default_lining").height); - cacheBuffer: 1000000; // Set a large cache to effectively just cache every list item. + spacing: UM.Theme.getSize("default_lining").height + cacheBuffer: 1000000 // Set a large cache to effectively just cache every list item. model: UM.SettingDefinitionsModel { - id: definitionsModel; + id: definitionsModel containerId: Cura.MachineManager.activeDefinitionId visibilityHandler: UM.SettingPreferenceVisibilityHandler { } exclude: ["machine_settings", "command_line_settings", "infill_mesh", "infill_mesh_order", "cutting_mesh", "support_mesh", "anti_overhang_mesh"] // TODO: infill_mesh settigns are excluded hardcoded, but should be based on the fact that settable_globally, settable_per_meshgroup and settable_per_extruder are false. expanded: CuraApplication.expandedCategories onExpandedChanged: { - if(!findingSettings) + if (!findingSettings) { // Do not change expandedCategories preference while filtering settings // because all categories are expanded while filtering @@ -337,7 +250,7 @@ Item { id: delegate - width: Math.round(UM.Theme.getSize("sidebar").width); + width: scrollView.width height: provider.properties.enabled == "True" ? UM.Theme.getSize("section").height : - contents.spacing Behavior on height { NumberAnimation { duration: 100 } } opacity: provider.properties.enabled == "True" ? 1 : 0 @@ -407,17 +320,17 @@ Item // machine gets changed. var activeMachineId = Cura.MachineManager.activeMachineId; - if(!model.settable_per_extruder) + if (!model.settable_per_extruder) { //Not settable per extruder or there only is global, so we must pick global. return activeMachineId; } - if(inheritStackProvider.properties.limit_to_extruder != null && inheritStackProvider.properties.limit_to_extruder >= 0) + if (inheritStackProvider.properties.limit_to_extruder != null && inheritStackProvider.properties.limit_to_extruder >= 0) { //We have limit_to_extruder, so pick that stack. return Cura.ExtruderManager.extruderIds[String(inheritStackProvider.properties.limit_to_extruder)]; } - if(Cura.ExtruderManager.activeExtruderStackId) + if (Cura.ExtruderManager.activeExtruderStackId) { //We're on an extruder tab. Pick the current extruder. return Cura.ExtruderManager.activeExtruderStackId; @@ -458,7 +371,7 @@ Item contextMenu.provider = provider contextMenu.popup(); } - onShowTooltip: base.showTooltip(delegate, { x: -UM.Theme.getSize("default_arrow").width, y: Math.round(delegate.height / 2) }, text) + onShowTooltip: base.showTooltip(delegate, Qt.point(- settingsView.x - UM.Theme.getSize("default_margin").width, 0), text) onHideTooltip: base.hideTooltip() onShowAllHiddenInheritedSettings: { @@ -479,14 +392,14 @@ Item } onSetActiveFocusToNextSetting: { - if(forward == undefined || forward) + if (forward == undefined || forward) { contents.currentIndex = contents.indexWithFocus + 1; while(contents.currentItem && contents.currentItem.height <= 0) { contents.currentIndex++; } - if(contents.currentItem) + if (contents.currentItem) { contents.currentItem.item.focusItem.forceActiveFocus(); } @@ -498,7 +411,7 @@ Item { contents.currentIndex--; } - if(contents.currentItem) + if (contents.currentItem) { contents.currentItem.item.focusItem.forceActiveFocus(); } diff --git a/resources/qml/SidebarAdvanced.qml b/resources/qml/SidebarAdvanced.qml deleted file mode 100644 index ff5f545c80..0000000000 --- a/resources/qml/SidebarAdvanced.qml +++ /dev/null @@ -1,10 +0,0 @@ -// Copyright (c) 2015 Ultimaker B.V. -// Cura is released under the terms of the LGPLv3 or higher. - -import QtQuick 2.7 -import QtQuick.Controls 2.0 - -import "Settings" - -SettingView { -} diff --git a/resources/qml/SidebarContents.qml b/resources/qml/SidebarContents.qml deleted file mode 100644 index 0b19bfe3c1..0000000000 --- a/resources/qml/SidebarContents.qml +++ /dev/null @@ -1,43 +0,0 @@ -// Copyright (c) 2016 Ultimaker B.V. -// Cura is released under the terms of the LGPLv3 or higher. - -import QtQuick 2.7 -import QtQuick.Controls 1.1 -import QtQuick.Controls.Styles 1.1 -import QtQuick.Layouts 1.1 - -import UM 1.2 as UM -import Cura 1.0 as Cura - -StackView -{ - id: sidebarContents - - delegate: StackViewDelegate - { - function transitionFinished(properties) - { - properties.exitItem.opacity = 1 - } - - pushTransition: StackViewTransition - { - PropertyAnimation - { - target: enterItem - property: "opacity" - from: 0 - to: 1 - duration: 100 - } - PropertyAnimation - { - target: exitItem - property: "opacity" - from: 1 - to: 0 - duration: 100 - } - } - } -} \ No newline at end of file diff --git a/resources/qml/SidebarHeader.qml b/resources/qml/SidebarHeader.qml deleted file mode 100644 index 5fde199cd0..0000000000 --- a/resources/qml/SidebarHeader.qml +++ /dev/null @@ -1,617 +0,0 @@ -// Copyright (c) 2017 Ultimaker B.V. -// Cura is released under the terms of the LGPLv3 or higher. - -import QtQuick 2.7 -import QtQuick.Controls 1.1 -import QtQuick.Controls.Styles 1.1 - -import UM 1.2 as UM -import Cura 1.0 as Cura - -import "Menus" - -Column -{ - id: base; - - property int currentExtruderIndex: Cura.ExtruderManager.activeExtruderIndex; - property bool currentExtruderVisible: extrudersList.visible; - property bool printerConnected: Cura.MachineManager.printerConnected - property bool hasManyPrinterTypes: - { - if (printerConnected) - { - if (Cura.MachineManager.printerOutputDevices[0].connectedPrintersTypeCount != null) - { - return Cura.MachineManager.printerOutputDevices[0].connectedPrintersTypeCount.length > 1; - } - } - return false; - } - property bool buildplateCompatibilityError: !Cura.MachineManager.variantBuildplateCompatible && !Cura.MachineManager.variantBuildplateUsable - property bool buildplateCompatibilityWarning: Cura.MachineManager.variantBuildplateUsable - - spacing: Math.round(UM.Theme.getSize("sidebar_margin").width * 0.9) - - signal showTooltip(Item item, point location, string text) - signal hideTooltip() - - Item - { - id: initialSeparator - anchors - { - left: parent.left - right: parent.right - } - visible: printerTypeSelectionRow.visible || buildplateRow.visible || extruderSelectionRow.visible - height: UM.Theme.getSize("default_lining").height - width: height - } - - // Printer Type Row - Item - { - id: printerTypeSelectionRow - height: UM.Theme.getSize("sidebar_setup").height - visible: printerConnected && hasManyPrinterTypes && !sidebar.hideSettings - - anchors - { - left: parent.left - leftMargin: UM.Theme.getSize("sidebar_margin").width - right: parent.right - rightMargin: UM.Theme.getSize("sidebar_margin").width - } - - Label - { - id: configurationLabel - text: catalog.i18nc("@label", "Printer type"); - width: Math.round(parent.width * 0.4 - UM.Theme.getSize("default_margin").width) - height: parent.height - verticalAlignment: Text.AlignVCenter - font: UM.Theme.getFont("default"); - color: UM.Theme.getColor("text"); - } - - ToolButton - { - id: printerTypeSelection - text: Cura.MachineManager.activeMachineDefinitionName - tooltip: Cura.MachineManager.activeMachineDefinitionName - height: UM.Theme.getSize("setting_control").height - width: Math.round(parent.width * 0.7) + UM.Theme.getSize("sidebar_margin").width - anchors.right: parent.right - style: UM.Theme.styles.sidebar_header_button - activeFocusOnPress: true; - - menu: PrinterTypeMenu { } - } - } - - Rectangle { - id: headerSeparator - width: parent.width - visible: printerTypeSelectionRow.visible - height: visible ? UM.Theme.getSize("sidebar_lining").height : 0 - color: UM.Theme.getColor("sidebar_lining") - } - - // Extruder Row - Item - { - id: extruderSelectionRow - width: parent.width - height: Math.round(UM.Theme.getSize("sidebar_tabs").height * 2 / 3) - visible: machineExtruderCount.properties.value > 1 - - anchors - { - left: parent.left - leftMargin: Math.round(UM.Theme.getSize("sidebar_margin").width * 0.7) - right: parent.right - rightMargin: Math.round(UM.Theme.getSize("sidebar_margin").width * 0.7) - topMargin: UM.Theme.getSize("sidebar_margin").height - } - - ListView - { - id: extrudersList - property var index: 0 - - height: UM.Theme.getSize("sidebar_header_mode_tabs").height - width: Math.round(parent.width) - boundsBehavior: Flickable.StopAtBounds - - anchors - { - left: parent.left - leftMargin: Math.round(UM.Theme.getSize("default_margin").width / 2) - right: parent.right - rightMargin: Math.round(UM.Theme.getSize("default_margin").width / 2) - verticalCenter: parent.verticalCenter - } - - ExclusiveGroup { id: extruderMenuGroup; } - - orientation: ListView.Horizontal - - model: Cura.ExtrudersModel { id: extrudersModel; } - - Connections - { - target: Cura.MachineManager - onGlobalContainerChanged: forceActiveFocus() // Changing focus applies the currently-being-typed values so it can change the displayed setting values. - } - - delegate: Button - { - height: ListView.view.height - width: Math.round(ListView.view.width / extrudersModel.rowCount()) - - text: model.name - tooltip: model.name - exclusiveGroup: extruderMenuGroup - checked: base.currentExtruderIndex == index - - property bool extruder_enabled: true - - MouseArea - { - anchors.fill: parent - acceptedButtons: Qt.LeftButton | Qt.RightButton - onClicked: { - switch (mouse.button) { - case Qt.LeftButton: - extruder_enabled = Cura.MachineManager.getExtruder(model.index).isEnabled - if (extruder_enabled) - { - forceActiveFocus(); // Changing focus applies the currently-being-typed values so it can change the displayed setting values. - Cura.ExtruderManager.setActiveExtruderIndex(index); - } - break; - case Qt.RightButton: - extruder_enabled = Cura.MachineManager.getExtruder(model.index).isEnabled - extruderMenu.popup(); - break; - } - - } - } - - Menu - { - id: extruderMenu - - MenuItem { - text: catalog.i18nc("@action:inmenu", "Enable Extruder") - onTriggered: Cura.MachineManager.setExtruderEnabled(model.index, true) - visible: !extruder_enabled // using an intermediate variable prevents an empty popup that occured now and then - } - - MenuItem { - text: catalog.i18nc("@action:inmenu", "Disable Extruder") - onTriggered: Cura.MachineManager.setExtruderEnabled(model.index, false) - visible: extruder_enabled - enabled: Cura.MachineManager.numberExtrudersEnabled > 1 - } - } - - style: ButtonStyle - { - background: Item - { - function buttonBackgroundColor(index) - { - var extruder = Cura.MachineManager.getExtruder(index) - if (extruder.isEnabled) { - return (control.checked || control.pressed) ? UM.Theme.getColor("action_button_active") : - control.hovered ? UM.Theme.getColor("action_button_hovered") : - UM.Theme.getColor("action_button") - } else { - return UM.Theme.getColor("action_button_disabled") - } - } - - function buttonBorderColor(index) - { - var extruder = Cura.MachineManager.getExtruder(index) - if (extruder.isEnabled) { - return (control.checked || control.pressed) ? UM.Theme.getColor("action_button_active_border") : - control.hovered ? UM.Theme.getColor("action_button_hovered_border") : - UM.Theme.getColor("action_button_border") - } else { - return UM.Theme.getColor("action_button_disabled_border") - } - } - - function buttonColor(index) { - var extruder = Cura.MachineManager.getExtruder(index); - if (extruder.isEnabled) - { - return ( - control.checked || control.pressed) ? UM.Theme.getColor("action_button_active_text") : - control.hovered ? UM.Theme.getColor("action_button_hovered_text") : - UM.Theme.getColor("action_button_text"); - } else { - return UM.Theme.getColor("action_button_disabled_text"); - } - } - - Rectangle - { - anchors.fill: parent - border.width: control.checked ? UM.Theme.getSize("default_lining").width * 2 : UM.Theme.getSize("default_lining").width - border.color: buttonBorderColor(index) - color: buttonBackgroundColor(index) - Behavior on color { ColorAnimation { duration: 50; } } - } - - Item - { - id: extruderButtonFace - anchors.centerIn: parent - - width: { - var extruderTextWidth = extruderStaticText.visible ? extruderStaticText.width : 0; - var iconWidth = extruderIconItem.width; - return Math.round(extruderTextWidth + iconWidth + UM.Theme.getSize("default_margin").width / 2); - } - - // Static text "Extruder" - Label - { - id: extruderStaticText - anchors.verticalCenter: parent.verticalCenter - anchors.left: parent.left - - color: buttonColor(index) - - font: UM.Theme.getFont("large_nonbold") - text: catalog.i18nc("@label", "Extruder") - visible: width < (control.width - extruderIconItem.width - UM.Theme.getSize("default_margin").width) - elide: Text.ElideRight - } - - // Everything for the extruder icon - Item - { - id: extruderIconItem - anchors.verticalCenter: parent.verticalCenter - anchors.right: parent.right - - property var sizeToUse: - { - var minimumWidth = control.width < UM.Theme.getSize("button").width ? control.width : UM.Theme.getSize("button").width; - var minimumHeight = control.height < UM.Theme.getSize("button").height ? control.height : UM.Theme.getSize("button").height; - var minimumSize = minimumWidth < minimumHeight ? minimumWidth : minimumHeight; - minimumSize -= Math.round(UM.Theme.getSize("default_margin").width / 2); - return minimumSize; - } - - width: sizeToUse - height: sizeToUse - - UM.RecolorImage { - id: mainCircle - anchors.fill: parent - - sourceSize.width: parent.width - sourceSize.height: parent.width - source: UM.Theme.getIcon("extruder_button") - - color: extruderNumberText.color - } - - Label - { - id: extruderNumberText - anchors.centerIn: parent - text: index + 1; - color: buttonColor(index) - font: UM.Theme.getFont("default_bold") - } - - // Material colour circle - // Only draw the filling colour of the material inside the SVG border. - Rectangle - { - id: materialColorCircle - - anchors - { - right: parent.right - top: parent.top - rightMargin: Math.round(parent.sizeToUse * 0.01) - topMargin: Math.round(parent.sizeToUse * 0.05) - } - - color: model.color - - width: Math.round(parent.width * 0.35) - height: Math.round(parent.height * 0.35) - radius: Math.round(width / 2) - - border.width: 1 - border.color: UM.Theme.getColor("extruder_button_material_border") - - opacity: !control.checked ? 0.6 : 1.0 - } - } - } - } - label: Item {} - } - } - } - } - - Item - { - id: variantRowSpacer - height: Math.round(UM.Theme.getSize("sidebar_margin").height / 4) - width: height - visible: !extruderSelectionRow.visible && !initialSeparator.visible - } - - // Material Row - Item - { - id: materialRow - height: UM.Theme.getSize("sidebar_setup").height - visible: Cura.MachineManager.hasMaterials && !sidebar.hideSettings - - anchors - { - left: parent.left - leftMargin: UM.Theme.getSize("sidebar_margin").width - right: parent.right - rightMargin: UM.Theme.getSize("sidebar_margin").width - } - - Label - { - id: materialLabel - text: catalog.i18nc("@label", "Material"); - width: Math.round(parent.width * 0.45 - UM.Theme.getSize("default_margin").width) - height: parent.height - verticalAlignment: Text.AlignVCenter - font: UM.Theme.getFont("default"); - color: UM.Theme.getColor("text"); - } - - ToolButton - { - id: materialSelection - - property var activeExtruder: Cura.MachineManager.activeStack - property var hasActiveExtruder: activeExtruder != null - property var currentRootMaterialName: hasActiveExtruder ? activeExtruder.material.name : "" - - text: currentRootMaterialName - tooltip: currentRootMaterialName - visible: Cura.MachineManager.hasMaterials - enabled: !extrudersList.visible || base.currentExtruderIndex > -1 - height: UM.Theme.getSize("setting_control").height - width: Math.round(parent.width * 0.7) + UM.Theme.getSize("sidebar_margin").width - anchors.right: parent.right - style: UM.Theme.styles.sidebar_header_button - activeFocusOnPress: true; - menu: MaterialMenu - { - extruderIndex: base.currentExtruderIndex - } - - property var valueError: !isMaterialSupported() - property var valueWarning: ! Cura.MachineManager.isActiveQualitySupported - - function isMaterialSupported () - { - if (!hasActiveExtruder) - { - return false; - } - return Cura.ContainerManager.getContainerMetaDataEntry(activeExtruder.material.id, "compatible", "") == "True" - } - } - } - - //Variant row - Item - { - id: variantRow - height: UM.Theme.getSize("sidebar_setup").height - visible: Cura.MachineManager.hasVariants && !sidebar.hideSettings - - anchors - { - left: parent.left - leftMargin: UM.Theme.getSize("sidebar_margin").width - right: parent.right - rightMargin: UM.Theme.getSize("sidebar_margin").width - } - - Label - { - id: variantLabel - text: Cura.MachineManager.activeDefinitionVariantsName; - width: Math.round(parent.width * 0.45 - UM.Theme.getSize("default_margin").width) - height: parent.height - verticalAlignment: Text.AlignVCenter - font: UM.Theme.getFont("default"); - color: UM.Theme.getColor("text"); - } - - ToolButton - { - id: variantSelection - text: Cura.MachineManager.activeVariantName - tooltip: Cura.MachineManager.activeVariantName; - visible: Cura.MachineManager.hasVariants - - height: UM.Theme.getSize("setting_control").height - width: Math.round(parent.width * 0.7 + UM.Theme.getSize("sidebar_margin").width) - anchors.right: parent.right - style: UM.Theme.styles.sidebar_header_button - activeFocusOnPress: true; - - menu: NozzleMenu { extruderIndex: base.currentExtruderIndex } - } - } - - Rectangle - { - id: buildplateSeparator - anchors.left: parent.left - anchors.leftMargin: UM.Theme.getSize("sidebar_margin").width - width: parent.width - 2 * UM.Theme.getSize("sidebar_margin").width - visible: buildplateRow.visible - height: visible ? UM.Theme.getSize("sidebar_lining_thin").height : 0 - color: UM.Theme.getColor("sidebar_lining") - } - - //Buildplate row - Item - { - id: buildplateRow - height: UM.Theme.getSize("sidebar_setup").height - // TODO Only show in dev mode. Remove check when feature ready - visible: CuraSDKVersion == "dev" ? Cura.MachineManager.hasVariantBuildplates && !sidebar.hideSettings : false - - anchors - { - left: parent.left - leftMargin: UM.Theme.getSize("sidebar_margin").width - right: parent.right - rightMargin: UM.Theme.getSize("sidebar_margin").width - } - - Label - { - id: buildplateLabel - text: catalog.i18nc("@label", "Build plate"); - width: Math.floor(parent.width * 0.45 - UM.Theme.getSize("default_margin").width) - height: parent.height - verticalAlignment: Text.AlignVCenter - font: UM.Theme.getFont("default"); - color: UM.Theme.getColor("text"); - } - - ToolButton - { - id: buildplateSelection - text: Cura.MachineManager.activeVariantBuildplateName - tooltip: Cura.MachineManager.activeVariantBuildplateName - visible: Cura.MachineManager.hasVariantBuildplates - - height: UM.Theme.getSize("setting_control").height - width: Math.floor(parent.width * 0.7 + UM.Theme.getSize("sidebar_margin").width) - anchors.right: parent.right - style: UM.Theme.styles.sidebar_header_button - activeFocusOnPress: true; - - menu: BuildplateMenu {} - - property var valueError: !Cura.MachineManager.variantBuildplateCompatible && !Cura.MachineManager.variantBuildplateUsable - property var valueWarning: Cura.MachineManager.variantBuildplateUsable - } - } - - // Material info row - Item - { - id: materialInfoRow - height: Math.round(UM.Theme.getSize("sidebar_setup").height / 2) - visible: (Cura.MachineManager.hasVariants || Cura.MachineManager.hasMaterials || Cura.MachineManager.hasVariantBuildplates) && !sidebar.hideSettings - - anchors - { - left: parent.left - leftMargin: UM.Theme.getSize("sidebar_margin").width - right: parent.right - rightMargin: UM.Theme.getSize("sidebar_margin").width - } - - // TODO This was added to replace the buildplate selector. Remove this component when the feature is ready - Label - { - id: materialCompatibilityLabel - y: -Math.round(UM.Theme.getSize("sidebar_margin").height / 3) - anchors.left: parent.left - width: parent.width - materialCompatibilityLink.width - text: catalog.i18nc("@label", "Use glue with this material combination") - font: UM.Theme.getFont("very_small") - color: UM.Theme.getColor("text") - visible: CuraSDKVersion == "dev" ? false : buildplateCompatibilityError || buildplateCompatibilityWarning - wrapMode: Text.WordWrap - opacity: 0.5 - } - - Item - { - id: materialCompatibilityLink - height: UM.Theme.getSize("sidebar_setup").height - anchors.right: parent.right - width: childrenRect.width + UM.Theme.getSize("default_margin").width - - UM.RecolorImage { - id: warningImage - anchors.right: materialInfoLabel.left - anchors.rightMargin: UM.Theme.getSize("default_margin").width - anchors.verticalCenter: parent.Bottom - source: UM.Theme.getIcon("warning") - width: UM.Theme.getSize("section_icon").width - height: UM.Theme.getSize("section_icon").height - sourceSize.width: width - sourceSize.height: height - color: UM.Theme.getColor("material_compatibility_warning") - visible: !Cura.MachineManager.isCurrentSetupSupported || buildplateCompatibilityError || buildplateCompatibilityWarning - } - - Label { - id: materialInfoLabel - wrapMode: Text.WordWrap - text: "" + catalog.i18nc("@label", "Check compatibility") + "" - font: UM.Theme.getFont("default") - color: UM.Theme.getColor("text") - linkColor: UM.Theme.getColor("text_link") - verticalAlignment: Text.AlignTop - anchors.top: parent.top - anchors.right: parent.right - anchors.bottom: parent.bottom - - MouseArea { - anchors.fill: parent - hoverEnabled: true - onClicked: { - // open the material URL with web browser - var url = "https://ultimaker.com/incoming-links/cura/material-compatibilty" - Qt.openUrlExternally(url); - } - onEntered: { - var content = catalog.i18nc("@tooltip", "Click to check the material compatibility on Ultimaker.com."); - base.showTooltip( - materialInfoRow, - Qt.point(-UM.Theme.getSize("sidebar_margin").width, 0), - catalog.i18nc("@tooltip", content) - ); - } - onExited: base.hideTooltip(); - } - } - } - } - - UM.SettingPropertyProvider - { - id: machineExtruderCount - - containerStack: Cura.MachineManager.activeMachine - key: "machine_extruder_count" - watchedProperties: [ "value" ] - storeIndex: 0 - } - - UM.I18nCatalog { id: catalog; name:"cura" } -} diff --git a/resources/qml/SidebarSimple.qml b/resources/qml/SidebarSimple.qml deleted file mode 100644 index ddb42f44c6..0000000000 --- a/resources/qml/SidebarSimple.qml +++ /dev/null @@ -1,1168 +0,0 @@ -// Copyright (c) 2018 Ultimaker B.V. -// Cura is released under the terms of the LGPLv3 or higher. - -import QtQuick 2.7 -import QtQuick.Controls 1.4 -import QtQuick.Controls.Styles 1.4 -import QtQuick.Layouts 1.3 - -import UM 1.2 as UM -import Cura 1.0 as Cura - -Item -{ - id: base - - signal showTooltip(Item item, point location, string text); - signal hideTooltip(); - - property Action configureSettings; - property variant minimumPrintTime: PrintInformation.minimumPrintTime; - property variant maximumPrintTime: PrintInformation.maximumPrintTime; - property bool settingsEnabled: Cura.ExtruderManager.activeExtruderStackId || extrudersEnabledCount.properties.value == 1 - Component.onCompleted: PrintInformation.enabled = true - Component.onDestruction: PrintInformation.enabled = false - UM.I18nCatalog { id: catalog; name: "cura" } - - ScrollView - { - visible: Cura.MachineManager.activeMachineName != "" // If no printers added then the view is invisible - anchors.fill: parent - style: UM.Theme.styles.scrollview - flickableItem.flickableDirection: Flickable.VerticalFlick - - Rectangle - { - width: childrenRect.width - height: childrenRect.height - color: UM.Theme.getColor("sidebar") - - // - // Quality profile - // - Item - { - id: qualityRow - - height: UM.Theme.getSize("sidebar_margin").height - anchors.topMargin: UM.Theme.getSize("sidebar_margin").height - anchors.left: parent.left - anchors.leftMargin: UM.Theme.getSize("sidebar_margin").width - anchors.right: parent.right - - Timer - { - id: qualitySliderChangeTimer - interval: 50 - running: false - repeat: false - onTriggered: - { - var item = Cura.QualityProfilesDropDownMenuModel.getItem(qualitySlider.value); - Cura.MachineManager.activeQualityGroup = item.quality_group; - } - } - - Component.onCompleted: qualityModel.update() - - Connections - { - target: Cura.QualityProfilesDropDownMenuModel - onItemsChanged: qualityModel.update() - } - - Connections { - target: base - onVisibleChanged: - { - // update needs to be called when the widgets are visible, otherwise the step width calculation - // will fail because the width of an invisible item is 0. - if (visible) - { - qualityModel.update(); - } - } - } - - ListModel - { - id: qualityModel - - property var totalTicks: 0 - property var availableTotalTicks: 0 - property var existingQualityProfile: 0 - - property var qualitySliderActiveIndex: 0 - property var qualitySliderStepWidth: 0 - property var qualitySliderAvailableMin: 0 - property var qualitySliderAvailableMax: 0 - property var qualitySliderMarginRight: 0 - - function update () - { - reset() - - var availableMin = -1 - var availableMax = -1 - - for (var i = 0; i < Cura.QualityProfilesDropDownMenuModel.rowCount(); i++) - { - var qualityItem = Cura.QualityProfilesDropDownMenuModel.getItem(i) - - // Add each quality item to the UI quality model - qualityModel.append(qualityItem) - - // Set selected value - if (Cura.MachineManager.activeQualityType == qualityItem.quality_type) - { - // set to -1 when switching to user created profile so all ticks are clickable - if (Cura.SimpleModeSettingsManager.isProfileUserCreated) - { - qualityModel.qualitySliderActiveIndex = -1 - } - else - { - qualityModel.qualitySliderActiveIndex = i - } - - qualityModel.existingQualityProfile = 1 - } - - // Set min available - if (qualityItem.available && availableMin == -1) - { - availableMin = i - } - - // Set max available - if (qualityItem.available) - { - availableMax = i - } - } - - // Set total available ticks for active slider part - if (availableMin != -1) - { - qualityModel.availableTotalTicks = availableMax - availableMin + 1 - } - - // Calculate slider values - calculateSliderStepWidth(qualityModel.totalTicks) - calculateSliderMargins(availableMin, availableMax, qualityModel.totalTicks) - - qualityModel.qualitySliderAvailableMin = availableMin - qualityModel.qualitySliderAvailableMax = availableMax - } - - function calculateSliderStepWidth (totalTicks) - { - qualityModel.qualitySliderStepWidth = totalTicks != 0 ? Math.round((base.width * 0.55) / (totalTicks)) : 0 - } - - function calculateSliderMargins (availableMin, availableMax, totalTicks) - { - if (availableMin == -1 || (availableMin == 0 && availableMax == 0)) - { - qualityModel.qualitySliderMarginRight = Math.round(base.width * 0.55) - } - else if (availableMin == availableMax) - { - qualityModel.qualitySliderMarginRight = Math.round((totalTicks - availableMin) * qualitySliderStepWidth) - } - else - { - qualityModel.qualitySliderMarginRight = Math.round((totalTicks - availableMax) * qualitySliderStepWidth) - } - } - - function reset () { - qualityModel.clear() - qualityModel.availableTotalTicks = 0 - qualityModel.existingQualityProfile = 0 - - // check, the ticks count cannot be less than zero - qualityModel.totalTicks = Math.max(0, Cura.QualityProfilesDropDownMenuModel.rowCount() - 1) - } - } - - Label - { - id: qualityRowTitle - text: catalog.i18nc("@label", "Layer Height") - font: UM.Theme.getFont("default") - color: UM.Theme.getColor("text") - } - - // Show titles for the each quality slider ticks - Item - { - y: -5; - anchors.left: speedSlider.left - Repeater - { - model: qualityModel - - Label - { - anchors.verticalCenter: parent.verticalCenter - anchors.top: parent.top - anchors.topMargin: Math.round(UM.Theme.getSize("sidebar_margin").height / 2) - color: (Cura.MachineManager.activeMachine != null && Cura.QualityProfilesDropDownMenuModel.getItem(index).available) ? UM.Theme.getColor("quality_slider_available") : UM.Theme.getColor("quality_slider_unavailable") - text: - { - var result = "" - if(Cura.MachineManager.activeMachine != null) - { - result = Cura.QualityProfilesDropDownMenuModel.getItem(index).layer_height - - if(result == undefined) - { - result = ""; - } - else - { - result = Number(Math.round(result + "e+2") + "e-2"); //Round to 2 decimals. Javascript makes this difficult... - if (result == undefined || result != result) //Parse failure. - { - result = ""; - } - } - } - return result - } - - x: - { - // Make sure the text aligns correctly with each tick - if (qualityModel.totalTicks == 0) - { - // If there is only one tick, align it centrally - return Math.round(((base.width * 0.55) - width) / 2) - } - else if (index == 0) - { - return Math.round(base.width * 0.55 / qualityModel.totalTicks) * index - } - else if (index == qualityModel.totalTicks) - { - return Math.round(base.width * 0.55 / qualityModel.totalTicks) * index - width - } - else - { - return Math.round((base.width * 0.55 / qualityModel.totalTicks) * index - (width / 2)) - } - } - } - } - } - - //Print speed slider - Item - { - id: speedSlider - width: Math.round(base.width * 0.55) - height: UM.Theme.getSize("sidebar_margin").height - anchors.right: parent.right - anchors.top: parent.top - anchors.topMargin: UM.Theme.getSize("sidebar_margin").height - - // This Item is used only for tooltip, for slider area which is unavailable - Item - { - function showTooltip (showTooltip) - { - if (showTooltip) - { - var content = catalog.i18nc("@tooltip", "This quality profile is not available for you current material and nozzle configuration. Please change these to enable this quality profile") - base.showTooltip(qualityRow, Qt.point(-UM.Theme.getSize("sidebar_margin").width, customisedSettings.height), content) - } - else - { - base.hideTooltip() - } - } - - id: unavailableLineToolTip - height: 20 * screenScaleFactor // hovered area height - z: parent.z + 1 // should be higher, otherwise the area can be hovered - x: 0 - anchors.verticalCenter: qualitySlider.verticalCenter - - Rectangle - { - id: leftArea - width: - { - if (qualityModel.availableTotalTicks == 0) - { - return qualityModel.qualitySliderStepWidth * qualityModel.totalTicks - } - return qualityModel.qualitySliderStepWidth * qualityModel.qualitySliderAvailableMin - 10 - } - height: parent.height - color: "transparent" - - MouseArea - { - anchors.fill: parent - hoverEnabled: true - enabled: Cura.SimpleModeSettingsManager.isProfileUserCreated == false - onEntered: unavailableLineToolTip.showTooltip(true) - onExited: unavailableLineToolTip.showTooltip(false) - } - } - - Rectangle - { - id: rightArea - width: - { - if(qualityModel.availableTotalTicks == 0) - return 0 - - return qualityModel.qualitySliderMarginRight - 10 - } - height: parent.height - color: "transparent" - x: - { - if (qualityModel.availableTotalTicks == 0) - { - return 0 - } - - var leftUnavailableArea = qualityModel.qualitySliderStepWidth * qualityModel.qualitySliderAvailableMin - var totalGap = qualityModel.qualitySliderStepWidth * (qualityModel.availableTotalTicks -1) + leftUnavailableArea + 10 - - return totalGap - } - - MouseArea - { - anchors.fill: parent - hoverEnabled: true - enabled: Cura.SimpleModeSettingsManager.isProfileUserCreated == false - onEntered: unavailableLineToolTip.showTooltip(true) - onExited: unavailableLineToolTip.showTooltip(false) - } - } - } - - // Draw Unavailable line - Rectangle - { - id: groovechildrect - width: Math.round(base.width * 0.55) - height: 2 * screenScaleFactor - color: UM.Theme.getColor("quality_slider_unavailable") - anchors.verticalCenter: qualitySlider.verticalCenter - x: 0 - } - - // Draw ticks - Repeater - { - id: qualityRepeater - model: qualityModel.totalTicks > 0 ? qualityModel : 0 - - Rectangle - { - anchors.verticalCenter: parent.verticalCenter - color: Cura.QualityProfilesDropDownMenuModel.getItem(index).available ? UM.Theme.getColor("quality_slider_available") : UM.Theme.getColor("quality_slider_unavailable") - width: 1 * screenScaleFactor - height: 6 * screenScaleFactor - y: 0 - x: Math.round(qualityModel.qualitySliderStepWidth * index) - } - } - - Slider - { - id: qualitySlider - height: UM.Theme.getSize("sidebar_margin").height - anchors.bottom: speedSlider.bottom - enabled: qualityModel.totalTicks > 0 && !Cura.SimpleModeSettingsManager.isProfileCustomized - visible: qualityModel.availableTotalTicks > 0 - updateValueWhileDragging : false - - minimumValue: qualityModel.qualitySliderAvailableMin >= 0 ? qualityModel.qualitySliderAvailableMin : 0 - // maximumValue must be greater than minimumValue to be able to see the handle. While the value is strictly - // speaking not always correct, it seems to have the correct behavior (switching from 0 available to 1 available) - maximumValue: qualityModel.qualitySliderAvailableMax >= 1 ? qualityModel.qualitySliderAvailableMax : 1 - stepSize: 1 - - value: qualityModel.qualitySliderActiveIndex - - width: qualityModel.qualitySliderStepWidth * (qualityModel.availableTotalTicks - 1) - - anchors.right: parent.right - anchors.rightMargin: qualityModel.qualitySliderMarginRight - - style: SliderStyle - { - //Draw Available line - groove: Rectangle - { - implicitHeight: 2 * screenScaleFactor - color: UM.Theme.getColor("quality_slider_available") - radius: Math.round(height / 2) - } - handle: Item - { - Rectangle - { - id: qualityhandleButton - anchors.centerIn: parent - color: UM.Theme.getColor("quality_slider_available") - implicitWidth: 10 * screenScaleFactor - implicitHeight: implicitWidth - radius: Math.round(implicitWidth / 2) - visible: !Cura.SimpleModeSettingsManager.isProfileCustomized && !Cura.SimpleModeSettingsManager.isProfileUserCreated && qualityModel.existingQualityProfile - } - } - } - - onValueChanged: - { - // 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.qualitySliderActiveIndex && qualityModel.qualitySliderActiveIndex != -1) - { - // start updating with short delay - qualitySliderChangeTimer.start() - } - } - } - } - - MouseArea - { - id: speedSliderMouseArea - anchors.fill: parent - hoverEnabled: true - enabled: Cura.SimpleModeSettingsManager.isProfileUserCreated - - onEntered: - { - var content = catalog.i18nc("@tooltip","A custom profile is currently active. To enable the quality slider, choose a default quality profile in Custom tab") - base.showTooltip(qualityRow, Qt.point(-UM.Theme.getSize("sidebar_margin").width, customisedSettings.height), content) - } - onExited: - { - base.hideTooltip(); - } - } - } - - Label - { - id: speedLabel - anchors.top: speedSlider.bottom - - anchors.left: parent.left - - text: catalog.i18nc("@label", "Print Speed") - font: UM.Theme.getFont("default") - color: UM.Theme.getColor("text") - width: Math.round(UM.Theme.getSize("sidebar").width * 0.35) - elide: Text.ElideRight - } - - Label - { - anchors.bottom: speedLabel.bottom - anchors.left: speedSlider.left - - text: catalog.i18nc("@label", "Slower") - font: UM.Theme.getFont("default") - color: (qualityModel.availableTotalTicks > 1) ? UM.Theme.getColor("quality_slider_available") : UM.Theme.getColor("quality_slider_unavailable") - horizontalAlignment: Text.AlignLeft - } - - Label - { - anchors.bottom: speedLabel.bottom - anchors.right: speedSlider.right - - text: catalog.i18nc("@label", "Faster") - font: UM.Theme.getFont("default") - color: (qualityModel.availableTotalTicks > 1) ? UM.Theme.getColor("quality_slider_available") : UM.Theme.getColor("quality_slider_unavailable") - horizontalAlignment: Text.AlignRight - } - - UM.SimpleButton - { - id: customisedSettings - - visible: Cura.SimpleModeSettingsManager.isProfileCustomized || Cura.SimpleModeSettingsManager.isProfileUserCreated - height: Math.round(speedSlider.height * 0.8) - width: Math.round(speedSlider.height * 0.8) - - anchors.verticalCenter: speedSlider.verticalCenter - anchors.right: speedSlider.left - anchors.rightMargin: Math.round(UM.Theme.getSize("sidebar_margin").width / 2) - - color: hovered ? UM.Theme.getColor("setting_control_button_hover") : UM.Theme.getColor("setting_control_button"); - iconSource: UM.Theme.getIcon("reset"); - - onClicked: - { - // if the current profile is user-created, switch to a built-in quality - Cura.MachineManager.resetToUseDefaultQuality() - } - onEntered: - { - var content = catalog.i18nc("@tooltip","You have modified some profile settings. If you want to change these go to custom mode.") - base.showTooltip(qualityRow, Qt.point(-UM.Theme.getSize("sidebar_margin").width, customisedSettings.height), content) - } - onExited: base.hideTooltip() - } - } - - // - // Infill - // - Item - { - id: infillCellLeft - - anchors.top: qualityRow.bottom - anchors.topMargin: UM.Theme.getSize("sidebar_margin").height * 2 - anchors.left: parent.left - - width: Math.round(UM.Theme.getSize("sidebar").width * .45) - UM.Theme.getSize("sidebar_margin").width - - Label - { - id: infillLabel - text: catalog.i18nc("@label", "Infill") - font: UM.Theme.getFont("default") - color: UM.Theme.getColor("text") - - anchors.top: parent.top - anchors.topMargin: Math.round(UM.Theme.getSize("sidebar_margin").height * 1.7) - anchors.left: parent.left - anchors.leftMargin: UM.Theme.getSize("sidebar_margin").width - } - } - - Item - { - id: infillCellRight - - height: infillSlider.height + UM.Theme.getSize("sidebar_margin").height + enableGradualInfillCheckBox.visible * (enableGradualInfillCheckBox.height + UM.Theme.getSize("sidebar_margin").height) - width: Math.round(UM.Theme.getSize("sidebar").width * .55) - - anchors.left: infillCellLeft.right - anchors.top: infillCellLeft.top - anchors.topMargin: UM.Theme.getSize("sidebar_margin").height - - Label { - id: selectedInfillRateText - - //anchors.top: parent.top - anchors.left: infillSlider.left - anchors.leftMargin: Math.round((infillSlider.value / infillSlider.stepSize) * (infillSlider.width / (infillSlider.maximumValue / infillSlider.stepSize)) - 10 * screenScaleFactor) - anchors.right: parent.right - - text: parseInt(infillDensity.properties.value) + "%" - horizontalAlignment: Text.AlignLeft - - color: infillSlider.enabled ? UM.Theme.getColor("quality_slider_available") : UM.Theme.getColor("quality_slider_unavailable") - } - - // We use a binding to make sure that after manually setting infillSlider.value it is still bound to the property provider - Binding { - target: infillSlider - property: "value" - value: parseInt(infillDensity.properties.value) - } - - Slider - { - id: infillSlider - - anchors.top: selectedInfillRateText.bottom - anchors.left: parent.left - anchors.right: infillIcon.left - anchors.rightMargin: UM.Theme.getSize("sidebar_margin").width - - height: UM.Theme.getSize("sidebar_margin").height - width: parseInt(infillCellRight.width - UM.Theme.getSize("sidebar_margin").width - style.handleWidth) - - minimumValue: 0 - maximumValue: 100 - stepSize: 1 - tickmarksEnabled: true - - // disable slider when gradual support is enabled - enabled: parseInt(infillSteps.properties.value) == 0 - - // set initial value from stack - value: parseInt(infillDensity.properties.value) - - onValueChanged: { - - // Don't round the value if it's already the same - if (parseInt(infillDensity.properties.value) == infillSlider.value) { - return - } - - // Round the slider value to the nearest multiple of 10 (simulate step size of 10) - var roundedSliderValue = Math.round(infillSlider.value / 10) * 10 - - // Update the slider value to represent the rounded value - infillSlider.value = roundedSliderValue - - // Update value only if the Recomended mode is Active, - // Otherwise if I change the value in the Custom mode the Recomended view will try to repeat - // same operation - var active_mode = UM.Preferences.getValue("cura/active_mode") - - if (active_mode == 0 || active_mode == "simple") - { - Cura.MachineManager.setSettingForAllExtruders("infill_sparse_density", "value", roundedSliderValue) - Cura.MachineManager.resetSettingForAllExtruders("infill_line_distance") - } - } - - style: SliderStyle - { - groove: Rectangle { - id: groove - implicitWidth: 200 * screenScaleFactor - implicitHeight: 2 * screenScaleFactor - color: control.enabled ? UM.Theme.getColor("quality_slider_available") : UM.Theme.getColor("quality_slider_unavailable") - radius: 1 - } - - handle: Item { - Rectangle { - id: handleButton - anchors.centerIn: parent - color: control.enabled ? UM.Theme.getColor("quality_slider_available") : UM.Theme.getColor("quality_slider_unavailable") - implicitWidth: 10 * screenScaleFactor - implicitHeight: 10 * screenScaleFactor - radius: 10 * screenScaleFactor - } - } - - tickmarks: Repeater { - id: repeater - model: control.maximumValue / control.stepSize + 1 - - // check if a tick should be shown based on it's index and wether the infill density is a multiple of 10 (slider step size) - function shouldShowTick (index) { - if (index % 10 == 0) { - return true - } - return false - } - - Rectangle { - anchors.verticalCenter: parent.verticalCenter - color: control.enabled ? UM.Theme.getColor("quality_slider_available") : UM.Theme.getColor("quality_slider_unavailable") - width: 1 * screenScaleFactor - height: 6 * screenScaleFactor - y: 0 - x: Math.round(styleData.handleWidth / 2 + index * ((repeater.width - styleData.handleWidth) / (repeater.count-1))) - visible: shouldShowTick(index) - } - } - } - } - - Rectangle - { - id: infillIcon - - width: Math.round((parent.width / 5) - (UM.Theme.getSize("sidebar_margin").width)) - height: width - - anchors.right: parent.right - anchors.top: parent.top - anchors.topMargin: Math.round(UM.Theme.getSize("sidebar_margin").height / 2) - - // we loop over all density icons and only show the one that has the current density and steps - Repeater - { - id: infillIconList - model: infillModel - anchors.fill: parent - - function activeIndex () { - for (var i = 0; i < infillModel.count; i++) { - var density = Math.round(infillDensity.properties.value) - var steps = Math.round(infillSteps.properties.value) - var infillModelItem = infillModel.get(i) - - if (infillModelItem != "undefined" - && density >= infillModelItem.percentageMin - && density <= infillModelItem.percentageMax - && steps >= infillModelItem.stepsMin - && steps <= infillModelItem.stepsMax - ){ - return i - } - } - return -1 - } - - Rectangle - { - anchors.fill: parent - visible: infillIconList.activeIndex() == index - - border.width: UM.Theme.getSize("default_lining").width - border.color: UM.Theme.getColor("quality_slider_unavailable") - - UM.RecolorImage { - anchors.fill: parent - anchors.margins: 2 * screenScaleFactor - sourceSize.width: width - sourceSize.height: width - source: UM.Theme.getIcon(model.icon) - color: UM.Theme.getColor("quality_slider_unavailable") - } - } - } - } - - // Gradual Support Infill Checkbox - CheckBox { - id: enableGradualInfillCheckBox - property alias _hovered: enableGradualInfillMouseArea.containsMouse - - anchors.top: infillSlider.bottom - anchors.topMargin: Math.round(UM.Theme.getSize("sidebar_margin").height / 2) // closer to slider since it belongs to the same category - anchors.left: infillCellRight.left - - style: UM.Theme.styles.checkbox - enabled: base.settingsEnabled - visible: infillSteps.properties.enabled == "True" - checked: parseInt(infillSteps.properties.value) > 0 - - MouseArea { - id: enableGradualInfillMouseArea - - anchors.fill: parent - hoverEnabled: true - enabled: true - - property var previousInfillDensity: parseInt(infillDensity.properties.value) - - onClicked: { - // Set to 90% only when enabling gradual infill - var newInfillDensity; - if (parseInt(infillSteps.properties.value) == 0) { - previousInfillDensity = parseInt(infillDensity.properties.value) - newInfillDensity = 90; - } else { - newInfillDensity = previousInfillDensity; - } - Cura.MachineManager.setSettingForAllExtruders("infill_sparse_density", "value", String(newInfillDensity)) - - var infill_steps_value = 0; - if (parseInt(infillSteps.properties.value) == 0) - infill_steps_value = 5; - - Cura.MachineManager.setSettingForAllExtruders("gradual_infill_steps", "value", infill_steps_value) - } - - onEntered: { - base.showTooltip(enableGradualInfillCheckBox, Qt.point(-infillCellRight.x, 0), - catalog.i18nc("@label", "Gradual infill will gradually increase the amount of infill towards the top.")) - } - - onExited: { - base.hideTooltip() - } - } - - Label { - id: gradualInfillLabel - height: parent.height - anchors.left: enableGradualInfillCheckBox.right - anchors.leftMargin: Math.round(UM.Theme.getSize("sidebar_margin").width / 2) - verticalAlignment: Text.AlignVCenter; - text: catalog.i18nc("@label", "Enable gradual") - font: UM.Theme.getFont("default") - color: UM.Theme.getColor("text") - } - } - - // Infill list model for mapping icon - ListModel - { - id: infillModel - Component.onCompleted: - { - infillModel.append({ - percentageMin: -1, - percentageMax: 0, - stepsMin: -1, - stepsMax: 0, - icon: "hollow" - }) - infillModel.append({ - percentageMin: 0, - percentageMax: 40, - stepsMin: -1, - stepsMax: 0, - icon: "sparse" - }) - infillModel.append({ - percentageMin: 40, - percentageMax: 89, - stepsMin: -1, - stepsMax: 0, - icon: "dense" - }) - infillModel.append({ - percentageMin: 90, - percentageMax: 9999999999, - stepsMin: -1, - stepsMax: 0, - icon: "solid" - }) - infillModel.append({ - percentageMin: 0, - percentageMax: 9999999999, - stepsMin: 1, - stepsMax: 9999999999, - icon: "gradual" - }) - } - } - } - - // - // Enable support - // - Label - { - id: enableSupportLabel - visible: enableSupportCheckBox.visible - - anchors.top: infillCellRight.bottom - anchors.topMargin: Math.round(UM.Theme.getSize("sidebar_margin").height * 1.5) - 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: enableSupportCheckBox.verticalCenter - - text: catalog.i18nc("@label", "Generate Support"); - font: UM.Theme.getFont("default"); - color: UM.Theme.getColor("text"); - elide: Text.ElideRight - } - - CheckBox - { - id: enableSupportCheckBox - property alias _hovered: enableSupportMouseArea.containsMouse - - anchors.top: enableSupportLabel.top - anchors.left: infillCellRight.left - - style: UM.Theme.styles.checkbox; - enabled: base.settingsEnabled - - visible: supportEnabled.properties.enabled == "True" - checked: supportEnabled.properties.value == "True"; - - MouseArea - { - id: enableSupportMouseArea - anchors.fill: parent - hoverEnabled: true - enabled: true - onClicked: - { - // The value is a string "True" or "False" - supportEnabled.setPropertyValue("value", supportEnabled.properties.value != "True"); - } - onEntered: - { - base.showTooltip(enableSupportCheckBox, Qt.point(-enableSupportCheckBox.x, 0), - catalog.i18nc("@label", "Generate structures to support parts of the model which have overhangs. Without these structures, such parts would collapse during printing.")); - } - onExited: - { - base.hideTooltip(); - } - } - } - - ComboBox - { - id: supportExtruderCombobox - visible: enableSupportCheckBox.visible && (supportEnabled.properties.value == "True") && (extrudersEnabledCount.properties.value > 1) - model: extruderModel - - property string color_override: "" // for manually setting values - property string color: // is evaluated automatically, but the first time is before extruderModel being filled - { - var current_extruder = extruderModel.get(currentIndex); - color_override = ""; - if (current_extruder === undefined) return "" - return (current_extruder.color) ? current_extruder.color : ""; - } - - textRole: "text" // this solves that the combobox isn't populated in the first time Cura is started - - anchors.top: enableSupportCheckBox.top - //anchors.topMargin: ((supportEnabled.properties.value === "True") && (machineExtruderCount.properties.value > 1)) ? UM.Theme.getSize("sidebar_margin").height : 0 - anchors.left: enableSupportCheckBox.right - anchors.leftMargin: Math.round(UM.Theme.getSize("sidebar_margin").width / 2) - - width: Math.round(UM.Theme.getSize("sidebar").width * .55) - Math.round(UM.Theme.getSize("sidebar_margin").width / 2) - enableSupportCheckBox.width - height: ((supportEnabled.properties.value == "True") && (machineExtruderCount.properties.value > 1)) ? UM.Theme.getSize("setting_control").height : 0 - - Behavior on height { NumberAnimation { duration: 100 } } - - style: UM.Theme.styles.combobox_color - enabled: base.settingsEnabled - property alias _hovered: supportExtruderMouseArea.containsMouse - - currentIndex: - { - if (supportExtruderNr.properties == null) - { - return Cura.MachineManager.defaultExtruderPosition; - } - else - { - var extruder = parseInt(supportExtruderNr.properties.value); - if ( extruder === -1) - { - return Cura.MachineManager.defaultExtruderPosition; - } - return extruder; - } - } - - onActivated: - { - // Send the extruder nr as a string. - supportExtruderNr.setPropertyValue("value", String(index)); - } - MouseArea - { - id: supportExtruderMouseArea - anchors.fill: parent - hoverEnabled: true - enabled: base.settingsEnabled - acceptedButtons: Qt.NoButton - onEntered: - { - base.showTooltip(supportExtruderCombobox, Qt.point(-supportExtruderCombobox.x, 0), - catalog.i18nc("@label", "Select which extruder to use for support. This will build up supporting structures below the model to prevent the model from sagging or printing in mid air.")); - } - onExited: - { - base.hideTooltip(); - } - } - - function updateCurrentColor() - { - var current_extruder = extruderModel.get(currentIndex); - if (current_extruder !== undefined) { - supportExtruderCombobox.color_override = current_extruder.color; - } - } - - } - - Label - { - id: adhesionHelperLabel - visible: adhesionCheckBox.visible - - text: catalog.i18nc("@label", "Build Plate Adhesion") - font: UM.Theme.getFont("default") - color: UM.Theme.getColor("text") - elide: Text.ElideRight - - anchors { - left: parent.left - leftMargin: UM.Theme.getSize("sidebar_margin").width - right: infillCellLeft.right - rightMargin: UM.Theme.getSize("sidebar_margin").width - verticalCenter: adhesionCheckBox.verticalCenter - } - } - - CheckBox - { - id: adhesionCheckBox - property alias _hovered: adhesionMouseArea.containsMouse - - anchors.top: enableSupportCheckBox.bottom - anchors.topMargin: UM.Theme.getSize("sidebar_margin").height - anchors.left: infillCellRight.left - - //: Setting enable printing build-plate adhesion helper checkbox - style: UM.Theme.styles.checkbox; - enabled: base.settingsEnabled - - visible: platformAdhesionType.properties.enabled == "True" - checked: platformAdhesionType.properties.value != "skirt" && platformAdhesionType.properties.value != "none" - - MouseArea - { - id: adhesionMouseArea - anchors.fill: parent - hoverEnabled: true - enabled: base.settingsEnabled - onClicked: - { - var adhesionType = "skirt"; - if(!parent.checked) - { - // Remove the "user" setting to see if the rest of the stack prescribes a brim or a raft - platformAdhesionType.removeFromContainer(0); - adhesionType = platformAdhesionType.properties.value; - if(adhesionType == "skirt" || adhesionType == "none") - { - // If the rest of the stack doesn't prescribe an adhesion-type, default to a brim - adhesionType = "brim"; - } - } - platformAdhesionType.setPropertyValue("value", adhesionType); - } - onEntered: - { - base.showTooltip(adhesionCheckBox, Qt.point(-adhesionCheckBox.x, 0), - catalog.i18nc("@label", "Enable printing a brim or raft. This will add a flat area around or under your object which is easy to cut off afterwards.")); - } - onExited: - { - base.hideTooltip(); - } - } - } - - ListModel - { - id: extruderModel - Component.onCompleted: populateExtruderModel() - } - - //: Model used to populate the extrudelModel - Cura.ExtrudersModel - { - id: extruders - onModelChanged: populateExtruderModel() - } - - Item - { - id: tipsCell - anchors.top: adhesionCheckBox.visible ? adhesionCheckBox.bottom : (enableSupportCheckBox.visible ? supportExtruderCombobox.bottom : infillCellRight.bottom) - anchors.topMargin: Math.round(UM.Theme.getSize("sidebar_margin").height * 2) - anchors.left: parent.left - width: parent.width - height: tipsText.contentHeight * tipsText.lineCount - - Label - { - id: tipsText - anchors.left: parent.left - anchors.leftMargin: UM.Theme.getSize("sidebar_margin").width - anchors.right: parent.right - anchors.rightMargin: UM.Theme.getSize("sidebar_margin").width - anchors.top: parent.top - wrapMode: Text.WordWrap - 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") - onLinkActivated: Qt.openUrlExternally(link) - } - } - - UM.SettingPropertyProvider - { - id: infillExtruderNumber - containerStackId: Cura.MachineManager.activeStackId - key: "infill_extruder_nr" - watchedProperties: [ "value" ] - storeIndex: 0 - } - - UM.SettingPropertyProvider - { - id: infillDensity - containerStackId: Cura.MachineManager.activeStackId - key: "infill_sparse_density" - watchedProperties: [ "value" ] - storeIndex: 0 - } - - UM.SettingPropertyProvider - { - id: infillSteps - containerStackId: Cura.MachineManager.activeStackId - key: "gradual_infill_steps" - watchedProperties: ["value", "enabled"] - storeIndex: 0 - } - - UM.SettingPropertyProvider - { - id: platformAdhesionType - containerStack: Cura.MachineManager.activeMachine - removeUnusedValue: false //Doesn't work with settings that are resolved. - key: "adhesion_type" - watchedProperties: [ "value", "enabled" ] - storeIndex: 0 - } - - UM.SettingPropertyProvider - { - id: supportEnabled - containerStack: Cura.MachineManager.activeMachine - key: "support_enable" - watchedProperties: [ "value", "enabled", "description" ] - storeIndex: 0 - } - - UM.SettingPropertyProvider - { - id: extrudersEnabledCount - containerStack: Cura.MachineManager.activeMachine - key: "extruders_enabled_count" - watchedProperties: [ "value" ] - storeIndex: 0 - } - - UM.SettingPropertyProvider - { - id: supportExtruderNr - containerStack: Cura.MachineManager.activeMachine - key: "support_extruder_nr" - watchedProperties: [ "value" ] - storeIndex: 0 - } - } - } - - function populateExtruderModel() - { - extruderModel.clear(); - for(var extruderNumber = 0; extruderNumber < extruders.rowCount() ; extruderNumber++) - { - extruderModel.append({ - text: extruders.getItem(extruderNumber).name, - color: extruders.getItem(extruderNumber).color - }) - } - supportExtruderCombobox.updateCurrentColor(); - } -} diff --git a/resources/qml/Toolbar.qml b/resources/qml/Toolbar.qml index a04b3650df..1e335472d4 100644 --- a/resources/qml/Toolbar.qml +++ b/resources/qml/Toolbar.qml @@ -2,96 +2,162 @@ // Cura is released under the terms of the LGPLv3 or higher. import QtQuick 2.2 -import QtQuick.Controls 1.1 -import QtQuick.Controls.Styles 1.1 -import QtQuick.Layouts 1.1 +import QtQuick.Controls 2.3 import UM 1.2 as UM import Cura 1.0 as Cura Item { - id: base; + id: base - width: buttons.width; + width: buttons.width height: buttons.height property int activeY - Column + Item { - id: buttons; + id: buttons + width: parent.visible ? toolButtons.width : 0 + height: childrenRect.height - anchors.bottom: parent.bottom - anchors.left: parent.left - spacing: UM.Theme.getSize("button_lining").width + Behavior on width { NumberAnimation { duration: 100 } } - Repeater + // Used to create a rounded rectangle behind the toolButtons + Rectangle { - id: repeat - - model: UM.ToolModel { } - width: childrenRect.width - height: childrenRect.height - Button + anchors { - text: model.name + (model.shortcut ? (" (" + model.shortcut + ")") : "") - iconSource: (UM.Theme.getIcon(model.icon) != "") ? UM.Theme.getIcon(model.icon) : "file:///" + model.location + "/" + model.icon - checkable: true - checked: model.active - enabled: model.enabled && UM.Selection.hasSelection && UM.Controller.toolsEnabled - style: UM.Theme.styles.tool_button + fill: toolButtons + leftMargin: -radius - border.width + rightMargin: -border.width + topMargin: -border.width + bottomMargin: -border.width + } + radius: UM.Theme.getSize("default_radius").width + color: UM.Theme.getColor("lining") + } - onCheckedChanged: + Column + { + id: toolButtons + + anchors.top: parent.top + anchors.right: parent.right + spacing: UM.Theme.getSize("default_lining").height + + Repeater + { + id: repeat + + model: UM.ToolModel { id: toolsModel } + width: childrenRect.width + height: childrenRect.height + + delegate: ToolbarButton { - if (checked) + text: model.name + (model.shortcut ? (" (" + model.shortcut + ")") : "") + checkable: true + checked: model.active + enabled: model.enabled && UM.Selection.hasSelection && UM.Controller.toolsEnabled + + isTopElement: toolsModel.getItem(0).id == model.id + isBottomElement: toolsModel.getItem(toolsModel.count - 1).id == model.id + + toolItem: UM.RecolorImage { - base.activeY = y; + source: UM.Theme.getIcon(model.icon) != "" ? UM.Theme.getIcon(model.icon) : "file:///" + model.location + "/" + model.icon + color: UM.Theme.getColor("toolbar_button_text") + + sourceSize: UM.Theme.getSize("button_icon") } - } - //Workaround since using ToolButton's onClicked would break the binding of the checked property, instead - //just catch the click so we do not trigger that behaviour. - MouseArea - { - anchors.fill: parent; - onClicked: + onCheckedChanged: { - forceActiveFocus() //First grab focus, so all the text fields are updated - if(parent.checked) + if (checked) { - UM.Controller.setActiveTool(null); + base.activeY = y; } - else + } + + //Workaround since using ToolButton's onClicked would break the binding of the checked property, instead + //just catch the click so we do not trigger that behaviour. + MouseArea + { + anchors.fill: parent; + onClicked: { - UM.Controller.setActiveTool(model.id); + forceActiveFocus() //First grab focus, so all the text fields are updated + if(parent.checked) + { + UM.Controller.setActiveTool(null); + } + else + { + UM.Controller.setActiveTool(model.id); + } } } } } } - Item { height: UM.Theme.getSize("default_margin").height; width: UM.Theme.getSize("default_lining").width; visible: extruders.count > 0 } - - Repeater + // Used to create a rounded rectangle behind the extruderButtons + Rectangle { - id: extruders - width: childrenRect.width - height: childrenRect.height - property var _model: Cura.ExtrudersModel { id: extrudersModel } - model: _model.items.length > 1 ? _model : 0 - ExtruderButton { extruder: model } + anchors + { + fill: extruderButtons + leftMargin: -radius - border.width + rightMargin: -border.width + topMargin: -border.width + bottomMargin: -border.width + } + radius: UM.Theme.getSize("default_radius").width + color: UM.Theme.getColor("lining") + visible: extrudersModel.items.length > 1 } + + Column + { + id: extruderButtons + + anchors.topMargin: UM.Theme.getSize("default_margin").height + anchors.top: toolButtons.bottom + anchors.right: parent.right + spacing: UM.Theme.getSize("default_lining").height + + Repeater + { + id: extruders + width: childrenRect.width + height: childrenRect.height + model: extrudersModel.items.length > 1 ? extrudersModel : 0 + + delegate: ExtruderButton + { + extruder: model + isTopElement: extrudersModel.getItem(0).id == model.id + isBottomElement: extrudersModel.getItem(extrudersModel.rowCount() - 1).id == model.id + } + } + } + } + + Cura.ExtrudersModel + { + id: extrudersModel } UM.PointingRectangle { - id: panelBorder; + id: panelBorder - anchors.left: parent.right; - anchors.leftMargin: UM.Theme.getSize("default_margin").width; - anchors.top: base.top; + anchors.left: parent.right + anchors.leftMargin: UM.Theme.getSize("default_margin").width + anchors.top: base.top anchors.topMargin: base.activeY - z: buttons.z -1 + z: buttons.z - 1 target: Qt.point(parent.right, base.activeY + Math.round(UM.Theme.getSize("button").height/2)) arrowSize: UM.Theme.getSize("default_arrow").width @@ -100,14 +166,14 @@ Item { if (panel.item && panel.width > 0) { - return Math.max(panel.width + 2 * UM.Theme.getSize("default_margin").width); + return Math.max(panel.width + 2 * UM.Theme.getSize("default_margin").width) } else { return 0; } } - height: panel.item ? panel.height + 2 * UM.Theme.getSize("default_margin").height : 0; + height: panel.item ? panel.height + 2 * UM.Theme.getSize("default_margin").height : 0 opacity: panel.item && panel.width > 0 ? 1 : 0 Behavior on opacity { NumberAnimation { duration: 100 } } @@ -125,11 +191,11 @@ Item { id: panel - x: UM.Theme.getSize("default_margin").width; - y: UM.Theme.getSize("default_margin").height; + x: UM.Theme.getSize("default_margin").width + y: UM.Theme.getSize("default_margin").height source: UM.ActiveTool.valid ? UM.ActiveTool.activeToolPanel : "" - enabled: UM.Controller.toolsEnabled; + enabled: UM.Controller.toolsEnabled } } diff --git a/resources/qml/ToolbarButton.qml b/resources/qml/ToolbarButton.qml new file mode 100644 index 0000000000..adff73fb7c --- /dev/null +++ b/resources/qml/ToolbarButton.qml @@ -0,0 +1,99 @@ +// Copyright (c) 2018 Ultimaker B.V. +// Cura is released under the terms of the LGPLv3 or higher. + +import QtQuick 2.7 +import QtQuick.Controls 2.3 + +import UM 1.2 as UM +import Cura 1.0 as Cura + +Button +{ + id: base + + property alias toolItem: contentItemLoader.sourceComponent + + // These two properties indicate whether the toolbar button is at the top of the toolbar column or at the bottom. + // If it is somewhere in the middle, then both has to be false. If there is only one element in the column, then + // both properties have to be set to true. This is used to create a rounded corner. + property bool isTopElement: false + property bool isBottomElement: false + + hoverEnabled: true + + background: Rectangle + { + implicitWidth: UM.Theme.getSize("button").width + implicitHeight: UM.Theme.getSize("button").height + color: + { + if (base.checked && base.hovered) + { + return UM.Theme.getColor("toolbar_button_active_hover") + } + else if (base.checked) + { + return UM.Theme.getColor("toolbar_button_active") + } + else if(base.hovered) + { + return UM.Theme.getColor("toolbar_button_hover") + } + return UM.Theme.getColor("toolbar_background") + } + radius: UM.Theme.getSize("default_radius").width + + Rectangle + { + id: topSquare + anchors + { + left: parent.left + right: parent.right + top: parent.top + } + height: parent.radius + color: parent.color + visible: !base.isTopElement + } + + Rectangle + { + id: bottomSquare + anchors + { + left: parent.left + right: parent.right + bottom: parent.bottom + } + height: parent.radius + color: parent.color + visible: !base.isBottomElement + } + + Rectangle + { + id: leftSquare + anchors + { + left: parent.left + top: parent.top + bottom: parent.bottom + } + width: parent.radius + color: parent.color + } + } + + contentItem: Item + { + opacity: parent.enabled ? 1.0 : 0.2 + Loader + { + id: contentItemLoader + anchors.centerIn: parent + width: UM.Theme.getSize("button_icon").width + height: UM.Theme.getSize("button_icon").height + } + } +} diff --git a/resources/qml/Topbar.qml b/resources/qml/Topbar.qml deleted file mode 100644 index 17819dbd27..0000000000 --- a/resources/qml/Topbar.qml +++ /dev/null @@ -1,247 +0,0 @@ -// Copyright (c) 2017 Ultimaker B.V. -// Cura is released under the terms of the LGPLv3 or higher. - -import QtQuick 2.2 -import QtQuick.Controls 1.1 -import QtQuick.Controls.Styles 1.1 -import QtQuick.Layouts 1.1 - -import UM 1.4 as UM -import Cura 1.0 as Cura -import "Menus" - -Rectangle -{ - id: base - anchors.left: parent.left - anchors.right: parent.right - height: UM.Theme.getSize("sidebar_header").height - color: UM.Controller.activeStage.stageId == "MonitorStage" ? UM.Theme.getColor("topbar_background_color_monitoring") : UM.Theme.getColor("topbar_background_color") - - property bool printerConnected: Cura.MachineManager.printerConnected - property bool printerAcceptsCommands: printerConnected && Cura.MachineManager.printerOutputDevices[0].acceptsCommands - - property int rightMargin: UM.Theme.getSize("sidebar").width + UM.Theme.getSize("default_margin").width; - property int allItemsWidth: 0; - - function updateMarginsAndSizes() { - if (UM.Preferences.getValue("cura/sidebar_collapsed")) - { - rightMargin = UM.Theme.getSize("default_margin").width; - } - else - { - rightMargin = UM.Theme.getSize("sidebar").width + UM.Theme.getSize("default_margin").width; - } - allItemsWidth = ( - logo.width + UM.Theme.getSize("topbar_logo_right_margin").width + - UM.Theme.getSize("topbar_logo_right_margin").width + stagesMenuContainer.width + - UM.Theme.getSize("default_margin").width + viewModeButton.width + - rightMargin); - } - - UM.I18nCatalog - { - id: catalog - name:"cura" - } - - Image - { - id: logo - anchors.left: parent.left - anchors.leftMargin: UM.Theme.getSize("default_margin").width - anchors.verticalCenter: parent.verticalCenter - - source: UM.Theme.getImage("logo"); - width: UM.Theme.getSize("logo").width; - height: UM.Theme.getSize("logo").height; - - sourceSize.width: width; - sourceSize.height: height; - } - - Row - { - id: stagesMenuContainer - anchors.left: logo.right - anchors.leftMargin: UM.Theme.getSize("topbar_logo_right_margin").width - spacing: UM.Theme.getSize("default_margin").width - - // The topbar is dynamically filled with all available stages - Repeater - { - id: stagesMenu - - model: UM.StageModel{} - - delegate: Button - { - text: model.name - checkable: true - checked: model.active - exclusiveGroup: topbarMenuGroup - style: (model.stage.iconSource != "") ? UM.Theme.styles.topbar_header_tab_no_overlay : UM.Theme.styles.topbar_header_tab - height: UM.Theme.getSize("sidebar_header").height - onClicked: UM.Controller.setActiveStage(model.id) - iconSource: model.stage.iconSource - - property color overlayColor: "transparent" - property string overlayIconSource: "" - } - } - - ExclusiveGroup { id: topbarMenuGroup } - } - - // View orientation Item - Row - { - id: viewOrientationControl - height: 30 - - spacing: 2 - visible: UM.Controller.activeStage.stageId != "MonitorStage" - - anchors - { - verticalCenter: base.verticalCenter - right: viewModeButton.left - rightMargin: UM.Theme.getSize("default_margin").width - } - - // #1 3d view - Button - { - iconSource: UM.Theme.getIcon("view_3d") - style: UM.Theme.styles.small_tool_button - anchors.verticalCenter: viewOrientationControl.verticalCenter - onClicked:UM.Controller.rotateView("3d", 0) - visible: base.width - allItemsWidth - 4 * this.width > 0 - } - - // #2 Front view - Button - { - iconSource: UM.Theme.getIcon("view_front") - style: UM.Theme.styles.small_tool_button - anchors.verticalCenter: viewOrientationControl.verticalCenter - onClicked: UM.Controller.rotateView("home", 0); - visible: base.width - allItemsWidth - 3 * this.width > 0 - } - - // #3 Top view - Button - { - iconSource: UM.Theme.getIcon("view_top") - style: UM.Theme.styles.small_tool_button - anchors.verticalCenter: viewOrientationControl.verticalCenter - onClicked: UM.Controller.rotateView("y", 90) - visible: base.width - allItemsWidth - 2 * this.width > 0 - } - - // #4 Left view - Button - { - iconSource: UM.Theme.getIcon("view_left") - style: UM.Theme.styles.small_tool_button - anchors.verticalCenter: viewOrientationControl.verticalCenter - onClicked: UM.Controller.rotateView("x", 90) - visible: base.width - allItemsWidth - 1 * this.width > 0 - } - - // #5 Right view - Button - { - iconSource: UM.Theme.getIcon("view_right") - style: UM.Theme.styles.small_tool_button - anchors.verticalCenter: viewOrientationControl.verticalCenter - onClicked: UM.Controller.rotateView("x", -90) - visible: base.width - allItemsWidth > 0 - } - } - - ComboBox - { - id: viewModeButton - - anchors { - verticalCenter: parent.verticalCenter - right: parent.right - rightMargin: rightMargin - } - - style: UM.Theme.styles.combobox - visible: UM.Controller.activeStage.stageId != "MonitorStage" - - model: UM.ViewModel { } - textRole: "name" - - // update the model's active index - function updateItemActiveFlags () { - currentIndex = getActiveIndex() - for (var i = 0; i < model.rowCount(); i++) { - model.getItem(i).active = (i == currentIndex) - } - } - - // get the index of the active model item on start - function getActiveIndex () { - for (var i = 0; i < model.rowCount(); i++) { - if (model.getItem(i).active) { - return i - } - } - return 0 - } - - // set the active index - function setActiveIndex (index) { - UM.Controller.setActiveView(index) - // the connection to UM.ActiveView will trigger update so there is no reason to call it manually here - } - - onCurrentIndexChanged: - { - if (model.getItem(currentIndex).id != undefined) - viewModeButton.setActiveIndex(model.getItem(currentIndex).id) - } - currentIndex: getActiveIndex() - - // watch the active view proxy for changes made from the menu item - Connections - { - target: UM.ActiveView - onActiveViewChanged: viewModeButton.updateItemActiveFlags() - } - } - - Loader - { - id: view_panel - - anchors.top: viewModeButton.bottom - anchors.topMargin: UM.Theme.getSize("default_margin").height - anchors.right: viewModeButton.right - - property var buttonTarget: Qt.point(viewModeButton.x + Math.round(viewModeButton.width / 2), viewModeButton.y + Math.round(viewModeButton.height / 2)) - - height: childrenRect.height - width: childrenRect.width - - source: UM.ActiveView.valid ? UM.ActiveView.activeViewPanel : ""; - } - - // Expand or collapse sidebar - Connections - { - target: Cura.Actions.expandSidebar - onTriggered: updateMarginsAndSizes() - } - - Component.onCompleted: - { - updateMarginsAndSizes(); - } - -} diff --git a/resources/qml/ViewOrientationButton.qml b/resources/qml/ViewOrientationButton.qml new file mode 100644 index 0000000000..5371f8549b --- /dev/null +++ b/resources/qml/ViewOrientationButton.qml @@ -0,0 +1,15 @@ +// Copyright (c) 2018 Ultimaker B.V. +// Cura is released under the terms of the LGPLv3 or higher. + +import QtQuick 2.2 + +import UM 1.4 as UM + +UM.SimpleButton +{ + width: UM.Theme.getSize("small_button").width + height: UM.Theme.getSize("small_button").height + hoverColor: UM.Theme.getColor("small_button_text_hover") + color: UM.Theme.getColor("small_button_text") + iconMargin: 0.5 * UM.Theme.getSize("wide_lining").width +} \ No newline at end of file diff --git a/resources/qml/ViewOrientationControls.qml b/resources/qml/ViewOrientationControls.qml new file mode 100644 index 0000000000..51ed6e3dcb --- /dev/null +++ b/resources/qml/ViewOrientationControls.qml @@ -0,0 +1,48 @@ +// Copyright (c) 2018 Ultimaker B.V. +// Cura is released under the terms of the LGPLv3 or higher. + +import QtQuick 2.2 +import QtQuick.Controls 1.1 +import QtQuick.Controls.Styles 1.1 + +import UM 1.4 as UM + +// A row of buttons that control the view direction +Row +{ + id: viewOrientationControl + + spacing: UM.Theme.getSize("narrow_margin").width + height: childrenRect.height + width: childrenRect.width + + ViewOrientationButton + { + iconSource: UM.Theme.getIcon("view_3d") + onClicked: UM.Controller.rotateView("3d", 0) + } + + ViewOrientationButton + { + iconSource: UM.Theme.getIcon("view_front") + onClicked: UM.Controller.rotateView("home", 0) + } + + ViewOrientationButton + { + iconSource: UM.Theme.getIcon("view_top") + onClicked: UM.Controller.rotateView("y", 90) + } + + ViewOrientationButton + { + iconSource: UM.Theme.getIcon("view_left") + onClicked: UM.Controller.rotateView("x", 90) + } + + ViewOrientationButton + { + iconSource: UM.Theme.getIcon("view_right") + onClicked: UM.Controller.rotateView("x", -90) + } +} diff --git a/resources/qml/ViewsSelector.qml b/resources/qml/ViewsSelector.qml new file mode 100644 index 0000000000..f2906f9d4c --- /dev/null +++ b/resources/qml/ViewsSelector.qml @@ -0,0 +1,131 @@ +// Copyright (c) 2018 Ultimaker B.V. +// Cura is released under the terms of the LGPLv3 or higher. + +import QtQuick 2.7 +import QtQuick.Controls 2.3 + +import UM 1.2 as UM +import Cura 1.0 as Cura + +Cura.ExpandablePopup +{ + id: viewSelector + + contentPadding: UM.Theme.getSize("default_lining").width + contentAlignment: Cura.ExpandablePopup.ContentAlignment.AlignLeft + + property var viewModel: UM.ViewModel { } + + property var activeView: + { + for (var i = 0; i < viewModel.count; i++) + { + if (viewModel.items[i].active) + { + return viewModel.items[i] + } + } + return null + } + + Component.onCompleted: + { + // Nothing was active, so just return the first one (the list is sorted by priority, so the most + // important one should be returned) + if (activeView == null) + { + UM.Controller.setActiveView(viewModel.getItem(0).id) + } + } + + headerItem: Item + { + Label + { + id: title + text: catalog.i18nc("@button", "View types") + verticalAlignment: Text.AlignVCenter + height: parent.height + elide: Text.ElideRight + font: UM.Theme.getFont("default") + color: UM.Theme.getColor("text_medium") + renderType: Text.NativeRendering + } + + Label + { + text: viewSelector.activeView ? viewSelector.activeView.name : "" + verticalAlignment: Text.AlignVCenter + anchors + { + left: title.right + leftMargin: UM.Theme.getSize("default_margin").width + right: parent.right + } + height: parent.height + elide: Text.ElideRight + font: UM.Theme.getFont("default") + color: UM.Theme.getColor("text") + renderType: Text.NativeRendering + } + } + + contentItem: Column + { + id: viewSelectorPopup + width: viewSelector.width - 2 * viewSelector.contentPadding + leftPadding: UM.Theme.getSize("default_lining").width + rightPadding: UM.Theme.getSize("default_lining").width + + // For some reason the height/width of the column gets set to 0 if this is not set... + Component.onCompleted: + { + height = implicitHeight + width = viewSelector.width - 2 * viewSelector.contentPadding + } + + Repeater + { + id: viewsList + model: viewSelector.viewModel + + delegate: Button + { + id: viewsSelectorButton + text: model.name + width: parent.width - viewSelectorPopup.leftPadding - viewSelectorPopup.rightPadding + height: UM.Theme.getSize("action_button").height + leftPadding: UM.Theme.getSize("default_margin").width + rightPadding: UM.Theme.getSize("default_margin").width + checkable: true + checked: viewSelector.activeView != null ? viewSelector.activeView.id == id : false + + contentItem: Label + { + id: buttonText + text: viewsSelectorButton.text + color: UM.Theme.getColor("text") + font: UM.Theme.getFont("action_button") + renderType: Text.NativeRendering + verticalAlignment: Text.AlignVCenter + elide: Text.ElideRight + } + + background: Rectangle + { + id: backgroundRect + color: viewsSelectorButton.hovered ? UM.Theme.getColor("action_button_hovered") : "transparent" + radius: UM.Theme.getSize("action_button_radius").width + border.width: UM.Theme.getSize("default_lining").width + border.color: viewsSelectorButton.checked ? UM.Theme.getColor("primary") : "transparent" + } + + onClicked: + { + toggleContent() + UM.Controller.setActiveView(id) + } + } + } + } +} \ No newline at end of file diff --git a/resources/qml/qmldir b/resources/qml/qmldir new file mode 100644 index 0000000000..1dc21150ce --- /dev/null +++ b/resources/qml/qmldir @@ -0,0 +1,17 @@ +module Cura + +MachineSelector 1.0 MachineSelector.qml +CustomConfigurationSelector 1.0 CustomConfigurationSelector.qml +PrintSetupSelector 1.0 PrintSetupSelector.qml +ActionButton 1.0 ActionButton.qml +MaterialMenu 1.0 MaterialMenu.qml +NozzleMenu 1.0 NozzleMenu.qml +ActionPanelWidget 1.0 ActionPanelWidget.qml +IconWithText 1.0 IconWithText.qml +OutputDevicesActionButton 1.0 OutputDevicesActionButton.qml +ExpandableComponent 1.0 ExpandableComponent.qml +PrinterTypeLabel 1.0 PrinterTypeLabel.qml +ViewsSelector 1.0 ViewsSelector.qml +ToolbarButton 1.0 ToolbarButton.qml +SettingView 1.0 SettingView.qml +ProfileMenu 1.0 ProfileMenu.qml \ No newline at end of file diff --git a/resources/quality/ultimaker3/um3_aa0.4_ABS_High_Quality.inst.cfg b/resources/quality/ultimaker3/um3_aa0.4_ABS_High_Quality.inst.cfg index 9ceab110e9..4e79728945 100644 --- a/resources/quality/ultimaker3/um3_aa0.4_ABS_High_Quality.inst.cfg +++ b/resources/quality/ultimaker3/um3_aa0.4_ABS_High_Quality.inst.cfg @@ -17,6 +17,7 @@ machine_nozzle_cool_down_speed = 0.8 machine_nozzle_heat_up_speed = 1.5 material_standby_temperature = 100 material_print_temperature = =default_material_print_temperature - 5 +material_print_temperature_layer_0 = =material_print_temperature + 15 material_initial_print_temperature = =material_print_temperature - 5 material_final_print_temperature = =material_print_temperature - 10 prime_tower_enable = False diff --git a/resources/quality/ultimaker3/um3_aa0.4_ABS_Normal_Quality.inst.cfg b/resources/quality/ultimaker3/um3_aa0.4_ABS_Normal_Quality.inst.cfg index e5b699c35f..3bded3b97c 100644 --- a/resources/quality/ultimaker3/um3_aa0.4_ABS_Normal_Quality.inst.cfg +++ b/resources/quality/ultimaker3/um3_aa0.4_ABS_Normal_Quality.inst.cfg @@ -14,6 +14,7 @@ variant = AA 0.4 [values] machine_nozzle_cool_down_speed = 0.85 machine_nozzle_heat_up_speed = 1.5 +material_print_temperature_layer_0 = =material_print_temperature + 10 material_initial_print_temperature = =material_print_temperature - 5 material_final_print_temperature = =material_print_temperature - 10 material_standby_temperature = 100 diff --git a/resources/quality/ultimaker_s5/um_s5_aa0.25_CPE_Normal_Quality.inst.cfg b/resources/quality/ultimaker_s5/um_s5_aa0.25_CPE_Normal_Quality.inst.cfg index 2068ed51c0..c15311d104 100644 --- a/resources/quality/ultimaker_s5/um_s5_aa0.25_CPE_Normal_Quality.inst.cfg +++ b/resources/quality/ultimaker_s5/um_s5_aa0.25_CPE_Normal_Quality.inst.cfg @@ -12,6 +12,7 @@ material = generic_cpe variant = AA 0.25 [values] +retraction_combing_max_distance = 50 retraction_extrusion_window = 0.5 speed_infill = =math.ceil(speed_print * 40 / 55) speed_topbottom = =math.ceil(speed_print * 30 / 55) diff --git a/resources/quality/ultimaker_s5/um_s5_aa0.4_CPEP_Draft_Print.inst.cfg b/resources/quality/ultimaker_s5/um_s5_aa0.4_CPEP_Draft_Print.inst.cfg index 421fcdf095..627302e0ab 100644 --- a/resources/quality/ultimaker_s5/um_s5_aa0.4_CPEP_Draft_Print.inst.cfg +++ b/resources/quality/ultimaker_s5/um_s5_aa0.4_CPEP_Draft_Print.inst.cfg @@ -29,7 +29,7 @@ material_print_temperature_layer_0 = =material_print_temperature multiple_mesh_overlap = 0 prime_tower_enable = True prime_tower_wipe_enabled = True -retraction_combing = off +retraction_combing_max_distance = 50 retraction_extrusion_window = 1 retraction_hop = 0.2 retraction_hop_enabled = False diff --git a/resources/quality/ultimaker_s5/um_s5_aa0.4_CPEP_Fast_Print.inst.cfg b/resources/quality/ultimaker_s5/um_s5_aa0.4_CPEP_Fast_Print.inst.cfg index 536c6c97b8..cda8d85211 100644 --- a/resources/quality/ultimaker_s5/um_s5_aa0.4_CPEP_Fast_Print.inst.cfg +++ b/resources/quality/ultimaker_s5/um_s5_aa0.4_CPEP_Fast_Print.inst.cfg @@ -29,7 +29,7 @@ material_print_temperature_layer_0 = =material_print_temperature multiple_mesh_overlap = 0 prime_tower_enable = True prime_tower_wipe_enabled = True -retraction_combing = off +retraction_combing_max_distance = 50 retraction_extrusion_window = 1 retraction_hop = 0.2 retraction_hop_enabled = False diff --git a/resources/quality/ultimaker_s5/um_s5_aa0.4_CPEP_High_Quality.inst.cfg b/resources/quality/ultimaker_s5/um_s5_aa0.4_CPEP_High_Quality.inst.cfg index 77182c21e1..3ce76bf6be 100644 --- a/resources/quality/ultimaker_s5/um_s5_aa0.4_CPEP_High_Quality.inst.cfg +++ b/resources/quality/ultimaker_s5/um_s5_aa0.4_CPEP_High_Quality.inst.cfg @@ -31,7 +31,7 @@ material_print_temperature_layer_0 = =material_print_temperature multiple_mesh_overlap = 0 prime_tower_enable = True prime_tower_wipe_enabled = True -retraction_combing = off +retraction_combing_max_distance = 50 retraction_extrusion_window = 1 retraction_hop = 0.2 retraction_hop_enabled = False diff --git a/resources/quality/ultimaker_s5/um_s5_aa0.4_CPEP_Normal_Quality.inst.cfg b/resources/quality/ultimaker_s5/um_s5_aa0.4_CPEP_Normal_Quality.inst.cfg index d779baf315..d402b663c6 100644 --- a/resources/quality/ultimaker_s5/um_s5_aa0.4_CPEP_Normal_Quality.inst.cfg +++ b/resources/quality/ultimaker_s5/um_s5_aa0.4_CPEP_Normal_Quality.inst.cfg @@ -31,7 +31,7 @@ material_print_temperature_layer_0 = =material_print_temperature multiple_mesh_overlap = 0 prime_tower_enable = True prime_tower_wipe_enabled = True -retraction_combing = off +retraction_combing_max_distance = 50 retraction_extrusion_window = 1 retraction_hop = 0.2 retraction_hop_enabled = False diff --git a/resources/quality/ultimaker_s5/um_s5_aa0.4_CPE_Draft_Print.inst.cfg b/resources/quality/ultimaker_s5/um_s5_aa0.4_CPE_Draft_Print.inst.cfg index c51e5652e1..505cd952d2 100644 --- a/resources/quality/ultimaker_s5/um_s5_aa0.4_CPE_Draft_Print.inst.cfg +++ b/resources/quality/ultimaker_s5/um_s5_aa0.4_CPE_Draft_Print.inst.cfg @@ -15,6 +15,7 @@ variant = AA 0.4 material_print_temperature = =default_material_print_temperature + 10 material_initial_print_temperature = =material_print_temperature - 5 material_final_print_temperature = =material_print_temperature - 10 +retraction_combing_max_distance = 50 skin_overlap = 20 speed_print = 60 speed_layer_0 = =math.ceil(speed_print * 20 / 60) @@ -24,5 +25,5 @@ speed_wall_0 = =math.ceil(speed_wall * 35 / 45) wall_thickness = 1 -infill_pattern = zigzag +infill_pattern = triangles speed_infill = =math.ceil(speed_print * 50 / 60) diff --git a/resources/quality/ultimaker_s5/um_s5_aa0.4_CPE_Fast_Print.inst.cfg b/resources/quality/ultimaker_s5/um_s5_aa0.4_CPE_Fast_Print.inst.cfg index b80d3ccf22..cc5df0abb9 100644 --- a/resources/quality/ultimaker_s5/um_s5_aa0.4_CPE_Fast_Print.inst.cfg +++ b/resources/quality/ultimaker_s5/um_s5_aa0.4_CPE_Fast_Print.inst.cfg @@ -16,11 +16,12 @@ cool_min_speed = 7 material_print_temperature = =default_material_print_temperature + 5 material_initial_print_temperature = =material_print_temperature - 5 material_final_print_temperature = =material_print_temperature - 10 +retraction_combing_max_distance = 50 speed_print = 60 speed_layer_0 = =math.ceil(speed_print * 20 / 60) speed_topbottom = =math.ceil(speed_print * 30 / 60) speed_wall = =math.ceil(speed_print * 40 / 60) speed_wall_0 = =math.ceil(speed_wall * 30 / 40) -infill_pattern = zigzag +infill_pattern = triangles speed_infill = =math.ceil(speed_print * 50 / 60) \ No newline at end of file diff --git a/resources/quality/ultimaker_s5/um_s5_aa0.4_CPE_High_Quality.inst.cfg b/resources/quality/ultimaker_s5/um_s5_aa0.4_CPE_High_Quality.inst.cfg index c90eedaec3..c81dc0f5a7 100644 --- a/resources/quality/ultimaker_s5/um_s5_aa0.4_CPE_High_Quality.inst.cfg +++ b/resources/quality/ultimaker_s5/um_s5_aa0.4_CPE_High_Quality.inst.cfg @@ -18,10 +18,11 @@ machine_nozzle_heat_up_speed = 1.5 material_print_temperature = =default_material_print_temperature - 5 material_initial_print_temperature = =material_print_temperature - 5 material_final_print_temperature = =material_print_temperature - 10 +retraction_combing_max_distance = 50 speed_print = 50 speed_layer_0 = =math.ceil(speed_print * 20 / 50) speed_topbottom = =math.ceil(speed_print * 30 / 50) speed_wall = =math.ceil(speed_print * 30 / 50) -infill_pattern = zigzag +infill_pattern = triangles speed_infill = =math.ceil(speed_print * 40 / 50) \ No newline at end of file diff --git a/resources/quality/ultimaker_s5/um_s5_aa0.4_CPE_Normal_Quality.inst.cfg b/resources/quality/ultimaker_s5/um_s5_aa0.4_CPE_Normal_Quality.inst.cfg index e098b0ffb4..7d29f8fb7c 100644 --- a/resources/quality/ultimaker_s5/um_s5_aa0.4_CPE_Normal_Quality.inst.cfg +++ b/resources/quality/ultimaker_s5/um_s5_aa0.4_CPE_Normal_Quality.inst.cfg @@ -16,10 +16,11 @@ machine_nozzle_cool_down_speed = 0.85 machine_nozzle_heat_up_speed = 1.5 material_initial_print_temperature = =material_print_temperature - 5 material_final_print_temperature = =material_print_temperature - 10 +retraction_combing_max_distance = 50 speed_print = 55 speed_layer_0 = =math.ceil(speed_print * 20 / 55) speed_topbottom = =math.ceil(speed_print * 30 / 55) speed_wall = =math.ceil(speed_print * 30 / 55) -infill_pattern = zigzag +infill_pattern = triangles speed_infill = =math.ceil(speed_print * 45 / 55) \ No newline at end of file diff --git a/resources/quality/ultimaker_s5/um_s5_aa0.4_aluminum_CPEP_Draft_Print.inst.cfg b/resources/quality/ultimaker_s5/um_s5_aa0.4_aluminum_CPEP_Draft_Print.inst.cfg index 46e3483a6a..4a55f5d24c 100644 --- a/resources/quality/ultimaker_s5/um_s5_aa0.4_aluminum_CPEP_Draft_Print.inst.cfg +++ b/resources/quality/ultimaker_s5/um_s5_aa0.4_aluminum_CPEP_Draft_Print.inst.cfg @@ -30,7 +30,7 @@ material_print_temperature_layer_0 = =material_print_temperature multiple_mesh_overlap = 0 prime_tower_enable = True prime_tower_wipe_enabled = True -retraction_combing = off +retraction_combing_max_distance = 50 retraction_extrusion_window = 1 retraction_hop = 0.2 retraction_hop_enabled = False diff --git a/resources/quality/ultimaker_s5/um_s5_aa0.4_aluminum_CPEP_Fast_Print.inst.cfg b/resources/quality/ultimaker_s5/um_s5_aa0.4_aluminum_CPEP_Fast_Print.inst.cfg index 5c235b656a..730e058212 100644 --- a/resources/quality/ultimaker_s5/um_s5_aa0.4_aluminum_CPEP_Fast_Print.inst.cfg +++ b/resources/quality/ultimaker_s5/um_s5_aa0.4_aluminum_CPEP_Fast_Print.inst.cfg @@ -30,7 +30,7 @@ material_print_temperature_layer_0 = =material_print_temperature multiple_mesh_overlap = 0 prime_tower_enable = True prime_tower_wipe_enabled = True -retraction_combing = off +retraction_combing_max_distance = 50 retraction_extrusion_window = 1 retraction_hop = 0.2 retraction_hop_enabled = False diff --git a/resources/quality/ultimaker_s5/um_s5_aa0.4_aluminum_CPEP_High_Quality.inst.cfg b/resources/quality/ultimaker_s5/um_s5_aa0.4_aluminum_CPEP_High_Quality.inst.cfg index 326a730fe4..e6921e63d8 100644 --- a/resources/quality/ultimaker_s5/um_s5_aa0.4_aluminum_CPEP_High_Quality.inst.cfg +++ b/resources/quality/ultimaker_s5/um_s5_aa0.4_aluminum_CPEP_High_Quality.inst.cfg @@ -32,7 +32,7 @@ material_print_temperature_layer_0 = =material_print_temperature multiple_mesh_overlap = 0 prime_tower_enable = True prime_tower_wipe_enabled = True -retraction_combing = off +retraction_combing_max_distance = 50 retraction_extrusion_window = 1 retraction_hop = 0.2 retraction_hop_enabled = False diff --git a/resources/quality/ultimaker_s5/um_s5_aa0.4_aluminum_CPEP_Normal_Quality.inst.cfg b/resources/quality/ultimaker_s5/um_s5_aa0.4_aluminum_CPEP_Normal_Quality.inst.cfg index d40b2db90e..a4eec45e38 100644 --- a/resources/quality/ultimaker_s5/um_s5_aa0.4_aluminum_CPEP_Normal_Quality.inst.cfg +++ b/resources/quality/ultimaker_s5/um_s5_aa0.4_aluminum_CPEP_Normal_Quality.inst.cfg @@ -32,7 +32,7 @@ material_print_temperature_layer_0 = =material_print_temperature multiple_mesh_overlap = 0 prime_tower_enable = True prime_tower_wipe_enabled = True -retraction_combing = off +retraction_combing_max_distance = 50 retraction_extrusion_window = 1 retraction_hop = 0.2 retraction_hop_enabled = False diff --git a/resources/quality/ultimaker_s5/um_s5_aa0.4_aluminum_CPE_Draft_Print.inst.cfg b/resources/quality/ultimaker_s5/um_s5_aa0.4_aluminum_CPE_Draft_Print.inst.cfg index c812066e0c..4f085f10a6 100644 --- a/resources/quality/ultimaker_s5/um_s5_aa0.4_aluminum_CPE_Draft_Print.inst.cfg +++ b/resources/quality/ultimaker_s5/um_s5_aa0.4_aluminum_CPE_Draft_Print.inst.cfg @@ -16,6 +16,7 @@ buildplate = Aluminum material_print_temperature = =default_material_print_temperature + 10 material_initial_print_temperature = =material_print_temperature - 5 material_final_print_temperature = =material_print_temperature - 10 +retraction_combing_max_distance = 50 skin_overlap = 20 speed_print = 60 speed_layer_0 = 20 @@ -25,7 +26,7 @@ speed_wall_0 = =math.ceil(speed_wall * 35 / 45) wall_thickness = 1 -infill_pattern = zigzag +infill_pattern = triangles speed_infill = =math.ceil(speed_print * 50 / 60) prime_tower_purge_volume = 1 diff --git a/resources/quality/ultimaker_s5/um_s5_aa0.4_aluminum_CPE_Fast_Print.inst.cfg b/resources/quality/ultimaker_s5/um_s5_aa0.4_aluminum_CPE_Fast_Print.inst.cfg index ef634316da..2580bf952d 100644 --- a/resources/quality/ultimaker_s5/um_s5_aa0.4_aluminum_CPE_Fast_Print.inst.cfg +++ b/resources/quality/ultimaker_s5/um_s5_aa0.4_aluminum_CPE_Fast_Print.inst.cfg @@ -17,13 +17,14 @@ cool_min_speed = 7 material_print_temperature = =default_material_print_temperature + 5 material_initial_print_temperature = =material_print_temperature - 5 material_final_print_temperature = =material_print_temperature - 10 +retraction_combing_max_distance = 50 speed_print = 60 speed_layer_0 = 20 speed_topbottom = =math.ceil(speed_print * 30 / 60) speed_wall = =math.ceil(speed_print * 40 / 60) speed_wall_0 = =math.ceil(speed_wall * 30 / 40) -infill_pattern = zigzag +infill_pattern = triangles speed_infill = =math.ceil(speed_print * 50 / 60) prime_tower_purge_volume = 1 diff --git a/resources/quality/ultimaker_s5/um_s5_aa0.4_aluminum_CPE_High_Quality.inst.cfg b/resources/quality/ultimaker_s5/um_s5_aa0.4_aluminum_CPE_High_Quality.inst.cfg index cda97e6ab3..d6f07c37a5 100644 --- a/resources/quality/ultimaker_s5/um_s5_aa0.4_aluminum_CPE_High_Quality.inst.cfg +++ b/resources/quality/ultimaker_s5/um_s5_aa0.4_aluminum_CPE_High_Quality.inst.cfg @@ -19,12 +19,13 @@ machine_nozzle_heat_up_speed = 1.5 material_print_temperature = =default_material_print_temperature - 5 material_initial_print_temperature = =material_print_temperature - 5 material_final_print_temperature = =material_print_temperature - 10 +retraction_combing_max_distance = 50 speed_print = 50 speed_layer_0 = 20 speed_topbottom = =math.ceil(speed_print * 30 / 50) speed_wall = =math.ceil(speed_print * 30 / 50) -infill_pattern = zigzag +infill_pattern = triangles speed_infill = =math.ceil(speed_print * 40 / 50) prime_tower_purge_volume = 1 diff --git a/resources/quality/ultimaker_s5/um_s5_aa0.4_aluminum_CPE_Normal_Quality.inst.cfg b/resources/quality/ultimaker_s5/um_s5_aa0.4_aluminum_CPE_Normal_Quality.inst.cfg index 5a75f3b6e3..6032ff3845 100644 --- a/resources/quality/ultimaker_s5/um_s5_aa0.4_aluminum_CPE_Normal_Quality.inst.cfg +++ b/resources/quality/ultimaker_s5/um_s5_aa0.4_aluminum_CPE_Normal_Quality.inst.cfg @@ -17,12 +17,13 @@ machine_nozzle_cool_down_speed = 0.85 machine_nozzle_heat_up_speed = 1.5 material_initial_print_temperature = =material_print_temperature - 5 material_final_print_temperature = =material_print_temperature - 10 +retraction_combing_max_distance = 50 speed_print = 55 speed_layer_0 = 20 speed_topbottom = =math.ceil(speed_print * 30 / 55) speed_wall = =math.ceil(speed_print * 30 / 55) -infill_pattern = zigzag +infill_pattern = triangles speed_infill = =math.ceil(speed_print * 45 / 55) prime_tower_purge_volume = 1 diff --git a/resources/quality/ultimaker_s5/um_s5_aa0.8_CPEP_Fast_Print.inst.cfg b/resources/quality/ultimaker_s5/um_s5_aa0.8_CPEP_Fast_Print.inst.cfg index 4bdd09e9b3..d126dddaad 100644 --- a/resources/quality/ultimaker_s5/um_s5_aa0.8_CPEP_Fast_Print.inst.cfg +++ b/resources/quality/ultimaker_s5/um_s5_aa0.8_CPEP_Fast_Print.inst.cfg @@ -23,7 +23,7 @@ material_print_temperature = =default_material_print_temperature - 10 material_print_temperature_layer_0 = =material_print_temperature material_standby_temperature = 100 prime_tower_enable = True -retraction_combing = off +retraction_combing_max_distance = 50 retraction_hop = 0.1 retraction_hop_enabled = False skin_overlap = 0 diff --git a/resources/quality/ultimaker_s5/um_s5_aa0.8_CPEP_Superdraft_Print.inst.cfg b/resources/quality/ultimaker_s5/um_s5_aa0.8_CPEP_Superdraft_Print.inst.cfg index f9b6b0c7a6..dd8b20652a 100644 --- a/resources/quality/ultimaker_s5/um_s5_aa0.8_CPEP_Superdraft_Print.inst.cfg +++ b/resources/quality/ultimaker_s5/um_s5_aa0.8_CPEP_Superdraft_Print.inst.cfg @@ -23,7 +23,7 @@ material_print_temperature = =default_material_print_temperature - 5 material_print_temperature_layer_0 = =material_print_temperature material_standby_temperature = 100 prime_tower_enable = True -retraction_combing = off +retraction_combing_max_distance = 50 retraction_hop = 0.1 retraction_hop_enabled = False skin_overlap = 0 diff --git a/resources/quality/ultimaker_s5/um_s5_aa0.8_CPEP_Verydraft_Print.inst.cfg b/resources/quality/ultimaker_s5/um_s5_aa0.8_CPEP_Verydraft_Print.inst.cfg index 9c6c7de7f0..bc107422f1 100644 --- a/resources/quality/ultimaker_s5/um_s5_aa0.8_CPEP_Verydraft_Print.inst.cfg +++ b/resources/quality/ultimaker_s5/um_s5_aa0.8_CPEP_Verydraft_Print.inst.cfg @@ -23,7 +23,7 @@ material_print_temperature = =default_material_print_temperature - 7 material_print_temperature_layer_0 = =material_print_temperature material_standby_temperature = 100 prime_tower_enable = True -retraction_combing = off +retraction_combing_max_distance = 50 retraction_hop = 0.1 retraction_hop_enabled = False skin_overlap = 0 diff --git a/resources/quality/ultimaker_s5/um_s5_aa0.8_CPE_Draft_Print.inst.cfg b/resources/quality/ultimaker_s5/um_s5_aa0.8_CPE_Draft_Print.inst.cfg index 532aacabf7..7cb69ba3eb 100644 --- a/resources/quality/ultimaker_s5/um_s5_aa0.8_CPE_Draft_Print.inst.cfg +++ b/resources/quality/ultimaker_s5/um_s5_aa0.8_CPE_Draft_Print.inst.cfg @@ -17,6 +17,7 @@ line_width = =machine_nozzle_size * 0.875 material_print_temperature = =default_material_print_temperature + 15 material_standby_temperature = 100 prime_tower_enable = True +retraction_combing_max_distance = 50 speed_print = 40 speed_topbottom = =math.ceil(speed_print * 25 / 40) speed_wall = =math.ceil(speed_print * 30 / 40) diff --git a/resources/quality/ultimaker_s5/um_s5_aa0.8_CPE_Superdraft_Print.inst.cfg b/resources/quality/ultimaker_s5/um_s5_aa0.8_CPE_Superdraft_Print.inst.cfg index 55b9ae8315..6c323fe602 100644 --- a/resources/quality/ultimaker_s5/um_s5_aa0.8_CPE_Superdraft_Print.inst.cfg +++ b/resources/quality/ultimaker_s5/um_s5_aa0.8_CPE_Superdraft_Print.inst.cfg @@ -17,6 +17,7 @@ line_width = =machine_nozzle_size * 0.875 material_print_temperature = =default_material_print_temperature + 20 material_standby_temperature = 100 prime_tower_enable = True +retraction_combing_max_distance = 50 speed_print = 45 speed_topbottom = =math.ceil(speed_print * 30 / 45) speed_wall = =math.ceil(speed_print * 40 / 45) diff --git a/resources/quality/ultimaker_s5/um_s5_aa0.8_CPE_Verydraft_Print.inst.cfg b/resources/quality/ultimaker_s5/um_s5_aa0.8_CPE_Verydraft_Print.inst.cfg index 01761062a4..a0380ecc0e 100644 --- a/resources/quality/ultimaker_s5/um_s5_aa0.8_CPE_Verydraft_Print.inst.cfg +++ b/resources/quality/ultimaker_s5/um_s5_aa0.8_CPE_Verydraft_Print.inst.cfg @@ -17,6 +17,7 @@ line_width = =machine_nozzle_size * 0.875 material_print_temperature = =default_material_print_temperature + 17 material_standby_temperature = 100 prime_tower_enable = True +retraction_combing_max_distance = 50 speed_print = 40 speed_topbottom = =math.ceil(speed_print * 25 / 40) speed_wall = =math.ceil(speed_print * 30 / 40) diff --git a/resources/quality/ultimaker_s5/um_s5_aa0.8_aluminum_CPEP_Fast_Print.inst.cfg b/resources/quality/ultimaker_s5/um_s5_aa0.8_aluminum_CPEP_Fast_Print.inst.cfg index 4098c86ad9..50091a6fb4 100644 --- a/resources/quality/ultimaker_s5/um_s5_aa0.8_aluminum_CPEP_Fast_Print.inst.cfg +++ b/resources/quality/ultimaker_s5/um_s5_aa0.8_aluminum_CPEP_Fast_Print.inst.cfg @@ -24,7 +24,7 @@ material_print_temperature = =default_material_print_temperature - 10 material_print_temperature_layer_0 = =material_print_temperature material_standby_temperature = 100 prime_tower_enable = True -retraction_combing = off +retraction_combing_max_distance = 50 retraction_hop = 0.1 retraction_hop_enabled = False skin_overlap = 0 diff --git a/resources/quality/ultimaker_s5/um_s5_aa0.8_aluminum_CPEP_Superdraft_Print.inst.cfg b/resources/quality/ultimaker_s5/um_s5_aa0.8_aluminum_CPEP_Superdraft_Print.inst.cfg index 4c1b807430..b9c9ef6611 100644 --- a/resources/quality/ultimaker_s5/um_s5_aa0.8_aluminum_CPEP_Superdraft_Print.inst.cfg +++ b/resources/quality/ultimaker_s5/um_s5_aa0.8_aluminum_CPEP_Superdraft_Print.inst.cfg @@ -23,7 +23,7 @@ material_print_temperature = =default_material_print_temperature - 5 material_print_temperature_layer_0 = =material_print_temperature material_standby_temperature = 100 prime_tower_enable = True -retraction_combing = off +retraction_combing_max_distance = 50 retraction_hop = 0.1 retraction_hop_enabled = False skin_overlap = 0 diff --git a/resources/quality/ultimaker_s5/um_s5_aa0.8_aluminum_CPEP_Verydraft_Print.inst.cfg b/resources/quality/ultimaker_s5/um_s5_aa0.8_aluminum_CPEP_Verydraft_Print.inst.cfg index 11aefc90cd..be2cc62b08 100644 --- a/resources/quality/ultimaker_s5/um_s5_aa0.8_aluminum_CPEP_Verydraft_Print.inst.cfg +++ b/resources/quality/ultimaker_s5/um_s5_aa0.8_aluminum_CPEP_Verydraft_Print.inst.cfg @@ -23,7 +23,7 @@ material_print_temperature = =default_material_print_temperature - 7 material_print_temperature_layer_0 = =material_print_temperature material_standby_temperature = 100 prime_tower_enable = True -retraction_combing = off +retraction_combing_max_distance = 50 retraction_hop = 0.1 retraction_hop_enabled = False skin_overlap = 0 diff --git a/resources/quality/ultimaker_s5/um_s5_aa0.8_aluminum_CPE_Draft_Print.inst.cfg b/resources/quality/ultimaker_s5/um_s5_aa0.8_aluminum_CPE_Draft_Print.inst.cfg index 80c0585061..0d0ed8f8b2 100644 --- a/resources/quality/ultimaker_s5/um_s5_aa0.8_aluminum_CPE_Draft_Print.inst.cfg +++ b/resources/quality/ultimaker_s5/um_s5_aa0.8_aluminum_CPE_Draft_Print.inst.cfg @@ -18,6 +18,7 @@ line_width = =machine_nozzle_size * 0.875 material_print_temperature = =default_material_print_temperature + 15 material_standby_temperature = 100 prime_tower_enable = True +retraction_combing_max_distance = 50 speed_print = 40 speed_topbottom = =math.ceil(speed_print * 25 / 40) speed_wall = =math.ceil(speed_print * 30 / 40) diff --git a/resources/quality/ultimaker_s5/um_s5_aa0.8_aluminum_CPE_Superdraft_Print.inst.cfg b/resources/quality/ultimaker_s5/um_s5_aa0.8_aluminum_CPE_Superdraft_Print.inst.cfg index 5dcc454173..a163e0c735 100644 --- a/resources/quality/ultimaker_s5/um_s5_aa0.8_aluminum_CPE_Superdraft_Print.inst.cfg +++ b/resources/quality/ultimaker_s5/um_s5_aa0.8_aluminum_CPE_Superdraft_Print.inst.cfg @@ -18,6 +18,7 @@ line_width = =machine_nozzle_size * 0.875 material_print_temperature = =default_material_print_temperature + 20 material_standby_temperature = 100 prime_tower_enable = True +retraction_combing_max_distance = 50 speed_print = 45 speed_topbottom = =math.ceil(speed_print * 30 / 45) speed_wall = =math.ceil(speed_print * 40 / 45) diff --git a/resources/quality/ultimaker_s5/um_s5_aa0.8_aluminum_CPE_Verydraft_Print.inst.cfg b/resources/quality/ultimaker_s5/um_s5_aa0.8_aluminum_CPE_Verydraft_Print.inst.cfg index 8423e109e8..2137cf740b 100644 --- a/resources/quality/ultimaker_s5/um_s5_aa0.8_aluminum_CPE_Verydraft_Print.inst.cfg +++ b/resources/quality/ultimaker_s5/um_s5_aa0.8_aluminum_CPE_Verydraft_Print.inst.cfg @@ -18,6 +18,7 @@ line_width = =machine_nozzle_size * 0.875 material_print_temperature = =default_material_print_temperature + 17 material_standby_temperature = 100 prime_tower_enable = True +retraction_combing_max_distance = 50 speed_print = 40 speed_topbottom = =math.ceil(speed_print * 25 / 40) speed_wall = =math.ceil(speed_print * 30 / 40) diff --git a/resources/themes/cura-dark/icons/tab_status_unknown.svg b/resources/themes/cura-dark/icons/tab_status_unknown.svg deleted file mode 100644 index d20218bc00..0000000000 --- a/resources/themes/cura-dark/icons/tab_status_unknown.svg +++ /dev/null @@ -1,13 +0,0 @@ - - - - Unknown - Created with Sketch. - - - - - - - - \ No newline at end of file diff --git a/resources/themes/cura-dark/images/logo.svg b/resources/themes/cura-dark/images/logo.svg deleted file mode 100644 index 92ffe4ca0c..0000000000 --- a/resources/themes/cura-dark/images/logo.svg +++ /dev/null @@ -1,72 +0,0 @@ - - - - - - image/svg+xml - - - - - - - - - - - - - diff --git a/resources/themes/cura-dark/theme.json b/resources/themes/cura-dark/theme.json index 39546b6370..8540abf61a 100644 --- a/resources/themes/cura-dark/theme.json +++ b/resources/themes/cura-dark/theme.json @@ -5,7 +5,9 @@ }, "colors": { - "sidebar": [39, 44, 48, 255], + "main_background": [39, 44, 48, 255], + "wide_lining": [31, 36, 39, 255], + "thick_lining": [255, 255, 255, 30], "lining": [64, 69, 72, 255], "viewport_overlay": [0, 6, 9, 222], @@ -13,14 +15,13 @@ "primary_hover": [48, 182, 231, 255], "primary_text": [255, 255, 255, 204], "border": [127, 127, 127, 255], - "secondary": [241, 242, 242, 255], + "secondary": [95, 95, 95, 255], - "topbar_background_color": [0, 0, 0, 0], - "topbar_background_color_monitoring": [31, 36, 39, 255], + "main_window_header_button_text_inactive": [128, 128, 128, 255], + "main_window_header_button_text_hovered": [255, 255, 255, 255], - "topbar_button_text_active": [255, 255, 255, 255], - "topbar_button_text_inactive": [128, 128, 128, 255], - "topbar_button_text_hovered": [255, 255, 255, 255], + "machine_selector_bar": [39, 44, 48, 255], + "machine_selector_active": [39, 44, 48, 255], "text": [255, 255, 255, 204], "text_detail": [255, 255, 255, 172], @@ -34,16 +35,7 @@ "text_scene_hover": [255, 255, 255, 204], "error": [212, 31, 53, 255], - "sidebar_header_bar": [39, 44, 48, 255], - "sidebar_header_active": [39, 44, 48, 255], - "sidebar_header_hover": [68, 72, 75, 255], - "sidebar_header_highlight": [68, 192, 255, 255], - "sidebar_header_highlight_hover": [68, 192, 255, 255], - "sidebar_header_text_active": [255, 255, 255, 255], - "sidebar_header_text_hover": [255, 255, 255, 255], - "sidebar_header_text_inactive": [255, 255, 255, 127], - "sidebar_lining": [31, 36, 39, 255], - "sidebar_lining_thin": [255, 255, 255, 30], + "disabled": [32, 32, 32, 255], "button": [39, 44, 48, 255], "button_hover": [39, 44, 48, 255], @@ -142,9 +134,7 @@ "slider_groove_border": [127, 127, 127, 255], "slider_groove_fill": [245, 245, 245, 255], "slider_handle": [255, 255, 255, 255], - "slider_handle_hover": [77, 182, 226, 255], "slider_handle_active": [68, 192, 255, 255], - "slider_handle_border": [39, 44, 48, 255], "slider_text_background": [255, 255, 255, 255], "checkbox": [43, 48, 52, 255], @@ -207,21 +197,14 @@ "layerview_support_interface": [64, 192, 255, 255], "layerview_nozzle": [181, 166, 66, 120], - "configuration_item": [0, 0, 0, 0], - "configuration_item_active": [12, 169, 227, 179], - "configuration_item_text": [255, 255, 255, 255], - "configuration_item_text_active": [255, 255, 255, 255], - "configuration_item_border": [255, 255, 255, 255], - "configuration_item_border_active": [12, 169, 227, 179], - "configuration_item_border_hover": [12, 169, 227, 179], - "material_compatibility_warning": [255, 255, 255, 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], + + "toolbox_header_button_text_active": [255, 255, 255, 255], + "toolbox_header_button_text_inactive": [128, 128, 128, 255], + "toolbox_header_button_text_hovered": [255, 255, 255, 255], "monitor_card_background_inactive": [43, 48, 52, 255], "monitor_card_background": [43, 48, 52, 255], diff --git a/resources/themes/cura-light/icons/buildplate.svg b/resources/themes/cura-light/icons/buildplate.svg index 9e61296958..7505c8204e 100644 --- a/resources/themes/cura-light/icons/buildplate.svg +++ b/resources/themes/cura-light/icons/buildplate.svg @@ -1,17 +1,9 @@ - - - icn_buildplate - Created with Sketch. - - - - - - - - - - + + + + + + \ No newline at end of file diff --git a/resources/themes/cura-light/icons/circle_outline.svg b/resources/themes/cura-light/icons/circle_outline.svg new file mode 100644 index 0000000000..3a8fb197f3 --- /dev/null +++ b/resources/themes/cura-light/icons/circle_outline.svg @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/resources/themes/cura-light/icons/clock.svg b/resources/themes/cura-light/icons/clock.svg new file mode 100644 index 0000000000..0b6cb78881 --- /dev/null +++ b/resources/themes/cura-light/icons/clock.svg @@ -0,0 +1,53 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/resources/themes/cura-light/icons/connected.svg b/resources/themes/cura-light/icons/connected.svg deleted file mode 100644 index 18423bb6c4..0000000000 --- a/resources/themes/cura-light/icons/connected.svg +++ /dev/null @@ -1,5 +0,0 @@ - - - - - \ No newline at end of file diff --git a/resources/themes/cura-light/icons/disconnected.svg b/resources/themes/cura-light/icons/disconnected.svg deleted file mode 100644 index 019dff117e..0000000000 --- a/resources/themes/cura-light/icons/disconnected.svg +++ /dev/null @@ -1,6 +0,0 @@ - - - - - - \ No newline at end of file diff --git a/resources/themes/cura-light/icons/extruder_button.svg b/resources/themes/cura-light/icons/extruder_button.svg index e3c01b6a0a..c79ba5c5df 100644 --- a/resources/themes/cura-light/icons/extruder_button.svg +++ b/resources/themes/cura-light/icons/extruder_button.svg @@ -1,64 +1,9 @@ - - - - - - image/svg+xml - - Artboard 3 Copy - - - - - - Artboard 3 Copy - Created with Sketch. - - - + + + + + + + + + \ No newline at end of file diff --git a/resources/themes/cura-light/icons/info.svg b/resources/themes/cura-light/icons/info.svg new file mode 100644 index 0000000000..9896b3dac8 --- /dev/null +++ b/resources/themes/cura-light/icons/info.svg @@ -0,0 +1,13 @@ + + + + Icon/ info + Created with Sketch. + + + + + + + + \ No newline at end of file diff --git a/resources/themes/cura-light/icons/tab_status_connected.svg b/resources/themes/cura-light/icons/printer_connected.svg similarity index 100% rename from resources/themes/cura-light/icons/tab_status_connected.svg rename to resources/themes/cura-light/icons/printer_connected.svg diff --git a/resources/themes/cura-light/icons/printer_group.svg b/resources/themes/cura-light/icons/printer_group.svg index 614bea90b8..5e439faca4 100644 --- a/resources/themes/cura-light/icons/printer_group.svg +++ b/resources/themes/cura-light/icons/printer_group.svg @@ -1,12 +1,20 @@ - - - icn_groupPrinters + + + Icon/ group printer/ disconnected Created with Sketch. - - - - + + + + + + + + + + + + \ No newline at end of file diff --git a/resources/themes/cura-light/icons/printer_single.svg b/resources/themes/cura-light/icons/printer_single.svg index f7dc83987d..69c4e212bc 100644 --- a/resources/themes/cura-light/icons/printer_single.svg +++ b/resources/themes/cura-light/icons/printer_single.svg @@ -1,13 +1,12 @@ - - - icn_singlePrinter + + + Icon/ single printer/ disconnected Created with Sketch. - - - - - + + + + diff --git a/resources/themes/cura-light/icons/search.svg b/resources/themes/cura-light/icons/search.svg index 8272991300..a9ccb612fd 100644 --- a/resources/themes/cura-light/icons/search.svg +++ b/resources/themes/cura-light/icons/search.svg @@ -1,4 +1,21 @@ - - - + + + + Shape + Created with Sketch. + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/resources/themes/cura-light/icons/spool.svg b/resources/themes/cura-light/icons/spool.svg new file mode 100644 index 0000000000..0d8ae42d9d --- /dev/null +++ b/resources/themes/cura-light/icons/spool.svg @@ -0,0 +1,7 @@ + + + + + + + diff --git a/resources/themes/cura-light/icons/tab_status_busy.svg b/resources/themes/cura-light/icons/tab_status_busy.svg deleted file mode 100644 index debe4f6360..0000000000 --- a/resources/themes/cura-light/icons/tab_status_busy.svg +++ /dev/null @@ -1,13 +0,0 @@ - - - - Busy - Created with Sketch. - - - - - - - - \ No newline at end of file diff --git a/resources/themes/cura-light/icons/tab_status_finished.svg b/resources/themes/cura-light/icons/tab_status_finished.svg deleted file mode 100644 index 2519f2f862..0000000000 --- a/resources/themes/cura-light/icons/tab_status_finished.svg +++ /dev/null @@ -1,13 +0,0 @@ - - - - Wait cleanup - Created with Sketch. - - - - - - - - \ No newline at end of file diff --git a/resources/themes/cura-light/icons/tab_status_paused.svg b/resources/themes/cura-light/icons/tab_status_paused.svg deleted file mode 100644 index bab6c9ca6b..0000000000 --- a/resources/themes/cura-light/icons/tab_status_paused.svg +++ /dev/null @@ -1,13 +0,0 @@ - - - - paused - Created with Sketch. - - - - - - - - \ No newline at end of file diff --git a/resources/themes/cura-light/icons/tab_status_stopped.svg b/resources/themes/cura-light/icons/tab_status_stopped.svg deleted file mode 100644 index c9b150db3a..0000000000 --- a/resources/themes/cura-light/icons/tab_status_stopped.svg +++ /dev/null @@ -1,13 +0,0 @@ - - - - Aborted - Created with Sketch. - - - - - - - - \ No newline at end of file diff --git a/resources/themes/cura-light/icons/tab_status_unknown.svg b/resources/themes/cura-light/icons/tab_status_unknown.svg deleted file mode 100644 index 9f413baffc..0000000000 --- a/resources/themes/cura-light/icons/tab_status_unknown.svg +++ /dev/null @@ -1,13 +0,0 @@ - - - - Unknown - Created with Sketch. - - - - - - - - \ No newline at end of file diff --git a/resources/themes/cura-light/images/avatar_default.svg b/resources/themes/cura-light/images/avatar_default.svg new file mode 100644 index 0000000000..7ec704bc8c --- /dev/null +++ b/resources/themes/cura-light/images/avatar_default.svg @@ -0,0 +1,76 @@ + + + + + + + + + + image/svg+xml + + + + + + + + + + + + diff --git a/resources/themes/cura-light/images/avatar_no_user.svg b/resources/themes/cura-light/images/avatar_no_user.svg new file mode 100644 index 0000000000..bef9cb52db --- /dev/null +++ b/resources/themes/cura-light/images/avatar_no_user.svg @@ -0,0 +1,76 @@ + + + + + + + + + + image/svg+xml + + + + + + + + + + + + diff --git a/resources/themes/cura-light/images/header_pattern.svg b/resources/themes/cura-light/images/header_pattern.svg new file mode 100644 index 0000000000..eff5f01cfa --- /dev/null +++ b/resources/themes/cura-light/images/header_pattern.svg @@ -0,0 +1,1901 @@ + + + + Desktop HD + Created with Sketch. + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/resources/themes/cura-light/images/logo.svg b/resources/themes/cura-light/images/logo.svg index 5fa5895443..55842ef530 100644 --- a/resources/themes/cura-light/images/logo.svg +++ b/resources/themes/cura-light/images/logo.svg @@ -1,4 +1,6 @@ + + + id="svg8" + inkscape:version="0.92.2 (5c3e80d, 2017-08-06)" + sodipodi:docname="logo.svg"> + + + id="metadata5"> image/svg+xml - + - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/resources/themes/cura-light/images/logo_about.svg b/resources/themes/cura-light/images/logo_about.svg new file mode 100644 index 0000000000..34301fd6c9 --- /dev/null +++ b/resources/themes/cura-light/images/logo_about.svg @@ -0,0 +1,172 @@ + + + + + + + + + + image/svg+xml + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/resources/themes/cura-light/styles.qml b/resources/themes/cura-light/styles.qml index b71ddd2d86..bcc754f4ca 100755 --- a/resources/themes/cura-light/styles.qml +++ b/resources/themes/cura-light/styles.qml @@ -1,16 +1,20 @@ -// Copyright (c) 2017 Ultimaker B.V. +// Copyright (c) 2018 Ultimaker B.V. // Cura is released under the terms of the LGPLv3 or higher. -import QtQuick 2.1 -import QtQuick.Controls 1.1 -import QtQuick.Controls.Styles 1.1 +import QtQuick 2.10 +import QtQuick.Controls 1.4 +import QtQuick.Controls.Styles 1.4 import UM 1.1 as UM -QtObject { - property Component sidebar_header_button: Component { - ButtonStyle { - background: Rectangle { +QtObject +{ + property Component print_setup_header_button: Component + { + ButtonStyle + { + background: Rectangle + { color: { if(control.enabled) @@ -34,6 +38,7 @@ QtObject { } } + radius: UM.Theme.getSize("setting_control_radius").width border.width: Theme.getSize("default_lining").width border.color: { @@ -61,20 +66,21 @@ QtObject { return Theme.getColor("setting_control_disabled_border"); } } - UM.RecolorImage { + UM.RecolorImage + { id: downArrow anchors.verticalCenter: parent.verticalCenter anchors.right: parent.right anchors.rightMargin: Theme.getSize("default_margin").width width: Theme.getSize("standard_arrow").width height: Theme.getSize("standard_arrow").height - sourceSize.width: width sourceSize.height: width color: control.enabled ? Theme.getColor("setting_category_text") : Theme.getColor("setting_category_disabled_text") source: Theme.getIcon("arrow_bottom") } - Label { - id: sidebarComboBoxLabel + Label + { + id: printSetupComboBoxLabel color: control.enabled ? Theme.getColor("setting_control_text") : Theme.getColor("setting_control_disabled_text") text: control.text; elide: Text.ElideRight; @@ -90,178 +96,92 @@ QtObject { } } - property Component topbar_header_tab_no_overlay: Component { - ButtonStyle { - background: Rectangle { - implicitHeight: Theme.getSize("topbar_button").height - implicitWidth: Theme.getSize("topbar_button").width - color: "transparent" - anchors.fill: parent + property Component main_window_header_tab: Component + { + ButtonStyle + { + // This property will be back-propagated when the width of the label is calculated + property var buttonWidth: 0 + background: Item + { + implicitHeight: control.height + implicitWidth: buttonWidth Rectangle { - id: underline + id: buttonFace + implicitHeight: parent.height + implicitWidth: parent.width + radius: UM.Theme.getSize("action_button_radius").width - anchors.left: parent.left - anchors.right: parent.right - anchors.bottom: parent.bottom - width: parent.width - height: Theme.getSize("sidebar_header_highlight").height - color: control.checked ? UM.Theme.getColor("sidebar_header_highlight") : UM.Theme.getColor("sidebar_header_highlight_hover") - visible: control.hovered || control.checked - } - } - - label: Rectangle { - implicitHeight: Theme.getSize("topbar_button_icon").height - implicitWidth: Theme.getSize("topbar_button").width - color: "transparent" - anchors.fill: parent - - Item - { - anchors.centerIn: parent - width: Math.round(textLabel.width + icon.width + Theme.getSize("default_margin").width / 2) - Label + color: { - id: textLabel - text: control.text - anchors.right: icon.visible ? icon.left : parent.right - anchors.rightMargin: icon.visible ? Math.round(Theme.getSize("default_margin").width / 2) : 0 - anchors.verticalCenter: parent.verticalCenter; - font: control.checked ? UM.Theme.getFont("large") : UM.Theme.getFont("large_nonbold") - color: + if (control.checked) { - if(control.hovered) - { - return UM.Theme.getColor("topbar_button_text_hovered"); - } - if(control.checked) - { - return UM.Theme.getColor("topbar_button_text_active"); - } - else - { - return UM.Theme.getColor("topbar_button_text_inactive"); - } + return UM.Theme.getColor("main_window_header_button_background_active") + } + else + { + if (control.hovered) + { + return UM.Theme.getColor("main_window_header_button_background_hovered") + } + return UM.Theme.getColor("main_window_header_button_background_inactive") } - } - Image - { - id: icon - visible: control.iconSource != "" - anchors.right: parent.right - anchors.verticalCenter: parent.verticalCenter - opacity: !control.enabled ? 0.2 : 1.0 - source: control.iconSource - width: visible ? Theme.getSize("topbar_button_icon").width : 0 - height: Theme.getSize("topbar_button_icon").height - - sourceSize: Theme.getSize("topbar_button_icon") - } - } - } - } - } - - property Component topbar_header_tab: Component { - ButtonStyle { - background: Item { - implicitHeight: Theme.getSize("topbar_button").height - implicitWidth: Theme.getSize("topbar_button").width + Theme.getSize("topbar_button_icon").width - - Rectangle { - id: buttonFace; - anchors.fill: parent; - - color: "transparent" - Behavior on color { ColorAnimation { duration: 50; } } - - Rectangle { - id: underline; - - anchors.horizontalCenter: parent.horizontalCenter - anchors.bottom: parent.bottom - width: Theme.getSize("topbar_button").width + Theme.getSize("topbar_button_icon").width - height: Theme.getSize("sidebar_header_highlight").height - color: control.checked ? UM.Theme.getColor("sidebar_header_highlight") : UM.Theme.getColor("sidebar_header_highlight_hover") - visible: control.hovered || control.checked } } } label: Item { - implicitHeight: Theme.getSize("topbar_button_icon").height - implicitWidth: Theme.getSize("topbar_button").width + Theme.getSize("topbar_button_icon").width - Item + id: contents + anchors.horizontalCenter: parent.horizontalCenter + anchors.verticalCenter: parent.verticalCenter + height: control.height + width: buttonLabel.width + 4 * UM.Theme.getSize("default_margin").width + + Label { + id: buttonLabel + text: control.text + anchors.verticalCenter: parent.verticalCenter anchors.horizontalCenter: parent.horizontalCenter - anchors.verticalCenter: parent.verticalCenter; - width: childrenRect.width - height: Theme.getSize("topbar_button_icon").height - Label + font: UM.Theme.getFont("medium") + color: { - id: button_label - text: control.text; - anchors.verticalCenter: parent.verticalCenter; - font: control.checked ? UM.Theme.getFont("large") : UM.Theme.getFont("large_nonbold") - color: + if (control.checked) { - if(control.hovered) + return UM.Theme.getColor("main_window_header_button_text_active") + } + else + { + if (control.hovered) { - return UM.Theme.getColor("topbar_button_text_hovered"); - } - if(control.checked) - { - return UM.Theme.getColor("topbar_button_text_active"); - } - else - { - return UM.Theme.getColor("topbar_button_text_inactive"); + return UM.Theme.getColor("main_window_header_button_text_hovered") } + return UM.Theme.getColor("main_window_header_button_text_inactive") } } - UM.RecolorImage - { - visible: control.iconSource != "" - id: icon - anchors.left: button_label.right - anchors.leftMargin: (icon.visible || overlayIcon.visible) ? Theme.getSize("default_margin").width : 0 - color: UM.Theme.getColor("text_emphasis") - opacity: !control.enabled ? 0.2 : 1.0 - source: control.iconSource - width: visible ? Theme.getSize("topbar_button_icon").width : 0 - height: Theme.getSize("topbar_button_icon").height - - sourceSize: Theme.getSize("topbar_button_icon") - } - UM.RecolorImage - { - id: overlayIcon - anchors.left: button_label.right - anchors.leftMargin: (icon.visible || overlayIcon.visible) ? Theme.getSize("default_margin").width : 0 - visible: control.overlayIconSource != "" && control.iconSource != "" - color: control.overlayColor - opacity: !control.enabled ? 0.2 : 1.0 - source: control.overlayIconSource - width: visible ? Theme.getSize("topbar_button_icon").width : 0 - height: Theme.getSize("topbar_button_icon").height - - sourceSize: Theme.getSize("topbar_button_icon") - } + } + Component.onCompleted: + { + buttonWidth = width } } } } - property Component tool_button: Component { - ButtonStyle { - background: Item { + property Component tool_button: Component + { + ButtonStyle + { + background: Item + { implicitWidth: Theme.getSize("button").width; implicitHeight: Theme.getSize("button").height; - UM.PointingRectangle { + UM.PointingRectangle + { id: button_tooltip anchors.left: parent.right @@ -280,7 +200,8 @@ QtObject { Behavior on width { NumberAnimation { duration: 100; } } Behavior on opacity { NumberAnimation { duration: 100; } } - Label { + Label + { id: button_tip anchors.horizontalCenter: parent.horizontalCenter @@ -292,7 +213,8 @@ QtObject { } } - Rectangle { + Rectangle + { id: buttonFace; anchors.fill: parent; @@ -326,7 +248,8 @@ QtObject { border.width: (control.hasOwnProperty("needBorder") && control.needBorder) ? 2 * screenScaleFactor : 0 border.color: Theme.getColor("tool_button_border") - UM.RecolorImage { + UM.RecolorImage + { id: tool_button_arrow anchors.right: parent.right; anchors.rightMargin: Theme.getSize("button").width - Math.round(Theme.getSize("button_icon").width / 4) @@ -334,7 +257,6 @@ QtObject { anchors.bottomMargin: Theme.getSize("button").height - Math.round(Theme.getSize("button_icon").height / 4) width: Theme.getSize("standard_arrow").width height: Theme.getSize("standard_arrow").height - sourceSize.width: width sourceSize.height: width visible: control.menu != null; color: @@ -361,8 +283,10 @@ QtObject { } } - label: Item { - UM.RecolorImage { + label: Item + { + UM.RecolorImage + { anchors.centerIn: parent; opacity: !control.enabled ? 0.2 : 1.0 source: control.iconSource; @@ -394,119 +318,19 @@ QtObject { } } - property Component small_tool_button: Component { - ButtonStyle { - background: Item { - implicitWidth: Theme.getSize("small_button").width; - implicitHeight: Theme.getSize("small_button").height; - - Rectangle { - id: smallButtonFace; - - anchors.fill: parent; - property bool down: control.pressed || (control.checkable && control.checked); - - color: - { - if(control.customColor !== undefined && control.customColor !== null) - { - return control.customColor - } - else if(control.checkable && control.checked && control.hovered) - { - return Theme.getColor("small_button_active_hover"); - } - else if(control.pressed || (control.checkable && control.checked)) - { - return Theme.getColor("small_button_active"); - } - else if(control.hovered) - { - return Theme.getColor("small_button_hover"); - } - else - { - return Theme.getColor("small_button"); - } - } - Behavior on color { ColorAnimation { duration: 50; } } - - border.width: (control.hasOwnProperty("needBorder") && control.needBorder) ? 2 * screenScaleFactor : 0 - border.color: Theme.getColor("tool_button_border") - - UM.RecolorImage { - id: smallToolButtonArrow - - width: 5 - height: 5 - sourceSize.width: 5 - sourceSize.height: 5 - visible: control.menu != null; - color: - { - if(control.checkable && control.checked && control.hovered) - { - return Theme.getColor("small_button_text_active_hover"); - } - else if(control.pressed || (control.checkable && control.checked)) - { - return Theme.getColor("small_button_text_active"); - } - else if(control.hovered) - { - return Theme.getColor("small_button_text_hover"); - } - else - { - return Theme.getColor("small_button_text"); - } - } - source: Theme.getIcon("arrow_bottom") - } - } - } - - label: Item { - UM.RecolorImage { - anchors.centerIn: parent; - opacity: !control.enabled ? 0.2 : 1.0 - source: control.iconSource; - width: Theme.getSize("small_button_icon").width; - height: Theme.getSize("small_button_icon").height; - color: - { - if(control.checkable && control.checked && control.hovered) - { - return Theme.getColor("small_button_text_active_hover"); - } - else if(control.pressed || (control.checkable && control.checked)) - { - return Theme.getColor("small_button_text_active"); - } - else if(control.hovered) - { - return Theme.getColor("small_button_text_hover"); - } - else - { - return Theme.getColor("small_button_text"); - } - } - - sourceSize: Theme.getSize("small_button_icon") - } - } - } - } - - property Component progressbar: Component{ - ProgressBarStyle { - background: Rectangle { + property Component progressbar: Component + { + ProgressBarStyle + { + background: Rectangle + { implicitWidth: Theme.getSize("message").width - (Theme.getSize("default_margin").width * 2) implicitHeight: Theme.getSize("progressbar").height color: control.hasOwnProperty("backgroundColor") ? control.backgroundColor : Theme.getColor("progressbar_background") + radius: Theme.getSize("progressbar_radius").width } - progress: Rectangle { + progress: Rectangle + { color: { if(control.indeterminate) @@ -523,14 +347,16 @@ QtObject { } } radius: Theme.getSize("progressbar_radius").width - Rectangle{ + Rectangle + { radius: Theme.getSize("progressbar_radius").width color: control.hasOwnProperty("controlColor") ? control.controlColor : Theme.getColor("progressbar_control") width: Theme.getSize("progressbar_control").width height: Theme.getSize("progressbar_control").height visible: control.indeterminate - SequentialAnimation on x { + SequentialAnimation on x + { id: xAnim property int animEndPoint: Theme.getSize("message").width - Math.round((Theme.getSize("default_margin").width * 2.5)) - Theme.getSize("progressbar_control").width running: control.indeterminate && control.visible @@ -543,194 +369,41 @@ QtObject { } } - property Component sidebar_category: Component { - ButtonStyle { - background: Rectangle { - anchors.fill: parent; - anchors.left: parent.left - anchors.leftMargin: Theme.getSize("sidebar_margin").width - anchors.right: parent.right - anchors.rightMargin: Theme.getSize("sidebar_margin").width - implicitHeight: Theme.getSize("section").height; - color: { - if(control.color) { - return control.color; - } else if(!control.enabled) { - return Theme.getColor("setting_category_disabled"); - } else if(control.hovered && control.checkable && control.checked) { - return Theme.getColor("setting_category_active_hover"); - } else if(control.pressed || (control.checkable && control.checked)) { - return Theme.getColor("setting_category_active"); - } else if(control.hovered) { - return Theme.getColor("setting_category_hover"); - } else { - return Theme.getColor("setting_category"); - } - } - Behavior on color { ColorAnimation { duration: 50; } } - Rectangle { - height: Theme.getSize("default_lining").height - width: parent.width - anchors.bottom: parent.bottom - color: { - if(!control.enabled) { - return Theme.getColor("setting_category_disabled_border"); - } else if((control.hovered || control.activeFocus) && control.checkable && control.checked) { - return Theme.getColor("setting_category_active_hover_border"); - } else if(control.pressed || (control.checkable && control.checked)) { - return Theme.getColor("setting_category_active_border"); - } else if(control.hovered || control.activeFocus) { - return Theme.getColor("setting_category_hover_border"); - } else { - return Theme.getColor("setting_category_border"); - } - } - } - } - label: Item { - anchors.fill: parent; - anchors.left: parent.left - Item{ - id: icon; - anchors.left: parent.left - height: parent.height - width: Theme.getSize("section_icon_column").width - UM.RecolorImage { - anchors.verticalCenter: parent.verticalCenter - anchors.left: parent.left - anchors.leftMargin: Theme.getSize("sidebar_margin").width - color: - { - if(!control.enabled) - { - return Theme.getColor("setting_category_disabled_text"); - } - else if((control.hovered || control.activeFocus) && control.checkable && control.checked) - { - return Theme.getColor("setting_category_active_hover_text"); - } - else if(control.pressed || (control.checkable && control.checked)) - { - return Theme.getColor("setting_category_active_text"); - } - else if(control.hovered || control.activeFocus) - { - return Theme.getColor("setting_category_hover_text"); - } - else - { - return Theme.getColor("setting_category_text"); - } - } - source: control.iconSource; - width: Theme.getSize("section_icon").width; - height: Theme.getSize("section_icon").height; - sourceSize.width: width + 15 * screenScaleFactor - sourceSize.height: width + 15 * screenScaleFactor - } - } - - Label { - anchors { - left: icon.right; - leftMargin: Theme.getSize("default_margin").width; - right: parent.right; - verticalCenter: parent.verticalCenter; - } - text: control.text; - font: Theme.getFont("setting_category"); - color: - { - if(!control.enabled) - { - return Theme.getColor("setting_category_disabled_text"); - } - else if((control.hovered || control.activeFocus) && control.checkable && control.checked) - { - return Theme.getColor("setting_category_active_hover_text"); - } - else if(control.pressed || (control.checkable && control.checked)) - { - return Theme.getColor("setting_category_active_text"); - } - else if(control.hovered || control.activeFocus) - { - return Theme.getColor("setting_category_hover_text"); - } - else - { - return Theme.getColor("setting_category_text"); - } - } - fontSizeMode: Text.HorizontalFit; - minimumPointSize: 8 - } - UM.RecolorImage { - id: category_arrow - anchors.verticalCenter: parent.verticalCenter - anchors.right: parent.right - anchors.rightMargin: Theme.getSize("default_margin").width * 3 - Math.round(width / 2) - width: Theme.getSize("standard_arrow").width - height: Theme.getSize("standard_arrow").height - sourceSize.width: width - sourceSize.height: width - color: - { - if(!control.enabled) - { - return Theme.getColor("setting_category_disabled_text"); - } - else if((control.hovered || control.activeFocus) && control.checkable && control.checked) - { - return Theme.getColor("setting_category_active_hover_text"); - } - else if(control.pressed || (control.checkable && control.checked)) - { - return Theme.getColor("setting_category_active_text"); - } - else if(control.hovered || control.activeFocus) - { - return Theme.getColor("setting_category_hover_text"); - } - else - { - return Theme.getColor("setting_category_text"); - } - } - source: control.checked ? Theme.getIcon("arrow_bottom") : Theme.getIcon("arrow_left") - } - } - } - } - - property Component scrollview: Component { - ScrollViewStyle { + property Component scrollview: Component + { + ScrollViewStyle + { decrementControl: Item { } incrementControl: Item { } transientScrollBars: false - scrollBarBackground: Rectangle { + scrollBarBackground: Rectangle + { implicitWidth: Theme.getSize("scrollbar").width radius: Math.round(implicitWidth / 2) - color: Theme.getColor("scrollbar_background"); + color: Theme.getColor("scrollbar_background") } - handle: Rectangle { + handle: Rectangle + { id: scrollViewHandle - implicitWidth: Theme.getSize("scrollbar").width; + implicitWidth: Theme.getSize("scrollbar").width radius: Math.round(implicitWidth / 2) - color: styleData.pressed ? Theme.getColor("scrollbar_handle_down") : styleData.hovered ? Theme.getColor("scrollbar_handle_hover") : Theme.getColor("scrollbar_handle"); + color: styleData.pressed ? Theme.getColor("scrollbar_handle_down") : styleData.hovered ? Theme.getColor("scrollbar_handle_hover") : Theme.getColor("scrollbar_handle") Behavior on color { ColorAnimation { duration: 50; } } } } } - property Component combobox: Component { - ComboBoxStyle { + property Component combobox: Component + { + ComboBoxStyle + { - background: Rectangle { + background: Rectangle + { implicitHeight: Theme.getSize("setting_control").height; implicitWidth: Theme.getSize("setting_control").width; @@ -739,30 +412,33 @@ QtObject { border.width: Theme.getSize("default_lining").width; border.color: control.hovered ? Theme.getColor("setting_control_border_highlight") : Theme.getColor("setting_control_border"); + radius: UM.Theme.getSize("setting_control_radius").width } - label: Item { - - Label { - anchors.left: parent.left; + label: Item + { + Label + { + anchors.left: parent.left anchors.leftMargin: Theme.getSize("default_lining").width - anchors.right: downArrow.left; - anchors.rightMargin: Theme.getSize("default_lining").width; - anchors.verticalCenter: parent.verticalCenter; + anchors.right: downArrow.left + anchors.rightMargin: Theme.getSize("default_lining").width + anchors.verticalCenter: parent.verticalCenter - text: control.currentText; + text: control.currentText font: Theme.getFont("default"); - color: !enabled ? Theme.getColor("setting_control_disabled_text") : Theme.getColor("setting_control_text"); + color: !enabled ? Theme.getColor("setting_control_disabled_text") : Theme.getColor("setting_control_text") - elide: Text.ElideRight; - verticalAlignment: Text.AlignVCenter; + elide: Text.ElideRight + verticalAlignment: Text.AlignVCenter } - UM.RecolorImage { + UM.RecolorImage + { id: downArrow - anchors.right: parent.right; - anchors.rightMargin: Theme.getSize("default_lining").width * 2; - anchors.verticalCenter: parent.verticalCenter; + anchors.right: parent.right + anchors.rightMargin: Theme.getSize("default_lining").width * 2 + anchors.verticalCenter: parent.verticalCenter source: Theme.getIcon("arrow_bottom") width: Theme.getSize("standard_arrow").width @@ -777,19 +453,24 @@ QtObject { } // Combobox with items with colored rectangles - property Component combobox_color: Component { + property Component combobox_color: Component + { - ComboBoxStyle { + ComboBoxStyle + { - background: Rectangle { + background: Rectangle + { color: !enabled ? UM.Theme.getColor("setting_control_disabled") : control._hovered ? UM.Theme.getColor("setting_control_highlight") : UM.Theme.getColor("setting_control") border.width: UM.Theme.getSize("default_lining").width border.color: !enabled ? UM.Theme.getColor("setting_control_disabled_border") : control._hovered ? UM.Theme.getColor("setting_control_border_highlight") : UM.Theme.getColor("setting_control_border") + radius: UM.Theme.getSize("setting_control_radius").width } - label: Item { - - Label { + label: Item + { + Label + { anchors.left: parent.left anchors.leftMargin: UM.Theme.getSize("default_lining").width anchors.right: swatch.left @@ -804,20 +485,23 @@ QtObject { verticalAlignment: Text.AlignVCenter } - Rectangle { + UM.RecolorImage + { id: swatch - height: Math.round(UM.Theme.getSize("setting_control").height / 2) + height: Math.round(control.height / 2) width: height anchors.right: downArrow.left anchors.verticalCenter: parent.verticalCenter - anchors.margins: Math.round(UM.Theme.getSize("default_margin").width / 4) - radius: Math.round(width / 2) - border.width: UM.Theme.getSize("default_lining").width - border.color: UM.Theme.getColor("lining") + anchors.rightMargin: UM.Theme.getSize("default_margin").width + + sourceSize.width: width + sourceSize.height: height + source: UM.Theme.getIcon("extruder_button") color: (control.color_override !== "") ? control.color_override : control.color } - UM.RecolorImage { + UM.RecolorImage + { id: downArrow anchors.right: parent.right anchors.rightMargin: UM.Theme.getSize("default_lining").width * 2 @@ -835,27 +519,30 @@ QtObject { } } - property Component checkbox: Component { - CheckBoxStyle { + property Component checkbox: Component + { + CheckBoxStyle + { background: Item { } - indicator: Rectangle { - implicitWidth: Theme.getSize("checkbox").width; - implicitHeight: Theme.getSize("checkbox").height; + indicator: Rectangle + { + implicitWidth: Theme.getSize("checkbox").width + implicitHeight: Theme.getSize("checkbox").height - color: (control.hovered || control._hovered) ? Theme.getColor("checkbox_hover") : Theme.getColor("checkbox"); + color: (control.hovered || control._hovered) ? Theme.getColor("checkbox_hover") : (control.enabled ? Theme.getColor("checkbox") : Theme.getColor("checkbox_disabled")) Behavior on color { ColorAnimation { duration: 50; } } - radius: control.exclusiveGroup ? Math.round(Theme.getSize("checkbox").width / 2) : 0 + radius: control.exclusiveGroup ? Math.round(Theme.getSize("checkbox").width / 2) : UM.Theme.getSize("checkbox_radius").width - border.width: Theme.getSize("default_lining").width; - border.color: (control.hovered || control._hovered) ? Theme.getColor("checkbox_border_hover") : Theme.getColor("checkbox_border"); + border.width: Theme.getSize("default_lining").width + border.color: (control.hovered || control._hovered) ? Theme.getColor("checkbox_border_hover") : Theme.getColor("checkbox_border") - UM.RecolorImage { + UM.RecolorImage + { anchors.verticalCenter: parent.verticalCenter anchors.horizontalCenter: parent.horizontalCenter width: Math.round(parent.width / 2.5) height: Math.round(parent.height / 2.5) - sourceSize.width: width sourceSize.height: width color: Theme.getColor("checkbox_mark") source: control.exclusiveGroup ? Theme.getIcon("dot") : Theme.getIcon("check") @@ -863,98 +550,74 @@ QtObject { Behavior on opacity { NumberAnimation { duration: 100; } } } } - label: Label { + label: Label + { text: control.text color: Theme.getColor("checkbox_text") font: Theme.getFont("default") elide: Text.ElideRight + renderType: Text.NativeRendering } } } - property Component partially_checkbox: Component { - CheckBoxStyle { + property Component partially_checkbox: Component + { + CheckBoxStyle + { background: Item { } - indicator: Rectangle { - implicitWidth: Theme.getSize("checkbox").width; - implicitHeight: Theme.getSize("checkbox").height; + indicator: Rectangle + { + implicitWidth: Theme.getSize("checkbox").width + implicitHeight: Theme.getSize("checkbox").height color: (control.hovered || control._hovered) ? Theme.getColor("checkbox_hover") : Theme.getColor("checkbox"); Behavior on color { ColorAnimation { duration: 50; } } - radius: control.exclusiveGroup ? Math.round(Theme.getSize("checkbox").width / 2) : 0 + radius: control.exclusiveGroup ? Math.round(Theme.getSize("checkbox").width / 2) : UM.Theme.getSize("checkbox_radius").width border.width: Theme.getSize("default_lining").width; border.color: (control.hovered || control._hovered) ? Theme.getColor("checkbox_border_hover") : Theme.getColor("checkbox_border"); - UM.RecolorImage { + UM.RecolorImage + { anchors.verticalCenter: parent.verticalCenter anchors.horizontalCenter: parent.horizontalCenter width: Math.round(parent.width / 2.5) height: Math.round(parent.height / 2.5) - sourceSize.width: width sourceSize.height: width color: Theme.getColor("checkbox_mark") - source: { - if (control.checkbox_state == 2){ - return Theme.getIcon("solid") + source: + { + if (control.checkbox_state == 2) + { + return Theme.getIcon("solid"); } - else{ - return control.exclusiveGroup ? Theme.getIcon("dot") : Theme.getIcon("check") + else + { + return control.exclusiveGroup ? Theme.getIcon("dot") : Theme.getIcon("check"); } } opacity: control.checked Behavior on opacity { NumberAnimation { duration: 100; } } } } - label: Label { - text: control.text; - color: Theme.getColor("checkbox_text"); - font: Theme.getFont("default"); + label: Label + { + text: control.text + color: Theme.getColor("checkbox_text") + font: Theme.getFont("default") } } } - property Component slider: Component { - SliderStyle { - groove: Rectangle { - implicitWidth: control.width; - implicitHeight: Theme.getSize("slider_groove").height; - - color: Theme.getColor("slider_groove"); - border.width: Theme.getSize("default_lining").width; - border.color: Theme.getColor("slider_groove_border"); - - radius: Math.round(width / 2); - - Rectangle { - anchors { - left: parent.left; - top: parent.top; - bottom: parent.bottom; - } - color: Theme.getColor("slider_groove_fill"); - width: Math.round((control.value / (control.maximumValue - control.minimumValue)) * parent.width); - radius: Math.round(width / 2); - } - } - handle: Rectangle { - width: Theme.getSize("slider_handle").width; - height: Theme.getSize("slider_handle").height; - color: control.hovered ? Theme.getColor("slider_handle_hover") : Theme.getColor("slider_handle"); - border.width: Theme.getSize("default_lining").width - border.color: control.hovered ? Theme.getColor("slider_handle_hover_border") : Theme.getColor("slider_handle_border") - radius: Math.round(Theme.getSize("slider_handle").width / 2); //Round. - Behavior on color { ColorAnimation { duration: 50; } } - } - } - } - - property Component text_field: Component { - TextFieldStyle { - textColor: Theme.getColor("setting_control_text"); + property Component text_field: Component + { + TextFieldStyle + { + textColor: Theme.getColor("setting_control_text") placeholderTextColor: Theme.getColor("setting_control_text") - font: Theme.getFont("default"); + font: Theme.getFont("default") background: Rectangle { @@ -963,10 +626,12 @@ QtObject { border.width: Theme.getSize("default_lining").width; border.color: control.hovered ? Theme.getColor("setting_control_border_highlight") : Theme.getColor("setting_control_border"); + radius: UM.Theme.getSize("setting_control_radius").width color: Theme.getColor("setting_validation_ok"); - Label { + Label + { anchors.right: parent.right; anchors.rightMargin: Theme.getSize("setting_unit_margin").width; anchors.verticalCenter: parent.verticalCenter; @@ -979,7 +644,8 @@ QtObject { } } - property Component sidebar_action_button: Component { + property Component print_setup_action_button: Component + { ButtonStyle { background: Rectangle @@ -988,28 +654,44 @@ QtObject { border.color: { if(!control.enabled) + { return UM.Theme.getColor("action_button_disabled_border"); + } else if(control.pressed) + { return UM.Theme.getColor("action_button_active_border"); + } else if(control.hovered) + { return UM.Theme.getColor("action_button_hovered_border"); + } else + { return UM.Theme.getColor("action_button_border"); + } } color: { if(!control.enabled) + { return UM.Theme.getColor("action_button_disabled"); + } else if(control.pressed) + { return UM.Theme.getColor("action_button_active"); + } else if(control.hovered) + { return UM.Theme.getColor("action_button_hovered"); + } else + { return UM.Theme.getColor("action_button"); + } } - Behavior on color { ColorAnimation { duration: 50; } } + Behavior on color { ColorAnimation { duration: 50 } } - implicitWidth: actualLabel.contentWidth + (UM.Theme.getSize("sidebar_margin").width * 2) + implicitWidth: actualLabel.contentWidth + (UM.Theme.getSize("thick_margin").width * 2) Label { @@ -1018,13 +700,21 @@ QtObject { color: { if(!control.enabled) + { return UM.Theme.getColor("action_button_disabled_text"); + } else if(control.pressed) + { return UM.Theme.getColor("action_button_active_text"); + } else if(control.hovered) + { return UM.Theme.getColor("action_button_hovered_text"); + } else + { return UM.Theme.getColor("action_button_text"); + } } font: UM.Theme.getFont("action_button") text: control.text @@ -1034,7 +724,8 @@ QtObject { } } - property Component toolbox_action_button: Component { + property Component toolbox_action_button: Component + { ButtonStyle { background: Rectangle @@ -1045,17 +736,17 @@ QtObject { { if (control.installed) { - return UM.Theme.getColor("action_button_disabled") + return UM.Theme.getColor("action_button_disabled"); } else { if (control.hovered) { - return UM.Theme.getColor("primary_hover") + return UM.Theme.getColor("primary_hover"); } else { - return UM.Theme.getColor("primary") + return UM.Theme.getColor("primary"); } } @@ -1068,17 +759,17 @@ QtObject { { if (control.installed) { - return UM.Theme.getColor("action_button_disabled_text") + return UM.Theme.getColor("action_button_disabled_text"); } else { if (control.hovered) { - return UM.Theme.getColor("button_text_hover") + return UM.Theme.getColor("button_text_hover"); } else { - return UM.Theme.getColor("button_text") + return UM.Theme.getColor("button_text"); } } } @@ -1088,4 +779,153 @@ QtObject { } } } + + property Component monitor_button_style: Component + { + 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("action_button_active_border"); + } + else if(control.hovered) + { + return UM.Theme.getColor("action_button_hovered_border"); + } + return UM.Theme.getColor("action_button_border"); + } + color: + { + if(!control.enabled) + { + return UM.Theme.getColor("action_button_disabled"); + } + else if(control.pressed) + { + return UM.Theme.getColor("action_button_active"); + } + else if(control.hovered) + { + return UM.Theme.getColor("action_button_hovered"); + } + return UM.Theme.getColor("action_button"); + } + Behavior on color + { + ColorAnimation + { + duration: 50 + } + } + } + + label: Item + { + UM.RecolorImage + { + anchors.verticalCenter: parent.verticalCenter + anchors.horizontalCenter: parent.horizontalCenter + width: Math.floor(control.width / 2) + height: Math.floor(control.height / 2) + sourceSize.height: width + color: + { + if(!control.enabled) + { + return UM.Theme.getColor("action_button_disabled_text"); + } + else if(control.pressed) + { + return UM.Theme.getColor("action_button_active_text"); + } + else if(control.hovered) + { + return UM.Theme.getColor("action_button_hovered_text"); + } + return UM.Theme.getColor("action_button_text"); + } + source: control.iconSource + } + } + } + } + + property Component monitor_checkable_button_style: Component + { + ButtonStyle { + background: Rectangle { + border.width: control.checked ? UM.Theme.getSize("default_lining").width * 2 : UM.Theme.getSize("default_lining").width + border.color: + { + if(!control.enabled) + { + return UM.Theme.getColor("action_button_disabled_border"); + } + else if (control.checked || control.pressed) + { + return UM.Theme.getColor("action_button_active_border"); + } + else if(control.hovered) + { + return UM.Theme.getColor("action_button_hovered_border"); + } + return UM.Theme.getColor("action_button_border"); + } + color: + { + if(!control.enabled) + { + return UM.Theme.getColor("action_button_disabled"); + } + else if (control.checked || control.pressed) + { + return UM.Theme.getColor("action_button_active"); + } + else if (control.hovered) + { + return UM.Theme.getColor("action_button_hovered"); + } + return UM.Theme.getColor("action_button"); + } + Behavior on color { ColorAnimation { duration: 50; } } + Label { + anchors.left: parent.left + anchors.right: parent.right + anchors.verticalCenter: parent.verticalCenter + anchors.leftMargin: UM.Theme.getSize("default_lining").width * 2 + anchors.rightMargin: UM.Theme.getSize("default_lining").width * 2 + color: + { + if(!control.enabled) + { + return UM.Theme.getColor("action_button_disabled_text"); + } + else if (control.checked || control.pressed) + { + return UM.Theme.getColor("action_button_active_text"); + } + else if (control.hovered) + { + return UM.Theme.getColor("action_button_hovered_text"); + } + return UM.Theme.getColor("action_button_text"); + } + font: UM.Theme.getFont("default") + text: control.text + horizontalAlignment: Text.AlignHCenter + elide: Text.ElideMiddle + } + } + label: Item { } + } + } } diff --git a/resources/themes/cura-light/theme.json b/resources/themes/cura-light/theme.json index 25c9a678c1..3dc216ad70 100644 --- a/resources/themes/cura-light/theme.json +++ b/resources/themes/cura-light/theme.json @@ -35,18 +35,18 @@ "family": "Noto Sans" }, "default_italic": { - "size": 1.15, + "size": 1.0, "weight": 50, "italic": true, "family": "Noto Sans" }, "small": { - "size": 1.0, - "weight": 63, + "size": 0.85, + "weight": 50, "family": "Noto Sans" }, "very_small": { - "size": 1.0, + "size": 0.7, "weight": 50, "family": "Noto Sans" }, @@ -69,46 +69,72 @@ "colors": { - "sidebar": [255, 255, 255, 255], + "main_background": [255, 255, 255, 255], + "wide_lining": [245, 245, 245, 255], + "thick_lining": [127, 127, 127, 255], "lining": [192, 193, 194, 255], "viewport_overlay": [0, 0, 0, 192], - "primary": [12, 169, 227, 255], + "primary": [50, 130, 255, 255], + "primary_shadow": [64, 47, 205, 255], "primary_hover": [48, 182, 231, 255], "primary_text": [255, 255, 255, 255], "border": [127, 127, 127, 255], - "secondary": [245, 245, 245, 255], + "secondary": [240, 240, 240, 255], + "secondary_shadow": [216, 216, 216, 255], - "topbar_background_color": [255, 255, 255, 0], - "topbar_background_color_monitoring": [255, 255, 255, 255], + "primary_button": [38, 113, 231, 255], + "primary_button_shadow": [27, 95, 202, 255], + "primary_button_hover": [81, 145, 247, 255], + "primary_button_text": [255, 255, 255, 255], - "topbar_button_text_active": [0, 0, 0, 255], - "topbar_button_text_inactive": [128, 128, 128, 255], - "topbar_button_text_hovered": [0, 0, 0, 255], + "secondary_button": [240, 240, 240, 255], + "secondary_button_shadow": [216, 216, 216, 255], + "secondary_button_hover": [228, 228, 228, 255], + "secondary_button_text": [30, 102, 215, 255], + + "main_window_header_background": [8, 7, 63, 255], + "main_window_header_background_gradient": [25, 23, 91, 255], + "main_window_header_button_text_active": [8, 7, 63, 255], + "main_window_header_button_text_inactive": [255, 255, 255, 255], + "main_window_header_button_text_hovered": [255, 255, 255, 255], + "main_window_header_button_background_active": [255, 255, 255, 255], + "main_window_header_button_background_inactive": [255, 255, 255, 0], + "main_window_header_button_background_hovered": [117, 114, 159, 255], + + "account_widget_outline_active": [70, 66, 126, 255], + + "machine_selector_bar": [31, 36, 39, 255], + "machine_selector_active": [68, 72, 75, 255], + "machine_selector_hover": [68, 72, 75, 255], + "machine_selector_text_active": [255, 255, 255, 255], + "machine_selector_printer_icon": [8, 7, 63, 255], + + "action_panel_secondary": [27, 95, 202, 255], + + "toolbar_background": [255, 255, 255, 255], + + "printer_type_label_background": [228, 228, 242, 255], "text": [0, 0, 0, 255], "text_detail": [174, 174, 174, 128], - "text_link": [12, 169, 227, 255], + "text_link": [50, 130, 255, 255], "text_inactive": [174, 174, 174, 255], - "text_hover": [70, 84, 113, 255], - "text_pressed": [12, 169, 227, 255], + "text_pressed": [50, 130, 255, 255], "text_subtext": [0, 0, 0, 255], "text_medium": [128, 128, 128, 255], "text_emphasis": [255, 255, 255, 255], - "text_scene": [31, 36, 39, 255], - "text_scene_hover": [70, 84, 113, 255], + "text_scene": [102, 102, 102, 255], + "text_scene_hover": [123, 123, 113, 255], "error": [255, 140, 0, 255], - "sidebar_header_bar": [31, 36, 39, 255], - "sidebar_header_active": [68, 72, 75, 255], - "sidebar_header_hover": [68, 72, 75, 255], - "sidebar_header_highlight": [68, 192, 255, 255], - "sidebar_header_highlight_hover": [68, 192, 255, 255], - "sidebar_header_text_inactive": [255, 255, 255, 255], - "sidebar_header_text_active": [255, 255, 255, 255], - "sidebar_header_text_hover": [255, 255, 255, 255], - "sidebar_lining": [245, 245, 245, 255], - "sidebar_lining_thin": [127, 127, 127, 255], + "warning": [245, 166, 35, 255], + "disabled": [229, 229, 229, 255], + + "toolbar_button_text": [8, 7, 63, 255], + "toolbar_button_hover": [232, 242, 252, 255], + "toolbar_button_active": [232, 242, 252, 255], + "toolbar_button_active_hover": [232, 242, 252, 255], "button": [31, 36, 39, 255], "button_hover": [68, 72, 75, 255], @@ -118,15 +144,13 @@ "button_text_hover": [255, 255, 255, 255], "button_text_active": [255, 255, 255, 255], "button_text_active_hover": [255, 255, 255, 255], - "button_disabled": [31, 36, 39, 255], - "button_disabled_text": [255, 255, 255, 101], - "small_button": [31, 36, 39, 0], - "small_button_hover": [68, 72, 75, 255], - "small_button_active": [68, 72, 75, 255], - "small_button_active_hover": [68, 72, 75, 255], - "small_button_text": [31, 36, 39, 197], - "small_button_text_hover": [255, 255, 255, 255], + "small_button": [0, 0, 0, 0], + "small_button_hover": [102, 102, 102, 255], + "small_button_active": [10, 8, 80, 255], + "small_button_active_hover": [10, 8, 80, 255], + "small_button_text": [102, 102, 102, 255], + "small_button_text_hover": [8, 7, 63, 255], "small_button_text_active": [255, 255, 255, 255], "small_button_text_active_hover": [255, 255, 255, 255], @@ -142,54 +166,47 @@ "action_button": [255, 255, 255, 255], "action_button_text": [0, 0, 0, 255], "action_button_border": [127, 127, 127, 255], - "action_button_hovered": [255, 255, 255, 255], + "action_button_hovered": [232, 242, 252, 255], "action_button_hovered_text": [31, 36, 39, 255], - "action_button_hovered_border": [12, 169, 227, 255], + "action_button_hovered_border": [50, 130, 255, 255], "action_button_active": [255, 255, 255, 255], "action_button_active_text": [0, 0, 0, 255], - "action_button_active_border": [12, 169, 227, 255], + "action_button_active_border": [50, 130, 255, 255], "action_button_disabled": [245, 245, 245, 255], "action_button_disabled_text": [127, 127, 127, 255], "action_button_disabled_border": [245, 245, 245, 255], - - "print_button_ready": [12, 169, 227, 255], - "print_button_ready_border": [12, 169, 227, 255], - "print_button_ready_text": [255, 255, 255, 255], - "print_button_ready_hovered": [30, 186, 245, 243], - "print_button_ready_hovered_border": [30, 186, 245, 243], - "print_button_ready_pressed": [30, 186, 245, 243], - "print_button_ready_pressed_border": [30, 186, 245, 243], + "action_button_shadow": [223, 223, 223, 255], + "action_button_disabled_shadow": [228, 228, 228, 255], "scrollbar_background": [255, 255, 255, 255], - "scrollbar_handle": [31, 36, 39, 255], - "scrollbar_handle_hover": [12, 159, 227, 255], - "scrollbar_handle_down": [12, 159, 227, 255], + "scrollbar_handle": [10, 8, 80, 255], + "scrollbar_handle_hover": [50, 130, 255, 255], + "scrollbar_handle_down": [50, 130, 255, 255], - "setting_category": [245, 245, 245, 255], + "setting_category": [240, 240, 240, 255], "setting_category_disabled": [255, 255, 255, 255], - "setting_category_hover": [245, 245, 245, 255], - "setting_category_active": [245, 245, 245, 255], - "setting_category_active_hover": [245, 245, 245, 255], - "setting_category_text": [31, 36, 39, 255], + "setting_category_hover": [232, 242, 252, 255], + "setting_category_active": [240, 240, 240, 255], + "setting_category_active_hover": [232, 242, 252, 255], + "setting_category_text": [35, 35, 35, 255], "setting_category_disabled_text": [24, 41, 77, 101], - "setting_category_hover_text": [31, 36, 39, 255], - "setting_category_active_text": [31, 36, 39, 255], - "setting_category_active_hover_text": [31, 36, 39, 255], - "setting_category_border": [245, 245, 245, 255], - "setting_category_disabled_border": [245, 245, 245, 255], - "setting_category_hover_border": [12, 159, 227, 255], - "setting_category_active_border": [245, 245, 245, 255], - "setting_category_active_hover_border": [12, 159, 227, 255], + "setting_category_hover_text": [35, 35, 35, 255], + "setting_category_active_text": [35, 35, 35, 255], + "setting_category_active_hover_text": [35, 35, 35, 255], + "setting_category_border": [240, 240, 240, 255], + "setting_category_disabled_border": [240, 240, 240, 255], + "setting_category_hover_border": [50, 130, 255, 255], + "setting_category_active_border": [50, 130, 255, 255], + "setting_category_active_hover_border": [50, 130, 255, 255], "setting_control": [255, 255, 255, 255], "setting_control_selected": [31, 36, 39, 255], "setting_control_highlight": [255, 255, 255, 255], - "setting_control_border": [127, 127, 127, 255], - "setting_control_border_highlight": [12, 169, 227, 255], - "setting_control_text": [27, 27, 27, 255], - "setting_control_depth_line": [127, 127, 127, 255], - "setting_control_button": [127, 127, 127, 255], - "setting_control_button_hover": [70, 84, 113, 255], + "setting_control_border": [199, 199, 199, 255], + "setting_control_border_highlight": [50, 130, 255, 255], + "setting_control_text": [35, 35, 35, 255], + "setting_control_button": [102, 102, 102, 255], + "setting_control_button_hover": [8, 7, 63, 255], "setting_control_disabled": [245, 245, 245, 255], "setting_control_disabled_text": [127, 127, 127, 255], "setting_control_disabled_border": [127, 127, 127, 255], @@ -199,42 +216,29 @@ "setting_validation_warning_background": [255, 145, 62, 255], "setting_validation_warning": [127, 127, 127, 255], "setting_validation_ok": [255, 255, 255, 255], + "setting_filter_field" : [153, 153, 153, 255], "material_compatibility_warning": [0, 0, 0, 255], "progressbar_background": [245, 245, 245, 255], - "progressbar_control": [31, 36, 39, 255], + "progressbar_control": [50, 130, 255, 255], - "slider_groove": [245, 245, 245, 255], - "slider_groove_border": [127, 127, 127, 255], - "slider_groove_fill": [127, 127, 127, 255], - "slider_handle": [0, 0, 0, 255], - "slider_handle_hover": [77, 182, 226, 255], - "slider_handle_active": [68, 192, 255, 255], - "slider_handle_border": [39, 44, 48, 255], + "slider_groove": [223, 223, 223, 255], + "slider_groove_fill": [8, 7, 63, 255], + "slider_handle": [8, 7, 63, 255], + "slider_handle_active": [50, 130, 255, 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], - "checkbox_border_hover": [12, 169, 227, 255], - "checkbox_mark": [119, 122, 124, 255], - "checkbox_text": [27, 27, 27, 255], - - "mode_switch": [255, 255, 255, 255], - "mode_switch_hover": [255, 255, 255, 255], - "mode_switch_border": [127, 127, 127, 255], - "mode_switch_border_hover": [12, 169, 227, 255], - "mode_switch_handle": [31, 36, 39, 255], - "mode_switch_text": [31, 36, 39, 255], - "mode_switch_text_hover": [31, 36, 39, 255], - "mode_switch_text_checked": [12, 169, 227, 255], + "checkbox_border": [199, 199, 199, 255], + "checkbox_border_hover": [50, 130, 255, 255], + "checkbox_mark": [50, 130, 255, 255], + "checkbox_disabled": [223, 223, 223, 255], + "checkbox_text": [35, 35, 35, 255], "tooltip": [68, 192, 255, 255], "tooltip_text": [255, 255, 255, 255], @@ -243,11 +247,13 @@ "message_background": [255, 255, 255, 255], "message_shadow": [0, 0, 0, 120], - "message_border": [127, 127, 127, 255], + "message_border": [192, 193, 194, 255], "message_text": [0, 0, 0, 255], - "message_button": [12, 169, 227, 255], - "message_button_hover": [12, 169, 227, 255], - "message_button_active": [12, 169, 227, 255], + "message_close": [102, 102, 102, 255], + "message_close_hover": [8, 7, 63, 255], + "message_button": [38, 113, 231, 255], + "message_button_hover": [81, 145, 247, 255], + "message_button_active": [38, 113, 231, 255], "message_button_text": [255, 255, 255, 255], "message_button_text_hover": [255, 255, 255, 255], "message_button_text_active": [255, 255, 255, 255], @@ -258,7 +264,7 @@ "status_offline": [0, 0, 0, 255], "status_ready": [0, 205, 0, 255], - "status_busy": [12, 169, 227, 255], + "status_busy": [50, 130, 255, 255], "status_paused": [255, 140, 0, 255], "status_stopped": [236, 82, 80, 255], "status_unknown": [127, 127, 127, 255], @@ -269,8 +275,8 @@ "z_axis": [0, 255, 0, 255], "all_axis": [255, 255, 255, 255], - "viewport_background": [245, 245, 245, 255], - "volume_outline": [12, 169, 227, 255], + "viewport_background": [250, 250, 250, 255], + "volume_outline": [50, 130, 255, 255], "buildplate": [244, 244, 244, 255], "buildplate_grid": [129, 131, 134, 255], "buildplate_grid_minor": [230, 230, 231, 255], @@ -283,40 +289,36 @@ "model_overhang": [255, 0, 0, 255], "model_unslicable": [122, 122, 122, 255], "model_unslicable_alt": [172, 172, 127, 255], - "model_selection_outline": [12, 169, 227, 255], + "model_selection_outline": [50, 130, 255, 255], "model_non_printing": [122, 122, 122, 255], "xray": [26, 26, 62, 255], "xray_error": [255, 0, 0, 255], "layerview_ghost": [32, 32, 32, 96], - "layerview_none": [255, 255, 255, 255], - "layerview_inset_0": [255, 0, 0, 255], - "layerview_inset_x": [0, 255, 0, 255], - "layerview_skin": [255, 255, 0, 255], - "layerview_support": [0, 255, 255, 255], - "layerview_skirt": [0, 255, 255, 255], - "layerview_infill": [255, 192, 0, 255], - "layerview_support_infill": [0, 255, 255, 255], - "layerview_move_combing": [0, 0, 255, 255], - "layerview_move_retraction": [128, 128, 255, 255], + "layerview_none": [255, 255, 255, 255], + "layerview_inset_0": [255, 0, 0, 255], + "layerview_inset_x": [0, 255, 0, 255], + "layerview_skin": [255, 255, 0, 255], + "layerview_support": [0, 255, 255, 255], + "layerview_skirt": [0, 255, 255, 255], + "layerview_infill": [255, 192, 0, 255], + "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_nozzle": [181, 166, 66, 50], - "configuration_item": [255, 255, 255, 0], - "configuration_item_active": [12, 169, 227, 32], - "configuration_item_text": [0, 0, 0, 255], - "configuration_item_text_active": [0, 0, 0, 255], - "configuration_item_border": [127, 127, 127, 255], - "configuration_item_border_active": [12, 169, 227, 32], - "configuration_item_border_hover": [12, 169, 227, 255], - - "tab_status_connected": [12, 169, 227, 255], + "tab_status_connected": [50, 130, 255, 255], "tab_status_disconnected": [200, 200, 200, 255], - "printer_config_matched": [12, 169, 227, 255], + "printer_config_matched": [50, 130, 255, 255], "printer_config_mismatch": [127, 127, 127, 255], + "toolbox_header_button_text_active": [0, 0, 0, 255], + "toolbox_header_button_text_inactive": [128, 128, 128, 255], + "toolbox_header_button_text_hovered": [0, 0, 0, 255], + "favorites_header_bar": [245, 245, 245, 255], "favorites_header_hover": [245, 245, 245, 255], "favorites_header_text": [31, 36, 39, 255], @@ -334,12 +336,12 @@ "monitor_pill_background": [245, 245, 245, 255], "monitor_placeholder_image": [230, 230, 230, 255], "monitor_printer_icon_inactive": [154, 154, 154, 255], - "monitor_printer_icon": [12, 169, 227, 255], + "monitor_printer_icon": [50, 130, 255, 255], "monitor_progress_background_text": [0,0,0,255], "monitor_progress_background": [245, 245, 245, 255], "monitor_progress_fill_inactive": [154, 154, 154, 255], "monitor_progress_fill_text": [255,255,255,255], - "monitor_progress_fill": [12, 169, 227, 255], + "monitor_progress_fill": [50, 130, 255, 255], "monitor_shadow": [0, 0, 0, 63], "monitor_skeleton_fill": [245, 245, 245, 255], "monitor_skeleton_fill_dark": [216, 216, 216, 255], @@ -347,42 +349,65 @@ }, "sizes": { - "window_minimum_size": [70, 50], + "window_minimum_size": [106, 66], + "main_window_header": [0.0, 4.0], + "main_window_header_button": [8, 2.35], + "main_window_header_button_icon": [1.2, 1.2], + + "stage_menu": [0.0, 4.0], + + "account_button": [12, 3], + + "print_setup_widget": [38.0, 30.0], + "print_setup_mode_toggle": [0.0, 2.0], + "print_setup_item": [0.0, 2.0], + "print_setup_extruder_box": [0.0, 6.0], + "print_setup_slider_groove": [0.16, 0.16], + "print_setup_slider_handle": [1.0, 1.0], + "print_setup_slider_tickmarks": [0.32, 0.32], + "print_setup_big_item": [28, 2.5], + "print_setup_icon": [1.2, 1.2], + + "expandable_component_content_header": [0.0, 3.0], + + "configuration_selector_mode_tabs": [0.0, 3.0], + + "action_panel_widget": [25.0, 0.0], + "action_panel_information_widget": [20.0, 0.0], + + "machine_selector_widget": [20.0, 4.0], + "machine_selector_widget_content": [25.0, 32.0], + "machine_selector_icon": [2.66, 2.66], + + "views_selector": [16.0, 4.5], + + "printer_type_label": [3.5, 1.5], + + "default_radius": [0.25, 0.25], + + "wide_lining": [0.5, 0.5], + "thick_lining": [0.2, 0.2], "default_lining": [0.08, 0.08], + "default_arrow": [0.8, 0.8], - "logo": [7.6, 1.6], + "logo": [8, 2.4], - "default_margin": [1.0, 1.0], "wide_margin": [2.0, 2.0], + "thick_margin": [1.71, 1.43], + "default_margin": [1.0, 1.0], + "thin_margin": [0.71, 0.71], "narrow_margin": [0.5, 0.5], - "window_margin": [1.0, 1.0], - "extruder_button_material_margin": [0.70, 0.9], - "extruder_button_material": [0.75, 0.75], + "extruder_icon": [2.33, 2.33], - "sidebar": [35.0, 10.0], - "sidebar_margin": [1.71, 1.43], - "sidebar_margin_thin": [0.71, 0.71], - "sidebar_header": [0.0, 4.0], - "sidebar_header_highlight": [0.25, 0.25], - "sidebar_header_mode_toggle": [0.0, 2.0], - "sidebar_header_mode_tabs": [0.0, 3.0], - "sidebar_lining": [0.5, 0.5], - "sidebar_lining_thin": [0.2, 0.2], - "sidebar_setup": [0.0, 2.0], - "sidebar_tabs": [0.0, 3.5], - "sidebar_inputfields": [0.0, 2.0], - "sidebar_extruder_box": [0.0, 6.0], - "simple_mode_infill_caption": [0.0, 5.0], - "simple_mode_infill_height": [0.0, 8.0], - - "section": [0.0, 2.2], + "section": [0.0, 2], "section_icon": [1.6, 1.6], "section_icon_column": [2.8, 0.0], "setting": [25.0, 1.8], - "setting_control": [10.0, 2.0], + "setting_control": [11.0, 2.0], + "setting_control_radius": [0.15, 0.15], "setting_control_depth_margin": [1.4, 0.0], "setting_preferences_button_margin": [4, 0.0], "setting_control_margin": [0.0, 0.0], @@ -390,13 +415,15 @@ "setting_text_maxwidth": [40.0, 0.0], "standard_list_lineheight": [1.5, 1.5], - "standard_list_input": [20.0, 25.0], - "standard_arrow": [0.8, 0.8], + "standard_arrow": [1.0, 1.0], "button": [4, 4], "button_icon": [2.5, 2.5], "button_lining": [0, 0], + "action_button": [15.0, 3.0], + "action_button_radius": [0.15, 0.15], + "small_button": [2, 2], "small_button_icon": [1.5, 1.5], @@ -404,42 +431,32 @@ "favorites_button": [2, 2], "favorites_button_icon": [1.2, 1.2], - "printer_status_icon": [1.8, 1.8], + "printer_status_icon": [1.0, 1.0], "printer_sync_icon": [1.2, 1.2], - "topbar_logo_right_margin": [3, 0], - "topbar_button": [8, 4], - "topbar_button_icon": [1.2, 1.2], - "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], + "progressbar": [26.0, 0.75], + "progressbar_radius": [0.15, 0.15], + "progressbar_control": [8.0, 0.75], "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], - "slider_layerview_background": [4.0, 0.0], - "slider_layerview_margin": [1.0, 1.5], + "slider_groove": [0.5, 0.5], + "slider_groove_radius": [0.15, 0.15], + "slider_handle": [1.5, 1.5], + "slider_layerview_size": [1.0, 26.0], "layerview_menu_size": [15, 20], - "layerview_menu_size_material_color_mode": [15, 16], - "layerview_menu_size_collapsed": [15, 6], - "layerview_menu_size_compatibility": [22, 22.0], - "layerview_menu_size_compatibility_collapsed": [15, 3.5], "layerview_legend_size": [1.0, 1.0], "layerview_row": [11.0, 1.5], "layerview_row_spacing": [0.0, 0.5], - "checkbox": [2.0, 2.0], + "checkbox": [1.5, 1.5], + "checkbox_radius": [0.08, 0.08], "tooltip": [20.0, 10.0], "tooltip_margins": [1.0, 1.0], @@ -463,6 +480,8 @@ "message_shadow": [0, 0], "message_margin": [0, 1.0], "message_inner_margin": [1.5, 1.5], + "message_radius": [0.25, 0.25], + "message_button_radius": [0.15, 0.15], "infill_button_margin": [0.5, 0.5], @@ -488,11 +507,14 @@ "toolbox_property_label": [1.0, 2.0], "toolbox_heading_label": [1.0, 4.0], "toolbox_header": [1.0, 4.0], + "toolbox_header_highlight": [0.25, 0.25], "toolbox_progress_bar": [8.0, 0.5], "toolbox_chart_row": [1.0, 2.0], "toolbox_action_button": [8.0, 2.5], "toolbox_loader": [2.0, 2.0], + "avatar_image": [6.8, 6.8], + "monitor_config_override_box": [1.0, 14.0], "monitor_extruder_circle": [2.75, 2.75], "monitor_text_line": [1.16, 1.16], diff --git a/resources/variants/ultimaker_s5_cc06.inst.cfg b/resources/variants/ultimaker_s5_cc06.inst.cfg index d41d08118a..7adf7ab7a0 100644 --- a/resources/variants/ultimaker_s5_cc06.inst.cfg +++ b/resources/variants/ultimaker_s5_cc06.inst.cfg @@ -13,7 +13,6 @@ brim_width = 7 machine_nozzle_cool_down_speed = 0.9 machine_nozzle_id = CC 0.6 machine_nozzle_size = 0.6 -material_print_temperature = =default_material_print_temperature + 10 raft_acceleration = =acceleration_print raft_airgap = 0.3 raft_base_thickness = =resolveOrValue('layer_height_0') * 1.2 diff --git a/tests/TestPrintInformation.py b/tests/TestPrintInformation.py index a226a437c6..baa36fb338 100644 --- a/tests/TestPrintInformation.py +++ b/tests/TestPrintInformation.py @@ -1,5 +1,7 @@ +import functools from cura import PrintInformation +from cura.Settings.MachineManager import MachineManager from unittest.mock import MagicMock, patch from UM.Application import Application @@ -11,14 +13,20 @@ def getPrintInformation(printer_name) -> PrintInformation: mock_application = MagicMock() global_container_stack = MagicMock() - global_container_stack.definition.getName = MagicMock(return_value=printer_name) - mock_application.getGlobalContainerStack = MagicMock(return_value=global_container_stack) + global_container_stack.definition.getName = MagicMock(return_value = printer_name) + mock_application.getGlobalContainerStack = MagicMock(return_value = global_container_stack) - multiBuildPlateModel = MagicMock() - multiBuildPlateModel.maxBuildPlate = 0 - mock_application.getMultiBuildPlateModel = MagicMock(return_value=multiBuildPlateModel) + multi_build_plate_model = MagicMock() + multi_build_plate_model.maxBuildPlate = 0 + mock_application.getMultiBuildPlateModel = MagicMock(return_value = multi_build_plate_model) - Application.getInstance = MagicMock(return_type=mock_application) + # Mock-up the entire machine manager except the function that needs to be tested: getAbbreviatedMachineName + original_get_abbreviated_name = MachineManager.getAbbreviatedMachineName + mock_machine_manager = MagicMock() + mock_machine_manager.getAbbreviatedMachineName = functools.partial(original_get_abbreviated_name, mock_machine_manager) + mock_application.getMachineManager = MagicMock(return_value = mock_machine_manager) + + Application.getInstance = MagicMock(return_type = mock_application) with patch("json.loads", lambda x: {}): print_information = PrintInformation.PrintInformation(mock_application) @@ -28,17 +36,17 @@ def getPrintInformation(printer_name) -> PrintInformation: def setup_module(): MimeTypeDatabase.addMimeType( MimeType( - name="application/vnd.ms-package.3dmanufacturing-3dmodel+xml", - comment="3MF", - suffixes=["3mf"] + name = "application/vnd.ms-package.3dmanufacturing-3dmodel+xml", + comment = "3MF", + suffixes = ["3mf"] ) ) MimeTypeDatabase.addMimeType( MimeType( - name="application/x-cura-gcode-file", - comment="Cura GCode File", - suffixes=["gcode"] + name = "application/x-cura-gcode-file", + comment = "Cura GCode File", + suffixes = ["gcode"] ) ) @@ -49,42 +57,42 @@ def test_setProjectName(): print_information = getPrintInformation("ultimaker") # Test simple name - project_name = ["HelloWorld",".3mf"] + project_name = ["HelloWorld", ".3mf"] print_information.setProjectName(project_name[0] + project_name[1]) assert "UM_" + project_name[0] == print_information._job_name # Test the name with one dot - project_name = ["Hello.World",".3mf"] + project_name = ["Hello.World", ".3mf"] print_information.setProjectName(project_name[0] + project_name[1]) assert "UM_" + project_name[0] == print_information._job_name # Test the name with two dot - project_name = ["Hello.World.World",".3mf"] + project_name = ["Hello.World.World", ".3mf"] print_information.setProjectName(project_name[0] + project_name[1]) assert "UM_" + project_name[0] == print_information._job_name # Test the name with dot at the beginning - project_name = [".Hello.World",".3mf"] + project_name = [".Hello.World", ".3mf"] print_information.setProjectName(project_name[0] + project_name[1]) assert "UM_" + project_name[0] == print_information._job_name # Test the name with underline - project_name = ["Hello_World",".3mf"] + project_name = ["Hello_World", ".3mf"] print_information.setProjectName(project_name[0] + project_name[1]) assert "UM_" + project_name[0] == print_information._job_name # Test gcode extension - project_name = ["Hello_World",".gcode"] + project_name = ["Hello_World", ".gcode"] print_information.setProjectName(project_name[0] + project_name[1]) assert "UM_" + project_name[0] == print_information._job_name # Test empty project name - project_name = ["",""] + project_name = ["", ""] print_information.setProjectName(project_name[0] + project_name[1]) assert print_information.UNTITLED_JOB_NAME == print_information._job_name # Test wrong file extension - project_name = ["Hello_World",".test"] + project_name = ["Hello_World", ".test"] print_information.setProjectName(project_name[0] + project_name[1]) assert "UM_" + project_name[0] != print_information._job_name @@ -93,7 +101,7 @@ def test_setJobName(): print_information = getPrintInformation("ultimaker") print_information._abbr_machine = "UM" - print_information.setJobName("UM_HelloWorld", is_user_specified_job_name=False) + print_information.setJobName("UM_HelloWorld", is_user_specified_job_name = False) def test_defineAbbreviatedMachineName(): @@ -102,6 +110,6 @@ def test_defineAbbreviatedMachineName(): print_information = getPrintInformation(printer_name) # Test not ultimaker printer, name suffix should have first letter from the printer name - project_name = ["HelloWorld",".3mf"] + project_name = ["HelloWorld", ".3mf"] print_information.setProjectName(project_name[0] + project_name[1]) assert printer_name[0] + "_" + project_name[0] == print_information._job_name \ No newline at end of file