Browse Source

Merge branch 'master' into CURA-4333_Notification_icon_for_recommended_mode

Lipu Fei 7 years ago
parent
commit
b59b245bff

+ 4 - 1
cura/CuraApplication.py

@@ -125,6 +125,8 @@ class CuraApplication(QtApplication):
     #        Cura will always show the Add Machine Dialog upon start.
     stacksValidationFinished = pyqtSignal()  # Emitted whenever a validation is finished
 
+    projectFileLoaded = pyqtSignal(str)  # Emitted whenever a project file is loaded
+
     def __init__(self):
         # this list of dir names will be used by UM to detect an old cura directory
         for dir_name in ["extruders", "machine_instances", "materials", "plugins", "quality", "user", "variants"]:
@@ -1365,8 +1367,9 @@ class CuraApplication(QtApplication):
                     # Find node location
                     offset_shape_arr, hull_shape_arr = ShapeArray.fromNode(node, min_offset = min_offset)
 
+                    # If a model is to small then it will not contain any points
                     if offset_shape_arr is None and hull_shape_arr is None:
-                        Message(self._i18n_catalog.i18nc("@info:status","Could not load a model"),
+                        Message(self._i18n_catalog.i18nc("@info:status", "The selected model was too small to load."),
                                 title=self._i18n_catalog.i18nc("@info:title", "Warning")).show()
                         return
 

+ 12 - 2
cura/PrintInformation.py

@@ -66,10 +66,11 @@ class PrintInformation(QObject):
         self._base_name = ""
         self._abbr_machine = ""
         self._job_name = ""
+        self._project_name = ""
 
         Application.getInstance().globalContainerStackChanged.connect(self._updateJobName)
         Application.getInstance().fileLoaded.connect(self.setBaseName)
-
+        Application.getInstance().projectFileLoaded.connect(self.setProjectName)
         Preferences.getInstance().preferenceChanged.connect(self._onPreferencesChanged)
 
         self._active_material_container = None
@@ -78,7 +79,6 @@ class PrintInformation(QObject):
 
         self._material_amounts = []
 
-
     # Crate cura message translations and using translation keys initialize empty time Duration object for total time
     # and time for each feature
     def initializeCuraMessagePrintTimeProperties(self):
@@ -241,6 +241,11 @@ class PrintInformation(QObject):
         self._job_name = name
         self.jobNameChanged.emit()
 
+    @pyqtSlot(str)
+    def setProjectName(self, name):
+        self._project_name = name
+        self.setJobName(name)
+
     jobNameChanged = pyqtSignal()
 
     @pyqtProperty(str, notify = jobNameChanged)
@@ -248,6 +253,11 @@ class PrintInformation(QObject):
         return self._job_name
 
     def _updateJobName(self):
+        # if the project name is set, we use the project name as the job name, so the job name should not get updated
+        # if a model file is loaded after that.
+        if self._project_name != "":
+            return
+
         if self._base_name == "":
             self._job_name = ""
             self.jobNameChanged.emit()

+ 4 - 4
cura/ShapeArray.py

@@ -43,13 +43,13 @@ class ShapeArray:
         transform_x = transform._data[0][3]
         transform_y = transform._data[2][3]
         hull_verts = node.callDecoration("getConvexHull")
-
-        if not hull_verts.getPoints().any(): # IF a model is to small then it will not contain any points
-            return None, None
-
         # For one_at_a_time printing you need the convex hull head.
         hull_head_verts = node.callDecoration("getConvexHullHead") or hull_verts
 
+        # If a model is to small then it will not contain any points
+        if not hull_verts.getPoints().any():
+            return None, None
+
         offset_verts = hull_head_verts.getMinkowskiHull(Polygon.approximatedCircle(min_offset))
         offset_points = copy.deepcopy(offset_verts._points)  # x, y
         offset_points[:, 0] = numpy.add(offset_points[:, 0], -transform_x)

+ 6 - 0
plugins/3MFReader/ThreeMFWorkspaceReader.py

@@ -26,6 +26,7 @@ from configparser import ConfigParser
 import zipfile
 import io
 import configparser
+import os
 
 i18n_catalog = i18nCatalog("cura")
 
@@ -876,6 +877,11 @@ class ThreeMFWorkspaceReader(WorkspaceReader):
         nodes = self._3mf_mesh_reader.read(file_name)
         if nodes is None:
             nodes = []
+
+        base_file_name = os.path.basename(file_name)
+        if base_file_name.endswith(".curaproject.3mf"):
+            base_file_name = base_file_name[:base_file_name.rfind(".curaproject.3mf")]
+        Application.getInstance().projectFileLoaded.emit(base_file_name)
         return nodes
 
     ##  HACK: Replaces the material container in the given stack with a newly created material container.

+ 38 - 4
plugins/LayerView/LayerSlider.qml

@@ -20,6 +20,7 @@ Item {
     property color lowerHandleColor: "black"
     property color rangeHandleColor: "black"
     property real handleLabelWidth: width
+    property var activeHandle: upperHandle
 
     // track properties
     property real trackThickness: 4 // width of the slider track
@@ -60,6 +61,11 @@ Item {
         rangeHandle.height = lowerHandle.y - (upperHandle.y + upperHandle.height)
     }
 
+    // set the active handle to show only one label at a time
+    function setActiveHandle (handle) {
+        activeHandle = handle
+    }
+
     // slider track
     Rectangle {
         id: track
@@ -98,6 +104,15 @@ Item {
             UM.LayerView.setMinimumLayer(lowerValue)
         }
 
+        function setValue (value) {
+            var range = sliderRoot.upperValue - sliderRoot.lowerValue
+            value = Math.min(value, sliderRoot.maximumValue)
+            value = Math.max(value, sliderRoot.minimumValue + range)
+
+            UM.LayerView.setCurrentLayer(value)
+            UM.LayerView.setMinimumLayer(value - range)
+        }
+
         Rectangle {
             width: sliderRoot.trackThickness - 2 * sliderRoot.trackBorderWidth
             height: parent.height + sliderRoot.handleSize
@@ -116,6 +131,23 @@ Item {
             }
 
             onPositionChanged: parent.onHandleDragged()
+            onPressed: sliderRoot.setActiveHandle(rangeHandle)
+        }
+
+        LayerSliderLabel {
+            id: rangleHandleLabel
+
+            height: sliderRoot.handleSize + UM.Theme.getSize("default_margin").height
+            x: parent.x - width - UM.Theme.getSize("default_margin").width
+            anchors.verticalCenter: parent.verticalCenter
+            target: Qt.point(sliderRoot.width, y + height / 2)
+            visible: sliderRoot.activeHandle == parent
+
+            // custom properties
+            maximumValue: sliderRoot.maximumValue
+            value: sliderRoot.upperValue
+            busy: UM.LayerView.busy
+            setValue: rangeHandle.setValue // connect callback functions
         }
     }
 
@@ -178,6 +210,7 @@ Item {
             }
 
             onPositionChanged: parent.onHandleDragged()
+            onPressed: sliderRoot.setActiveHandle(upperHandle)
         }
 
         LayerSliderLabel {
@@ -187,13 +220,13 @@ Item {
             x: parent.x - width - UM.Theme.getSize("default_margin").width
             anchors.verticalCenter: parent.verticalCenter
             target: Qt.point(sliderRoot.width, y + height / 2)
-            visible: sliderRoot.layersVisible
+            visible: sliderRoot.activeHandle == parent
 
             // custom properties
             maximumValue: sliderRoot.maximumValue
             value: sliderRoot.upperValue
             busy: UM.LayerView.busy
-            setValue: sliderRoot.setUpperValue // connect callback functions
+            setValue: upperHandle.setValue // connect callback functions
         }
     }
 
@@ -257,6 +290,7 @@ Item {
             }
 
             onPositionChanged: parent.onHandleDragged()
+            onPressed: sliderRoot.setActiveHandle(lowerHandle)
         }
 
         LayerSliderLabel {
@@ -266,13 +300,13 @@ Item {
             x: parent.x - width - UM.Theme.getSize("default_margin").width
             anchors.verticalCenter: parent.verticalCenter
             target: Qt.point(sliderRoot.width, y + height / 2)
-            visible: sliderRoot.layersVisible
+            visible: sliderRoot.activeHandle == parent
 
             // custom properties
             maximumValue: sliderRoot.maximumValue
             value: sliderRoot.lowerValue
             busy: UM.LayerView.busy
-            setValue: sliderRoot.setLowerValue // connect callback functions
+            setValue: lowerHandle.setValue // connect callback functions
         }
     }
 }

+ 9 - 5
plugins/LayerView/LayerSliderLabel.qml

@@ -22,13 +22,16 @@ UM.PointingRectangle {
     arrowSize: UM.Theme.getSize("default_arrow").width
     height: parent.height
     width: valueLabel.width + UM.Theme.getSize("default_margin").width
+    visible: false
+
+    // make sure the text field is focussed when pressing the parent handle
+    // needed to connect the key bindings when switching active handle
+    onVisibleChanged: if (visible) valueLabel.forceActiveFocus()
 
     color: UM.Theme.getColor("tool_panel_background")
     borderColor: UM.Theme.getColor("lining")
     borderWidth: UM.Theme.getSize("default_lining").width
 
-    visible: true
-
     Behavior on height {
         NumberAnimation {
             duration: 50
@@ -53,6 +56,10 @@ UM.PointingRectangle {
         text: sliderLabelRoot.value + 1 // the current handle value, add 1 because layers is an array
         horizontalAlignment: TextInput.AlignRight
 
+        // key bindings, work when label is currenctly focused (active handle in LayerSlider)
+        Keys.onUpPressed: sliderLabelRoot.setValue(sliderLabelRoot.value + ((event.modifiers & Qt.ShiftModifier) ? 10 : 1))
+        Keys.onDownPressed: sliderLabelRoot.setValue(sliderLabelRoot.value - ((event.modifiers & Qt.ShiftModifier) ? 10 : 1))
+
         style: TextFieldStyle {
             textColor: UM.Theme.getColor("setting_control_text")
             font: UM.Theme.getFont("default")
@@ -76,9 +83,6 @@ UM.PointingRectangle {
             bottom: 1
             top: sliderLabelRoot.maximumValue + 1 // +1 because actual layers is an array
         }
-
-        Keys.onUpPressed: sliderLabelRoot.setValue(sliderLabelRoot.value + ((event.modifiers & Qt.ShiftModifier) ? 10 : 1))
-        Keys.onDownPressed: sliderLabelRoot.setValue(sliderLabelRoot.value - ((event.modifiers & Qt.ShiftModifier) ? 10 : 1))
     }
 
     BusyIndicator {

+ 1 - 0
plugins/LayerView/LayerView.qml

@@ -368,6 +368,7 @@ Item
             // update values when layer data changes
             Connections {
                 target: UM.LayerView
+                onMaxLayersChanged: slider.setUpperValue(UM.LayerView.currentLayer)
                 onMinimumLayerChanged: slider.setLowerValue(UM.LayerView.minimumLayer)
                 onCurrentLayerChanged: slider.setUpperValue(UM.LayerView.currentLayer)
             }

+ 2 - 2
plugins/UM3NetworkPrinting/DiscoverUM3Action.qml

@@ -285,11 +285,11 @@ Cura.MachineAction
                         }
                         else if (base.selectedPrinter.clusterSize === 0)
                         {
-                            return catalog.i18nc("@label", "Cura Connect: This printer is not set up to host a group of connected Ultimaker 3 printers.");
+                            return catalog.i18nc("@label", "This printer is not set up to host a group of Ultimaker 3 printers.");
                         }
                         else
                         {
-                            return catalog.i18nc("@label", "Cura Connect: This printer is set up to host a group of %1 connected Ultimaker 3 printers".arg(base.selectedPrinter.clusterSize));
+                            return catalog.i18nc("@label", "This printer is the host for a group of %1 Ultimaker 3 printers.".arg(base.selectedPrinter.clusterSize));
                         }
                     }
 

+ 13 - 2
plugins/UM3NetworkPrinting/NetworkClusterPrinterOutputDevice.py

@@ -19,6 +19,7 @@ from UM.Message import Message
 from UM.OutputDevice import OutputDeviceError
 from UM.i18n import i18nCatalog
 from UM.Qt.Duration import Duration, DurationFormat
+from UM.PluginRegistry import PluginRegistry
 
 from . import NetworkPrinterOutputDevice
 
@@ -36,7 +37,7 @@ class NetworkClusterPrinterOutputDevice(NetworkPrinterOutputDevice.NetworkPrinte
     printersChanged = pyqtSignal()
     selectedPrinterChanged = pyqtSignal()
 
-    def __init__(self, key, address, properties, api_prefix, plugin_path):
+    def __init__(self, key, address, properties, api_prefix):
         super().__init__(key, address, properties, api_prefix)
         # Store the address of the master.
         self._master_address = address
@@ -47,7 +48,6 @@ class NetworkClusterPrinterOutputDevice(NetworkPrinterOutputDevice.NetworkPrinte
             name = key
 
         self._authentication_state = NetworkPrinterOutputDevice.AuthState.Authenticated  # The printer is always authenticated
-        self._plugin_path = plugin_path
 
         self.setName(name)
         description = i18n_catalog.i18nc("@action:button Preceded by 'Ready to'.", "Print over network")
@@ -709,3 +709,14 @@ class NetworkClusterPrinterOutputDevice(NetworkPrinterOutputDevice.NetworkPrinte
     @pyqtSlot(int, result=str)
     def formatDuration(self, seconds):
         return Duration(seconds).getDisplayString(DurationFormat.Format.Short)
+
+    ##  For cluster below
+    def _get_plugin_directory_name(self):
+        current_file_absolute_path = os.path.realpath(__file__)
+        directory_path = os.path.dirname(current_file_absolute_path)
+        _, directory_name = os.path.split(directory_path)
+        return directory_name
+
+    @property
+    def _plugin_path(self):
+        return PluginRegistry.getInstance().getPluginPath(self._get_plugin_directory_name())

+ 5 - 0
plugins/UM3NetworkPrinting/NetworkPrinterOutputDevice.py

@@ -775,6 +775,11 @@ class NetworkPrinterOutputDevice(PrinterOutputDevice):
 
     ##  Start requesting data from printer
     def connect(self):
+        # Don't allow to connect to a printer with a faulty connection state.
+        # For instance when switching printers but the printer is disconnected from the network
+        if self._connection_state == ConnectionState.error:
+            return
+
         if self.isConnected():
             self.close()  # Close previous connection
 

Some files were not shown because too many files changed in this diff