Просмотр исходного кода

WIP: Create new Machine Settings dialog widgets

Lipu Fei 6 лет назад
Родитель
Сommit
6c2e80d2a1

+ 105 - 0
resources/qml/MachineSettings/ComboBoxWithOptions.qml

@@ -0,0 +1,105 @@
+// Copyright (c) 2019 Ultimaker B.V.
+// Cura is released under the terms of the LGPLv3 or higher.
+
+import QtQuick 2.10
+import QtQuick.Controls 2.3
+import QtQuick.Layouts 1.3
+
+import UM 1.3 as UM
+import Cura 1.1 as Cura
+
+
+//
+// ComboBox with dropdown options in the Machine Settings dialog.
+//
+UM.TooltipArea
+{
+    id: comboBoxWithOptions
+
+    UM.I18nCatalog { id: catalog; name: "cura"; }
+
+    height: childrenRect.height
+    width: childrenRect.width
+    text: tooltip
+
+    property alias containerStackId: propertyProvider.containerStackId
+    property alias settingKey: propertyProvider.key
+    property alias settingStoreIndex: propertyProvider.storeIndex
+
+    property alias labelText: fieldLabel.text
+    property alias labelWidth: fieldLabel.width
+
+    property string tooltip: propertyProvider.properties.description
+
+    // callback functions
+    property var afterOnActivateFunction: dummy_func
+    property var forceUpdateOnChangeFunction: dummy_func
+
+    // a dummy function for default property values
+    function dummy_func() {}
+
+    UM.SettingPropertyProvider
+    {
+        id: propertyProvider
+        watchedProperties: [ "value", "options", "description" ]
+    }
+
+    Row
+    {
+        spacing: UM.Theme.getSize("default_margin").width
+
+        Label
+        {
+            id: fieldLabel
+            anchors.verticalCenter: comboBox.verticalCenter
+            visible: text != ""
+            elide: Text.ElideRight
+            //width: Math.max(0, settingsTabs.labelColumnWidth)
+        }
+        ComboBox
+        {
+            id: comboBox
+            model: ListModel
+            {
+                id: optionsModel
+                Component.onCompleted:
+                {
+                    // Options come in as a string-representation of an OrderedDict
+                    var options = propertyProvider.properties.options.match(/^OrderedDict\(\[\((.*)\)\]\)$/)
+                    if (options)
+                    {
+                        options = options[1].split("), (")
+                        for (var i = 0; i < options.length; i++)
+                        {
+                            var option = options[i].substring(1, options[i].length - 1).split("', '")
+                            optionsModel.append({text: option[1], value: option[0]});
+                        }
+                    }
+                }
+            }
+            currentIndex:
+            {
+                var currentValue = propertyProvider.properties.value
+                var index = 0
+                for (var i = 0; i < optionsModel.count; i++)
+                {
+                    if (optionsModel.get(i).value == currentValue)
+                    {
+                        index = i
+                        break
+                    }
+                }
+                return index
+            }
+            onActivated:
+            {
+                if(propertyProvider.properties.value != optionsModel.get(index).value)
+                {
+                    propertyProvider.setPropertyValue("value", optionsModel.get(index).value);
+                    forceUpdateOnChangeFunction()
+                    afterOnActivateFunction()
+                }
+            }
+        }
+    }
+}

+ 55 - 0
resources/qml/MachineSettings/GcodeTextArea.qml

@@ -0,0 +1,55 @@
+// Copyright (c) 2019 Ultimaker B.V.
+// Cura is released under the terms of the LGPLv3 or higher.
+
+import QtQuick 2.10
+import QtQuick.Controls 2.3
+import QtQuick.Layouts 1.3
+
+import UM 1.3 as UM
+import Cura 1.1 as Cura
+
+
+//
+// TextArea widget for editing Gcode in the Machine Settings dialog.
+//
+UM.TooltipArea
+{
+    id: gcodeTextArea
+
+    UM.I18nCatalog { id: catalog; name: "cura"; }
+
+    height: childrenRect.height
+    width: childrenRect.width
+    text: tooltip
+
+    property alias containerStackId: propertyProvider.containerStackId
+    property alias settingKey: propertyProvider.key
+    property alias settingStoreIndex: propertyProvider.storeIndex
+
+    property string tooltip: propertyProvider.properties.description
+
+    UM.SettingPropertyProvider
+    {
+        id: propertyProvider
+        watchedProperties: [ "value", "description" ]
+    }
+
+    // TODO: put label here
+
+    TextArea
+    {
+        id: gcodeArea
+        width: areaWidth
+        height: areaHeight
+        font: UM.Theme.getFont("fixed")
+        text: (propertyProvider.properties.value) ? propertyProvider.properties.value : ""
+        wrapMode: TextEdit.NoWrap
+        onActiveFocusChanged:
+        {
+            if (!activeFocus)
+            {
+                propertyProvider.setPropertyValue("value", text)
+            }
+        }
+    }
+}

+ 55 - 0
resources/qml/MachineSettings/MachineSettingsContent.qml

@@ -0,0 +1,55 @@
+import QtQuick 2.10
+import QtQuick.Controls 2.3
+import QtQuick.Layouts 1.3
+
+
+Item
+{
+    id: base
+    anchors.fill: parent
+
+    TabBar
+    {
+        id: bar
+        width: parent.width
+        TabButton
+        {
+            text: "Printer"
+        }
+
+        Repeater
+        {
+            id: extrudersTabsRepeater
+            model: ["Extruder 1", "Extruder 2", "Extruder 3"]
+
+            TabButton
+            {
+                text: modelData
+            }
+        }
+    }
+
+    StackLayout
+    {
+        width: parent.width
+        currentIndex: bar.currentIndex
+        Item
+        {
+            id: printerTab
+        }
+        Repeater
+        {
+            model: ["Extruder 1", "Extruder 2", "Extruder 3"]
+            Item
+            {
+                anchors.centerIn: parent
+
+                Label  // TODO: this is a dummy
+                {
+                    anchors.centerIn: parent
+                    text: modelData
+                }
+            }
+        }
+    }
+}

+ 123 - 0
resources/qml/MachineSettings/NumericTextFieldWithUnit.qml

@@ -0,0 +1,123 @@
+// Copyright (c) 2019 Ultimaker B.V.
+// Cura is released under the terms of the LGPLv3 or higher.
+
+import QtQuick 2.10
+import QtQuick.Controls 2.3
+import QtQuick.Layouts 1.3
+
+import UM 1.3 as UM
+import Cura 1.1 as Cura
+
+
+//
+// TextField widget with validation for editing numeric data in the Machine Settings dialog.
+//
+UM.TooltipArea
+{
+    id: numericTextFieldWithUnit
+
+    UM.I18nCatalog { id: catalog; name: "cura"; }
+
+    height: childrenRect.height
+    width: childrenRect.width
+    text: tooltip
+
+    property alias containerStackId: propertyProvider.containerStackId
+    property alias settingKey: propertyProvider.key
+    property alias settingStoreIndex: propertyProvider.storeIndex
+
+    property alias labelText: fieldLabel.text
+    property alias labelWidth: fieldLabel.width
+    property alias unitText: unitLabel.text
+
+    property string tooltip: propertyProvider.properties.description
+
+    // whether negative value is allowed. This affects the validation of the input field.
+    property bool allowNegativeValue: false
+
+    // callback functions
+    property var afterOnEditingFinishedFunction: dummy_func
+    property var forceUpdateOnChangeFunction: dummy_func
+    property var setValueFunction: null
+
+    // a dummy function for default property values
+    function dummy_func() {}
+
+    UM.SettingPropertyProvider
+    {
+        id: propertyProvider
+        watchedProperties: [ "value", "description" ]
+    }
+
+    Row
+    {
+        id: itemRow
+        spacing: UM.Theme.getSize("default_margin").width
+
+        Label
+        {
+            id: fieldLabel
+            anchors.verticalCenter: textFieldWithUnit.verticalCenter
+            visible: text != ""
+            elide: Text.ElideRight
+            renderType: Text.NativeRendering
+            //width: Math.max(0, settingsTabs.labelColumnWidth)
+        }
+
+        Item
+        {
+            id: textFieldWithUnit
+
+            width: textField.width
+            height: textField.height
+
+            TextField
+            {
+                id: textField
+                text:
+                {
+                    const value = propertyProvider.properties.value
+                    return value ? value : ""
+                }
+                validator: RegExpValidator { regExp: allowNegativeValue ? /-?[0-9\.,]{0,6}/ : /[0-9\.,]{0,6}/ }
+                onEditingFinished:
+                {
+                    if (propertyProvider && text != propertyProvider.properties.value)
+                    {
+                        // For some properties like the extruder-compatible material diameter, they need to
+                        // trigger many updates, such as the available materials, the current material may
+                        // need to be switched, etc. Although setting the diameter can be done directly via
+                        // the provider, all the updates that need to be triggered then need to depend on
+                        // the metadata update, a signal that can be fired way too often. The update functions
+                        // can have if-checks to filter out the irrelevant updates, but still it incurs unnecessary
+                        // overhead.
+                        // The ExtruderStack class has a dedicated function for this call "setCompatibleMaterialDiameter()",
+                        // and it triggers the diameter update signals only when it is needed. Here it is optionally
+                        // choose to use setCompatibleMaterialDiameter() or other more specific functions that
+                        // are available.
+                        if (setValueFunction !== null)
+                        {
+                            setValueFunction(text)
+                        }
+                        else
+                        {
+                            propertyProvider.setPropertyValue("value", text)
+                        }
+                        forceUpdateOnChangeFunction()
+                        afterOnEditingFinished()
+                    }
+                }
+            }
+
+            Label
+            {
+                id: unitLabel
+                anchors.right: textField.right
+                anchors.rightMargin: y - textField.y
+                anchors.verticalCenter: textField.verticalCenter
+                text: unitText
+                renderType: Text.NativeRendering
+            }
+        }
+    }
+}

+ 120 - 0
resources/qml/MachineSettings/PolygonTextField.qml

@@ -0,0 +1,120 @@
+// Copyright (c) 2019 Ultimaker B.V.
+// Cura is released under the terms of the LGPLv3 or higher.
+
+import QtQuick 2.10
+import QtQuick.Controls 2.3
+import QtQuick.Layouts 1.3
+
+import UM 1.3 as UM
+import Cura 1.1 as Cura
+
+
+//
+// TextField for editing polygon data in the Machine Settings dialog.
+//
+UM.TooltipArea
+{
+    UM.I18nCatalog { id: catalog; name: "cura"; }
+
+    height: textField.height
+    width: textField.width
+    text: tooltip
+
+    property alias containerStackId: propertyProvider.containerStackId
+    property alias settingKey: propertyProvider.key
+    property alias settingStoreIndex: propertyProvider.storeIndex
+
+    property alias labelText: fieldLabel.text
+    property alias labelWidth: fieldLabel.width
+    property string unitText: catalog.i18nc("@label", "mm")
+
+    // callback functions
+    property var forceUpdateOnChangeFunction: dummy_func
+
+    // a dummy function for default property values
+    function dummy_func() {}
+
+    property var printHeadPolygon:
+    {
+        "x": {
+            "min": 0,
+            "max": 0,
+        },
+        "y": {
+            "min": 0,
+            "max": 0,
+        },
+    }
+
+    UM.SettingPropertyProvider
+    {
+        id: propertyProvider
+        watchedProperties: [ "value" ]
+    }
+
+    Row
+    {
+        spacing: UM.Theme.getSize("default_margin").width
+
+        Label
+        {
+            id: fieldLabel
+            anchors.verticalCenter: textFieldWithUnit.verticalCenter
+            visible: text != ""
+            elide: Text.ElideRight
+            //width: Math.max(0, settingsTabs.labelColumnWidth)
+        }
+
+        Item
+        {
+            id: textFieldWithUnit
+            width: textField.width
+            height: textField.height
+
+            TextField
+            {
+                id: textField
+                text:
+                {
+                    var polygon = JSON.parse(propertyProvider.properties.value)
+                    var item = (axis == "x") ? 0 : 1
+                    var result = polygon[0][item]
+                    for (var i = 1; i < polygon.length; i++) {
+                        result = (side == "min")
+                                 ? Math.min(result, polygon[i][item])
+                                 : Math.max(result, polygon[i][item])
+                    }
+                    result = Math.abs(result)
+                    printHeadPolygon[axis][side] = result
+                    return result
+                }
+                validator: RegExpValidator { regExp: /[0-9\.,]{0,6}/ }
+                onEditingFinished:
+                {
+                    printHeadPolygon[axis][side] = parseFloat(textField.text.replace(',','.'))
+                    var polygon = [
+                        [-printHeadPolygon["x"]["min"],  printHeadPolygon["y"]["max"]],
+                        [-printHeadPolygon["x"]["min"], -printHeadPolygon["y"]["min"]],
+                        [ printHeadPolygon["x"]["max"],  printHeadPolygon["y"]["max"]],
+                        [ printHeadPolygon["x"]["max"], -printHeadPolygon["y"]["min"]]
+                    ]
+                    var polygon_string = JSON.stringify(polygon)
+                    if (polygon_string != propertyProvider.properties.value)
+                    {
+                        propertyProvider.setPropertyValue("value", polygon_string)
+                        forceUpdateOnChangeFunction()
+                    }
+                }
+            }
+
+            Label
+            {
+                id: unitLabel
+                text: unitText
+                anchors.right: textField.right
+                anchors.rightMargin: y - textField.y
+                anchors.verticalCenter: textField.verticalCenter
+            }
+        }
+    }
+}

+ 272 - 0
resources/qml/MachineSettings/PrintSetupContent.qml

@@ -0,0 +1,272 @@
+import QtQuick 2.10
+import QtQuick.Controls 2.3
+import QtQuick.Layouts 1.3
+
+
+Column
+{
+    spacing: UM.Theme.getSize("default_margin").height
+
+    Row
+    {
+        width: parent.width
+        spacing: UM.Theme.getSize("default_margin").height
+
+        Column
+        {
+            width: settingsTabs.columnWidth
+            spacing: UM.Theme.getSize("default_lining").height
+
+            Label
+            {
+                text: catalog.i18nc("@label", "Printer Settings")
+                font.bold: true
+                renderType: Text.NativeRendering
+            }
+
+            Item { width: UM.Theme.getSize("default_margin").width; height: UM.Theme.getSize("default_margin").height }
+
+            Loader
+            {
+                id: buildAreaWidthField
+                sourceComponent: numericTextFieldWithUnit
+                property string settingKey: "machine_width"
+                property string label: catalog.i18nc("@label", "X (Width)")
+                property string unit: catalog.i18nc("@label", "mm")
+                property bool forceUpdateOnChange: true
+            }
+
+            Loader
+            {
+                id: buildAreaDepthField
+                sourceComponent: numericTextFieldWithUnit
+                property string settingKey: "machine_depth"
+                property string label: catalog.i18nc("@label", "Y (Depth)")
+                property string unit: catalog.i18nc("@label", "mm")
+                property bool forceUpdateOnChange: true
+            }
+
+            Loader
+            {
+                id: buildAreaHeightField
+                sourceComponent: numericTextFieldWithUnit
+                property string settingKey: "machine_height"
+                property string label: catalog.i18nc("@label", "Z (Height)")
+                property string unit: catalog.i18nc("@label", "mm")
+                property bool forceUpdateOnChange: true
+            }
+
+            Item { width: UM.Theme.getSize("default_margin").width; height: UM.Theme.getSize("default_margin").height }
+
+            Loader
+            {
+                id: shapeComboBox
+                sourceComponent: comboBoxWithOptions
+                property string settingKey: "machine_shape"
+                property string label: catalog.i18nc("@label", "Build plate shape")
+                property bool forceUpdateOnChange: true
+            }
+
+            Loader
+            {
+                id: centerIsZeroCheckBox
+                sourceComponent: simpleCheckBox
+                property string settingKey: "machine_center_is_zero"
+                property string label: catalog.i18nc("@option:check", "Origin at center")
+                property bool forceUpdateOnChange: true
+            }
+            Loader
+            {
+                id: heatedBedCheckBox
+                sourceComponent: simpleCheckBox
+                property var settingKey: "machine_heated_bed"
+                property string label: catalog.i18nc("@option:check", "Heated bed")
+                property bool forceUpdateOnChange: true
+            }
+
+            Item { width: UM.Theme.getSize("default_margin").width; height: UM.Theme.getSize("default_margin").height }
+
+            Loader
+            {
+                id: gcodeFlavorComboBox
+                sourceComponent: comboBoxWithOptions
+                property string settingKey: "machine_gcode_flavor"
+                property string label: catalog.i18nc("@label", "G-code flavor")
+                property bool forceUpdateOnChange: true
+                property var afterOnActivate: manager.updateHasMaterialsMetadata
+            }
+        }
+
+        Column
+        {
+            width: settingsTabs.columnWidth
+            spacing: UM.Theme.getSize("default_lining").height
+
+            Label
+            {
+                text: catalog.i18nc("@label", "Printhead Settings")
+                font.bold: true
+                renderType: Text.NativeRendering
+            }
+
+            Item { width: UM.Theme.getSize("default_margin").width; height: UM.Theme.getSize("default_margin").height }
+
+            Loader
+            {
+                id: printheadXMinField
+                sourceComponent: headPolygonTextField
+                property string label: catalog.i18nc("@label", "X min")
+                property string tooltip: catalog.i18nc("@tooltip", "Distance from the left of the printhead to the center of the nozzle. Used to prevent colissions between previous prints and the printhead when printing \"One at a Time\".")
+                property string axis: "x"
+                property string side: "min"
+            }
+
+            Loader
+            {
+                id: printheadYMinField
+                sourceComponent: headPolygonTextField
+                property string label: catalog.i18nc("@label", "Y min")
+                property string tooltip: catalog.i18nc("@tooltip", "Distance from the front of the printhead to the center of the nozzle. Used to prevent colissions between previous prints and the printhead when printing \"One at a Time\".")
+                property string axis: "y"
+                property string side: "min"
+            }
+
+            Loader
+            {
+                id: printheadXMaxField
+                sourceComponent: headPolygonTextField
+                property string label: catalog.i18nc("@label", "X max")
+                property string tooltip: catalog.i18nc("@tooltip", "Distance from the right of the printhead to the center of the nozzle. Used to prevent colissions between previous prints and the printhead when printing \"One at a Time\".")
+                property string axis: "x"
+                property string side: "max"
+            }
+
+            Loader
+            {
+                id: printheadYMaxField
+                sourceComponent: headPolygonTextField
+                property string label: catalog.i18nc("@label", "Y max")
+                property string tooltip: catalog.i18nc("@tooltip", "Distance from the rear of the printhead to the center of the nozzle. Used to prevent colissions between previous prints and the printhead when printing \"One at a Time\".")
+                property string axis: "y"
+                property string side: "max"
+            }
+
+            Item { width: UM.Theme.getSize("default_margin").width; height: UM.Theme.getSize("default_margin").height }
+
+            Loader
+            {
+                id: gantryHeightField
+                sourceComponent: numericTextFieldWithUnit
+                property string settingKey: "gantry_height"
+                property string label: catalog.i18nc("@label", "Gantry height")
+                property string unit: catalog.i18nc("@label", "mm")
+                property string tooltip: catalog.i18nc("@tooltip", "The height difference between the tip of the nozzle and the gantry system (X and Y axes). Used to prevent collisions between previous prints and the gantry when printing \"One at a Time\".")
+                property bool forceUpdateOnChange: true
+            }
+
+            Item { width: UM.Theme.getSize("default_margin").width; height: UM.Theme.getSize("default_margin").height }
+
+            UM.TooltipArea
+            {
+                height: childrenRect.height
+                width: childrenRect.width
+                text: machineExtruderCountProvider.properties.description
+                visible: extruderCountModel.count >= 2
+
+                Row
+                {
+                    spacing: UM.Theme.getSize("default_margin").width
+
+                    Label
+                    {
+                        anchors.verticalCenter: extruderCountComboBox.verticalCenter
+                        width: Math.max(0, settingsTabs.labelColumnWidth)
+                        text: catalog.i18nc("@label", "Number of Extruders")
+                        elide: Text.ElideRight
+                        renderType: Text.NativeRendering
+                    }
+                    ComboBox
+                    {
+                        id: extruderCountComboBox
+                        model: ListModel
+                        {
+                            id: extruderCountModel
+                            Component.onCompleted:
+                            {
+                                for(var i = 0; i < manager.definedExtruderCount; i++)
+                                {
+                                    extruderCountModel.append({text: String(i + 1), value: i})
+                                }
+                            }
+                        }
+
+                        Connections
+                        {
+                            target: manager
+                            onDefinedExtruderCountChanged:
+                            {
+                                extruderCountModel.clear();
+                                for(var i = 0; i < manager.definedExtruderCount; ++i)
+                                {
+                                    extruderCountModel.append({text: String(i + 1), value: i});
+                                }
+                            }
+                        }
+
+                        currentIndex: machineExtruderCountProvider.properties.value - 1
+                        onActivated:
+                        {
+                            manager.setMachineExtruderCount(index + 1);
+                        }
+                    }
+                }
+            }
+        }
+    }
+
+    Row
+    {
+        spacing: UM.Theme.getSize("default_margin").width
+        anchors.left: parent.left
+        anchors.right: parent.right
+        height: parent.height - y
+        Column
+        {
+            height: parent.height
+            width: settingsTabs.columnWidth
+            Label
+            {
+                text: catalog.i18nc("@label", "Start G-code")
+                font.bold: true
+            }
+            Loader
+            {
+                id: machineStartGcodeField
+                sourceComponent: gcodeTextArea
+                property int areaWidth: parent.width
+                property int areaHeight: parent.height - y
+                property string settingKey: "machine_start_gcode"
+                property string tooltip: catalog.i18nc("@tooltip", "G-code commands to be executed at the very start.")
+            }
+        }
+
+        Column {
+            height: parent.height
+            width: settingsTabs.columnWidth
+            Label
+            {
+                text: catalog.i18nc("@label", "End G-code")
+                font.bold: true
+            }
+            Loader
+            {
+                id: machineEndGcodeField
+                sourceComponent: gcodeTextArea
+                property int areaWidth: parent.width
+                property int areaHeight: parent.height - y
+                property string settingKey: "machine_end_gcode"
+                property string tooltip: catalog.i18nc("@tooltip", "G-code commands to be executed at the very end.")
+            }
+        }
+    }
+}

+ 53 - 0
resources/qml/MachineSettings/SimpleCheckBox.qml

@@ -0,0 +1,53 @@
+// Copyright (c) 2019 Ultimaker B.V.
+// Cura is released under the terms of the LGPLv3 or higher.
+
+import QtQuick 2.10
+import QtQuick.Controls 2.3
+import QtQuick.Layouts 1.3
+
+import UM 1.3 as UM
+import Cura 1.1 as Cura
+
+
+//
+// CheckBox widget for the on/off or true/false settings in the Machine Settings Dialog.
+//
+UM.TooltipArea
+{
+    UM.I18nCatalog { id: catalog; name: "cura"; }
+
+    height: childrenRect.height
+    width: childrenRect.width
+    text: tooltip
+
+    property alias containerStackId: propertyProvider.containerStackId
+    property alias settingKey: propertyProvider.key
+    property alias settingStoreIndex: propertyProvider.storeIndex
+
+    property alias labelText: checkBox.text
+
+    property string tooltip: propertyProvider.properties.description
+
+    // callback functions
+    property var forceUpdateOnChangeFunction: dummy_func
+
+    // a dummy function for default property values
+    function dummy_func() {}
+
+    UM.SettingPropertyProvider
+    {
+        id: propertyProvider
+        watchedProperties: [ "value", "description" ]
+    }
+
+    CheckBox
+    {
+        id: checkBox
+        checked: String(propertyProvider.properties.value).toLowerCase() != 'false'
+        onClicked:
+        {
+            propertyProvider.setPropertyValue("value", checked)
+            forceUpdateOnChangeFunction()
+        }
+    }
+}