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 6e52a97518..b43e4d5e0e 100755 --- a/cura/CuraApplication.py +++ b/cura/CuraApplication.py @@ -1663,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/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/PrintInformation.py b/cura/PrintInformation.py index f1d8e81b3a..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: @@ -402,7 +401,7 @@ class PrintInformation(QObject): 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/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/MachineManager.py b/cura/Settings/MachineManager.py index 7e1a06f45c..a472cc7f09 100755 --- a/cura/Settings/MachineManager.py +++ b/cura/Settings/MachineManager.py @@ -66,7 +66,7 @@ class MachineManager(QObject): self.machine_extruder_material_update_dict = collections.defaultdict(list) #type: Dict[str, List[Callable[[], None]]] - self._instance_container_timer = QTimer() #type: QTimer + self._instance_container_timer = QTimer() # type: QTimer self._instance_container_timer.setInterval(250) self._instance_container_timer.setSingleShot(True) self._instance_container_timer.timeout.connect(self.__emitChangedSignals) @@ -76,7 +76,7 @@ class MachineManager(QObject): self._application.globalContainerStackChanged.connect(self._onGlobalContainerChanged) self._container_registry.containerLoadComplete.connect(self._onContainersChanged) - ## When the global container is changed, active material probably needs to be updated. + # When the global container is changed, active material probably needs to be updated. self.globalContainerChanged.connect(self.activeMaterialChanged) self.globalContainerChanged.connect(self.activeVariantChanged) self.globalContainerChanged.connect(self.activeQualityChanged) @@ -117,15 +117,15 @@ class MachineManager(QObject): self._material_incompatible_message = Message(catalog.i18nc("@info:status", "The selected material is incompatible with the selected machine or configuration."), - title = catalog.i18nc("@info:title", "Incompatible Material")) #type: Message + title = catalog.i18nc("@info:title", "Incompatible Material")) # type: Message - containers = CuraContainerRegistry.getInstance().findInstanceContainers(id = self.activeMaterialId) #type: List[InstanceContainer] + containers = CuraContainerRegistry.getInstance().findInstanceContainers(id = self.activeMaterialId) # type: List[InstanceContainer] if containers: containers[0].nameChanged.connect(self._onMaterialNameChanged) - self._material_manager = self._application.getMaterialManager() #type: MaterialManager - self._variant_manager = self._application.getVariantManager() #type: VariantManager - self._quality_manager = self._application.getQualityManager() #type: QualityManager + self._material_manager = self._application.getMaterialManager() # type: MaterialManager + self._variant_manager = self._application.getVariantManager() # type: VariantManager + self._quality_manager = self._application.getQualityManager() # type: QualityManager # When the materials lookup table gets updated, it can mean that a material has its name changed, which should # be reflected on the GUI. This signal emission makes sure that it happens. @@ -158,7 +158,7 @@ class MachineManager(QObject): blurSettings = pyqtSignal() # Emitted to force fields in the advanced sidebar to un-focus, so they update properly outputDevicesChanged = pyqtSignal() - currentConfigurationChanged = pyqtSignal() # Emitted every time the current configurations of the machine changes + currentConfigurationChanged = pyqtSignal() # Emitted every time the current configurations of the machine changes printerConnectedStatusChanged = pyqtSignal() # Emitted every time the active machine change or the outputdevices change rootMaterialChanged = pyqtSignal() @@ -203,7 +203,7 @@ class MachineManager(QObject): extruder_configuration.hotendID = extruder.variant.getName() if extruder.variant != empty_variant_container else None self._current_printer_configuration.extruderConfigurations.append(extruder_configuration) - # an empty build plate configuration from the network printer is presented as an empty string, so use "" for an + # An empty build plate configuration from the network printer is presented as an empty string, so use "" for an # empty build plate. self._current_printer_configuration.buildplateConfiguration = self._global_container_stack.getProperty("machine_buildplate_type", "value") if self._global_container_stack.variant != empty_variant_container else "" self.currentConfigurationChanged.emit() @@ -249,7 +249,7 @@ class MachineManager(QObject): self.updateNumberExtrudersEnabled() self.globalContainerChanged.emit() - # after switching the global stack we reconnect all the signals and set the variant and material references + # After switching the global stack we reconnect all the signals and set the variant and material references if self._global_container_stack: self._application.getPreferences().setValue("cura/active_machine", self._global_container_stack.getId()) @@ -263,7 +263,7 @@ class MachineManager(QObject): if global_variant.getMetaDataEntry("hardware_type") != "buildplate": self._global_container_stack.setVariant(empty_variant_container) - # set the global material to empty as we now use the extruder stack at all times - CURA-4482 + # Set the global material to empty as we now use the extruder stack at all times - CURA-4482 global_material = self._global_container_stack.material if global_material != empty_material_container: self._global_container_stack.setMaterial(empty_material_container) @@ -421,7 +421,7 @@ class MachineManager(QObject): # Not a very pretty solution, but the extruder manager doesn't really know how many extruders there are machine_extruder_count = self._global_container_stack.getProperty("machine_extruder_count", "value") extruder_stacks = ExtruderManager.getInstance().getActiveExtruderStacks() - count = 1 # we start with the global stack + count = 1 # We start with the global stack for stack in extruder_stacks: md = stack.getMetaData() if "position" in md and int(md["position"]) >= machine_extruder_count: @@ -618,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, @@ -648,7 +656,7 @@ class MachineManager(QObject): new_value = self._active_container_stack.getProperty(key, "value") extruder_stacks = [stack for stack in ExtruderManager.getInstance().getActiveExtruderStacks()] - # check in which stack the value has to be replaced + # Check in which stack the value has to be replaced for extruder_stack in extruder_stacks: if extruder_stack != self._active_container_stack and extruder_stack.getProperty(key, "value") != new_value: extruder_stack.userChanges.setProperty(key, "value", new_value) # TODO: nested property access, should be improved @@ -664,7 +672,7 @@ class MachineManager(QObject): for key in self._active_container_stack.userChanges.getAllKeys(): new_value = self._active_container_stack.getProperty(key, "value") - # check if the value has to be replaced + # Check if the value has to be replaced extruder_stack.userChanges.setProperty(key, "value", new_value) @pyqtProperty(str, notify = activeVariantChanged) @@ -733,7 +741,7 @@ class MachineManager(QObject): # If the machine that is being removed is the currently active machine, set another machine as the active machine. activate_new_machine = (self._global_container_stack and self._global_container_stack.getId() == machine_id) - # activate a new machine before removing a machine because this is safer + # Activate a new machine before removing a machine because this is safer if activate_new_machine: machine_stacks = CuraContainerRegistry.getInstance().findContainerStacksMetadata(type = "machine") other_machine_stacks = [s for s in machine_stacks if s["id"] != machine_id] @@ -917,9 +925,12 @@ class MachineManager(QObject): if settable_per_extruder: limit_to_extruder = int(self._global_container_stack.getProperty(setting_key, "limit_to_extruder")) - extruder_position = str(max(0, limit_to_extruder)) - extruder_stack = self._global_container_stack.extruders[extruder_position] - extruder_stack.userChanges.setProperty(setting_key, "value", global_user_container.getProperty(setting_key, "value")) + extruder_position = max(0, limit_to_extruder) + extruder_stack = self.getExtruder(extruder_position) + if extruder_stack: + extruder_stack.userChanges.setProperty(setting_key, "value", global_user_container.getProperty(setting_key, "value")) + else: + Logger.log("e", "Unable to find extruder on position %s", extruder_position) global_user_container.removeInstance(setting_key) # Signal that the global stack has changed @@ -928,10 +939,9 @@ class MachineManager(QObject): @pyqtSlot(int, result = QObject) def getExtruder(self, position: int) -> Optional[ExtruderStack]: - extruder = None if self._global_container_stack: - extruder = self._global_container_stack.extruders.get(str(position)) - return extruder + return self._global_container_stack.extruders.get(str(position)) + return None def updateDefaultExtruder(self) -> None: if self._global_container_stack is None: @@ -993,12 +1003,16 @@ class MachineManager(QObject): self.updateNumberExtrudersEnabled() self.correctExtruderSettings() - # ensure that the quality profile is compatible with current combination, or choose a compatible one if available + # In case this extruder is being disabled and it's the currently selected one, switch to the default extruder + if not enabled and position == ExtruderManager.getInstance().activeExtruderIndex: + ExtruderManager.getInstance().setActiveExtruderIndex(int(self._default_extruder_position)) + + # Ensure that the quality profile is compatible with current combination, or choose a compatible one if available self._updateQualityWithMaterial() self.extruderChanged.emit() - # update material compatibility color + # Update material compatibility color self.activeQualityGroupChanged.emit() - # update items in SettingExtruder + # Update items in SettingExtruder ExtruderManager.getInstance().extrudersChanged.emit(self._global_container_stack.getId()) # Make sure the front end reflects changes self.forceUpdateAllSettings() @@ -1072,7 +1086,6 @@ class MachineManager(QObject): return result - # # Sets all quality and quality_changes containers to empty_quality and empty_quality_changes containers # for all stacks in the currently active machine. # @@ -1131,7 +1144,7 @@ class MachineManager(QObject): def _setQualityChangesGroup(self, quality_changes_group: "QualityChangesGroup") -> None: if self._global_container_stack is None: - return #Can't change that. + return # Can't change that. quality_type = quality_changes_group.quality_type # A custom quality can be created based on "not supported". # In that case, do not set quality containers to empty. @@ -1201,7 +1214,7 @@ class MachineManager(QObject): self.rootMaterialChanged.emit() def activeMaterialsCompatible(self) -> bool: - # check material - variant compatibility + # Check material - variant compatibility if self._global_container_stack is not None: if Util.parseBool(self._global_container_stack.getMetaDataEntry("has_materials", False)): for position, extruder in self._global_container_stack.extruders.items(): @@ -1411,7 +1424,7 @@ class MachineManager(QObject): material_diameter, root_material_id) self.setMaterial(position, material_node) - ## global_stack: if you want to provide your own global_stack instead of the current active one + ## Global_stack: if you want to provide your own global_stack instead of the current active one # if you update an active machine, special measures have to be taken. @pyqtSlot(str, "QVariant") def setMaterial(self, position: str, container_node, global_stack: Optional["GlobalStack"] = None) -> None: 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/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/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/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/Toolbox/resources/qml/ToolboxCompatibilityChart.qml b/plugins/Toolbox/resources/qml/ToolboxCompatibilityChart.qml index 6a01d7ff2f..d4c0ae14eb 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 { @@ -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("default") diff --git a/plugins/Toolbox/resources/qml/ToolboxDetailPage.qml b/plugins/Toolbox/resources/qml/ToolboxDetailPage.qml index 73217e4682..9e2e178b71 100644 --- a/plugins/Toolbox/resources/qml/ToolboxDetailPage.qml +++ b/plugins/Toolbox/resources/qml/ToolboxDetailPage.qml @@ -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/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/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/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 8314b0f089..3b124faf66 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 daea696cd1..b96c508d70 100644 --- a/plugins/UM3NetworkPrinting/src/UM3OutputDevicePlugin.py +++ b/plugins/UM3NetworkPrinting/src/UM3OutputDevicePlugin.py @@ -341,7 +341,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/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/ActionPanel/OutputProcessWidget.qml b/resources/qml/ActionPanel/OutputProcessWidget.qml index 92f2bfab30..3a85a13810 100644 --- a/resources/qml/ActionPanel/OutputProcessWidget.qml +++ b/resources/qml/ActionPanel/OutputProcessWidget.qml @@ -18,6 +18,7 @@ Column id: widget spacing: UM.Theme.getSize("thin_margin").height + property bool preSlicedData: PrintInformation.preSliced UM.I18nCatalog { @@ -48,7 +49,7 @@ Column id: estimatedTime width: parent.width - text: PrintInformation.currentPrintTime.getDisplayString(UM.DurationFormat.Long) + text: preSlicedData ? catalog.i18nc("@label", "No time estimation available") : PrintInformation.currentPrintTime.getDisplayString(UM.DurationFormat.Long) source: UM.Theme.getIcon("clock") font: UM.Theme.getFont("default_bold") } @@ -63,6 +64,10 @@ Column text: { + if (preSlicedData) + { + return catalog.i18nc("@label", "No cost estimation available") + } var totalLengths = 0 var totalWeights = 0 if (printMaterialLengths) @@ -86,6 +91,7 @@ Column PrintInformationWidget { id: printInformationPanel + visible: !preSlicedData anchors { diff --git a/resources/qml/ActionPanel/PrintJobInformation.qml b/resources/qml/ActionPanel/PrintJobInformation.qml index b1172a91e0..8bd5d5a0d3 100644 --- a/resources/qml/ActionPanel/PrintJobInformation.qml +++ b/resources/qml/ActionPanel/PrintJobInformation.qml @@ -21,7 +21,6 @@ Column Column { id: timeSpecification - spacing: UM.Theme.getSize("thin_margin").width width: parent.width topPadding: UM.Theme.getSize("default_margin").height leftPadding: UM.Theme.getSize("default_margin").width @@ -71,7 +70,6 @@ Column Column { id: materialSpecification - spacing: UM.Theme.getSize("thin_margin").width width: parent.width bottomPadding: UM.Theme.getSize("default_margin").height leftPadding: UM.Theme.getSize("default_margin").width diff --git a/resources/qml/Cura.qml b/resources/qml/Cura.qml index 63888a4ee4..3578888886 100644 --- a/resources/qml/Cura.qml +++ b/resources/qml/Cura.qml @@ -146,6 +146,7 @@ UM.MainWindow Rectangle { + id: stageMenuBackground anchors { left: parent.left @@ -153,7 +154,7 @@ UM.MainWindow top: parent.top } visible: stageMenu.source != "" - height: Math.round(UM.Theme.getSize("stage_menu").height / 2) + height: visible ? Math.round(UM.Theme.getSize("stage_menu").height / 2) : 0 LinearGradient { @@ -212,7 +213,7 @@ UM.MainWindow verticalCenter: parent.verticalCenter left: parent.left } - visible: CuraApplication.platformActivity + visible: CuraApplication.platformActivity && !PrintInformation.preSliced } ObjectsList @@ -254,7 +255,13 @@ UM.MainWindow // A stage can control this area. If nothing is set, it will therefore show the 3D view. id: main - anchors.fill: parent + anchors + { + top: stageMenuBackground.bottom + left: parent.left + right: parent.right + bottom: parent.bottom + } source: UM.Controller.activeStage != null ? UM.Controller.activeStage.mainComponent : "" } diff --git a/resources/qml/Dialogs/AddMachineDialog.qml b/resources/qml/Dialogs/AddMachineDialog.qml index bcf5807949..918c717b94 100644 --- a/resources/qml/Dialogs/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; } - } - } - ] } } } diff --git a/resources/qml/ExtruderButton.qml b/resources/qml/ExtruderButton.qml index 8a1f0af44a..feb399d528 100644 --- a/resources/qml/ExtruderButton.qml +++ b/resources/qml/ExtruderButton.qml @@ -7,7 +7,7 @@ import QtQuick.Controls 2.0 import UM 1.2 as UM import Cura 1.0 as Cura -Button +Cura.ToolbarButton { id: base @@ -18,11 +18,9 @@ Button checked: Cura.ExtruderManager.selectedObjectExtruders.indexOf(extruder.id) != -1 enabled: UM.Selection.hasSelection && extruder.stack.isEnabled - background: Item {} - contentItem: ExtruderIcon + toolItem: ExtruderIcon { - width: UM.Theme.getSize("button_icon").width - materialColor: model.color + materialColor: extruder.color extruderEnabled: extruder.stack.isEnabled property int index: extruder.index } @@ -30,6 +28,6 @@ Button 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/Menus/ProfileMenu.qml b/resources/qml/Menus/ProfileMenu.qml index e09b7930a8..bf950aa409 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/MonitorSidebar.qml b/resources/qml/MonitorSidebar.qml index 2282034739..50416e34ab 100644 --- a/resources/qml/MonitorSidebar.qml +++ b/resources/qml/MonitorSidebar.qml @@ -1,15 +1,17 @@ // 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 @@ -85,7 +87,7 @@ Rectangle } } - MachineSelection + MachineSelector { id: machineSelection width: base.width - configSelection.width - separator.width @@ -104,7 +106,7 @@ Rectangle anchors.left: machineSelection.right } - ConfigurationSelection + CustomConfigurationSelector { id: configSelection visible: isNetworkPrinter && printerConnected @@ -112,7 +114,6 @@ Rectangle height: UM.Theme.getSize("stage_menu").height anchors.top: base.top anchors.right: parent.right - panelWidth: base.width } Loader diff --git a/resources/qml/Preferences/GeneralPage.qml b/resources/qml/Preferences/GeneralPage.qml index 444bdc2dd5..5ff5f567ea 100644 --- a/resources/qml/Preferences/GeneralPage.qml +++ b/resources/qml/Preferences/GeneralPage.qml @@ -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 bb47301b69..958a5f3d45 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/PrintMonitor.qml b/resources/qml/PrintMonitor.qml index 723279847a..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("wide_lining") - width: parent.width - height: childrenRect.height + anchors.fill: parent - Flow + Cura.ExtrudersModel { - id: extrudersGrid - spacing: UM.Theme.getSize("thick_lining").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("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 + 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("wide_lining") - width: parent.width - height: UM.Theme.getSize("thick_lining").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/PrinterOutput/ExtruderBox.qml b/resources/qml/PrinterOutput/ExtruderBox.qml index d72f9ba0b2..247bb3a27d 100644 --- a/resources/qml/PrinterOutput/ExtruderBox.qml +++ b/resources/qml/PrinterOutput/ExtruderBox.qml @@ -12,6 +12,8 @@ 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("print_setup_extruder_box").height diff --git a/resources/qml/PrinterOutput/HeatedBedBox.qml b/resources/qml/PrinterOutput/HeatedBedBox.qml index 59f7fa7bc6..33cf5cd1e2 100644 --- a/resources/qml/PrinterOutput/HeatedBedBox.qml +++ b/resources/qml/PrinterOutput/HeatedBedBox.qml @@ -1,10 +1,10 @@ // Copyright (c) 2017 Ultimaker B.V. // Cura is released under the terms of the LGPLv3 or higher. -import QtQuick 2.2 -import QtQuick.Controls 1.1 -import QtQuick.Controls.Styles 1.1 -import QtQuick.Layouts 1.1 +import QtQuick 2.10 +import QtQuick.Controls 1.4 +import QtQuick.Controls.Styles 1.4 +import QtQuick.Layouts 1.3 import UM 1.2 as UM import Cura 1.0 as Cura @@ -14,6 +14,7 @@ Item implicitWidth: parent.width 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 { @@ -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 4e81d852bb..16280eab5f 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("default_bold") color: UM.Theme.getColor("text_inactive") - anchors.top: parent.top - anchors.right: parent.right + anchors.top: outputDeviceNameLabel.bottom + anchors.left: parent.left anchors.margins: UM.Theme.getSize("default_margin").width } diff --git a/resources/qml/Settings/SettingCategory.qml b/resources/qml/Settings/SettingCategory.qml index 7995619af0..aafe36c546 100644 --- a/resources/qml/Settings/SettingCategory.qml +++ b/resources/qml/Settings/SettingCategory.qml @@ -14,23 +14,32 @@ Button anchors.right: parent.right 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/SettingView.qml b/resources/qml/Settings/SettingView.qml index cd9701aab6..ef1f123953 100644 --- a/resources/qml/Settings/SettingView.qml +++ b/resources/qml/Settings/SettingView.qml @@ -62,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" diff --git a/resources/qml/Toolbar.qml b/resources/qml/Toolbar.qml index 4e00bd7248..e019714abe 100644 --- a/resources/qml/Toolbar.qml +++ b/resources/qml/Toolbar.qml @@ -2,9 +2,7 @@ // 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 @@ -55,17 +53,24 @@ Item model: UM.ToolModel { id: toolsModel } width: childrenRect.width height: childrenRect.height - Button + + delegate: ToolbarButton { 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.toolbar_button - property bool isFirstElement: toolsModel.getItem(0).id == model.id - property bool isLastElement: toolsModel.getItem(toolsModel.count - 1).id == model.id + isTopElement: toolsModel.getItem(0).id == model.id + isBottomElement: toolsModel.getItem(toolsModel.count - 1).id == model.id + + toolItem: UM.RecolorImage + { + 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") + } onCheckedChanged: { @@ -128,11 +133,12 @@ Item height: childrenRect.height property var _model: Cura.ExtrudersModel { id: extrudersModel } model: _model.items.length > 1 ? _model : 0 - ExtruderButton + + delegate: ExtruderButton { extruder: model - height: UM.Theme.getSize("button").width - width: UM.Theme.getSize("button").width + isTopElement: extrudersModel.getItem(0).id == model.id + isBottomElement: extrudersModel.getItem(extrudersModel.rowCount() - 1).id == model.id } } } 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/qmldir b/resources/qml/qmldir index 9017739219..7e57119bc6 100644 --- a/resources/qml/qmldir +++ b/resources/qml/qmldir @@ -11,4 +11,5 @@ 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 \ No newline at end of file +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-light/styles.qml b/resources/themes/cura-light/styles.qml index 97eae65d27..90344d4644 100755 --- a/resources/themes/cura-light/styles.qml +++ b/resources/themes/cura-light/styles.qml @@ -1,9 +1,9 @@ // 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 @@ -171,123 +171,6 @@ QtObject } } - property Component toolbar_button: Component - { - ButtonStyle - { - background: Rectangle - { - implicitWidth: Theme.getSize("button").width - implicitHeight: Theme.getSize("button").height - color: - { - if (control.checked && control.hovered) - { - return Theme.getColor("toolbar_button_active_hover") - } - else if (control.checked) - { - return Theme.getColor("toolbar_button_active") - } - else if(control.hovered) - { - return Theme.getColor("toolbar_button_hover") - } - return 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: control.isFirstElement ? "transparent" : parent.color - } - - Rectangle - { - id: bottomSquare - anchors - { - left: parent.left - right: parent.right - bottom: parent.bottom - } - height: parent.radius - color: control.isLastElement ? "transparent" : parent.color - } - - Rectangle - { - id: leftSquare - anchors - { - left: parent.left - top: parent.top - bottom: parent.bottom - } - width: parent.radius - color: parent.color - } - - // This is the tooltip - UM.PointingRectangle - { - id: button_tooltip - - anchors.left: parent.right - anchors.leftMargin: Theme.getSize("button_tooltip_arrow").width * 2 - anchors.verticalCenter: parent.verticalCenter - - target: Qt.point(parent.x, y + Math.round(height/2)) - arrowSize: Theme.getSize("button_tooltip_arrow").width - color: Theme.getColor("button_tooltip") - opacity: control.hovered ? 1.0 : 0.0; - visible: control.text != "" - - width: control.hovered ? button_tip.width + Theme.getSize("button_tooltip").width : 0 - height: Theme.getSize("button_tooltip").height - - Behavior on width { NumberAnimation { duration: 100; } } - Behavior on opacity { NumberAnimation { duration: 100; } } - - Label - { - id: button_tip - - anchors.horizontalCenter: parent.horizontalCenter - anchors.verticalCenter: parent.verticalCenter; - - text: control.text; - font: Theme.getFont("button_tooltip"); - color: Theme.getColor("tooltip_text"); - } - } - } - - label: Item - { - UM.RecolorImage - { - anchors.centerIn: parent; - opacity: !control.enabled ? 0.2 : 1.0 - source: control.iconSource; - width: Theme.getSize("button_icon").width; - height: Theme.getSize("button_icon").height; - color: Theme.getColor("toolbar_button_text"); - - sourceSize: Theme.getSize("button_icon") - } - } - } - } - property Component tool_button: Component { ButtonStyle @@ -840,4 +723,210 @@ QtObject label: Item { } } } + + property Component toolbox_action_button: Component + { + ButtonStyle + { + background: Rectangle + { + implicitWidth: UM.Theme.getSize("toolbox_action_button").width + implicitHeight: UM.Theme.getSize("toolbox_action_button").height + color: + { + if (control.installed) + { + return UM.Theme.getColor("action_button_disabled"); + } + else + { + if (control.hovered) + { + return UM.Theme.getColor("primary_hover"); + } + else + { + return UM.Theme.getColor("primary"); + } + } + + } + } + label: Label + { + text: control.text + color: + { + if (control.installed) + { + return UM.Theme.getColor("action_button_disabled_text"); + } + else + { + if (control.hovered) + { + return UM.Theme.getColor("button_text_hover"); + } + else + { + return UM.Theme.getColor("button_text"); + } + } + } + verticalAlignment: Text.AlignVCenter + horizontalAlignment: Text.AlignHCenter + font: UM.Theme.getFont("default_bold") + } + } + } + + 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 0d77ecf802..767b6eaccd 100644 --- a/resources/themes/cura-light/theme.json +++ b/resources/themes/cura-light/theme.json @@ -388,7 +388,7 @@ "thin_margin": [0.71, 0.71], "narrow_margin": [0.5, 0.5], - "extruder_icon": [2.5, 2.5], + "extruder_icon": [2.33, 2.33], "section": [0.0, 2.2], "section_icon": [1.6, 1.6], @@ -459,6 +459,7 @@ "modal_window_minimum": [60.0, 45], "license_window_minimum": [45, 45], + "wizard_progress": [10.0, 0.0], "message": [30.0, 5.0], "message_close": [1, 1], @@ -499,9 +500,6 @@ "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],