diff --git a/resources/qml/MachineSettings/ComboBoxWithOptions.qml b/resources/qml/MachineSettings/ComboBoxWithOptions.qml new file mode 100644 index 0000000000..1a8f208bd6 --- /dev/null +++ b/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() + } + } + } + } +} diff --git a/resources/qml/MachineSettings/GcodeTextArea.qml b/resources/qml/MachineSettings/GcodeTextArea.qml new file mode 100644 index 0000000000..748111a8e2 --- /dev/null +++ b/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) + } + } + } +} diff --git a/resources/qml/MachineSettings/MachineSettingsContent.qml b/resources/qml/MachineSettings/MachineSettingsContent.qml new file mode 100644 index 0000000000..daa41d4c5d --- /dev/null +++ b/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 + } + } + } + } +} diff --git a/resources/qml/MachineSettings/NumericTextFieldWithUnit.qml b/resources/qml/MachineSettings/NumericTextFieldWithUnit.qml new file mode 100644 index 0000000000..f8b476d6f4 --- /dev/null +++ b/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 + } + } + } +} diff --git a/resources/qml/MachineSettings/PolygonTextField.qml b/resources/qml/MachineSettings/PolygonTextField.qml new file mode 100644 index 0000000000..59664b9f23 --- /dev/null +++ b/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 + } + } + } +} diff --git a/resources/qml/MachineSettings/PrintSetupContent.qml b/resources/qml/MachineSettings/PrintSetupContent.qml new file mode 100644 index 0000000000..d2469ff71d --- /dev/null +++ b/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.") + } + } + } +} diff --git a/resources/qml/MachineSettings/SimpleCheckBox.qml b/resources/qml/MachineSettings/SimpleCheckBox.qml new file mode 100644 index 0000000000..ab8877f935 --- /dev/null +++ b/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() + } + } +}