diff --git a/cura/CuraActions.py b/cura/CuraActions.py index 93a18318df..49f7e740a9 100644 --- a/cura/CuraActions.py +++ b/cura/CuraActions.py @@ -3,7 +3,7 @@ from PyQt5.QtCore import QObject, QUrl from PyQt5.QtGui import QDesktopServices -from typing import List, TYPE_CHECKING +from typing import List, TYPE_CHECKING, cast from UM.Event import CallFunctionEvent from UM.FlameProfiler import pyqtSlot @@ -61,8 +61,10 @@ class CuraActions(QObject): operation = GroupedOperation() for node in Selection.getAllSelectedObjects(): current_node = node - while current_node.getParent() and current_node.getParent().callDecoration("isGroup"): - current_node = current_node.getParent() + parent_node = current_node.getParent() + while parent_node and parent_node.callDecoration("isGroup"): + current_node = parent_node + parent_node = current_node.getParent() # This was formerly done with SetTransformOperation but because of # unpredictable matrix deconstruction it was possible that mirrors @@ -150,13 +152,13 @@ class CuraActions(QObject): root = cura.CuraApplication.CuraApplication.getInstance().getController().getScene().getRoot() - nodes_to_change = [] + nodes_to_change = [] # type: List[SceneNode] for node in Selection.getAllSelectedObjects(): parent_node = node # Find the parent node to change instead while parent_node.getParent() != root: - parent_node = parent_node.getParent() + parent_node = cast(SceneNode, parent_node.getParent()) - for single_node in BreadthFirstIterator(parent_node): #type: ignore #Ignore type error because iter() should get called automatically by Python syntax. + for single_node in BreadthFirstIterator(parent_node): # type: ignore #Ignore type error because iter() should get called automatically by Python syntax. nodes_to_change.append(single_node) if not nodes_to_change: diff --git a/cura/CuraApplication.py b/cura/CuraApplication.py index 47cc94f972..b43e4d5e0e 100755 --- a/cura/CuraApplication.py +++ b/cura/CuraApplication.py @@ -439,6 +439,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. @@ -631,9 +632,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 @@ -1664,7 +1663,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/Models/QualityProfilesDropDownMenuModel.py b/cura/Machines/Models/QualityProfilesDropDownMenuModel.py index a01cc1194f..747882b041 100644 --- a/cura/Machines/Models/QualityProfilesDropDownMenuModel.py +++ b/cura/Machines/Models/QualityProfilesDropDownMenuModel.py @@ -21,6 +21,7 @@ class QualityProfilesDropDownMenuModel(ListModel): AvailableRole = Qt.UserRole + 5 QualityGroupRole = Qt.UserRole + 6 QualityChangesGroupRole = Qt.UserRole + 7 + IsExperimentalRole = Qt.UserRole + 8 def __init__(self, parent = None): super().__init__(parent) @@ -32,6 +33,7 @@ class QualityProfilesDropDownMenuModel(ListModel): self.addRoleName(self.AvailableRole, "available") #Whether the quality profile is available in our current nozzle + material. self.addRoleName(self.QualityGroupRole, "quality_group") self.addRoleName(self.QualityChangesGroupRole, "quality_changes_group") + self.addRoleName(self.IsExperimentalRole, "is_experimental") self._application = Application.getInstance() self._machine_manager = self._application.getMachineManager() @@ -74,7 +76,8 @@ class QualityProfilesDropDownMenuModel(ListModel): "layer_height": layer_height, "layer_height_unit": self._layer_height_unit, "available": quality_group.is_available, - "quality_group": quality_group} + "quality_group": quality_group, + "is_experimental": quality_group.is_experimental} item_list.append(item) diff --git a/cura/Machines/QualityGroup.py b/cura/Machines/QualityGroup.py index 535ba453f8..f5bcbb0de8 100644 --- a/cura/Machines/QualityGroup.py +++ b/cura/Machines/QualityGroup.py @@ -4,6 +4,9 @@ from typing import Dict, Optional, List, Set from PyQt5.QtCore import QObject, pyqtSlot + +from UM.Util import parseBool + from cura.Machines.ContainerNode import ContainerNode @@ -29,6 +32,7 @@ class QualityGroup(QObject): self.nodes_for_extruders = {} # type: Dict[int, ContainerNode] self.quality_type = quality_type self.is_available = False + self.is_experimental = False @pyqtSlot(result = str) def getName(self) -> str: @@ -51,3 +55,17 @@ class QualityGroup(QObject): for extruder_node in self.nodes_for_extruders.values(): result.append(extruder_node) return result + + def setGlobalNode(self, node: "ContainerNode") -> None: + self.node_for_global = node + + # Update is_experimental flag + is_experimental = parseBool(node.getMetaDataEntry("is_experimental", False)) + self.is_experimental |= is_experimental + + def setExtruderNode(self, position: int, node: "ContainerNode") -> None: + self.nodes_for_extruders[position] = node + + # Update is_experimental flag + is_experimental = parseBool(node.getMetaDataEntry("is_experimental", False)) + self.is_experimental |= is_experimental diff --git a/cura/Machines/QualityManager.py b/cura/Machines/QualityManager.py index a784d17f0b..34cc9ce4b2 100644 --- a/cura/Machines/QualityManager.py +++ b/cura/Machines/QualityManager.py @@ -235,7 +235,7 @@ class QualityManager(QObject): for quality_type, quality_node in node.quality_type_map.items(): quality_group = QualityGroup(quality_node.getMetaDataEntry("name", ""), quality_type) - quality_group.node_for_global = quality_node + quality_group.setGlobalNode(quality_node) quality_group_dict[quality_type] = quality_group break @@ -337,7 +337,7 @@ class QualityManager(QObject): quality_group = quality_group_dict[quality_type] if position not in quality_group.nodes_for_extruders: - quality_group.nodes_for_extruders[position] = quality_node + quality_group.setExtruderNode(position, quality_node) # If the machine has its own specific qualities, for extruders, it should skip the global qualities # and use the material/variant specific qualities. @@ -367,7 +367,7 @@ class QualityManager(QObject): if node and node.quality_type_map: for quality_type, quality_node in node.quality_type_map.items(): quality_group = QualityGroup(quality_node.getMetaDataEntry("name", ""), quality_type) - quality_group.node_for_global = quality_node + quality_group.setGlobalNode(quality_node) quality_group_dict[quality_type] = quality_group break diff --git a/cura/Machines/VariantManager.py b/cura/Machines/VariantManager.py index f6feb70e09..eaaa9fc5f0 100644 --- a/cura/Machines/VariantManager.py +++ b/cura/Machines/VariantManager.py @@ -107,7 +107,7 @@ class VariantManager: break return variant_node - return self._machine_to_variant_dict_map[machine_definition_id].get(variant_type, {}).get(variant_name) + return self._machine_to_variant_dict_map.get(machine_definition_id, {}).get(variant_type, {}).get(variant_name) def getVariantNodes(self, machine: "GlobalStack", variant_type: "VariantType") -> Dict[str, ContainerNode]: machine_definition_id = machine.definition.getId() 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 e11f70a54c..e863689e21 100644 --- a/cura/PrintInformation.py +++ b/cura/PrintInformation.py @@ -14,8 +14,7 @@ from UM.Logger import Logger from UM.Qt.Duration import Duration from UM.Scene.SceneNode import SceneNode from UM.i18n import i18nCatalog -from UM.MimeTypeDatabase import MimeTypeDatabase - +from UM.MimeTypeDatabase import MimeTypeDatabase, MimeTypeNotFoundError from typing import TYPE_CHECKING @@ -361,7 +360,7 @@ class PrintInformation(QObject): try: mime_type = MimeTypeDatabase.getMimeTypeForFile(name) data = mime_type.stripExtension(name) - except: + except MimeTypeNotFoundError: Logger.log("w", "Unsupported Mime Type Database file extension %s", name) if data is not None and check_name is not None: @@ -395,28 +394,14 @@ 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: return ''.join(char for char in unicodedata.normalize('NFD', to_strip) if unicodedata.category(char) != 'Mn') @pyqtSlot(result = "QVariantMap") - def getFeaturePrintTimes(self): + def getFeaturePrintTimes(self) -> Dict[str, Duration]: result = {} if self._active_build_plate not in self._print_times_per_feature: self._initPrintTimesPerFeature(self._active_build_plate) 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/ConvexHullNode.py b/cura/Scene/ConvexHullNode.py index 4c79c7d5dc..886ed93ad3 100644 --- a/cura/Scene/ConvexHullNode.py +++ b/cura/Scene/ConvexHullNode.py @@ -1,7 +1,10 @@ # Copyright (c) 2015 Ultimaker B.V. # Cura is released under the terms of the LGPLv3 or higher. +from typing import Optional from UM.Application import Application +from UM.Math.Polygon import Polygon +from UM.Qt.QtApplication import QtApplication from UM.Scene.SceneNode import SceneNode from UM.Resources import Resources from UM.Math.Color import Color @@ -16,7 +19,7 @@ class ConvexHullNode(SceneNode): # location an object uses on the buildplate. This area (or area's in case of one at a time printing) is # then displayed as a transparent shadow. If the adhesion type is set to raft, the area is extruded # to represent the raft as well. - def __init__(self, node, hull, thickness, parent = None): + def __init__(self, node: SceneNode, hull: Optional[Polygon], thickness: float, parent: Optional[SceneNode] = None) -> None: super().__init__(parent) self.setCalculateBoundingBox(False) @@ -25,7 +28,11 @@ class ConvexHullNode(SceneNode): # Color of the drawn convex hull if not Application.getInstance().getIsHeadLess(): - self._color = Color(*Application.getInstance().getTheme().getColor("convex_hull").getRgb()) + theme = QtApplication.getInstance().getTheme() + if theme: + self._color = Color(*theme.getColor("convex_hull").getRgb()) + else: + self._color = Color(0, 0, 0) else: self._color = Color(0, 0, 0) @@ -75,7 +82,7 @@ class ConvexHullNode(SceneNode): return True - def _onNodeDecoratorsChanged(self, node): + def _onNodeDecoratorsChanged(self, node: SceneNode) -> None: convex_hull_head = self._node.callDecoration("getConvexHullHead") if convex_hull_head: convex_hull_head_builder = MeshBuilder() diff --git a/cura/Settings/ExtrudersModel.py b/cura/Settings/ExtrudersModel.py index 52fc502bfc..14a8dadc69 100644 --- a/cura/Settings/ExtrudersModel.py +++ b/cura/Settings/ExtrudersModel.py @@ -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) @@ -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) diff --git a/cura/Settings/MachineManager.py b/cura/Settings/MachineManager.py index f22029e083..53390ca88d 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 @@ -616,6 +618,14 @@ class MachineManager(QObject): is_supported = self._current_quality_group.is_available return is_supported + @pyqtProperty(bool, notify = activeQualityGroupChanged) + def isActiveQualityExperimental(self) -> bool: + is_experimental = False + if self._global_container_stack: + if self._current_quality_group: + is_experimental = self._current_quality_group.is_experimental + return is_experimental + ## Returns whether there is anything unsupported in the current set-up. # # The current set-up signifies the global stack and all extruder stacks, @@ -1532,3 +1542,22 @@ class MachineManager(QObject): 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/StartSliceJob.py b/plugins/CuraEngineBackend/StartSliceJob.py index 273dc0b6f6..9679360ad5 100644 --- a/plugins/CuraEngineBackend/StartSliceJob.py +++ b/plugins/CuraEngineBackend/StartSliceJob.py @@ -72,7 +72,7 @@ class GcodeStartEndFormatter(Formatter): # "-1" is global stack, and if the setting value exists in the global stack, use it as the fallback value. if key in kwargs["-1"]: value = kwargs["-1"] - if key in kwargs[str(extruder_nr)]: + if str(extruder_nr) in kwargs and key in kwargs[str(extruder_nr)]: value = kwargs[str(extruder_nr)][key] if value == default_value_str: 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/ModelChecker/ModelChecker.qml b/plugins/ModelChecker/ModelChecker.qml index 98db233bf8..5e41591d6b 100644 --- a/plugins/ModelChecker/ModelChecker.qml +++ b/plugins/ModelChecker/ModelChecker.qml @@ -16,7 +16,7 @@ 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.") 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/PostProcessingPlugin/PostProcessingPlugin.py b/plugins/PostProcessingPlugin/PostProcessingPlugin.py index 11ee610bec..78f9cc0516 100644 --- a/plugins/PostProcessingPlugin/PostProcessingPlugin.py +++ b/plugins/PostProcessingPlugin/PostProcessingPlugin.py @@ -55,14 +55,14 @@ class PostProcessingPlugin(QObject, Extension): def selectedScriptDefinitionId(self) -> Optional[str]: try: return self._script_list[self._selected_script_index].getDefinitionId() - except: + except IndexError: return "" @pyqtProperty(str, notify=selectedIndexChanged) def selectedScriptStackId(self) -> Optional[str]: try: return self._script_list[self._selected_script_index].getStackId() - except: + except IndexError: return "" ## Execute all post-processing scripts on the gcode. diff --git a/plugins/PostProcessingPlugin/PostProcessingPlugin.qml b/plugins/PostProcessingPlugin/PostProcessingPlugin.qml index d492e06462..bd4d361d35 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) @@ -260,7 +260,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 diff --git a/plugins/PostProcessingPlugin/scripts/ExampleScript.md b/plugins/PostProcessingPlugin/scripts/ExampleScript.md new file mode 100644 index 0000000000..08652132aa --- /dev/null +++ b/plugins/PostProcessingPlugin/scripts/ExampleScript.md @@ -0,0 +1,3 @@ +A good example script is SearchAndReplace.py. +If you have any questions please ask them at: +https://github.com/Ultimaker/Cura/issues \ No newline at end of file diff --git a/plugins/PostProcessingPlugin/scripts/ExampleScript.py b/plugins/PostProcessingPlugin/scripts/ExampleScript.py deleted file mode 100644 index 416a5f5404..0000000000 --- a/plugins/PostProcessingPlugin/scripts/ExampleScript.py +++ /dev/null @@ -1,43 +0,0 @@ -# Copyright (c) 2015 Jaime van Kessel, Ultimaker B.V. -# The PostProcessingPlugin is released under the terms of the AGPLv3 or higher. -from ..Script import Script - -class ExampleScript(Script): - def __init__(self): - super().__init__() - - def getSettingDataString(self): - return """{ - "name":"Example script", - "key": "ExampleScript", - "metadata": {}, - "version": 2, - "settings": - { - "test": - { - "label": "Test", - "description": "None", - "unit": "mm", - "type": "float", - "default_value": 0.5, - "minimum_value": "0", - "minimum_value_warning": "0.1", - "maximum_value_warning": "1" - }, - "derp": - { - "label": "zomg", - "description": "afgasgfgasfgasf", - "unit": "mm", - "type": "float", - "default_value": 0.5, - "minimum_value": "0", - "minimum_value_warning": "0.1", - "maximum_value_warning": "1" - } - } - }""" - - def execute(self, data): - return data \ No newline at end of file diff --git a/plugins/PrepareStage/PrepareMenu.qml b/plugins/PrepareStage/PrepareMenu.qml new file mode 100644 index 0000000000..10b4262f01 --- /dev/null +++ b/plugins/PrepareStage/PrepareMenu.qml @@ -0,0 +1,140 @@ +// 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 + // This widget doesn't show tooltips by itself. Instead it emits signals so others can do something with it. + signal showTooltip(Item item, point location, string text) + signal hideTooltip() + + + 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 + z: openFileButton.z - 1 //Ensure that the tooltip of the open file button stays above the item row. + 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.QuickConfigurationSelector + { + 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.width: width + 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..a1f59cd4ca --- /dev/null +++ b/plugins/PreviewStage/PreviewMenu.qml @@ -0,0 +1,77 @@ +// 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 + // This widget doesn't show tooltips by itself. Instead it emits signals so others can do something with it. + signal showTooltip(Item item, point location, string text) + signal hideTooltip() + + 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..16b9aeaae6 --- /dev/null +++ b/plugins/SimulationView/SimulationViewMainComponent.qml @@ -0,0 +1,212 @@ +// 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 + hoverBackgroundColor: UM.Theme.getColor("small_button_hover") + hoverColor: UM.Theme.getColor("small_button_text_hover") + color: UM.Theme.getColor("small_button_text") + iconMargin: 0.5 * UM.Theme.getSize("wide_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..53b64afb47 --- /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 + iconSource: UM.Theme.getIcon("pencil") + + 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 + } + + popupItem: 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..853cec399d 100644 --- a/plugins/Toolbox/resources/qml/Toolbox.qml +++ b/plugins/Toolbox/resources/qml/Toolbox.qml @@ -20,11 +20,11 @@ Window 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 { diff --git a/plugins/Toolbox/resources/qml/ToolboxCompatibilityChart.qml b/plugins/Toolbox/resources/qml/ToolboxCompatibilityChart.qml index a48cb2ee3f..4a6268df42 100644 --- a/plugins/Toolbox/resources/qml/ToolboxCompatibilityChart.qml +++ b/plugins/Toolbox/resources/qml/ToolboxCompatibilityChart.qml @@ -36,12 +36,19 @@ Item var pg_name = "printingGuidelines" return (pg_name in packageData.links) ? packageData.links[pg_name] : undefined } + + property var materialWebsiteUrl: + { + var pg_name = "website" + return (pg_name in packageData.links) ? packageData.links[pg_name] : undefined + } anchors.topMargin: UM.Theme.getSize("default_margin").height height: visible ? childrenRect.height : 0 visible: packageData.type == "material" && (packageData.has_configs || technicalDataSheetUrl !== undefined || - safetyDataSheetUrl !== undefined || printingGuidelinesUrl !== undefined) + safetyDataSheetUrl !== undefined || printingGuidelinesUrl !== undefined || + materialWebsiteUrl !== undefined) Item { @@ -83,7 +90,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 { @@ -180,7 +187,8 @@ Item anchors.top: combatibilityItem.bottom anchors.topMargin: UM.Theme.getSize("default_margin").height / 2 visible: base.technicalDataSheetUrl !== undefined || - base.safetyDataSheetUrl !== undefined || base.printingGuidelinesUrl !== undefined + base.safetyDataSheetUrl !== undefined || base.printingGuidelinesUrl !== undefined || + base.materialWebsiteUrl !== undefined height: visible ? contentHeight : 0 text: { @@ -208,6 +216,16 @@ Item var pg_name = catalog.i18nc("@action:label", "Printing Guidelines") result += "%2".arg(base.printingGuidelinesUrl).arg(pg_name) } + if (base.materialWebsiteUrl !== undefined) + { + if (result.length > 0) + { + result += "
" + } + var pg_name = catalog.i18nc("@action:label", "Website") + result += "%2".arg(base.materialWebsiteUrl).arg(pg_name) + } + return result } font: UM.Theme.getFont("very_small") diff --git a/plugins/Toolbox/resources/qml/ToolboxDetailPage.qml b/plugins/Toolbox/resources/qml/ToolboxDetailPage.qml index 437a2ef351..c5e9bb0a49 100644 --- a/plugins/Toolbox/resources/qml/ToolboxDetailPage.qml +++ b/plugins/Toolbox/resources/qml/ToolboxDetailPage.qml @@ -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 @@ -144,10 +144,6 @@ Item { return "" } - if (details.author_email) - { - return "" + details.author_name + "" - } else { return "" + details.author_name + "" diff --git a/plugins/Toolbox/resources/qml/ToolboxDetailTile.qml b/plugins/Toolbox/resources/qml/ToolboxDetailTile.qml index 9061a8e06b..1d701543ce 100644 --- a/plugins/Toolbox/resources/qml/ToolboxDetailTile.qml +++ b/plugins/Toolbox/resources/qml/ToolboxDetailTile.qml @@ -37,7 +37,7 @@ Item anchors.top: packageName.bottom width: parent.width text: model.description - maximumLineCount: 6 + maximumLineCount: 25 elide: Text.ElideRight wrapMode: Text.WordWrap color: UM.Theme.getColor("text") diff --git a/plugins/Toolbox/resources/qml/ToolboxTabButton.qml b/plugins/Toolbox/resources/qml/ToolboxTabButton.qml index 22fb6d73ca..b671d779f8 100644 --- a/plugins/Toolbox/resources/qml/ToolboxTabButton.qml +++ b/plugins/Toolbox/resources/qml/ToolboxTabButton.qml @@ -19,10 +19,10 @@ Button Rectangle { visible: control.active - color: UM.Theme.getColor("sidebar_header_highlight_hover") + color: UM.Theme.getColor("toolbox_header_highlight_hover") anchors.bottom: parent.bottom width: parent.width - height: UM.Theme.getSize("sidebar_header_highlight").height + height: UM.Theme.getSize("toolbox_header_highlight").height } } label: Label @@ -32,15 +32,15 @@ Button { if(control.hovered) { - return UM.Theme.getColor("topbar_button_text_hovered"); + return UM.Theme.getColor("toolbox_header_button_text_hovered"); } if(control.active) { - return UM.Theme.getColor("topbar_button_text_active"); + return UM.Theme.getColor("toolbox_header_button_text_active"); } else { - return UM.Theme.getColor("topbar_button_text_inactive"); + 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") diff --git a/plugins/UM3NetworkPrinting/resources/png/Ultimaker 3 Extended.png b/plugins/UM3NetworkPrinting/resources/png/Ultimaker 3 Extended.png new file mode 100644 index 0000000000..1ce19c2933 Binary files /dev/null and b/plugins/UM3NetworkPrinting/resources/png/Ultimaker 3 Extended.png differ diff --git a/plugins/UM3NetworkPrinting/resources/png/Ultimaker 3.png b/plugins/UM3NetworkPrinting/resources/png/Ultimaker 3.png new file mode 100644 index 0000000000..4639cb3fde Binary files /dev/null and b/plugins/UM3NetworkPrinting/resources/png/Ultimaker 3.png differ diff --git a/plugins/UM3NetworkPrinting/resources/png/Ultimaker S5.png b/plugins/UM3NetworkPrinting/resources/png/Ultimaker S5.png new file mode 100644 index 0000000000..29ba428e38 Binary files /dev/null and b/plugins/UM3NetworkPrinting/resources/png/Ultimaker S5.png differ diff --git a/plugins/UM3NetworkPrinting/resources/qml/CameraButton.qml b/plugins/UM3NetworkPrinting/resources/qml/CameraButton.qml index 7e5c254e5c..618dbed81c 100644 --- a/plugins/UM3NetworkPrinting/resources/qml/CameraButton.qml +++ b/plugins/UM3NetworkPrinting/resources/qml/CameraButton.qml @@ -9,10 +9,10 @@ import Cura 1.0 as Cura Rectangle { property var iconSource: null; - color: clickArea.containsMouse ? UM.Theme.getColor("primary_hover") : UM.Theme.getColor("primary"); // "Cura Blue" + color: "#0a0850" // TODO: Theme! height: width; radius: Math.round(0.5 * width); - width: 36 * screenScaleFactor; + width: 24 * screenScaleFactor; UM.RecolorImage { id: icon; diff --git a/plugins/UM3NetworkPrinting/resources/qml/ClusterControlItem.qml b/plugins/UM3NetworkPrinting/resources/qml/ClusterControlItem.qml index 068c369a3f..94e75a6de0 100644 --- a/plugins/UM3NetworkPrinting/resources/qml/ClusterControlItem.qml +++ b/plugins/UM3NetworkPrinting/resources/qml/ClusterControlItem.qml @@ -13,7 +13,7 @@ Component { 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"); + color: UM.Theme.getColor("main_background"); visible: OutputDevice != null; UM.I18nCatalog { diff --git a/plugins/UM3NetworkPrinting/resources/qml/ClusterMonitorItem.qml b/plugins/UM3NetworkPrinting/resources/qml/ClusterMonitorItem.qml index 19a152e6eb..adf5ea5e1c 100644 --- a/plugins/UM3NetworkPrinting/resources/qml/ClusterMonitorItem.qml +++ b/plugins/UM3NetworkPrinting/resources/qml/ClusterMonitorItem.qml @@ -10,14 +10,13 @@ import QtGraphicalEffects 1.0 Component { - Rectangle + Item { id: monitorFrame property var emphasisColor: UM.Theme.getColor("setting_control_border_highlight") property var cornerRadius: UM.Theme.getSize("monitor_corner_radius").width - color: "transparent" height: maximumHeight onVisibleChanged: { @@ -48,13 +47,45 @@ Component } } + ScrollView + { + id: printers + anchors + { + left: queue.left + right: queue.right + top: parent.top + topMargin: 48 * screenScaleFactor // TODO: Theme! + } + height: 264 * screenScaleFactor // TODO: Theme! + + Row + { + spacing: 60 * screenScaleFactor // TODO: Theme! + + Repeater + { + model: OutputDevice.printers + + MonitorPrinterCard + { + printer: modelData + } + } + } + } + Item { id: queue + width: Math.min(834 * screenScaleFactor, maximumWidth) - anchors.fill: parent - anchors.top: parent.top - anchors.topMargin: 400 * screenScaleFactor // TODO: Insert carousel here + anchors { + bottom: parent.bottom + horizontalCenter: parent.horizontalCenter + top: printers.bottom + topMargin: 48 * screenScaleFactor // TODO: Theme! + } Label { @@ -104,7 +135,6 @@ Component text: catalog.i18nc("@label link to connect manager", "Manage queue in Cura Connect") } } - MouseArea { @@ -187,7 +217,7 @@ Component } style: UM.Theme.styles.scrollview visible: OutputDevice.receivedPrintJobs - width: Math.min(834 * screenScaleFactor, maximumWidth) + width: parent.width ListView { @@ -214,5 +244,4 @@ Component visible: OutputDevice.activeCameraUrl != "" } } - } diff --git a/plugins/UM3NetworkPrinting/resources/qml/DiscoverUM3Action.qml b/plugins/UM3NetworkPrinting/resources/qml/DiscoverUM3Action.qml index 58443115a9..967adfc029 100644 --- a/plugins/UM3NetworkPrinting/resources/qml/DiscoverUM3Action.qml +++ b/plugins/UM3NetworkPrinting/resources/qml/DiscoverUM3Action.qml @@ -57,7 +57,7 @@ Cura.MachineAction spacing: UM.Theme.getSize("default_margin").height SystemPalette { id: palette } - UM.I18nCatalog { id: catalog; name:"cura" } + UM.I18nCatalog { id: catalog; name: "cura" } Label { id: pageTitle diff --git a/plugins/UM3NetworkPrinting/resources/qml/MonitorPrintJobProgressBar.qml b/plugins/UM3NetworkPrinting/resources/qml/MonitorPrintJobProgressBar.qml new file mode 100644 index 0000000000..f70e1175a1 --- /dev/null +++ b/plugins/UM3NetworkPrinting/resources/qml/MonitorPrintJobProgressBar.qml @@ -0,0 +1,137 @@ +// 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 + +/** + * NOTE: For most labels, a fixed height with vertical alignment is used to make + * layouts more deterministic (like the fixed-size textboxes used in original + * mock-ups). This is also a stand-in for CSS's 'line-height' property. Denoted + * with '// FIXED-LINE-HEIGHT:'. + */ +Item +{ + id: base + property var printJob: null + property var progress: + { + if (!printJob) + { + return 0 + } + var result = printJob.timeElapsed / printJob.timeTotal + if (result > 1.0) + { + result = 1.0 + } + return result + } + property var remainingTime: + { + if (!printJob) { + 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 (!printJob) + { + return ""; + } + switch (printJob.state) + { + case "wait_cleanup": + if (printJob.timeTotal > printJob.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 ) + } + } + width: childrenRect.width + height: 18 * screenScaleFactor // TODO: Theme! + + ProgressBar + { + id: progressBar + anchors + { + verticalCenter: parent.verticalCenter + } + value: progress; + style: ProgressBarStyle + { + background: Rectangle + { + color: "#e4e4f2" // TODO: Theme! + implicitHeight: visible ? 8 * screenScaleFactor : 0 // TODO: Theme! + implicitWidth: 180 * screenScaleFactor // TODO: Theme! + radius: 4 * screenScaleFactor // TODO: Theme! + } + progress: Rectangle + { + id: progressItem; + color: + { + if (printJob) + { + var state = printJob.state + var inactiveStates = [ + "pausing", + "paused", + "resuming", + "wait_cleanup" + ] + if (inactiveStates.indexOf(state) > -1 && remainingTime > 0) + { + return UM.Theme.getColor("monitor_progress_fill_inactive") + } + } + return "#0a0850" // TODO: Theme! + } + radius: 4 * screenScaleFactor // TODO: Theme! + } + } + } + Label + { + id: progressLabel + anchors + { + left: progressBar.right + leftMargin: 18 * screenScaleFactor // TODO: Theme! + } + text: progressText + color: "#374355" // TODO: Theme! + width: contentWidth + font: UM.Theme.getFont("medium") // 14pt, regular + + // FIXED-LINE-HEIGHT: + height: 18 * screenScaleFactor // TODO: Theme! + verticalAlignment: Text.AlignVCenter + } +} \ No newline at end of file diff --git a/plugins/UM3NetworkPrinting/resources/qml/MonitorPrinterCard.qml b/plugins/UM3NetworkPrinting/resources/qml/MonitorPrinterCard.qml new file mode 100644 index 0000000000..975fe12244 --- /dev/null +++ b/plugins/UM3NetworkPrinting/resources/qml/MonitorPrinterCard.qml @@ -0,0 +1,242 @@ +// 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 + +/** + * A Printer Card is has two main components: the printer portion and the print + * job portion, the latter being paired in the UI when a print job is paired + * a printer in-cluster. + * + * NOTE: For most labels, a fixed height with vertical alignment is used to make + * layouts more deterministic (like the fixed-size textboxes used in original + * mock-ups). This is also a stand-in for CSS's 'line-height' property. Denoted + * with '// FIXED-LINE-HEIGHT:'. + */ +Item +{ + id: base + + // The printer which all printer data is derived from + property var printer: null + + property var borderSize: 1 * screenScaleFactor // TODO: Theme, and remove from here + + width: 834 * screenScaleFactor // TODO: Theme! + height: 216 * screenScaleFactor // TODO: Theme! + + // Printer portion + Rectangle + { + id: printerInfo + border + { + color: "#EAEAEC" // TODO: Theme! + width: borderSize // TODO: Remove once themed + } + color: "white" // TODO: Theme! + width: parent.width + height: 144 * screenScaleFactor // TODO: Theme! + + Row + { + anchors + { + left: parent.left + leftMargin: 36 * screenScaleFactor // TODO: Theme! + verticalCenter: parent.verticalCenter + } + spacing: 18 * screenScaleFactor // TODO: Theme! + + Image + { + id: printerImage + width: 108 * screenScaleFactor // TODO: Theme! + height: 108 * screenScaleFactor // TODO: Theme! + fillMode: Image.PreserveAspectFit + source: "../png/" + printer.type + ".png" + mipmap: true + } + + Item + { + anchors + { + verticalCenter: parent.verticalCenter + } + width: 216 * screenScaleFactor // TODO: Theme! + height: printerNameLabel.height + printerFamilyPill.height + 6 * screenScaleFactor // TODO: Theme! + + Label + { + id: printerNameLabel + text: printer && printer.name ? printer.name : "" + color: "#414054" // TODO: Theme! + elide: Text.ElideRight + font: UM.Theme.getFont("large") // 16pt, bold + width: parent.width + + // FIXED-LINE-HEIGHT: + height: 18 * screenScaleFactor // TODO: Theme! + verticalAlignment: Text.AlignVCenter + } + + MonitorPrinterPill + { + id: printerFamilyPill + anchors + { + top: printerNameLabel.bottom + topMargin: 6 * screenScaleFactor // TODO: Theme! + left: printerNameLabel.left + } + text: printer.type + } + } + + MonitorPrinterConfiguration + { + id: printerConfiguration + anchors.verticalCenter: parent.verticalCenter + buildplate: "Glass" + configurations: + [ + base.printer.printerConfiguration.extruderConfigurations[0], + base.printer.printerConfiguration.extruderConfigurations[1] + ] + height: 72 * screenScaleFactor // TODO: Theme! + } + } + + PrintJobContextMenu + { + id: contextButton + anchors + { + right: parent.right + rightMargin: 12 * screenScaleFactor // TODO: Theme! + top: parent.top + topMargin: 12 * screenScaleFactor // TODO: Theme! + } + printJob: printer.activePrintJob + width: 36 * screenScaleFactor // TODO: Theme! + height: 36 * screenScaleFactor // TODO: Theme! + } + CameraButton + { + id: cameraButton; + anchors + { + right: parent.right + rightMargin: 20 * screenScaleFactor // TODO: Theme! + bottom: parent.bottom + bottomMargin: 20 * screenScaleFactor // TODO: Theme! + } + iconSource: "../svg/icons/camera.svg" + } + } + + + // Print job portion + Rectangle + { + id: printJobInfo + anchors + { + top: printerInfo.bottom + topMargin: -borderSize * screenScaleFactor // TODO: Theme! + } + border + { + color: "#EAEAEC" // TODO: Theme! + width: borderSize // TODO: Remove once themed + } + color: "white" // TODO: Theme! + height: 84 * screenScaleFactor + borderSize // TODO: Remove once themed + width: parent.width + + Row + { + anchors + { + fill: parent + topMargin: 12 * screenScaleFactor + borderSize // TODO: Theme! + bottomMargin: 12 * screenScaleFactor // TODO: Theme! + leftMargin: 36 * screenScaleFactor // TODO: Theme! + } + height: childrenRect.height + spacing: 18 * screenScaleFactor // TODO: Theme! + + Item + { + anchors + { + verticalCenter: parent.verticalCenter + } + width: printerImage.width + height: 60 * screenScaleFactor // TODO: Theme! + MonitorPrintJobPreview + { + anchors.centerIn: parent + printJob: base.printer.activePrintJob + size: parent.height + } + } + + Item + { + anchors + { + verticalCenter: parent.verticalCenter + } + width: 216 * screenScaleFactor // TODO: Theme! + height: printerNameLabel.height + printerFamilyPill.height + 6 * screenScaleFactor // TODO: Theme! + + Label + { + id: printerJobNameLabel + text: base.printer.activePrintJob ? base.printer.activePrintJob.name : "Untitled" // TODO: I18N + color: "#414054" // TODO: Theme! + elide: Text.ElideRight + font: UM.Theme.getFont("large") // 16pt, bold + width: parent.width + + // FIXED-LINE-HEIGHT: + height: 18 * screenScaleFactor // TODO: Theme! + verticalAlignment: Text.AlignVCenter + } + + Label + { + id: printerJobOwnerLabel + anchors + { + top: printerJobNameLabel.bottom + topMargin: 6 * screenScaleFactor // TODO: Theme! + left: printerJobNameLabel.left + } + text: printer.activePrintJob ? printer.activePrintJob.owner : "Anonymous" // TODO: I18N + color: "#53657d" // TODO: Theme! + elide: Text.ElideRight + font: UM.Theme.getFont("very_small") // 12pt, regular + width: parent.width + + // FIXED-LINE-HEIGHT: + height: 18 * screenScaleFactor // TODO: Theme! + verticalAlignment: Text.AlignVCenter + } + } + + MonitorPrintJobProgressBar + { + anchors + { + verticalCenter: parent.verticalCenter + } + printJob: printer.activePrintJob + } + } + } +} \ No newline at end of file diff --git a/plugins/UM3NetworkPrinting/resources/qml/PrintJobContextMenu.qml b/plugins/UM3NetworkPrinting/resources/qml/PrintJobContextMenu.qml index 11bc913d06..02a8e7ae69 100644 --- a/plugins/UM3NetworkPrinting/resources/qml/PrintJobContextMenu.qml +++ b/plugins/UM3NetworkPrinting/resources/qml/PrintJobContextMenu.qml @@ -25,7 +25,7 @@ Item { } contentItem: Label { color: UM.Theme.getColor("monitor_context_menu_dots"); - font.pixelSize: 25 * screenScaleFactor; + font.pixelSize: 32 * screenScaleFactor; horizontalAlignment: Text.AlignHCenter; text: button.text; verticalAlignment: Text.AlignVCenter; @@ -41,7 +41,7 @@ Item { var states = ["queued", "sent_to_printer", "pre_print", "printing", "pausing", "paused", "resuming"]; return states.indexOf(printJob.state) !== -1; } - width: 35 * screenScaleFactor; // TODO: Theme! + width: 36 * screenScaleFactor; // TODO: Theme! } Popup { diff --git a/plugins/UM3NetworkPrinting/resources/svg/icons/camera.svg b/plugins/UM3NetworkPrinting/resources/svg/icons/camera.svg new file mode 100644 index 0000000000..2eaebb812d --- /dev/null +++ b/plugins/UM3NetworkPrinting/resources/svg/icons/camera.svg @@ -0,0 +1,5 @@ + + + + + \ No newline at end of file diff --git a/plugins/UM3NetworkPrinting/src/ClusterUM3OutputDevice.py b/plugins/UM3NetworkPrinting/src/ClusterUM3OutputDevice.py index 54b888d2f0..8881584416 100644 --- a/plugins/UM3NetworkPrinting/src/ClusterUM3OutputDevice.py +++ b/plugins/UM3NetworkPrinting/src/ClusterUM3OutputDevice.py @@ -65,7 +65,6 @@ class ClusterUM3OutputDevice(NetworkedPrinterOutputDevice): 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._control_view_qml_path = os.path.join(os.path.dirname(os.path.abspath(__file__)), "../resources/qml/ClusterControlItem.qml") # See comments about this hack with the clusterPrintersChanged signal self.printersChanged.connect(self.clusterPrintersChanged) diff --git a/plugins/UM3NetworkPrinting/src/UM3OutputDevicePlugin.py b/plugins/UM3NetworkPrinting/src/UM3OutputDevicePlugin.py index e4b4c2bb0a..91c9cb32b9 100644 --- a/plugins/UM3NetworkPrinting/src/UM3OutputDevicePlugin.py +++ b/plugins/UM3NetworkPrinting/src/UM3OutputDevicePlugin.py @@ -344,7 +344,6 @@ class UM3OutputDevicePlugin(OutputDevicePlugin): # Request more data if info is not complete if not info.address: - Logger.log("d", "Trying to get address of %s", name) info = zero_conf.get_service_info(service_type, name) if info: diff --git a/plugins/USBPrinting/AutoDetectBaudJob.py b/plugins/USBPrinting/AutoDetectBaudJob.py index 8b37c4b29d..6f1af6727a 100644 --- a/plugins/USBPrinting/AutoDetectBaudJob.py +++ b/plugins/USBPrinting/AutoDetectBaudJob.py @@ -3,6 +3,7 @@ from UM.Job import Job from UM.Logger import Logger +from plugins.USBPrinting.avr_isp import ispBase from .avr_isp.stk500v2 import Stk500v2 @@ -14,12 +15,12 @@ from serial import Serial, SerialException # It tries a pre-set list of baud rates. All these baud rates are validated by requesting the temperature a few times # and checking if the results make sense. If getResult() is not None, it was able to find a correct baud rate. class AutoDetectBaudJob(Job): - def __init__(self, serial_port): + def __init__(self, serial_port: int) -> None: super().__init__() self._serial_port = serial_port self._all_baud_rates = [115200, 250000, 230400, 57600, 38400, 19200, 9600] - def run(self): + def run(self) -> None: Logger.log("d", "Auto detect baud rate started.") wait_response_timeouts = [3, 15, 30] wait_bootloader_times = [1.5, 5, 15] @@ -32,7 +33,7 @@ class AutoDetectBaudJob(Job): try: programmer.connect(self._serial_port) serial = programmer.leaveISP() - except: + except ispBase.IspError: programmer.close() for retry in range(tries): @@ -58,7 +59,7 @@ class AutoDetectBaudJob(Job): # We already have a serial connection, just change the baud rate. try: serial.baudrate = baud_rate - except: + except ValueError: continue sleep(wait_bootloader) # Ensure that we are not talking to the boot loader. 1.5 seconds seems to be the magic number successful_responses = 0 @@ -81,5 +82,5 @@ class AutoDetectBaudJob(Job): return serial.write(b"M105\n") - sleep(15) # Give the printer some time to init and try again. + sleep(15) # Give the printer some time to init and try again. self.setResult(None) # Unable to detect the correct baudrate. 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 ee82b17a75..678ea0a697 100644 --- a/resources/bundled_packages/cura.json +++ b/resources/bundled_packages/cura.json @@ -356,6 +356,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/definitions/cocoon_create_modelmaker.def.json b/resources/definitions/cocoon_create_modelmaker.def.json index 204d5b9492..22aa75d09e 100644 --- a/resources/definitions/cocoon_create_modelmaker.def.json +++ b/resources/definitions/cocoon_create_modelmaker.def.json @@ -1,11 +1,11 @@ { - "name": "Cocoon Create ModelMaker & Wanhao Duplicator i3 Mini", + "name": "Cocoon Create ModelMaker", "version": 2, "inherits": "fdmprinter", "metadata": { "visible": true, "author": "Samuel Pinches", - "manufacturer": "Cocoon Create / Wanhao", + "manufacturer": "Cocoon Create", "file_formats": "text/x-gcode", "preferred_quality_type": "fine", "machine_extruder_trains": @@ -15,7 +15,7 @@ }, "overrides": { "machine_name": { - "default_value": "Cocoon Create ModelMaker & Wanhao Duplicator i3 Mini" + "default_value": "Cocoon Create ModelMaker" }, "machine_start_gcode": { "default_value": "; -- START GCODE --\nG21 ;set units to millimetres\nG90 ;set to absolute positioning\nM106 S0 ;set fan speed to zero (turned off)\nG28 ;home all axis\nG92 E0 ;zero the extruded length\nG1 Z1 F1000 ;move up slightly\nG1 X60.0 Z0 E9.0 F1000.0;intro line\nG1 X100.0 E21.5 F1000.0 ;continue line\nG92 E0 ;zero the extruded length again\n; -- end of START GCODE --" @@ -51,7 +51,7 @@ "default_value": 220 }, "layer_height": { - "default_value": 0.15 + "default_value": 0.10 }, "layer_height_0": { "default_value": 0.2 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..a288426e0c --- /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: 2 * UM.Theme.getSize("default_margin").height + spacing: 2 * UM.Theme.getSize("default_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..b9a04f3b46 --- /dev/null +++ b/resources/qml/ActionButton.qml @@ -0,0 +1,98 @@ +// 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 + +Button +{ + id: button + property alias iconSource: buttonIcon.source + property alias textFont: buttonText.font + property alias cornerRadius: backgroundRect.radius + property alias tooltip: tooltip.text + + 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 + + hoverEnabled: true + + 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 + + contentItem: Row + { + UM.RecolorImage + { + id: buttonIcon + source: "" + height: Math.round(0.6 * parent.height) + width: height + sourceSize.width: width + sourceSize.height: height + color: button.hovered ? button.textHoverColor : button.textColor + visible: source != "" + 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 + } + } + + background: Rectangle + { + id: backgroundRect + 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 + } +} 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..2111038cfc --- /dev/null +++ b/resources/qml/ActionPanel/OutputDevicesActionButton.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 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 + + 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") + + anchors + { + top: parent.top + right: parent.right + } + + tooltip: 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..45cb1fdb41 --- /dev/null +++ b/resources/qml/ActionPanel/OutputProcessWidget.qml @@ -0,0 +1,130 @@ +// 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.IconLabel + { + 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("small") + } + + Cura.IconLabel + { + 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") + font: UM.Theme.getFont("very_small") + } + } + + PrintInformationWidget + { + id: printInformationPanel + visible: !preSlicedData + + anchors + { + right: parent.right + verticalCenter: timeAndCostsInformation.verticalCenter + } + } + } + + Row + { + id: buttonRow + spacing: UM.Theme.getSize("default_margin").width + width: parent.width + + Cura.SecondaryButton + { + id: previewStageShortcut + + height: UM.Theme.getSize("action_panel_button").height + 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 + { + width: previewStageShortcut.visible ? UM.Theme.getSize("action_panel_button").width : parent.width + height: UM.Theme.getSize("action_panel_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..82707576e0 --- /dev/null +++ b/resources/qml/ActionPanel/PrintInformationWidget.qml @@ -0,0 +1,64 @@ +// 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 + + //implicitHeight: UM.Theme.getSize("section_icon").height + //implicitWidth: UM.Theme.getSize("section_icon").width + + source: UM.Theme.getIcon("info") + width: UM.Theme.getSize("section_icon").width + height: UM.Theme.getSize("section_icon").height + + sourceSize.width: width + sourceSize.height: 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..156111af4d --- /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("small") + 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("very_small") + 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("small") + 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("very_small") + 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..3329ac4b23 --- /dev/null +++ b/resources/qml/ActionPanel/SliceProcessWidget.qml @@ -0,0 +1,154 @@ +// 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 + + text: catalog.i18nc("@label:PrintjobStatus", "Auto slicing...") + color: UM.Theme.getColor("text") + font: UM.Theme.getFont("very_small") + renderType: Text.NativeRendering + } + + Cura.IconLabel + { + 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") + font: UM.Theme.getFont("very_small") + } + + // 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 + visible: widget.backendState == UM.Backend.Processing + + 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_panel_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 + } + } + + // 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..3578888886 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,49 @@ 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 + MainWindowHeader { - id: machineExtruderCount - - containerStack: Cura.MachineManager.activeMachine - key: "machine_extruder_count" - watchedProperties: [ "value" ] - storeIndex: 0 + id: mainWindowHeader + anchors + { + left: parent.left + right: parent.right + top: applicationMenu.bottom + } } Item { - id: contentItem; + id: contentItem - y: menu.height - width: parent.width; - height: parent.height - menu.height; + anchors + { + top: mainWindowHeader.bottom + bottom: parent.bottom + left: parent.left + right: parent.right + } - Keys.forwardTo: menu + 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 +144,154 @@ UM.MainWindow } } + Rectangle + { + id: stageMenuBackground + anchors + { + left: parent.left + right: parent.right + top: parent.top + } + visible: stageMenu.source != "" + height: visible ? Math.round(UM.Theme.getSize("stage_menu").height / 2) : 0 + + 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") + } + } + } + } + + Connections + { + target: stageMenu.item + onShowTooltip: base.showTooltip(item, location, text) + onHideTooltip: base.hideTooltip() + } + JobSpecs { id: jobSpecs anchors { - bottom: parent.bottom; - right: sidebar.left; - bottomMargin: UM.Theme.getSize("default_margin").height; - rightMargin: UM.Theme.getSize("default_margin").width; + bottom: parent.bottom + bottomMargin: UM.Theme.getSize("default_margin").height } } - 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 + ViewOrientationControls + { + id: viewOrientationControls + + anchors + { + left: parent.left + margins: UM.Theme.getSize("default_margin").width + + bottom: parent.bottom + } + } + + 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 + top: stageMenuBackground.bottom 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 + onShowTooltip: base.showTooltip(item, location, text) + onHideTooltip: base.hideTooltip() + width: UM.Theme.getSize("print_setup_widget").width + height: UM.Theme.getSize("stage_menu").height + headerCornerSide: RoundedRectangle.Direction.Right } } @@ -517,20 +300,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() + SidebarTooltip + { + id: tooltip + } } UM.PreferencesDialog @@ -567,13 +347,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 +359,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 +416,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 +436,8 @@ UM.MainWindow } } - ContextMenu { + ContextMenu + { id: contextMenu } @@ -870,7 +604,8 @@ UM.MainWindow modality: Qt.ApplicationModal } - MessageDialog { + MessageDialog + { id: infoMultipleFilesWithGcodeDialog title: catalog.i18nc("@title:window", "Open File(s)") icon: StandardIcon.Information @@ -914,11 +649,6 @@ UM.MainWindow } } - EngineLog - { - id: engineLog; - } - Connections { target: Cura.Actions.showProfileFolder diff --git a/resources/qml/CustomConfigurationSelector.qml b/resources/qml/CustomConfigurationSelector.qml new file mode 100644 index 0000000000..c78ca700da --- /dev/null +++ b/resources/qml/CustomConfigurationSelector.qml @@ -0,0 +1,357 @@ +// 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 UM 1.2 as UM +import Cura 1.0 as Cura + +Rectangle +{ + implicitWidth: parent.width + implicitHeight: parent.height + + id: base + color: UM.Theme.getColor("main_background") + + // Height has an extra 2x margin for the top & bottom margin. + height: childrenRect.height + 2 * UM.Theme.getSize("default_margin").width + + Cura.ExtrudersModel { id: extrudersModel } + + ListView + { + // Horizontal list that shows the extruders + id: extrudersList + visible: extrudersModel.items.length > 1 + property var index: 0 + + height: UM.Theme.getSize("configuration_selector_mode_tabs").height + boundsBehavior: Flickable.StopAtBounds + + anchors + { + left: parent.left + right: parent.right + top: parent.top + margins: UM.Theme.getSize("thick_margin").width + } + + ExclusiveGroup { id: extruderMenuGroup } + + orientation: ListView.Horizontal + + model: 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: parent.height + width: Math.round(ListView.view.width / extrudersModel.rowCount()) + + text: model.name + tooltip: model.name + exclusiveGroup: extruderMenuGroup + checked: Cura.ExtruderManager.activeExtruderIndex == index + + property bool extruder_enabled: true + + MouseArea // TODO; This really should be fixed. It makes absolutely no sense to have a button AND a mouse area. + { + 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: Rectangle + { + anchors.fill: parent + border.width: control.checked ? UM.Theme.getSize("default_lining").width * 2 : UM.Theme.getSize("default_lining").width + border.color: + { + if (Cura.MachineManager.getExtruder(index).isEnabled) + { + 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") + } + return UM.Theme.getColor("action_button_disabled_border") + } + color: + { + if (Cura.MachineManager.getExtruder(index).isEnabled) + { + 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") + } + return UM.Theme.getColor("action_button_disabled") + } + Behavior on color { ColorAnimation { duration: 50; } } + + Item + { + id: extruderButtonFace + anchors.centerIn: parent + width: childrenRect.width + + Label + { + // Static text that holds the "Extruder" label + id: extruderStaticText + anchors.verticalCenter: parent.verticalCenter + anchors.left: parent.left + + color: + { + if (Cura.MachineManager.getExtruder(index).isEnabled) + { + 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") + } + return UM.Theme.getColor("action_button_disabled_text") + } + + font: UM.Theme.getFont("large_nonbold") + text: catalog.i18nc("@label", "Extruder") + visible: width < (control.width - extruderIcon.width - UM.Theme.getSize("default_margin").width) + elide: Text.ElideRight + } + + ExtruderIcon + { + // Round icon with the extruder number and material color indicator. + id: extruderIcon + + anchors.verticalCenter: parent.verticalCenter + anchors.left: extruderStaticText.right + anchors.leftMargin: UM.Theme.getSize("default_margin").width + width: control.height - Math.round(UM.Theme.getSize("default_margin").width / 2) + height: width + + checked: control.checked + materialColor: model.color + textColor: extruderStaticText.color + } + } + } + + label: Item {} + } + } + } + + Item + { + id: materialRow + height: UM.Theme.getSize("print_setup_item").height + visible: Cura.MachineManager.hasMaterials + + anchors + { + left: parent.left + right: parent.right + top: extrudersList.bottom + margins: UM.Theme.getSize("thick_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 || Cura.ExtruderManager.activeExtruderIndex > -1 + + height: UM.Theme.getSize("setting_control").height + width: Math.round(parent.width * 0.7) + UM.Theme.getSize("thick_margin").width + anchors.right: parent.right + style: UM.Theme.styles.sidebar_header_button + activeFocusOnPress: true; + menu: Cura.MaterialMenu + { + extruderIndex: Cura.ExtruderManager.activeExtruderIndex + } + + property var valueError: hasActiveExtruder ? Cura.ContainerManager.getContainerMetaDataEntry(activeExtruder.material.id, "compatible", "") != "True" : true + property var valueWarning: ! Cura.MachineManager.isActiveQualitySupported + } + } + + Item + { + id: variantRow + height: UM.Theme.getSize("print_setup_item").height + visible: Cura.MachineManager.hasVariants + + anchors + { + left: parent.left + right: parent.right + top: materialRow.bottom + margins: UM.Theme.getSize("thick_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("thick_margin").width) + anchors.right: parent.right + style: UM.Theme.styles.sidebar_header_button + activeFocusOnPress: true; + + menu: Cura.NozzleMenu { extruderIndex: Cura.ExtruderManager.activeExtruderIndex } + } + } + + Item + { + id: materialCompatibilityLink + height: UM.Theme.getSize("print_setup_item").height + + anchors.right: parent.right + anchors.top: variantRow.bottom + anchors.margins: UM.Theme.getSize("thick_margin").width + UM.RecolorImage + { + id: warningImage + + anchors.right: materialInfoLabel.left + anchors.rightMargin: UM.Theme.getSize("default_margin").width + + 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 + } + + 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.right: parent.right + + MouseArea + { + anchors.fill: parent + + onClicked: + { + // open the material URL with web browser + Qt.openUrlExternally("https://ultimaker.com/incoming-links/cura/material-compatibilty"); + } + } + } + } +} diff --git a/resources/qml/Dialogs/AboutDialog.qml b/resources/qml/Dialogs/AboutDialog.qml new file mode 100644 index 0000000000..25c9bbf74b --- /dev/null +++ b/resources/qml/Dialogs/AboutDialog.qml @@ -0,0 +1,170 @@ +// 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 * (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/AddMachineDialog.qml b/resources/qml/Dialogs/AddMachineDialog.qml similarity index 91% rename from resources/qml/AddMachineDialog.qml rename to resources/qml/Dialogs/AddMachineDialog.qml index aa160acd4d..8e966c3df7 100644 --- a/resources/qml/AddMachineDialog.qml +++ b/resources/qml/Dialogs/AddMachineDialog.qml @@ -213,28 +213,6 @@ UM.Dialog PropertyChanges { target: machineButton; opacity: 0; height: 0; } } - - transitions: - [ - Transition - { - to: "collapsed"; - SequentialAnimation - { - NumberAnimation { property: "opacity"; duration: 75; } - NumberAnimation { property: "height"; duration: 75; } - } - }, - Transition - { - from: "collapsed"; - SequentialAnimation - { - NumberAnimation { property: "height"; duration: 75; } - NumberAnimation { property: "opacity"; duration: 75; } - } - } - ] } } } @@ -298,7 +276,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 100% rename from resources/qml/WorkspaceSummaryDialog.qml rename to resources/qml/Dialogs/WorkspaceSummaryDialog.qml 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..b438f0398c --- /dev/null +++ b/resources/qml/ExpandableComponent.qml @@ -0,0 +1,196 @@ +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 3 major sub components: +// * The headerItem; Always visible and should hold some info about what happens if the component is expanded +// * The popupItem; The content that needs to be shown if the component is expanded. +// * The icon; An icon that is displayed on the right of the drawer. +Item +{ + id: base + + // Enumeration with the different possible alignments of the popup with respect of the headerItem + enum PopupAlignment + { + AlignLeft, + AlignRight + } + + // The headerItem holds the QML item that is always displayed. + property alias headerItem: headerItemLoader.sourceComponent + + // The popupItem holds the QML item that is shown when the "open" button is pressed + property var popupItem + + property color popupBackgroundColor: UM.Theme.getColor("action_button") + + property color headerBackgroundColor: UM.Theme.getColor("action_button") + property color headerHoverColor: UM.Theme.getColor("action_button_hovered") + + // Defines the alignment of the popup with respect of the headerItem, by default to the right + property int popupAlignment: ExpandableComponent.PopupAlignment.AlignRight + + // How much spacing is needed around the popupItem + property alias popupPadding: popup.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: popup.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 + + property alias headerShadowColor: shadow.color + + property alias enableHeaderShadow: shadow.visible + + property int shadowOffset: 2 + + function togglePopup() + { + if(popup.visible) + { + popup.close() + } + else + { + popup.open() + } + } + + onPopupItemChanged: + { + // Since we want the size of the popup to be set by the size of the content, + // we need to do it like this. + popup.width = popupItem.width + 2 * popup.padding + popup.height = popupItem.height + 2 * popup.padding + popup.contentItem = popupItem + } + + Connections + { + // Since it could be that the popup is dynamically populated, we should also take these changes into account. + target: popupItem + onWidthChanged: popup.width = popupItem.width + 2 * popup.padding + onHeightChanged: popup.height = popupItem.height + 2 * popup.padding + } + + implicitHeight: 100 * screenScaleFactor + implicitWidth: 400 * screenScaleFactor + + RoundedRectangle + { + id: background + property real padding: UM.Theme.getSize("default_margin").width + + color: headerBackgroundColor + anchors.fill: parent + + 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 popup 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 + } + sourceSize.width: width + sourceSize.height: height + visible: source != "" + width: height + height: Math.round(0.2 * base.height) + color: UM.Theme.getColor("text") + } + + MouseArea + { + id: mouseArea + anchors.fill: parent + onClicked: togglePopup() + hoverEnabled: true + onEntered: background.color = headerHoverColor + onExited: background.color = headerBackgroundColor + } + } + 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: popup + + // Ensure that the popup is located directly below the headerItem + y: headerItemLoader.height + 2 * background.padding + base.shadowOffset + + // Make the popup aligned with the rest, using the property popupAlignment 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: popupAlignment == ExpandableComponent.PopupAlignment.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: popupBackgroundColor + border.width: UM.Theme.getSize("default_lining").width + border.color: UM.Theme.getColor("lining") + radius: UM.Theme.getSize("default_radius").width + } + } +} 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..c1a202050b --- /dev/null +++ b/resources/qml/ExtruderIcon.qml @@ -0,0 +1,72 @@ +// 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 + + sourceSize.width: parent.width + sourceSize.height: parent.height + source: UM.Theme.getIcon("extruder_button") + color: extruderEnabled ? materialColor: "gray" + } + + 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("extruder_icon") + 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.width: width + sourceSize.height: width + source: UM.Theme.getIcon("cross1") + visible: !extruderEnabled + color: "black" + } + } +} \ No newline at end of file diff --git a/resources/qml/IconLabel.qml b/resources/qml/IconLabel.qml new file mode 100644 index 0000000000..0941254e7b --- /dev/null +++ b/resources/qml/IconLabel.qml @@ -0,0 +1,54 @@ +// 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 + +// This item will show a label with a squared icon in the left +Item +{ + id: container + + property alias text: label.text + property alias source: icon.source + property alias color: label.color + property alias font: label.font + property alias iconSize: icon.width + + implicitHeight: icon.height + + UM.RecolorImage + { + id: icon + + anchors.left: parent.left + anchors.verticalCenter: parent.verticalCenter + + source: "" + width: UM.Theme.getSize("section_icon").width + height: width + + sourceSize.width: width + sourceSize.height: height + + color: label.color + 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: "Empty label" + elide: Text.ElideRight + color: UM.Theme.getColor("text") + font: UM.Theme.getFont("very_small") + renderType: Text.NativeRendering + } +} \ No newline at end of file diff --git a/resources/qml/IconWithText.qml b/resources/qml/IconWithText.qml new file mode 100644 index 0000000000..dcb3ef7851 --- /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 iconColor: icon.color + property alias source: icon.source + property alias text: label.text + + 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 + + sourceSize.width: width + sourceSize.height: height + color: "black" + + 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..45111992c1 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 @@ -15,7 +15,7 @@ Item { property bool activity: CuraApplication.platformActivity property string fileBaseName: PrintInformation.baseName - UM.I18nCatalog { id: catalog; name:"cura"} + UM.I18nCatalog { id: catalog; name: "cura"} height: childrenRect.height 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..34936e9b5a --- /dev/null +++ b/resources/qml/MainWindow/MainWindowHeader.qml @@ -0,0 +1,146 @@ +// 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" + +Rectangle +{ + id: base + + implicitHeight: UM.Theme.getSize("main_window_header").height + implicitWidth: UM.Theme.getSize("main_window_header").width + + 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") + } + } + } + + 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: 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/ConfigurationItem.qml b/resources/qml/Menus/ConfigurationMenu/ConfigurationItem.qml index 942dd81d9c..7427b5ddff 100644 --- a/resources/qml/Menus/ConfigurationMenu/ConfigurationItem.qml +++ b/resources/qml/Menus/ConfigurationMenu/ConfigurationItem.qml @@ -63,7 +63,7 @@ Rectangle visible: buildplateInformation.visible width: parent.width - 2 * parent.padding - height: visible ? Math.round(UM.Theme.getSize("sidebar_lining_thin").height / 2) : 0 + height: visible ? Math.round(UM.Theme.getSize("thick_lining").height / 2) : 0 color: textColor } @@ -77,8 +77,8 @@ Rectangle UM.RecolorImage { id: buildplateIcon anchors.left: parent.left - width: UM.Theme.getSize("topbar_button_icon").width - height: UM.Theme.getSize("topbar_button_icon").height + width: UM.Theme.getSize("main_window_header_button_icon").width + height: UM.Theme.getSize("main_window_header_button_icon").height sourceSize.width: width sourceSize.height: height source: UM.Theme.getIcon("buildplate") @@ -110,7 +110,7 @@ Rectangle parent.border.color = UM.Theme.getColor("configuration_item_border_hover") if (configurationItem.selected == false) { - configurationItem.color = UM.Theme.getColor("sidebar_lining") + configurationItem.color = UM.Theme.getColor("wide_lining") } } onExited: diff --git a/resources/qml/Menus/ConfigurationMenu/ConfigurationListView.qml b/resources/qml/Menus/ConfigurationMenu/ConfigurationListView.qml index 7aaf87b4df..210ff6057f 100644 --- a/resources/qml/Menus/ConfigurationMenu/ConfigurationListView.qml +++ b/resources/qml/Menus/ConfigurationMenu/ConfigurationListView.qml @@ -21,7 +21,7 @@ Column { // 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 } 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/PrintCoreConfiguration.qml b/resources/qml/Menus/ConfigurationMenu/PrintCoreConfiguration.qml index 97b5bee745..73fc342d66 100644 --- a/resources/qml/Menus/ConfigurationMenu/PrintCoreConfiguration.qml +++ b/resources/qml/Menus/ConfigurationMenu/PrintCoreConfiguration.qml @@ -70,7 +70,7 @@ Column Label { id: materialLabel - text: printCoreConfiguration.material.name + text: printCoreConfiguration.material == null ? "" : printCoreConfiguration.material.name renderType: Text.NativeRendering elide: Text.ElideRight width: parent.width diff --git a/resources/qml/Menus/ConfigurationMenu/QuickConfigurationSelector.qml b/resources/qml/Menus/ConfigurationMenu/QuickConfigurationSelector.qml new file mode 100644 index 0000000000..eb6800cb36 --- /dev/null +++ b/resources/qml/Menus/ConfigurationMenu/QuickConfigurationSelector.qml @@ -0,0 +1,243 @@ +// 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 QtQuick.Layouts 1.3 + +import QtQuick.Controls 1.1 as OldControls + +import UM 1.2 as UM +import Cura 1.0 as Cura + + +Cura.ExpandableComponent +{ + id: base + + Cura.ExtrudersModel + { + id: extrudersModel + } + + UM.I18nCatalog + { + id: catalog + name: "cura" + } + + iconSource: expanded ? UM.Theme.getIcon("arrow_bottom") : UM.Theme.getIcon("arrow_left") + headerItem: Item + { + // Horizontal list that shows the extruders + ListView + { + id: extrudersList + + orientation: ListView.Horizontal + anchors.fill: parent + model: extrudersModel + + delegate: Item + { + height: parent.height + width: Math.round(ListView.view.width / extrudersModel.rowCount()) + + // Extruder icon. Shows extruder index and has the same color as the active material. + Cura.ExtruderIcon + { + id: extruderIcon + materialColor: model.color + extruderEnabled: model.enabled + anchors.verticalCenter: parent.verticalCenter + } + + // 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") + + 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") + + anchors + { + left: extruderIcon.right + leftMargin: UM.Theme.getSize("default_margin").width + right: parent.right + rightMargin: UM.Theme.getSize("default_margin").width + top: brandNameLabel.bottom + } + } + } + } + } + + popupItem: Item + { + width: base.width - 2 * UM.Theme.getSize("default_margin").width + height: 200 + + TabBar + { + id: tabBar + onCurrentIndexChanged: Cura.ExtruderManager.setActiveExtruderIndex(currentIndex) + width: parent.width + height: 50 + Repeater + { + model: extrudersModel + + delegate: TabButton + { + width: ListView.view != null ? Math.round(ListView.view.width / extrudersModel.rowCount()): 0 + height: parent.height + contentItem: Item + { + Cura.ExtruderIcon + { + anchors.horizontalCenter: parent.horizontalCenter + materialColor: model.color + extruderEnabled: model.enabled + width: parent.height + height: parent.height + } + } + } + } + } + + Item + { + id: tabControl + width: parent.width + anchors.top: tabBar.bottom + anchors.bottom: parent.bottom + property var model: extrudersModel.items[tabBar.currentIndex] + property real textWidth: Math.round(width * 0.3) + property real controlWidth: width - textWidth + Column + { + spacing: UM.Theme.getSize("default_margin").height + Row + { + height: UM.Theme.getSize("print_setup_item").height + + Label + { + text: catalog.i18nc("@label", "Enabled") + verticalAlignment: Text.AlignVCenter + font: UM.Theme.getFont("default") + color: UM.Theme.getColor("text") + height: parent.height + width: tabControl.textWidth + renderType: Text.NativeRendering + } + + OldControls.CheckBox + { + checked: tabControl.model != null ? Cura.MachineManager.getExtruder(tabControl.model.index).isEnabled: false + onClicked: Cura.MachineManager.setExtruderEnabled(tabControl.model.index, checked) + height: UM.Theme.getSize("setting_control").height + style: UM.Theme.styles.checkbox + } + } + + Row + { + height: UM.Theme.getSize("print_setup_item").height + Label + { + text: catalog.i18nc("@label", "Material") + verticalAlignment: Text.AlignVCenter + font: UM.Theme.getFont("default") + color: UM.Theme.getColor("text") + height: parent.height + width: tabControl.textWidth + renderType: Text.NativeRendering + } + + OldControls.ToolButton + { + id: materialSelection + + property var activeExtruder: Cura.MachineManager.activeStack + property var hasActiveExtruder: activeExtruder != null + property var currentRootMaterialName: hasActiveExtruder ? activeExtruder.material.name : "" + property var valueError: hasActiveExtruder ? Cura.ContainerManager.getContainerMetaDataEntry(activeExtruder.material.id, "compatible", "") != "True" : true + property var valueWarning: ! Cura.MachineManager.isActiveQualitySupported + + text: currentRootMaterialName + tooltip: currentRootMaterialName + visible: Cura.MachineManager.hasMaterials + + enabled: Cura.ExtruderManager.activeExtruderIndex > -1 + + height: UM.Theme.getSize("setting_control").height + width: tabControl.controlWidth + + style: UM.Theme.styles.sidebar_header_button + activeFocusOnPress: true + menu: Cura.MaterialMenu + { + extruderIndex: Cura.ExtruderManager.activeExtruderIndex + } + + } + } + + Row + { + height: UM.Theme.getSize("print_setup_item").height + + Label + { + text: Cura.MachineManager.activeDefinitionVariantsName + verticalAlignment: Text.AlignVCenter + font: UM.Theme.getFont("default") + color: UM.Theme.getColor("text") + height: parent.height + width: tabControl.textWidth + renderType: Text.NativeRendering + } + + OldControls.ToolButton + { + id: variantSelection + text: Cura.MachineManager.activeVariantName + tooltip: Cura.MachineManager.activeVariantName; + visible: Cura.MachineManager.hasVariants + + height: UM.Theme.getSize("setting_control").height + width: tabControl.controlWidth + style: UM.Theme.styles.sidebar_header_button + activeFocusOnPress: true; + + menu: Cura.NozzleMenu { extruderIndex: Cura.ExtruderManager.activeExtruderIndex } + } + } + } + + } + } +} diff --git a/resources/qml/Menus/ConfigurationMenu/SyncButton.qml b/resources/qml/Menus/ConfigurationMenu/SyncButton.qml index 3099d684c1..558ae1e477 100644 --- a/resources/qml/Menus/ConfigurationMenu/SyncButton.qml +++ b/resources/qml/Menus/ConfigurationMenu/SyncButton.qml @@ -42,15 +42,15 @@ Button { if(control.pressed) { - return UM.Theme.getColor("sidebar_header_active"); + return UM.Theme.getColor("machine_selector_active"); } else if(control.hovered) { - return UM.Theme.getColor("sidebar_header_hover"); + return UM.Theme.getColor("machine_selector_hover"); } else { - return UM.Theme.getColor("sidebar_header_bar"); + return UM.Theme.getColor("machine_selector_bar"); } } Behavior on color { ColorAnimation { duration: 50; } } 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 ffd3c556b6..fd46d2ef72 100644 --- a/resources/qml/Menus/ProfileMenu.qml +++ b/resources/qml/Menus/ProfileMenu.qml @@ -17,18 +17,21 @@ Menu MenuItem { - text: (model.layer_height != "") ? model.name + " - " + model.layer_height + model.layer_height_unit : model.name + text: + { + var full_text = (model.layer_height != "") ? model.name + " - " + model.layer_height + model.layer_height_unit : model.name + full_text += model.is_experimental ? " - Experimental" : "" + return full_text + } checkable: true checked: Cura.MachineManager.activeQualityOrQualityChangesName == model.name exclusiveGroup: group - onTriggered: { - Cura.MachineManager.setQualityGroup(model.quality_group) - } + onTriggered: Cura.MachineManager.setQualityGroup(model.quality_group) visible: model.available } - onObjectAdded: menu.insertItem(index, object); - onObjectRemoved: menu.removeItem(object); + onObjectAdded: menu.insertItem(index, object) + onObjectRemoved: menu.removeItem(object) } MenuSeparator 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..79f8c5b7bf --- /dev/null +++ b/resources/qml/Menus/SettingsMenu.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.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.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: 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..eef76bcb09 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 diff --git a/resources/qml/MonitorSidebar.qml b/resources/qml/MonitorSidebar.qml index 80bd5c1a2e..50416e34ab 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. diff --git a/resources/qml/Preferences/GeneralPage.qml b/resources/qml/Preferences/GeneralPage.qml index bba2cf764a..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 { @@ -151,7 +151,6 @@ UM.PreferencesPage { id: languageLabel text: catalog.i18nc("@label","Language:") - anchors.verticalCenter: languageComboBox.verticalCenter } ComboBox @@ -219,7 +218,6 @@ UM.PreferencesPage { id: currencyLabel text: catalog.i18nc("@label","Currency:") - anchors.verticalCenter: currencyField.verticalCenter } TextField @@ -233,7 +231,6 @@ UM.PreferencesPage { id: themeLabel text: catalog.i18nc("@label","Theme:") - anchors.verticalCenter: themeComboBox.verticalCenter } ComboBox diff --git a/resources/qml/Preferences/SettingVisibilityPage.qml b/resources/qml/Preferences/SettingVisibilityPage.qml index 8896d0611e..e319069502 100644 --- a/resources/qml/Preferences/SettingVisibilityPage.qml +++ b/resources/qml/Preferences/SettingVisibilityPage.qml @@ -117,7 +117,7 @@ UM.PreferencesPage { for(var i = 0; i < settingVisibilityPresetsModel.items.length; ++i) { - if(settingVisibilityPresetsModel.items[i].id == settingVisibilityPresetsModel.activePreset) + if(settingVisibilityPresetsModel.items[i].presetId == settingVisibilityPresetsModel.activePreset) { currentIndex = i; return; @@ -128,8 +128,8 @@ UM.PreferencesPage onActivated: { - var preset_id = settingVisibilityPresetsModel.items[index].id; - settingVisibilityPresetsModel.setActivePreset(preset_id); + var preset_id = settingVisibilityPresetsModel.items[index].presetId + settingVisibilityPresetsModel.setActivePreset(preset_id) } } 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..3cc161cbe7 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 + SidebarTooltip { - 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.qml b/resources/qml/PrintSetupSelector.qml new file mode 100644 index 0000000000..9b90d8589f --- /dev/null +++ b/resources/qml/PrintSetupSelector.qml @@ -0,0 +1,261 @@ +// 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 +import "Menus" +import "Menus/ConfigurationMenu" + +Cura.ExpandableComponent +{ + id: base + + property int currentModeIndex: -1 + property bool hideSettings: PrintInformation.preSliced + + property string enabledText: catalog.i18nc("@label:Should be short", "On") + property string disabledText: catalog.i18nc("@label:Should be short", "Off") + + // This widget doesn't show tooltips by itself. Instead it emits signals so others can do something with it. + signal showTooltip(Item item, point location, string text) + signal hideTooltip() + + implicitWidth: 200 * screenScaleFactor + height: childrenRect.height + iconSource: UM.Theme.getIcon("pencil") + + onCurrentModeIndexChanged: UM.Preferences.setValue("cura/active_mode", currentModeIndex) + + 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) + } + + headerItem: RowLayout + { + anchors.fill: parent + + IconWithText + { + source: UM.Theme.getIcon("category_layer_height") + text: Cura.MachineManager.activeStack ? Cura.MachineManager.activeQualityOrQualityChangesName + " " + layerHeight.properties.value + "mm" : "" + + UM.SettingPropertyProvider + { + id: layerHeight + containerStack: Cura.MachineManager.activeStack + key: "layer_height" + watchedProperties: ["value"] + } + } + + 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"] + } + } + + 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"] + } + } + + 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"] + } + } + } + + popupItem: Item + { + height: settingsModeSelection.height + sidebarContents.height + 2 * UM.Theme.getSize("default_margin").height + width: UM.Theme.getSize("print_setup_widget").width + ListView + { + // Settings mode selection toggle + id: settingsModeSelection + model: modesListModel + height: UM.Theme.getSize("print_setup_mode_toggle").height + visible: !hideSettings + + anchors + { + right: parent.right + left: parent.left + margins: UM.Theme.getSize("thick_margin").width + } + + ButtonGroup + { + id: modeMenuGroup + } + + delegate: 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") + } + } + } + } + + Item + { + id: sidebarContents + anchors.top: settingsModeSelection.bottom + anchors.topMargin: UM.Theme.getSize("thick_margin").height + anchors.left: parent.left + anchors.right: parent.right + height: UM.Theme.getSize("print_setup_widget").height + + visible: !hideSettings + + // We load both of them at once (instead of using a loader) because the advanced sidebar can take + // quite some time to load. So in this case we sacrifice memory for speed. + SidebarAdvanced + { + anchors.fill: parent + visible: currentModeIndex == 1 + onShowTooltip: base.showTooltip(item, location, text) + onHideTooltip: base.hideTooltip() + } + + SidebarSimple + { + anchors.fill: parent + visible: currentModeIndex != 1 + onShowTooltip: base.showTooltip(item, location, text) + onHideTooltip: base.hideTooltip() + } + } + + // Setting mode: Recommended or Custom + ListModel + { + id: modesListModel + } + + Component.onCompleted: + { + modesListModel.append({ + text: catalog.i18nc("@title:tab", "Recommended"), + tooltipText: "%1

%2".arg(catalog.i18nc("@tooltip:title", "Recommended Print Setup")).arg(catalog.i18nc("@tooltip", "Print with the recommended settings for the selected printer, material and quality.")) + }) + modesListModel.append({ + text: catalog.i18nc("@title:tab", "Custom"), + tooltipText: "%1

%2".arg(catalog.i18nc("@tooltip:title", "Custom Print Setup")).arg(catalog.i18nc("@tooltip", "Print with finegrained control over every last bit of the slicing process.")) + }) + + var index = Math.round(UM.Preferences.getValue("cura/active_mode")) + + if(index != null && !isNaN(index)) + { + currentModeIndex = index + } + else + { + currentModeIndex = 0 + } + } + } +} diff --git a/resources/qml/PrinterOutput/ExtruderBox.qml b/resources/qml/PrinterOutput/ExtruderBox.qml index f0abd4cd6c..f5a1bd75c4 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 { diff --git a/resources/qml/PrinterOutput/HeatedBedBox.qml b/resources/qml/PrinterOutput/HeatedBedBox.qml index 9de66ad0be..8c99814e02 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. @@ -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..e6328546ef 100644 --- a/resources/qml/PrinterOutput/OutputDeviceHeader.qml +++ b/resources/qml/PrinterOutput/OutputDeviceHeader.qml @@ -45,8 +45,8 @@ Item text: (outputDevice != null && outputDevice.address != null) ? outputDevice.address : "" font: UM.Theme.getFont("small") 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 } diff --git a/resources/qml/PrinterSelector/MachineSelector.qml b/resources/qml/PrinterSelector/MachineSelector.qml new file mode 100644 index 0000000000..15cd773c90 --- /dev/null +++ b/resources/qml/PrinterSelector/MachineSelector.qml @@ -0,0 +1,155 @@ +// 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.ExpandableComponent +{ + 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 + + popupPadding: UM.Theme.getSize("default_lining").width + popupAlignment: Cura.ExpandableComponent.PopupAlignment.AlignLeft + iconSource: expanded ? UM.Theme.getIcon("arrow_bottom") : UM.Theme.getIcon("arrow_left") + + UM.I18nCatalog + { + id: catalog + name: "cura" + } + + headerItem: Cura.IconLabel + { + text: isNetworkPrinter ? Cura.MachineManager.activeMachineNetworkGroupName : Cura.MachineManager.activeMachineName + source: + { + if (isNetworkPrinter) + { + if (machineSelector.outputDevice != null && machineSelector.outputDevice.clusterSize > 1) + { + return UM.Theme.getIcon("printer_group") + } + return UM.Theme.getIcon("printer_single") + } + return "" + } + font: UM.Theme.getFont("medium") + color: UM.Theme.getColor("text") + iconSize: UM.Theme.getSize("machine_selector_icon").width + + UM.RecolorImage + { + id: icon + + 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 + + sourceSize.width: width + sourceSize.height: 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 + } + } + } + + popupItem: 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: + { + togglePopup() + 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: + { + togglePopup() + Cura.Actions.configureMachines.trigger() + } + } + } + } +} diff --git a/resources/qml/PrinterSelector/MachineSelectorButton.qml b/resources/qml/PrinterSelector/MachineSelectorButton.qml new file mode 100644 index 0000000000..369e75cede --- /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: + { + togglePopup() + 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..5ef04b7351 --- /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", "Network 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/PrinterSelector/PrinterTypeLabel.qml b/resources/qml/PrinterSelector/PrinterTypeLabel.qml new file mode 100644 index 0000000000..cd9f3b9743 --- /dev/null +++ b/resources/qml/PrinterSelector/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("very_small") + 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..aafe36c546 100644 --- a/resources/qml/Settings/SettingCategory.qml +++ b/resources/qml/Settings/SettingCategory.qml @@ -12,25 +12,34 @@ 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 + anchors.leftMargin: UM.Theme.getSize("thick_margin").width + anchors.rightMargin: UM.Theme.getSize("thick_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") + } else + { + return UM.Theme.getColor("setting_category") } } Behavior on color { ColorAnimation { duration: 50; } } @@ -40,17 +49,23 @@ Button 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"); + 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") } } } @@ -65,18 +80,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 +100,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 @@ -111,16 +133,21 @@ Button 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") + } else + { + return UM.Theme.getColor("setting_category_text") } } source: base.checked ? UM.Theme.getIcon("arrow_bottom") : UM.Theme.getIcon("arrow_left") @@ -135,21 +162,26 @@ Button anchors.leftMargin: UM.Theme.getSize("default_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") + } else + { + 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 +191,26 @@ Button onClicked: { - if (definition.expanded) { - settingDefinitionsModel.collapse(definition.key); + if (definition.expanded) + { + settingDefinitionsModel.collapse(definition.key) } else { - settingDefinitionsModel.expandRecursive(definition.key); + 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) { - 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 +220,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 +232,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 +265,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/SettingItem.qml b/resources/qml/Settings/SettingItem.qml index 785562cff5..cad6a28bd6 100644 --- a/resources/qml/Settings/SettingItem.qml +++ b/resources/qml/Settings/SettingItem.qml @@ -128,11 +128,11 @@ 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 { 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 } @@ -290,7 +290,7 @@ Item { enabled: propertyProvider.isValueUsed anchors.right: parent.right; - anchors.rightMargin: UM.Theme.getSize("sidebar_margin").width + anchors.rightMargin: UM.Theme.getSize("thick_margin").width anchors.verticalCenter: parent.verticalCenter; width: UM.Theme.getSize("setting_control").width; height: UM.Theme.getSize("setting_control").height diff --git a/resources/qml/Settings/SettingView.qml b/resources/qml/Settings/SettingView.qml index da50b430ac..ef1f123953 100644 --- a/resources/qml/Settings/SettingView.qml +++ b/resources/qml/Settings/SettingView.qml @@ -24,16 +24,15 @@ Item Item { id: globalProfileRow - height: UM.Theme.getSize("sidebar_setup").height - visible: !sidebar.hideSettings + height: UM.Theme.getSize("print_setup_item").height anchors { top: parent.top left: parent.left - leftMargin: Math.round(UM.Theme.getSize("sidebar_margin").width) + leftMargin: Math.round(UM.Theme.getSize("thick_margin").width) right: parent.right - rightMargin: Math.round(UM.Theme.getSize("sidebar_margin").width) + rightMargin: Math.round(UM.Theme.getSize("thick_margin").width) } Label @@ -41,7 +40,7 @@ Item id: globalProfileLabel text: catalog.i18nc("@label","Profile:") textFormat: Text.PlainText - width: Math.round(parent.width * 0.45 - UM.Theme.getSize("sidebar_margin").width - 2) + width: Math.round(parent.width * 0.45 - UM.Theme.getSize("thick_margin").width - 2) font: UM.Theme.getFont("default") color: UM.Theme.getColor("text") verticalAlignment: Text.AlignVCenter @@ -54,7 +53,6 @@ Item 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 @@ -64,11 +62,18 @@ Item activeFocusOnPress: true menu: ProfileMenu { } - function generateActiveQualityText () { - var result = Cura.MachineManager.activeQualityOrQualityChangesName; + function generateActiveQualityText () + { + var result = Cura.MachineManager.activeQualityOrQualityChangesName + if (Cura.MachineManager.isActiveQualityExperimental) + { + result += " (Experimental)" + } - if (Cura.MachineManager.isActiveQualitySupported) { - if (Cura.MachineManager.activeQualityLayerHeight > 0) { + if (Cura.MachineManager.isActiveQualitySupported) + { + if (Cura.MachineManager.activeQualityLayerHeight > 0) + { result += " " result += " - " result += Cura.MachineManager.activeQualityLayerHeight + "mm" @@ -89,7 +94,7 @@ Item 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) + 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"); @@ -102,7 +107,7 @@ Item 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) + base.showTooltip(globalProfileRow, Qt.point(-UM.Theme.getSize("thick_margin").width, 0), content) } onExited: base.hideTooltip() } @@ -118,9 +123,9 @@ Item anchors { top: globalProfileRow.bottom - topMargin: UM.Theme.getSize("sidebar_margin").height + topMargin: UM.Theme.getSize("thick_margin").height right: parent.right - rightMargin: UM.Theme.getSize("sidebar_margin").width + rightMargin: UM.Theme.getSize("thick_margin").width } style: ButtonStyle { @@ -171,15 +176,13 @@ Item anchors { top: globalProfileRow.bottom - topMargin: UM.Theme.getSize("sidebar_margin").height + topMargin: UM.Theme.getSize("thick_margin").height left: parent.left - leftMargin: UM.Theme.getSize("sidebar_margin").width + leftMargin: UM.Theme.getSize("thick_margin").width right: settingVisibilityMenu.left rightMargin: Math.floor(UM.Theme.getSize("default_margin").width / 2) } - height: visible ? UM.Theme.getSize("setting_control").height : 0 - Behavior on height { NumberAnimation { duration: 100 } } - + height: UM.Theme.getSize("setting_control").height Timer { id: settingsSearchTimer @@ -195,7 +198,7 @@ Item 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...") @@ -292,8 +295,7 @@ Item 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 } } + anchors.topMargin: UM.Theme.getSize("thick_margin").height style: UM.Theme.styles.scrollview; flickableItem.flickableDirection: Flickable.VerticalFlick; @@ -330,7 +332,7 @@ Item { id: delegate - width: Math.round(UM.Theme.getSize("sidebar").width); + width: Math.round(UM.Theme.getSize("print_setup_widget").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 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 index ddb42f44c6..5e723a3d70 100644 --- a/resources/qml/SidebarSimple.qml +++ b/resources/qml/SidebarSimple.qml @@ -13,16 +13,18 @@ Item { id: base - signal showTooltip(Item item, point location, string text); - signal hideTooltip(); + signal showTooltip(Item item, point location, string text) + signal hideTooltip() + + property Action configureSettings - 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" } + + UM.I18nCatalog + { + id: catalog + name: "cura" + } ScrollView { @@ -31,11 +33,10 @@ Item style: UM.Theme.styles.scrollview flickableItem.flickableDirection: Flickable.VerticalFlick - Rectangle + Item { width: childrenRect.width height: childrenRect.height - color: UM.Theme.getColor("sidebar") // // Quality profile @@ -44,10 +45,10 @@ Item { id: qualityRow - height: UM.Theme.getSize("sidebar_margin").height - anchors.topMargin: UM.Theme.getSize("sidebar_margin").height + height: UM.Theme.getSize("thick_margin").height + anchors.topMargin: UM.Theme.getSize("thick_margin").height anchors.left: parent.left - anchors.leftMargin: UM.Theme.getSize("sidebar_margin").width + anchors.leftMargin: UM.Theme.getSize("thick_margin").width anchors.right: parent.right Timer @@ -207,7 +208,7 @@ Item { anchors.verticalCenter: parent.verticalCenter anchors.top: parent.top - anchors.topMargin: Math.round(UM.Theme.getSize("sidebar_margin").height / 2) + anchors.topMargin: Math.round(UM.Theme.getSize("thick_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: { @@ -262,10 +263,10 @@ Item { id: speedSlider width: Math.round(base.width * 0.55) - height: UM.Theme.getSize("sidebar_margin").height + height: UM.Theme.getSize("thick_margin").height anchors.right: parent.right anchors.top: parent.top - anchors.topMargin: UM.Theme.getSize("sidebar_margin").height + anchors.topMargin: UM.Theme.getSize("thick_margin").height // This Item is used only for tooltip, for slider area which is unavailable Item @@ -275,7 +276,7 @@ Item 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) + base.showTooltip(qualityRow, Qt.point(-UM.Theme.getSize("thick_margin").width, customisedSettings.height), content) } else { @@ -313,7 +314,7 @@ Item } } - Rectangle + Item { id: rightArea width: @@ -324,7 +325,6 @@ Item return qualityModel.qualitySliderMarginRight - 10 } height: parent.height - color: "transparent" x: { if (qualityModel.availableTotalTicks == 0) @@ -380,7 +380,7 @@ Item Slider { id: qualitySlider - height: UM.Theme.getSize("sidebar_margin").height + height: UM.Theme.getSize("thick_margin").height anchors.bottom: speedSlider.bottom enabled: qualityModel.totalTicks > 0 && !Cura.SimpleModeSettingsManager.isProfileCustomized visible: qualityModel.availableTotalTicks > 0 @@ -448,12 +448,9 @@ Item 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(); + base.showTooltip(qualityRow, Qt.point(-UM.Theme.getSize("thick_margin").width, customisedSettings.height), content) } + onExited: base.hideTooltip() } } @@ -467,7 +464,7 @@ Item 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) + width: Math.round(UM.Theme.getSize("print_setup_widget").width * 0.35) elide: Text.ElideRight } @@ -503,7 +500,7 @@ Item anchors.verticalCenter: speedSlider.verticalCenter anchors.right: speedSlider.left - anchors.rightMargin: Math.round(UM.Theme.getSize("sidebar_margin").width / 2) + anchors.rightMargin: Math.round(UM.Theme.getSize("thick_margin").width / 2) color: hovered ? UM.Theme.getColor("setting_control_button_hover") : UM.Theme.getColor("setting_control_button"); iconSource: UM.Theme.getIcon("reset"); @@ -516,7 +513,7 @@ Item 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) + base.showTooltip(qualityRow, Qt.point(-UM.Theme.getSize("thick_margin").width, customisedSettings.height), content) } onExited: base.hideTooltip() } @@ -530,10 +527,10 @@ Item id: infillCellLeft anchors.top: qualityRow.bottom - anchors.topMargin: UM.Theme.getSize("sidebar_margin").height * 2 + anchors.topMargin: UM.Theme.getSize("thick_margin").height * 2 anchors.left: parent.left - width: Math.round(UM.Theme.getSize("sidebar").width * .45) - UM.Theme.getSize("sidebar_margin").width + width: Math.round(UM.Theme.getSize("print_setup_widget").width * .45) - UM.Theme.getSize("thick_margin").width Label { @@ -543,9 +540,9 @@ Item color: UM.Theme.getColor("text") anchors.top: parent.top - anchors.topMargin: Math.round(UM.Theme.getSize("sidebar_margin").height * 1.7) + anchors.topMargin: Math.round(UM.Theme.getSize("thick_margin").height * 1.7) anchors.left: parent.left - anchors.leftMargin: UM.Theme.getSize("sidebar_margin").width + anchors.leftMargin: UM.Theme.getSize("thick_margin").width } } @@ -553,12 +550,12 @@ 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) + height: infillSlider.height + UM.Theme.getSize("thick_margin").height + enableGradualInfillCheckBox.visible * (enableGradualInfillCheckBox.height + UM.Theme.getSize("thick_margin").height) + width: Math.round(UM.Theme.getSize("print_setup_widget").width * .55) anchors.left: infillCellLeft.right anchors.top: infillCellLeft.top - anchors.topMargin: UM.Theme.getSize("sidebar_margin").height + anchors.topMargin: UM.Theme.getSize("thick_margin").height Label { id: selectedInfillRateText @@ -575,7 +572,8 @@ Item } // We use a binding to make sure that after manually setting infillSlider.value it is still bound to the property provider - Binding { + Binding + { target: infillSlider property: "value" value: parseInt(infillDensity.properties.value) @@ -588,10 +586,10 @@ Item anchors.top: selectedInfillRateText.bottom anchors.left: parent.left anchors.right: infillIcon.left - anchors.rightMargin: UM.Theme.getSize("sidebar_margin").width + anchors.rightMargin: UM.Theme.getSize("thick_margin").width - height: UM.Theme.getSize("sidebar_margin").height - width: parseInt(infillCellRight.width - UM.Theme.getSize("sidebar_margin").width - style.handleWidth) + height: UM.Theme.getSize("thick_margin").height + width: parseInt(infillCellRight.width - UM.Theme.getSize("thick_margin").width - style.handleWidth) minimumValue: 0 maximumValue: 100 @@ -604,10 +602,12 @@ Item // set initial value from stack value: parseInt(infillDensity.properties.value) - onValueChanged: { + onValueChanged: + { // Don't round the value if it's already the same - if (parseInt(infillDensity.properties.value) == infillSlider.value) { + if (parseInt(infillDensity.properties.value) == infillSlider.value) + { return } @@ -631,7 +631,8 @@ Item style: SliderStyle { - groove: Rectangle { + groove: Rectangle + { id: groove implicitWidth: 200 * screenScaleFactor implicitHeight: 2 * screenScaleFactor @@ -639,8 +640,10 @@ Item radius: 1 } - handle: Item { - Rectangle { + handle: Item + { + Rectangle + { id: handleButton anchors.centerIn: parent color: control.enabled ? UM.Theme.getColor("quality_slider_available") : UM.Theme.getColor("quality_slider_unavailable") @@ -650,24 +653,27 @@ Item } } - tickmarks: Repeater { + 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) { + function shouldShowTick (index) + { + if (index % 10 == 0) + { return true } return false } - Rectangle { + 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) } @@ -679,12 +685,12 @@ Item { id: infillIcon - width: Math.round((parent.width / 5) - (UM.Theme.getSize("sidebar_margin").width)) + width: Math.round((parent.width / 5) - (UM.Theme.getSize("thick_margin").width)) height: width anchors.right: parent.right anchors.top: parent.top - anchors.topMargin: Math.round(UM.Theme.getSize("sidebar_margin").height / 2) + anchors.topMargin: Math.round(UM.Theme.getSize("thick_margin").height / 2) // we loop over all density icons and only show the one that has the current density and steps Repeater @@ -693,8 +699,10 @@ Item model: infillModel anchors.fill: parent - function activeIndex () { - for (var i = 0; i < infillModel.count; i++) { + 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) @@ -703,8 +711,8 @@ Item && density >= infillModelItem.percentageMin && density <= infillModelItem.percentageMax && steps >= infillModelItem.stepsMin - && steps <= infillModelItem.stepsMax - ){ + && steps <= infillModelItem.stepsMax) + { return i } } @@ -719,7 +727,8 @@ Item border.width: UM.Theme.getSize("default_lining").width border.color: UM.Theme.getColor("quality_slider_unavailable") - UM.RecolorImage { + UM.RecolorImage + { anchors.fill: parent anchors.margins: 2 * screenScaleFactor sourceSize.width: width @@ -732,12 +741,13 @@ Item } // Gradual Support Infill Checkbox - 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.topMargin: Math.round(UM.Theme.getSize("thick_margin").height / 2) // closer to slider since it belongs to the same category anchors.left: infillCellRight.left style: UM.Theme.styles.checkbox @@ -745,7 +755,8 @@ Item visible: infillSteps.properties.enabled == "True" checked: parseInt(infillSteps.properties.value) > 0 - MouseArea { + MouseArea + { id: enableGradualInfillMouseArea anchors.fill: parent @@ -754,39 +765,41 @@ Item property var previousInfillDensity: parseInt(infillDensity.properties.value) - onClicked: { + onClicked: + { // Set to 90% only when enabling gradual infill var newInfillDensity; - if (parseInt(infillSteps.properties.value) == 0) { + if (parseInt(infillSteps.properties.value) == 0) + { previousInfillDensity = parseInt(infillDensity.properties.value) - newInfillDensity = 90; + newInfillDensity = 90 } else { - newInfillDensity = previousInfillDensity; + newInfillDensity = previousInfillDensity } Cura.MachineManager.setSettingForAllExtruders("infill_sparse_density", "value", String(newInfillDensity)) - var infill_steps_value = 0; + var infill_steps_value = 0 if (parseInt(infillSteps.properties.value) == 0) - infill_steps_value = 5; + { + infill_steps_value = 5 + } Cura.MachineManager.setSettingForAllExtruders("gradual_infill_steps", "value", infill_steps_value) } - onEntered: { - base.showTooltip(enableGradualInfillCheckBox, Qt.point(-infillCellRight.x, 0), + 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() - } + onExited: base.hideTooltip() + } - Label { + Label + { id: gradualInfillLabel height: parent.height anchors.left: enableGradualInfillCheckBox.right - anchors.leftMargin: Math.round(UM.Theme.getSize("sidebar_margin").width / 2) + anchors.leftMargin: Math.round(UM.Theme.getSize("thick_margin").width / 2) verticalAlignment: Text.AlignVCenter; text: catalog.i18nc("@label", "Enable gradual") font: UM.Theme.getFont("default") @@ -848,16 +861,16 @@ Item visible: enableSupportCheckBox.visible anchors.top: infillCellRight.bottom - anchors.topMargin: Math.round(UM.Theme.getSize("sidebar_margin").height * 1.5) + anchors.topMargin: Math.round(UM.Theme.getSize("thick_margin").height * 1.5) anchors.left: parent.left - anchors.leftMargin: UM.Theme.getSize("sidebar_margin").width + anchors.leftMargin: UM.Theme.getSize("thick_margin").width anchors.right: infillCellLeft.right - anchors.rightMargin: UM.Theme.getSize("sidebar_margin").width + anchors.rightMargin: UM.Theme.getSize("thick_margin").width anchors.verticalCenter: enableSupportCheckBox.verticalCenter - text: catalog.i18nc("@label", "Generate Support"); - font: UM.Theme.getFont("default"); - color: UM.Theme.getColor("text"); + text: catalog.i18nc("@label", "Generate Support") + font: UM.Theme.getFont("default") + color: UM.Theme.getColor("text") elide: Text.ElideRight } @@ -869,32 +882,24 @@ Item anchors.top: enableSupportLabel.top anchors.left: infillCellRight.left - style: UM.Theme.styles.checkbox; + style: UM.Theme.styles.checkbox enabled: base.settingsEnabled visible: supportEnabled.properties.enabled == "True" - checked: supportEnabled.properties.value == "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(); - } + onClicked: 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() + } } @@ -916,11 +921,11 @@ Item 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 + anchors.left: enableSupportCheckBox.right + anchors.leftMargin: Math.round(UM.Theme.getSize("thick_margin").width / 2) + + width: Math.round(UM.Theme.getSize("print_setup_widget").width * .55) - Math.round(UM.Theme.getSize("thick_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 } } @@ -933,24 +938,21 @@ Item { if (supportExtruderNr.properties == null) { - return Cura.MachineManager.defaultExtruderPosition; + return Cura.MachineManager.defaultExtruderPosition } else { - var extruder = parseInt(supportExtruderNr.properties.value); + var extruder = parseInt(supportExtruderNr.properties.value) if ( extruder === -1) { - return Cura.MachineManager.defaultExtruderPosition; + return Cura.MachineManager.defaultExtruderPosition } return extruder; } } - onActivated: - { - // Send the extruder nr as a string. - supportExtruderNr.setPropertyValue("value", String(index)); - } + onActivated: supportExtruderNr.setPropertyValue("value", String(index)) + MouseArea { id: supportExtruderMouseArea @@ -963,17 +965,16 @@ Item 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(); - } + onExited: base.hideTooltip() + } function updateCurrentColor() { - var current_extruder = extruderModel.get(currentIndex); - if (current_extruder !== undefined) { - supportExtruderCombobox.color_override = current_extruder.color; + var current_extruder = extruderModel.get(currentIndex) + if (current_extruder !== undefined) + { + supportExtruderCombobox.color_override = current_extruder.color } } @@ -989,11 +990,12 @@ Item color: UM.Theme.getColor("text") elide: Text.ElideRight - anchors { + anchors + { left: parent.left - leftMargin: UM.Theme.getSize("sidebar_margin").width + leftMargin: UM.Theme.getSize("thick_margin").width right: infillCellLeft.right - rightMargin: UM.Theme.getSize("sidebar_margin").width + rightMargin: UM.Theme.getSize("thick_margin").width verticalCenter: adhesionCheckBox.verticalCenter } } @@ -1004,11 +1006,11 @@ Item property alias _hovered: adhesionMouseArea.containsMouse anchors.top: enableSupportCheckBox.bottom - anchors.topMargin: UM.Theme.getSize("sidebar_margin").height + anchors.topMargin: UM.Theme.getSize("thick_margin").height anchors.left: infillCellRight.left //: Setting enable printing build-plate adhesion helper checkbox - style: UM.Theme.styles.checkbox; + style: UM.Theme.styles.checkbox enabled: base.settingsEnabled visible: platformAdhesionType.properties.enabled == "True" @@ -1022,29 +1024,27 @@ Item enabled: base.settingsEnabled onClicked: { - var adhesionType = "skirt"; + 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; + 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"; + adhesionType = "brim" } } - platformAdhesionType.setPropertyValue("value", adhesionType); + 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(); - } + onExited: base.hideTooltip() + } } @@ -1065,7 +1065,7 @@ 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.topMargin: Math.round(UM.Theme.getSize("thick_margin").height * 2) anchors.left: parent.left width: parent.width height: tipsText.contentHeight * tipsText.lineCount @@ -1074,9 +1074,9 @@ Item { id: tipsText anchors.left: parent.left - anchors.leftMargin: UM.Theme.getSize("sidebar_margin").width + anchors.leftMargin: UM.Theme.getSize("thick_margin").width anchors.right: parent.right - anchors.rightMargin: UM.Theme.getSize("sidebar_margin").width + anchors.rightMargin: UM.Theme.getSize("thick_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") @@ -1163,6 +1163,6 @@ Item color: extruders.getItem(extruderNumber).color }) } - supportExtruderCombobox.updateCurrentColor(); + supportExtruderCombobox.updateCurrentColor() } } diff --git a/resources/qml/SidebarTooltip.qml b/resources/qml/SidebarTooltip.qml index 29199481f6..4fa4ef9dd7 100644 --- a/resources/qml/SidebarTooltip.qml +++ b/resources/qml/SidebarTooltip.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/Toolbar.qml b/resources/qml/Toolbar.qml index a04b3650df..07522dd535 100644 --- a/resources/qml/Toolbar.qml +++ b/resources/qml/Toolbar.qml @@ -2,84 +2,145 @@ // 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.rowCount() - 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") + } + + 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 + property var _model: Cura.ExtrudersModel { id: extrudersModel } + model: _model.items.length > 1 ? _model : 0 + + delegate: ExtruderButton + { + extruder: model + isTopElement: extrudersModel.getItem(0).id == model.id + isBottomElement: extrudersModel.getItem(extrudersModel.rowCount() - 1).id == model.id + } + } } } @@ -91,7 +152,7 @@ Item 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 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..682fd71b4e --- /dev/null +++ b/resources/qml/ViewOrientationButton.qml @@ -0,0 +1,16 @@ +// 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 + hoverBackgroundColor: UM.Theme.getColor("small_button_hover") + 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..e9fdd57177 --- /dev/null +++ b/resources/qml/ViewsSelector.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.2 as UM +import Cura 1.0 as Cura + +Cura.ExpandableComponent +{ + id: viewSelector + + popupPadding: UM.Theme.getSize("default_lining").width + popupAlignment: Cura.ExpandableComponent.PopupAlignment.AlignLeft + iconSource: expanded ? UM.Theme.getIcon("arrow_bottom") : UM.Theme.getIcon("arrow_left") + + property var viewModel: UM.ViewModel { } + + property var activeView: + { + for (var i = 0; i < viewModel.rowCount(); 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 + } + height: parent.height + elide: Text.ElideRight + font: UM.Theme.getFont("default") + color: UM.Theme.getColor("text") + renderType: Text.NativeRendering + } + } + + popupItem: Column + { + id: viewSelectorPopup + width: viewSelector.width - 2 * viewSelector.popupPadding + + // 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.popupPadding + } + + Repeater + { + id: viewsList + model: viewSelector.viewModel + + delegate: Button + { + id: viewsSelectorButton + text: model.name + width: parent.width + 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: + { + viewSelector.togglePopup() + 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..2475f398f8 --- /dev/null +++ b/resources/qml/qmldir @@ -0,0 +1,16 @@ +module Cura + +MachineSelector 1.0 MachineSelector.qml +QuickConfigurationSelector 1.0 QuickConfigurationSelector.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 +IconLabel 1.0 IconLabel.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 \ No newline at end of file diff --git a/resources/quality/anycubic_i3_mega/anycubic_i3_mega_draft.inst.cfg b/resources/quality/anycubic_i3_mega/anycubic_i3_mega_draft.inst.cfg index bb47f68574..e94b9f01d1 100644 --- a/resources/quality/anycubic_i3_mega/anycubic_i3_mega_draft.inst.cfg +++ b/resources/quality/anycubic_i3_mega/anycubic_i3_mega_draft.inst.cfg @@ -8,6 +8,7 @@ setting_version = 5 type = quality quality_type = draft weight = 0 +global_quality = True [values] acceleration_enabled = True diff --git a/resources/quality/anycubic_i3_mega/anycubic_i3_mega_high.inst.cfg b/resources/quality/anycubic_i3_mega/anycubic_i3_mega_high.inst.cfg index a3ae98deba..c8c4bf9a81 100644 --- a/resources/quality/anycubic_i3_mega/anycubic_i3_mega_high.inst.cfg +++ b/resources/quality/anycubic_i3_mega/anycubic_i3_mega_high.inst.cfg @@ -8,6 +8,7 @@ setting_version = 5 type = quality quality_type = high weight = 2 +global_quality = True [values] acceleration_enabled = True diff --git a/resources/quality/anycubic_i3_mega/anycubic_i3_mega_normal.inst.cfg b/resources/quality/anycubic_i3_mega/anycubic_i3_mega_normal.inst.cfg index 13846b9702..399c3ebc55 100644 --- a/resources/quality/anycubic_i3_mega/anycubic_i3_mega_normal.inst.cfg +++ b/resources/quality/anycubic_i3_mega/anycubic_i3_mega_normal.inst.cfg @@ -8,6 +8,7 @@ setting_version = 5 type = quality quality_type = normal weight = 1 +global_quality = True [values] acceleration_enabled = True diff --git a/resources/quality/ultimaker3/um3_aa0.25_PC_Normal_Quality.inst.cfg b/resources/quality/ultimaker3/um3_aa0.25_PC_Normal_Quality.inst.cfg index e08fa27dc9..4d585b54c1 100644 --- a/resources/quality/ultimaker3/um3_aa0.25_PC_Normal_Quality.inst.cfg +++ b/resources/quality/ultimaker3/um3_aa0.25_PC_Normal_Quality.inst.cfg @@ -10,6 +10,7 @@ quality_type = normal weight = 0 material = generic_pc variant = AA 0.25 +is_experimental = True [values] acceleration_enabled = True diff --git a/resources/quality/ultimaker3/um3_aa0.25_PP_Normal_Quality.inst.cfg b/resources/quality/ultimaker3/um3_aa0.25_PP_Normal_Quality.inst.cfg index 6e9bbdce27..bee345e302 100644 --- a/resources/quality/ultimaker3/um3_aa0.25_PP_Normal_Quality.inst.cfg +++ b/resources/quality/ultimaker3/um3_aa0.25_PP_Normal_Quality.inst.cfg @@ -10,6 +10,7 @@ quality_type = normal weight = 0 material = generic_pp variant = AA 0.25 +is_experimental = True [values] acceleration_enabled = True diff --git a/resources/quality/ultimaker3/um3_aa0.8_CPEP_Fast_Print.inst.cfg b/resources/quality/ultimaker3/um3_aa0.8_CPEP_Fast_Print.inst.cfg index 73df9637f7..fc4acf3cb0 100644 --- a/resources/quality/ultimaker3/um3_aa0.8_CPEP_Fast_Print.inst.cfg +++ b/resources/quality/ultimaker3/um3_aa0.8_CPEP_Fast_Print.inst.cfg @@ -10,6 +10,7 @@ quality_type = draft weight = -2 material = generic_cpe_plus variant = AA 0.8 +is_experimental = True [values] brim_width = 14 diff --git a/resources/quality/ultimaker3/um3_aa0.8_CPEP_Superdraft_Print.inst.cfg b/resources/quality/ultimaker3/um3_aa0.8_CPEP_Superdraft_Print.inst.cfg index d59bfe7cea..36b3ef603f 100644 --- a/resources/quality/ultimaker3/um3_aa0.8_CPEP_Superdraft_Print.inst.cfg +++ b/resources/quality/ultimaker3/um3_aa0.8_CPEP_Superdraft_Print.inst.cfg @@ -10,6 +10,7 @@ quality_type = superdraft weight = -4 material = generic_cpe_plus variant = AA 0.8 +is_experimental = True [values] brim_width = 14 diff --git a/resources/quality/ultimaker3/um3_aa0.8_CPEP_Verydraft_Print.inst.cfg b/resources/quality/ultimaker3/um3_aa0.8_CPEP_Verydraft_Print.inst.cfg index 368317019f..14e08cb14d 100644 --- a/resources/quality/ultimaker3/um3_aa0.8_CPEP_Verydraft_Print.inst.cfg +++ b/resources/quality/ultimaker3/um3_aa0.8_CPEP_Verydraft_Print.inst.cfg @@ -10,6 +10,7 @@ quality_type = verydraft weight = -3 material = generic_cpe_plus variant = AA 0.8 +is_experimental = True [values] brim_width = 14 diff --git a/resources/quality/ultimaker3/um3_aa0.8_PC_Fast_Print.inst.cfg b/resources/quality/ultimaker3/um3_aa0.8_PC_Fast_Print.inst.cfg index 5b81532977..c2bb6d4988 100644 --- a/resources/quality/ultimaker3/um3_aa0.8_PC_Fast_Print.inst.cfg +++ b/resources/quality/ultimaker3/um3_aa0.8_PC_Fast_Print.inst.cfg @@ -10,6 +10,7 @@ quality_type = draft weight = 0 material = generic_pc variant = AA 0.8 +is_experimental = True [values] brim_width = 14 diff --git a/resources/quality/ultimaker3/um3_aa0.8_PC_Superdraft_Print.inst.cfg b/resources/quality/ultimaker3/um3_aa0.8_PC_Superdraft_Print.inst.cfg index 317b89ea85..e815b673d1 100644 --- a/resources/quality/ultimaker3/um3_aa0.8_PC_Superdraft_Print.inst.cfg +++ b/resources/quality/ultimaker3/um3_aa0.8_PC_Superdraft_Print.inst.cfg @@ -10,6 +10,7 @@ quality_type = superdraft weight = -2 material = generic_pc variant = AA 0.8 +is_experimental = True [values] brim_width = 14 diff --git a/resources/quality/ultimaker3/um3_aa0.8_PC_Verydraft_Print.inst.cfg b/resources/quality/ultimaker3/um3_aa0.8_PC_Verydraft_Print.inst.cfg index 2fd6bd7609..c50cee576d 100644 --- a/resources/quality/ultimaker3/um3_aa0.8_PC_Verydraft_Print.inst.cfg +++ b/resources/quality/ultimaker3/um3_aa0.8_PC_Verydraft_Print.inst.cfg @@ -10,6 +10,7 @@ quality_type = verydraft weight = -1 material = generic_pc variant = AA 0.8 +is_experimental = True [values] brim_width = 14 diff --git a/resources/quality/ultimaker_s5/um_s5_aa0.25_PC_Normal_Quality.inst.cfg b/resources/quality/ultimaker_s5/um_s5_aa0.25_PC_Normal_Quality.inst.cfg index 55d53c6c71..53c319d6e6 100644 --- a/resources/quality/ultimaker_s5/um_s5_aa0.25_PC_Normal_Quality.inst.cfg +++ b/resources/quality/ultimaker_s5/um_s5_aa0.25_PC_Normal_Quality.inst.cfg @@ -10,6 +10,7 @@ quality_type = normal weight = 0 material = generic_pc variant = AA 0.25 +is_experimental = True [values] acceleration_enabled = True diff --git a/resources/quality/ultimaker_s5/um_s5_aa0.25_PP_Normal_Quality.inst.cfg b/resources/quality/ultimaker_s5/um_s5_aa0.25_PP_Normal_Quality.inst.cfg index c925845dc1..b4d34cc392 100644 --- a/resources/quality/ultimaker_s5/um_s5_aa0.25_PP_Normal_Quality.inst.cfg +++ b/resources/quality/ultimaker_s5/um_s5_aa0.25_PP_Normal_Quality.inst.cfg @@ -10,6 +10,7 @@ quality_type = normal weight = 0 material = generic_pp variant = AA 0.25 +is_experimental = True [values] acceleration_enabled = True 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 e78006689b..4bdd09e9b3 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 @@ -10,6 +10,7 @@ quality_type = draft weight = -2 material = generic_cpe_plus variant = AA 0.8 +is_experimental = True [values] brim_width = 14 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 c6d0962157..f9b6b0c7a6 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 @@ -10,6 +10,7 @@ quality_type = superdraft weight = -4 material = generic_cpe_plus variant = AA 0.8 +is_experimental = True [values] brim_width = 14 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 b80f773594..9c6c7de7f0 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 @@ -10,6 +10,7 @@ quality_type = verydraft weight = -3 material = generic_cpe_plus variant = AA 0.8 +is_experimental = True [values] brim_width = 14 diff --git a/resources/quality/ultimaker_s5/um_s5_aa0.8_PC_Fast_Print.inst.cfg b/resources/quality/ultimaker_s5/um_s5_aa0.8_PC_Fast_Print.inst.cfg index 0ed4e3d994..c24aa9a98d 100644 --- a/resources/quality/ultimaker_s5/um_s5_aa0.8_PC_Fast_Print.inst.cfg +++ b/resources/quality/ultimaker_s5/um_s5_aa0.8_PC_Fast_Print.inst.cfg @@ -10,6 +10,7 @@ quality_type = draft weight = 0 material = generic_pc variant = AA 0.8 +is_experimental = True [values] brim_width = 14 diff --git a/resources/quality/ultimaker_s5/um_s5_aa0.8_PC_Superdraft_Print.inst.cfg b/resources/quality/ultimaker_s5/um_s5_aa0.8_PC_Superdraft_Print.inst.cfg index 53bf1d3107..5fc306b1f1 100644 --- a/resources/quality/ultimaker_s5/um_s5_aa0.8_PC_Superdraft_Print.inst.cfg +++ b/resources/quality/ultimaker_s5/um_s5_aa0.8_PC_Superdraft_Print.inst.cfg @@ -10,6 +10,7 @@ quality_type = superdraft weight = -2 material = generic_pc variant = AA 0.8 +is_experimental = True [values] brim_width = 14 diff --git a/resources/quality/ultimaker_s5/um_s5_aa0.8_PC_Verydraft_Print.inst.cfg b/resources/quality/ultimaker_s5/um_s5_aa0.8_PC_Verydraft_Print.inst.cfg index d9c45c2634..996adf5be7 100644 --- a/resources/quality/ultimaker_s5/um_s5_aa0.8_PC_Verydraft_Print.inst.cfg +++ b/resources/quality/ultimaker_s5/um_s5_aa0.8_PC_Verydraft_Print.inst.cfg @@ -10,6 +10,7 @@ quality_type = verydraft weight = -1 material = generic_pc variant = AA 0.8 +is_experimental = True [values] brim_width = 14 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 3e74390840..4098c86ad9 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 @@ -11,6 +11,7 @@ weight = -2 material = generic_cpe_plus variant = AA 0.8 buildplate = Aluminum +is_experimental = True [values] brim_width = 14 diff --git a/resources/quality/ultimaker_s5/um_s5_aa0.8_aluminum_PC_Fast_Print.inst.cfg b/resources/quality/ultimaker_s5/um_s5_aa0.8_aluminum_PC_Fast_Print.inst.cfg index 747e2fe8a5..6fdd22c6b0 100644 --- a/resources/quality/ultimaker_s5/um_s5_aa0.8_aluminum_PC_Fast_Print.inst.cfg +++ b/resources/quality/ultimaker_s5/um_s5_aa0.8_aluminum_PC_Fast_Print.inst.cfg @@ -11,6 +11,7 @@ weight = 0 material = generic_pc variant = AA 0.8 buildplate = Aluminum +is_experimental = True [values] brim_width = 10 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..34b944b25b 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], @@ -15,12 +17,11 @@ "border": [127, 127, 127, 255], "secondary": [241, 242, 242, 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,6 @@ "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], "button": [39, 44, 48, 255], "button_hover": [39, 44, 48, 255], @@ -142,9 +133,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], @@ -219,9 +208,10 @@ "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/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..97e4fc4f35 --- /dev/null +++ b/resources/themes/cura-light/icons/info.svg @@ -0,0 +1,48 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + 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/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..2a9de2f3e9 --- /dev/null +++ b/resources/themes/cura-light/images/header_pattern.svg @@ -0,0 +1 @@ +Pattern \ 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/styles.qml b/resources/themes/cura-light/styles.qml index b71ddd2d86..f2ad2b6f4a 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 sidebar_header_button: Component + { + ButtonStyle + { + background: Rectangle + { color: { if(control.enabled) @@ -61,7 +65,8 @@ QtObject { return Theme.getColor("setting_control_disabled_border"); } } - UM.RecolorImage { + UM.RecolorImage + { id: downArrow anchors.verticalCenter: parent.verticalCenter anchors.right: parent.right @@ -73,7 +78,8 @@ QtObject { color: control.enabled ? Theme.getColor("setting_category_text") : Theme.getColor("setting_category_disabled_text") source: Theme.getIcon("arrow_bottom") } - Label { + Label + { id: sidebarComboBoxLabel color: control.enabled ? Theme.getColor("setting_control_text") : Theme.getColor("setting_control_disabled_text") text: control.text; @@ -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_bold") + 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) @@ -361,8 +284,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 +319,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 +348,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,180 +370,24 @@ 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"); } - handle: Rectangle { + handle: Rectangle + { id: scrollViewHandle implicitWidth: Theme.getSize("scrollbar").width; radius: Math.round(implicitWidth / 2) @@ -727,10 +398,13 @@ QtObject { } } - 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; @@ -741,28 +415,31 @@ QtObject { border.color: control.hovered ? Theme.getColor("setting_control_border_highlight") : Theme.getColor("setting_control_border"); } - label: Item { + label: Item + { - Label { - anchors.left: parent.left; + 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 +454,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") } - label: Item { + label: Item + { - Label { + Label + { anchors.left: parent.left anchors.leftMargin: UM.Theme.getSize("default_lining").width anchors.right: swatch.left @@ -804,7 +486,8 @@ QtObject { verticalAlignment: Text.AlignVCenter } - Rectangle { + Rectangle + { id: swatch height: Math.round(UM.Theme.getSize("setting_control").height / 2) width: height @@ -817,7 +500,8 @@ QtObject { 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,22 +519,26 @@ 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") : Theme.getColor("checkbox") Behavior on color { ColorAnimation { duration: 50; } } radius: control.exclusiveGroup ? Math.round(Theme.getSize("checkbox").width / 2) : 0 - 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) @@ -863,7 +551,8 @@ QtObject { Behavior on opacity { NumberAnimation { duration: 100; } } } } - label: Label { + label: Label + { text: control.text color: Theme.getColor("checkbox_text") font: Theme.getFont("default") @@ -872,12 +561,15 @@ QtObject { } } - 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; } } @@ -887,7 +579,8 @@ QtObject { 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) @@ -895,66 +588,37 @@ QtObject { 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 { @@ -966,7 +630,8 @@ QtObject { 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 sidebar_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,154 @@ 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.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 + } + } + } + } + + 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..dfad5cfd17 100644 --- a/resources/themes/cura-light/theme.json +++ b/resources/themes/cura-light/theme.json @@ -64,34 +64,68 @@ "size": 1.15, "weight": 50, "family": "Noto Sans" + }, + "extruder_icon": + { + "size": 0.7, + "weight": 50, + "family": "Noto Sans" } }, "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": [10, 8, 80, 255], + "main_window_header_background_gradient": [25, 23, 91, 255], + "main_window_header_button_text_active": [10, 8, 80, 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": [255, 255, 255, 102], + + "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], + + "action_panel_secondary": [27, 95, 202, 255], + + "toolbar_background": [255, 255, 255, 255], + + "printer_type_label_background": [171, 171, 191, 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], @@ -99,16 +133,12 @@ "text_scene_hover": [70, 84, 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": [255, 190, 35, 255], + + "toolbar_button_text": [10, 8, 80, 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,14 +148,12 @@ "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": [0, 0, 0, 0], + "small_button_hover": [10, 8, 80, 255], + "small_button_active": [10, 8, 80, 255], + "small_button_active_hover": [10, 8, 80, 255], + "small_button_text": [171, 171, 191, 255], "small_button_text_hover": [255, 255, 255, 255], "small_button_text_active": [255, 255, 255, 255], "small_button_text_active_hover": [255, 255, 255, 255], @@ -142,23 +170,17 @@ "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], @@ -185,7 +207,7 @@ "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_border_highlight": [50, 130, 255, 255], "setting_control_text": [27, 27, 27, 255], "setting_control_depth_line": [127, 127, 127, 255], "setting_control_button": [127, 127, 127, 255], @@ -203,39 +225,24 @@ "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": [10, 8, 80, 255], + "slider_handle": [10, 8, 80, 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_border_hover": [50, 130, 255, 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], - "tooltip": [68, 192, 255, 255], "tooltip_text": [255, 255, 255, 255], @@ -245,9 +252,9 @@ "message_shadow": [0, 0, 0, 120], "message_border": [127, 127, 127, 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_button": [50, 130, 255, 255], + "message_button_hover": [50, 130, 255, 255], + "message_button_active": [50, 130, 255, 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 +265,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], @@ -270,7 +277,7 @@ "all_axis": [255, 255, 255, 255], "viewport_background": [245, 245, 245, 255], - "volume_outline": [12, 169, 227, 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,7 +290,7 @@ "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], @@ -309,14 +316,18 @@ "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], + "configuration_item_border_hover": [50, 130, 255, 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 +345,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,35 +358,51 @@ }, "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": [30.0, 42.0], + "print_setup_mode_toggle": [0.0, 2.0], + "print_setup_item": [0.0, 2.0], + "print_setup_extruder_box": [0.0, 6.0], + + "configuration_selector_mode_tabs": [0.0, 3.0], + + "action_panel_widget": [25.0, 0.0], + "action_panel_information_widget": [20.0, 0.0], + "action_panel_button": [15.0, 3.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], - - "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], + "extruder_icon": [2.33, 2.33], "section": [0.0, 2.2], "section_icon": [1.6, 1.6], @@ -390,7 +417,6 @@ "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], "button": [4, 4], @@ -404,37 +430,26 @@ "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], @@ -488,11 +503,17 @@ "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], + + "action_button": [15.0, 3.0], + "action_button_radius": [0.15, 0.15], + "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/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