Merge branch 'master' into feature_tray_icon_preference

This commit is contained in:
Aldo Hoeben 2022-03-22 14:38:50 +01:00 committed by GitHub
commit d655350aac
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
543 changed files with 7734 additions and 9460 deletions

View file

@ -2,11 +2,8 @@
// Cura is released under the terms of the LGPLv3 or higher.
import QtQuick 2.10
import QtQuick.Controls 1.1
import QtQuick.Controls 2.15
import QtQuick.Layouts 1.1
import QtQuick.Controls.Styles 1.1
import QtQuick.Controls 2.3 as NewControls
import UM 1.5 as UM
import Cura 1.1 as Cura
@ -17,7 +14,7 @@ UM.PreferencesPage
title: catalog.i18nc("@title:tab", "General")
id: generalPreferencesPage
width: parent.width
width: parent ? parent.width: 0
function setDefaultLanguage(languageCode)
{
@ -106,14 +103,14 @@ UM.PreferencesPage
invertZoomCheckbox.checked = boolCheck(UM.Preferences.getValue("view/invert_zoom"))
UM.Preferences.resetPreference("view/zoom_to_mouse");
zoomToMouseCheckbox.checked = boolCheck(UM.Preferences.getValue("view/zoom_to_mouse"))
UM.Preferences.resetPreference("view/top_layer_count");
topLayerCountCheckbox.checked = boolCheck(UM.Preferences.getValue("view/top_layer_count"))
//UM.Preferences.resetPreference("view/top_layer_count");
//topLayerCountCheckbox.checked = boolCheck(UM.Preferences.getValue("view/top_layer_count"))
UM.Preferences.resetPreference("general/restore_window_geometry")
restoreWindowPositionCheckbox.checked = boolCheck(UM.Preferences.getValue("general/restore_window_geometry"))
UM.Preferences.resetPreference("general/camera_perspective_mode")
var defaultCameraMode = UM.Preferences.getValue("general/camera_perspective_mode")
setDefaultCameraMode(defaultCameraMode)
//var defaultCameraMode = UM.Preferences.getValue("general/camera_perspective_mode")
// /setDefaultCameraMode(defaultCameraMode)
UM.Preferences.resetPreference("cura/choice_on_profile_override")
setDefaultDiscardOrKeepProfile(UM.Preferences.getValue("cura/choice_on_profile_override"))
@ -131,33 +128,60 @@ UM.PreferencesPage
pluginNotificationsUpdateCheckbox.checked = boolCheck(UM.Preferences.getValue("info/automatic_plugin_update_check"))
}
buttons: [
Cura.SecondaryButton
{
text: catalog.i18nc("@action:button", "Defaults")
onClicked: reset()
}
]
ScrollView
{
id: preferencesScrollView
width: parent.width
height: parent.height
ScrollBar.vertical: UM.ScrollBar
{
id: preferencesScrollBar
parent: preferencesScrollView
anchors
{
top: parent.top
bottom: parent.bottom
right: parent.right
}
onPositionChanged: {
// This removes focus from items when scrolling.
// This fixes comboboxes staying open and scrolling container
if (!activeFocus) {
forceActiveFocus();
}
}
}
Column
{
UM.I18nCatalog{id: catalog; name: "cura"}
width: preferencesScrollView.viewport.width
width: preferencesScrollView.width - preferencesScrollBar.width
Label
UM.Label
{
font.bold: true
font: UM.Theme.getFont("medium_bold")
text: catalog.i18nc("@label", "Interface")
}
GridLayout
{
id: interfaceGrid
columns: 4
columns: 2
width: parent.width
Label
UM.Label
{
id: languageLabel
text: "Language:" //Don't translate this, to make it easier to find the language drop-down if you can't read the current language.
text: "Language*:" //Don't translate this, to make it easier to find the language drop-down if you can't read the current language.
}
ListModel
@ -196,13 +220,14 @@ UM.PreferencesPage
}
}
NewControls.ComboBox
Cura.ComboBox
{
id: languageComboBox
textRole: "text"
model: languageList
Layout.fillWidth: true
implicitWidth: UM.Theme.getSize("combobox").width
implicitHeight: currencyField.height
function setCurrentIndex() {
var code = UM.Preferences.getValue("general/language");
@ -217,7 +242,9 @@ UM.PreferencesPage
currentIndex: setCurrentIndex()
onActivated: if (model.get(index).code != "")
onActivated:
{
if (model.get(index).code != "")
{
UM.Preferences.setValue("general/language", model.get(index).code);
}
@ -225,25 +252,28 @@ UM.PreferencesPage
{
currentIndex = setCurrentIndex();
}
}
}
Label
UM.Label
{
id: currencyLabel
text: catalog.i18nc("@label", "Currency:")
}
TextField
Cura.TextField
{
id: currencyField
selectByMouse: true
text: UM.Preferences.getValue("cura/currency")
implicitWidth: UM.Theme.getSize("combobox").width
onTextChanged: UM.Preferences.setValue("cura/currency", text)
}
Label
UM.Label
{
id: themeLabel
text: catalog.i18nc("@label","Theme:")
text: catalog.i18nc("@label: Please keep the asterix, it's to indicate that a restart is needed.", "Theme*:")
}
ListModel
@ -259,13 +289,14 @@ UM.PreferencesPage
}
}
NewControls.ComboBox
Cura.ComboBox
{
id: themeComboBox
model: themeList
textRole: "text"
Layout.fillWidth: true
implicitWidth: UM.Theme.getSize("combobox").width
implicitHeight: currencyField.height
currentIndex:
{
@ -283,23 +314,6 @@ UM.PreferencesPage
}
}
Label
{
id: languageCaption
//: Language change warning
text: catalog.i18nc("@label", "You will need to restart the application for these changes to have effect.")
wrapMode: Text.WordWrap
font.italic: true
}
Item
{
//: Spacer
height: UM.Theme.getSize("default_margin").height
width: UM.Theme.getSize("default_margin").width
}
UM.TooltipArea
{
width: childrenRect.width;
@ -330,10 +344,21 @@ UM.PreferencesPage
checked: boolCheck(UM.Preferences.getValue("general/use_tray_icon"))
onClicked: UM.Preferences.setValue("general/use_tray_icon", checked)
text: catalog.i18nc("@option:check", "Add icon to system tray (restart required)");
text: catalog.i18nc("@option:check", "Add icon to system tray *");
}
}
UM.Label
{
id: languageCaption
//: Language change warning
text: catalog.i18nc("@label", "*You will need to restart the application for these changes to have effect.")
wrapMode: Text.WordWrap
font.italic: true
}
Item
{
//: Spacer
@ -341,9 +366,9 @@ UM.PreferencesPage
width: UM.Theme.getSize("default_margin").width
}
Label
UM.Label
{
font.bold: true
font: UM.Theme.getFont("medium_bold")
text: catalog.i18nc("@label", "Viewport behavior")
}
@ -536,9 +561,9 @@ UM.PreferencesPage
text: catalog.i18nc("@info:tooltip", "What type of camera rendering should be used?")
Column
{
spacing: 4 * screenScaleFactor
spacing: UM.Theme.getSize("narrow_margin").height
Label
UM.Label
{
text: catalog.i18nc("@window:text", "Camera rendering:")
}
@ -552,12 +577,14 @@ UM.PreferencesPage
}
}
NewControls.ComboBox
Cura.ComboBox
{
id: cameraComboBox
model: comboBoxList
textRole: "text"
width: UM.Theme.getSize("combobox").width
height: UM.Theme.getSize("combobox").height
currentIndex:
{
@ -583,9 +610,9 @@ UM.PreferencesPage
width: UM.Theme.getSize("default_margin").height
}
Label
UM.Label
{
font.bold: true
font: UM.Theme.getFont("medium_bold")
text: catalog.i18nc("@label","Opening and saving files")
}
@ -599,6 +626,7 @@ UM.PreferencesPage
{
id: singleInstanceCheckbox
text: catalog.i18nc("@option:check","Use a single instance of Cura")
checked: boolCheck(UM.Preferences.getValue("cura/single_instance"))
onCheckedChanged: UM.Preferences.setValue("cura/single_instance", checked)
}
@ -702,17 +730,18 @@ UM.PreferencesPage
Column
{
spacing: 4 * screenScaleFactor
spacing: UM.Theme.getSize("narrow_margin").height
Label
UM.Label
{
text: catalog.i18nc("@window:text", "Default behavior when opening a project file: ")
}
NewControls.ComboBox
Cura.ComboBox
{
id: choiceOnOpenProjectDropDownButton
width: Math.round(250 * screenScaleFactor)
width: UM.Theme.getSize("combobox").width
height: UM.Theme.getSize("combobox").height
model: ListModel
{
@ -756,31 +785,31 @@ UM.PreferencesPage
UM.TooltipArea
{
width: childrenRect.width;
height: childrenRect.height;
width: childrenRect.width
height: childrenRect.height
text: catalog.i18nc("@info:tooltip", "When you have made changes to a profile and switched to a different one, a dialog will be shown asking whether you want to keep your modifications or not, or you can choose a default behaviour and never show that dialog again.")
Column
{
spacing: 4 * screenScaleFactor
spacing: UM.Theme.getSize("narrow_margin").height
Label
UM.Label
{
font.bold: true
font: UM.Theme.getFont("medium_bold")
text: catalog.i18nc("@label", "Profiles")
}
Label
UM.Label
{
text: catalog.i18nc("@window:text", "Default behavior for changed setting values when switching to a different profile: ")
}
NewControls.ComboBox
Cura.ComboBox
{
id: choiceOnProfileOverrideDropDownButton
width: Math.round(250 * screenScaleFactor)
popup.width: Math.round(350 * screenScaleFactor)
width: UM.Theme.getSize("combobox_wide").width
height: UM.Theme.getSize("combobox_wide").height
model: ListModel
{
id: discardOrKeepProfileListModel
@ -820,9 +849,9 @@ UM.PreferencesPage
width: UM.Theme.getSize("default_margin").height
}
Label
UM.Label
{
font.bold: true
font: UM.Theme.getFont("medium_bold")
text: catalog.i18nc("@label", "Privacy")
}
UM.TooltipArea
@ -839,15 +868,18 @@ UM.PreferencesPage
onCheckedChanged: UM.Preferences.setValue("info/send_slice_info", checked)
}
Button
UM.SimpleButton
{
id: showMoreInfo
anchors.top: sendDataCheckbox.bottom
text: catalog.i18nc("@action:button", "More information")
onClicked:
{
CuraApplication.showMoreInformationDialogForAnonymousDataCollection();
}
onClicked: CuraApplication.showMoreInformationDialogForAnonymousDataCollection()
iconSource: UM.Theme.getIcon("Information")
anchors.left: sendDataCheckbox.right
anchors.verticalCenter: sendDataCheckbox.verticalCenter
hoverBackgroundColor: UM.Theme.getColor("secondary_button_hover")
backgroundRadius: width / 2
height: UM.Theme.getSize("small_button_icon").height
color: UM.Theme.getColor("small_button_text")
width: height
}
}
@ -858,9 +890,9 @@ UM.PreferencesPage
width: UM.Theme.getSize("default_margin").height
}
Label
UM.Label
{
font.bold: true
font: UM.Theme.getFont("medium_bold")
text: catalog.i18nc("@label", "Updates")
}
@ -879,7 +911,12 @@ UM.PreferencesPage
}
}
ExclusiveGroup { id: curaUpdatesGroup }
ButtonGroup
{
id: curaUpdatesGroup
buttons: [checkUpdatesOptionBeta, checkUpdatesOptionStable]
}
UM.TooltipArea
{
width: childrenRect.width
@ -887,10 +924,10 @@ UM.PreferencesPage
text: catalog.i18nc("@info:tooltip", "When checking for updates, only check for stable releases.")
anchors.left: parent.left
anchors.leftMargin: UM.Theme.getSize("default_margin").width
RadioButton
Cura.RadioButton
{
id: checkUpdatesOptionStable
text: catalog.i18nc("@option:radio", "Stable releases only")
exclusiveGroup: curaUpdatesGroup
enabled: checkUpdatesCheckbox.checked
checked: UM.Preferences.getValue("info/latest_update_source") == "stable"
onClicked: UM.Preferences.setValue("info/latest_update_source", "stable")
@ -903,10 +940,10 @@ UM.PreferencesPage
text: catalog.i18nc("@info:tooltip", "When checking for updates, check for both stable and for beta releases.")
anchors.left: parent.left
anchors.leftMargin: UM.Theme.getSize("default_margin").width
RadioButton
Cura.RadioButton
{
id: checkUpdatesOptionBeta
text: catalog.i18nc("@option:radio", "Stable and Beta releases")
exclusiveGroup: curaUpdatesGroup
enabled: checkUpdatesCheckbox.checked
checked: UM.Preferences.getValue("info/latest_update_source") == "beta"
onClicked: UM.Preferences.setValue("info/latest_update_source", "beta")

View file

@ -1,25 +1,35 @@
// Copyright (c) 2018 Ultimaker B.V.
// Copyright (c) 2022 Ultimaker B.V.
// Cura is released under the terms of the LGPLv3 or higher.
import QtQuick 2.7
import QtQuick.Controls 1.4
import QtQuick.Controls 2.1
import QtQuick.Window 2.1
import UM 1.2 as UM
import UM 1.5 as UM
import Cura 1.0 as Cura
UM.ManagementPage
{
id: base;
id: base
title: catalog.i18nc("@title:tab", "Printers")
detailsPlaneCaption: base.currentItem && base.currentItem.name ? base.currentItem.name : ""
title: catalog.i18nc("@title:tab", "Printers");
model: Cura.GlobalStacksModel { }
sectionRole: "discoverySource"
activeId: Cura.MachineManager.activeMachine !== null ? Cura.MachineManager.activeMachine.id: ""
activeIndex: activeMachineIndex()
onHamburgeButtonClicked: {
const hamburerButtonHeight = hamburger_button.height;
menu.popup(hamburger_button, -menu.width + hamburger_button.width / 2, hamburger_button.height);
// for some reason the height of the hamburger changes when opening the popup
// reset height to initial heigt
hamburger_button.height = hamburerButtonHeight;
}
hamburgerButtonVisible: Cura.MachineManager.activeMachine !== null
function activeMachineIndex()
{
@ -34,87 +44,46 @@ UM.ManagementPage
}
buttons: [
Button
Cura.SecondaryButton
{
id: activateMenuButton
text: catalog.i18nc("@action:button", "Activate");
iconName: "list-activate";
enabled: base.currentItem != null && base.currentItem.id != Cura.MachineManager.activeMachine.id
onClicked: Cura.MachineManager.setActiveMachine(base.currentItem.id)
},
Button
{
id: addMenuButton
text: catalog.i18nc("@action:button", "Add");
iconName: "list-add";
text: catalog.i18nc("@action:button", "Add New")
onClicked: Cura.Actions.addMachine.trigger()
},
Button
{
id: removeMenuButton
text: catalog.i18nc("@action:button", "Remove");
iconName: "list-remove";
enabled: base.currentItem != null && model.count > 1
onClicked: confirmDialog.open();
},
Button
{
id: renameMenuButton
text: catalog.i18nc("@action:button", "Rename");
iconName: "edit-rename";
enabled: base.currentItem != null && base.currentItem.metadata.group_name == null
onClicked: renameDialog.open();
}
]
Item
Flow
{
visible: base.currentItem != null
visible: base.currentItem != null && currentItem && currentItem.id == Cura.MachineManager.activeMachine.id
anchors.fill: parent
spacing: UM.Theme.getSize("default_margin").height
Label
Repeater
{
id: machineName
text: base.currentItem && base.currentItem.name ? base.currentItem.name : ""
font: UM.Theme.getFont("large_bold")
width: parent.width
elide: Text.ElideRight
}
id: machineActionRepeater
model: base.currentItem ? Cura.MachineActionManager.getSupportedActions(Cura.MachineManager.getDefinitionByMachineId(base.currentItem.id)) : null
Flow
{
id: machineActions
visible: currentItem && currentItem.id == Cura.MachineManager.activeMachine.id
anchors.left: parent.left
anchors.right: parent.right
anchors.top: machineName.bottom
anchors.topMargin: UM.Theme.getSize("default_margin").height
Repeater
Item
{
id: machineActionRepeater
model: base.currentItem ? Cura.MachineActionManager.getSupportedActions(Cura.MachineManager.getDefinitionByMachineId(base.currentItem.id)) : null
Item
width: Math.round(childrenRect.width + 2 * screenScaleFactor)
height: childrenRect.height
Cura.SecondaryButton
{
width: Math.round(childrenRect.width + 2 * screenScaleFactor)
height: childrenRect.height
Button
text: machineActionRepeater.model[index].label
onClicked:
{
text: machineActionRepeater.model[index].label
onClicked:
{
var currentItem = machineActionRepeater.model[index]
actionDialog.loader.manager = currentItem
actionDialog.loader.source = currentItem.qmlPath
actionDialog.title = currentItem.label
actionDialog.show()
}
var currentItem = machineActionRepeater.model[index]
actionDialog.loader.manager = currentItem
actionDialog.loader.source = currentItem.qmlPath
actionDialog.title = currentItem.label
actionDialog.show()
}
}
}
}
}
Item
{
UM.Dialog
{
id: actionDialog
@ -122,12 +91,6 @@ UM.ManagementPage
minimumHeight: UM.Theme.getSize("modal_window_minimum").height
maximumWidth: minimumWidth * 3
maximumHeight: minimumHeight * 3
rightButtons: Button
{
text: catalog.i18nc("@action:button", "Close")
iconName: "dialog-close"
onClicked: actionDialog.reject()
}
}
UM.I18nCatalog { id: catalog; name: "cura"; }
@ -136,8 +99,9 @@ UM.ManagementPage
{
id: confirmDialog
object: base.currentItem && base.currentItem.name ? base.currentItem.name : ""
text: base.currentItem ? base.currentItem.removalWarning : "";
onYes:
text: base.currentItem ? base.currentItem.removalWarning : ""
onAccepted:
{
Cura.MachineManager.removeMachine(base.currentItem.id)
if(!base.currentItem)
@ -149,20 +113,43 @@ UM.ManagementPage
}
}
UM.RenameDialog
Cura.RenameDialog
{
id: renameDialog;
object: base.currentItem && base.currentItem.name ? base.currentItem.name : "";
id: renameDialog
object: base.currentItem && base.currentItem.name ? base.currentItem.name : ""
property var machine_name_validator: Cura.MachineNameValidator { }
validName: renameDialog.newName.match(renameDialog.machine_name_validator.machineNameRegex) != null;
validName: renameDialog.newName.match(renameDialog.machine_name_validator.machineNameRegex) != null
onAccepted:
{
Cura.MachineManager.renameMachine(base.currentItem.id, newName.trim());
Cura.MachineManager.renameMachine(base.currentItem.id, newName.trim())
//Force updating currentItem and the details panel
objectList.onCurrentIndexChanged()
}
}
Cura.Menu
{
id: menu
Cura.MenuItem
{
text: catalog.i18nc("@action:button", "Activate")
enabled: base.currentItem != null && base.currentItem.id != Cura.MachineManager.activeMachine.id
onTriggered: Cura.MachineManager.setActiveMachine(base.currentItem.id)
}
Cura.MenuItem
{
text: catalog.i18nc("@action:button", "Remove")
enabled: base.currentItem != null && model.count > 1
onTriggered: confirmDialog.open()
}
Cura.MenuItem
{
text: catalog.i18nc("@action:button", "Rename")
enabled: base.currentItem != null && base.currentItem.metadata.group_name == null
onTriggered: renameDialog.open()
}
}
Connections
{
target: Cura.MachineManager
@ -172,6 +159,5 @@ UM.ManagementPage
objectList.onCurrentIndexChanged()
}
}
}
}

View file

@ -1,112 +1,60 @@
// Copyright (c) 2019 Ultimaker B.V.
// Copyright (c) 2022 Ultimaker B.V.
// Cura is released under the terms of the LGPLv3 or higher.
import QtQuick 2.7
import QtQuick.Controls 1.4
import QtQuick.Controls.Styles 1.4
import QtQuick.Layouts 1.3
import QtQuick.Dialogs 1.2
import UM 1.2 as UM
import UM 1.5 as UM
import Cura 1.0 as Cura
// An expandable list of materials. Includes both the header (this file) and the items (brandMaterialList)
Item
Column
{
id: brand_section
property var sectionName: ""
property string sectionName: ""
property var elementsModel // This can be a MaterialTypesModel or GenericMaterialsModel or FavoriteMaterialsModel
property var hasMaterialTypes: true // It indicates whether it has material types or not
property var expanded: materialList.expandedBrands.indexOf(sectionName) > -1
height: childrenRect.height
property bool hasMaterialTypes: true // It indicates whether it has material types or not
property bool expanded: materialList.expandedBrands.indexOf(sectionName) !== -1
width: parent.width
Rectangle
Cura.CategoryButton
{
id: brand_header_background
color:
{
if(!expanded && sectionName == materialList.currentBrand)
{
return UM.Theme.getColor("favorites_row_selected")
}
else
{
return UM.Theme.getColor("favorites_header_bar")
}
}
anchors.fill: brand_header
}
Row
{
id: brand_header
width: parent.width
Label
labelText: sectionName
height: UM.Theme.getSize("preferences_page_list_item").height
labelFont: UM.Theme.getFont("default_bold")
expanded: brand_section.expanded
onClicked:
{
id: brand_name
text: sectionName
height: UM.Theme.getSize("favorites_row").height
width: parent.width - UM.Theme.getSize("favorites_button").width
verticalAlignment: Text.AlignVCenter
leftPadding: (UM.Theme.getSize("default_margin").width / 2) | 0
}
Item
{
implicitWidth: UM.Theme.getSize("favorites_button").width
implicitHeight: UM.Theme.getSize("favorites_button").height
UM.RecolorImage
const i = materialList.expandedBrands.indexOf(sectionName);
if (i !== -1)
{
anchors
{
verticalCenter: parent.verticalCenter
horizontalCenter: parent.horizontalCenter
}
width: UM.Theme.getSize("standard_arrow").width
height: UM.Theme.getSize("standard_arrow").height
color: "black"
source: brand_section.expanded ? UM.Theme.getIcon("ChevronSingleDown") : UM.Theme.getIcon("ChevronSingleLeft")
}
}
}
MouseArea
{
anchors.fill: brand_header
onPressed:
{
const i = materialList.expandedBrands.indexOf(sectionName)
if (i > -1)
{
// Remove it
materialList.expandedBrands.splice(i, 1)
brand_section.expanded = false
materialList.expandedBrands.splice(i, 1); // remove
}
else
{
// Add it
materialList.expandedBrands.push(sectionName)
brand_section.expanded = true
materialList.expandedBrands.push(sectionName); // add
}
UM.Preferences.setValue("cura/expanded_brands", materialList.expandedBrands.join(";"));
}
}
Column
{
id: brandMaterialList
anchors.top: brand_header.bottom
width: parent.width
anchors.left: parent ? parent.left : undefined
height: brand_section.expanded ? childrenRect.height : 0
visible: brand_section.expanded
Repeater
{
model: elementsModel
delegate: Loader
{
id: loader
width: parent ? parent.width : 0
width: parent.width
property var element: model
sourceComponent: hasMaterialTypes ? materialsTypeSection : materialSlot
}
@ -119,6 +67,7 @@ Item
MaterialsTypeSection
{
materialType: element
indented: true
}
}
@ -141,7 +90,7 @@ Item
return;
}
expanded = materialList.expandedBrands.indexOf(sectionName) > -1
brand_section.expanded = materialList.expandedBrands.indexOf(sectionName) !== -1;
}
}
}

View file

@ -1,13 +1,11 @@
// Copyright (c) 2018 Ultimaker B.V.
// Copyright (c) 2022 Ultimaker B.V.
// Uranium is released under the terms of the LGPLv3 or higher.
import QtQuick 2.7
import QtQuick.Controls 1.4
import QtQuick.Layouts 1.3
import QtQuick.Dialogs 1.2
import QtQuick.Controls 2.4
import UM 1.2 as UM
import Cura 1.0 as Cura
import UM 1.5 as UM
import Cura 1.5 as Cura
Item
{
@ -52,71 +50,44 @@ Item
materialProperties.approximate_diameter = currentItem.approximate_diameter || "0"
}
Item
// Material detailed information view below the title Label
MaterialsView
{
id: materialDetailsView
anchors.fill: parent
editingEnabled: currentItem != null && !currentItem.is_read_only
onResetSelectedMaterial: base.resetExpandedActiveMaterial()
Item // Material title Label
{
id: profileName
width: parent.width
height: childrenRect.height
Label {
width: parent.width
text: materialProperties.name
font: UM.Theme.getFont("large_bold")
elide: Text.ElideRight
}
}
MaterialsView // Material detailed information view below the title Label
{
id: materialDetailsView
anchors
{
left: parent.left
right: parent.right
top: profileName.bottom
topMargin: UM.Theme.getSize("default_margin").height
bottom: parent.bottom
}
editingEnabled: currentItem != null && !currentItem.is_read_only
onResetSelectedMaterial: base.resetExpandedActiveMaterial()
properties: materialProperties
containerId: currentItem != null ? currentItem.id : ""
currentMaterialNode: currentItem.container_node
}
QtObject
{
id: materialProperties
property string guid: "00000000-0000-0000-0000-000000000000"
property string container_id: "Unknown";
property string name: "Unknown";
property string profile_type: "Unknown";
property string brand: "Unknown";
property string material: "Unknown"; // This needs to be named as "material" to be consistent with
// the material container's metadata entry
property string color_name: "Yellow";
property color color_code: "yellow";
property real density: 0.0;
property real diameter: 0.0;
property string approximate_diameter: "0";
property real spool_cost: 0.0;
property real spool_weight: 0.0;
property real spool_length: 0.0;
property real cost_per_meter: 0.0;
property string description: "";
property string adhesion_info: "";
}
properties: materialProperties
containerId: currentItem != null ? currentItem.id : ""
currentMaterialNode: currentItem != null ? currentItem.container_node: null
}
}
QtObject
{
id: materialProperties
property string guid: "00000000-0000-0000-0000-000000000000"
property string container_id: "Unknown";
property string name: "Unknown";
property string profile_type: "Unknown";
property string brand: "Unknown";
property string material: "Unknown"; // This needs to be named as "material" to be consistent with
// the material container's metadata entry
property string color_name: "Yellow";
property color color_code: "yellow";
property real density: 0.0;
property real diameter: 0.0;
property string approximate_diameter: "0";
property real spool_cost: 0.0;
property real spool_weight: 0.0;
property real spool_length: 0.0;
property real cost_per_meter: 0.0;
property string description: "";
property string adhesion_info: "";
}
}

View file

@ -1,11 +1,9 @@
// Copyright (c) 2019 Ultimaker B.V.
// Copyright (c) 2022 Ultimaker B.V.
// Uranium is released under the terms of the LGPLv3 or higher.
import QtQuick 2.7
import QtQuick.Controls 1.4
import QtQuick.Controls.Styles 1.4
import QtQuick.Layouts 1.3
import QtQuick.Dialogs 1.2
import UM 1.2 as UM
import Cura 1.0 as Cura
@ -16,7 +14,6 @@ Item
height: childrenRect.height
// Children
UM.I18nCatalog { id: catalog; name: "cura"; }
Cura.MaterialBrandsModel
{
id: materialsModel

View file

@ -1,15 +1,14 @@
// Copyright (c) 2021 Ultimaker B.V.
// Copyright (c) 2022 Ultimaker B.V.
// Cura is released under the terms of the LGPLv3 or higher.
import QtQuick 2.7
import QtQuick.Controls 1.4
import QtQuick.Layouts 1.3
import QtQuick.Controls 2.15
import QtQuick.Dialogs 1.2
import UM 1.2 as UM
import UM 1.5 as UM
import Cura 1.5 as Cura
Item
UM.ManagementPage
{
id: base
@ -36,12 +35,6 @@ Item
property var extruder_position: Cura.ExtruderManager.activeExtruderIndex
property var active_root_material_id: Cura.MachineManager.currentRootMaterialId[extruder_position]
UM.I18nCatalog
{
id: catalog
name: "cura"
}
function resetExpandedActiveMaterial()
{
materialListView.expandActiveMaterial(active_root_material_id)
@ -74,57 +67,15 @@ Item
}
}
// Main layout
Label
{
id: titleLabel
anchors
{
top: parent.top
left: parent.left
right: parent.right
margins: 5 * screenScaleFactor
}
font.pointSize: 18
text: catalog.i18nc("@title:tab", "Materials")
}
title: catalog.i18nc("@title:tab", "Materials")
detailsPlaneCaption: currentItem ? currentItem.name: ""
scrollviewCaption: catalog.i18nc("@label", "Materials compatible with active printer:") + `<br /><b>${Cura.MachineManager.activeMachine.name}</b>`
// Button Row
Row
{
id: buttonRow
anchors
{
left: parent.left
right: parent.right
top: titleLabel.bottom
}
height: childrenRect.height
// Activate button
Button
{
id: activateMenuButton
text: catalog.i18nc("@action:button", "Activate")
iconName: "list-activate"
enabled: !isCurrentItemActivated && Cura.MachineManager.activeMachine.hasMaterials
onClicked:
{
forceActiveFocus()
// Set the current material as the one to be activated (needed to force the UI update)
base.newRootMaterialIdToSwitchTo = base.currentItem.root_material_id
const extruder_position = Cura.ExtruderManager.activeExtruderIndex
Cura.MachineManager.setMaterial(extruder_position, base.currentItem.container_node)
}
}
// Create button
Button
buttons: [
Cura.SecondaryButton
{
id: createMenuButton
text: catalog.i18nc("@action:button", "Create")
iconName: "list-add"
text: catalog.i18nc("@action:button", "Create new")
enabled: Cura.MachineManager.activeMachine.hasMaterials
onClicked:
{
@ -132,72 +83,22 @@ Item
base.newRootMaterialIdToSwitchTo = base.materialManagementModel.createMaterial();
base.toActivateNewMaterial = true;
}
}
// Duplicate button
Button
{
id: duplicateMenuButton
text: catalog.i18nc("@action:button", "Duplicate");
iconName: "list-add"
enabled: base.hasCurrentItem
onClicked:
{
forceActiveFocus();
base.newRootMaterialIdToSwitchTo = base.materialManagementModel.duplicateMaterial(base.currentItem.container_node);
base.toActivateNewMaterial = true;
}
}
// Remove button
Button
{
id: removeMenuButton
text: catalog.i18nc("@action:button", "Remove")
iconName: "list-remove"
enabled: base.hasCurrentItem && !base.currentItem.is_read_only && !base.isCurrentItemActivated && base.materialManagementModel.canMaterialBeRemoved(base.currentItem.container_node)
onClicked:
{
forceActiveFocus();
confirmRemoveMaterialDialog.open();
}
}
// Import button
Button
},
Cura.SecondaryButton
{
id: importMenuButton
text: catalog.i18nc("@action:button", "Import")
iconName: "document-import"
onClicked:
{
forceActiveFocus();
importMaterialDialog.open();
}
enabled: Cura.MachineManager.activeMachine.hasMaterials
}
// Export button
Button
{
id: exportMenuButton
text: catalog.i18nc("@action:button", "Export")
iconName: "document-export"
onClicked:
{
forceActiveFocus();
exportMaterialDialog.open();
}
enabled: base.hasCurrentItem
}
//Sync button.
Button
},
Cura.SecondaryButton
{
id: syncMaterialsButton
text: catalog.i18nc("@action:button Sending materials to printers", "Sync with Printers")
iconName: "sync-synchronizing"
text: catalog.i18nc("@action:button", "Sync with Printers")
onClicked:
{
forceActiveFocus();
@ -205,185 +106,177 @@ Item
}
visible: Cura.MachineManager.activeMachine.supportsMaterialExport
}
]
onHamburgeButtonClicked: {
const hamburerButtonHeight = hamburger_button.height;
menu.popup(hamburger_button, -menu.width + hamburger_button.width / 2, hamburger_button.height);
// for some reason the height of the hamburger changes when opening the popup
// reset height to initial heigt
hamburger_button.height = hamburerButtonHeight;
}
listContent: ScrollView
{
id: materialScrollView
anchors.fill: parent
anchors.margins: parent.border.width
width: (parent.width * 0.4) | 0
clip: true
ScrollBar.vertical: UM.ScrollBar
{
id: materialScrollBar
parent: materialScrollView
anchors
{
top: parent.top
right: parent.right
bottom: parent.bottom
}
}
contentHeight: materialListView.height //For some reason, this is not determined automatically with this ScrollView. Very weird!
MaterialsList
{
id: materialListView
width: materialScrollView.width - materialScrollBar.width
}
}
Item {
id: contentsItem
anchors
{
top: titleLabel.bottom
left: parent.left
right: parent.right
bottom: parent.bottom
margins: 5 * screenScaleFactor
bottomMargin: 0
}
clip: true
MaterialsDetailsPanel
{
id: materialDetailsPanel
anchors.fill: parent
}
Item
{
anchors
Cura.Menu
{
top: buttonRow.bottom
topMargin: UM.Theme.getSize("default_margin").height
left: parent.left
right: parent.right
bottom: parent.bottom
}
SystemPalette { id: palette }
Label
{
id: captionLabel
anchors
id: menu
Cura.MenuItem
{
top: parent.top
left: parent.left
}
visible: text != ""
text:
{
var caption = catalog.i18nc("@action:label", "Printer") + ": " + Cura.MachineManager.activeMachine.name;
if (Cura.MachineManager.activeMachine.hasVariants)
id: activateMenuButton
text: catalog.i18nc("@action:button", "Activate")
onClicked:
{
var activeVariantName = ""
if(Cura.MachineManager.activeStack != null)
{
activeVariantName = Cura.MachineManager.activeStack.variant.name
}
caption += ", " + Cura.MachineManager.activeDefinitionVariantsName + ": " + activeVariantName;
forceActiveFocus()
// Set the current material as the one to be activated (needed to force the UI update)
base.newRootMaterialIdToSwitchTo = base.currentItem.root_material_id
const extruder_position = Cura.ExtruderManager.activeExtruderIndex
Cura.MachineManager.setMaterial(extruder_position, base.currentItem.container_node)
}
return caption;
}
width: materialScrollView.width
elide: Text.ElideRight
}
ScrollView
{
id: materialScrollView
anchors
Cura.MenuItem
{
top: captionLabel.visible ? captionLabel.bottom : parent.top
topMargin: captionLabel.visible ? UM.Theme.getSize("default_margin").height : 0
bottom: parent.bottom
left: parent.left
id: duplicateMenuButton
text: catalog.i18nc("@action:button", "Duplicate");
enabled: base.hasCurrentItem
onClicked:
{
forceActiveFocus();
base.newRootMaterialIdToSwitchTo = base.materialManagementModel.duplicateMaterial(base.currentItem.container_node);
base.toActivateNewMaterial = true;
}
}
Rectangle
Cura.MenuItem
{
parent: viewport
anchors.fill: parent
color: palette.light
id: removeMenuButton
text: catalog.i18nc("@action:button", "Remove")
enabled: base.hasCurrentItem && !base.currentItem.is_read_only && !base.isCurrentItemActivated && base.materialManagementModel.canMaterialBeRemoved(base.currentItem.container_node)
onClicked:
{
forceActiveFocus();
confirmRemoveMaterialDialog.open();
}
}
width: (parent.width * 0.4) | 0
frameVisible: true
horizontalScrollBarPolicy: Qt.ScrollBarAlwaysOff
MaterialsList
Cura.MenuItem
{
id: materialListView
width: materialScrollView.viewport.width
id: exportMenuButton
text: catalog.i18nc("@action:button", "Export")
onClicked:
{
forceActiveFocus();
exportMaterialDialog.open();
}
enabled: base.hasCurrentItem
}
}
MaterialsDetailsPanel
// Dialogs
Cura.MessageDialog
{
id: materialDetailsPanel
anchors
id: confirmRemoveMaterialDialog
title: catalog.i18nc("@title:window", "Confirm Remove")
property string materialName: base.currentItem !== null ? base.currentItem.name : ""
text: catalog.i18nc("@label (%1 is object name)", "Are you sure you wish to remove %1? This cannot be undone!").arg(materialName)
standardButtons: Dialog.Yes | Dialog.No
onAccepted:
{
left: materialScrollView.right
leftMargin: UM.Theme.getSize("default_margin").width
top: parent.top
bottom: parent.bottom
right: parent.right
// Set the active material as the fallback. It will be selected when the current material is deleted
base.newRootMaterialIdToSwitchTo = base.active_root_material_id
base.materialManagementModel.removeMaterial(base.currentItem.container_node);
}
}
}
// Dialogs
MessageDialog
{
id: confirmRemoveMaterialDialog
icon: StandardIcon.Question;
title: catalog.i18nc("@title:window", "Confirm Remove")
property string materialName: base.currentItem !== null ? base.currentItem.name : ""
text: catalog.i18nc("@label (%1 is object name)", "Are you sure you wish to remove %1? This cannot be undone!").arg(materialName)
standardButtons: StandardButton.Yes | StandardButton.No
modality: Qt.ApplicationModal
onYes:
FileDialog
{
// Set the active material as the fallback. It will be selected when the current material is deleted
base.newRootMaterialIdToSwitchTo = base.active_root_material_id
base.materialManagementModel.removeMaterial(base.currentItem.container_node);
}
}
FileDialog
{
id: importMaterialDialog
title: catalog.i18nc("@title:window", "Import Material")
selectExisting: true
nameFilters: Cura.ContainerManager.getContainerNameFilters("material")
folder: CuraApplication.getDefaultPath("dialog_material_path")
onAccepted:
{
var result = Cura.ContainerManager.importMaterialContainer(fileUrl);
messageDialog.title = catalog.i18nc("@title:window", "Import Material");
messageDialog.text = catalog.i18nc("@info:status Don't translate the XML tags <filename> or <message>!", "Could not import material <filename>%1</filename>: <message>%2</message>").arg(fileUrl).arg(result.message);
if (result.status == "success")
id: importMaterialDialog
title: catalog.i18nc("@title:window", "Import Material")
selectExisting: true
nameFilters: Cura.ContainerManager.getContainerNameFilters("material")
folder: CuraApplication.getDefaultPath("dialog_material_path")
onAccepted:
{
messageDialog.icon = StandardIcon.Information;
messageDialog.text = catalog.i18nc("@info:status Don't translate the XML tag <filename>!", "Successfully imported material <filename>%1</filename>").arg(fileUrl);
}
else if (result.status == "duplicate")
{
messageDialog.icon = StandardIcon.Warning;
}
else
{
messageDialog.icon = StandardIcon.Critical;
}
messageDialog.open();
CuraApplication.setDefaultPath("dialog_material_path", folder);
}
}
const result = Cura.ContainerManager.importMaterialContainer(fileUrl);
FileDialog
{
id: exportMaterialDialog
title: catalog.i18nc("@title:window", "Export Material")
selectExisting: false
nameFilters: Cura.ContainerManager.getContainerNameFilters("material")
folder: CuraApplication.getDefaultPath("dialog_material_path")
onAccepted:
{
var result = Cura.ContainerManager.exportContainer(base.currentItem.root_material_id, selectedNameFilter, fileUrl);
messageDialog.title = catalog.i18nc("@title:window", "Export Material");
if (result.status == "error")
{
messageDialog.icon = StandardIcon.Critical;
messageDialog.text = catalog.i18nc("@info:status Don't translate the XML tags <filename> and <message>!", "Failed to export material to <filename>%1</filename>: <message>%2</message>").arg(fileUrl).arg(result.message);
const messageDialog = Qt.createQmlObject("import Cura 1.5 as Cura; Cura.MessageDialog { onClosed: destroy() }", base);
messageDialog.standardButtons = Dialog.Ok;
messageDialog.title = catalog.i18nc("@title:window", "Import Material");
switch (result.status)
{
case "success":
messageDialog.text = catalog.i18nc("@info:status Don't translate the XML tag <filename>!", "Successfully imported material <filename>%1</filename>").arg(fileUrl);
break;
default:
messageDialog.text = catalog.i18nc("@info:status Don't translate the XML tags <filename> or <message>!", "Could not import material <filename>%1</filename>: <message>%2</message>").arg(fileUrl).arg(result.message);
break;
}
messageDialog.open();
CuraApplication.setDefaultPath("dialog_material_path", folder);
}
else if (result.status == "success")
{
messageDialog.icon = StandardIcon.Information;
messageDialog.text = catalog.i18nc("@info:status Don't translate the XML tag <filename>!", "Successfully exported material to <filename>%1</filename>").arg(result.path);
messageDialog.open();
}
CuraApplication.setDefaultPath("dialog_material_path", folder);
}
}
MessageDialog
{
id: messageDialog
FileDialog
{
id: exportMaterialDialog
title: catalog.i18nc("@title:window", "Export Material")
selectExisting: false
nameFilters: Cura.ContainerManager.getContainerNameFilters("material")
folder: CuraApplication.getDefaultPath("dialog_material_path")
onAccepted:
{
const result = Cura.ContainerManager.exportContainer(base.currentItem.root_material_id, selectedNameFilter, fileUrl);
const messageDialog = Qt.createQmlObject("import Cura 1.5 as Cura; Cura.MessageDialog { onClosed: destroy() }", base);
messageDialog.title = catalog.i18nc("@title:window", "Export Material");
messageDialog.standardButtons = Dialog.Ok;
switch (result.status)
{
case "error":
messageDialog.text = catalog.i18nc("@info:status Don't translate the XML tags <filename> and <message>!", "Failed to export material to <filename>%1</filename>: <message>%2</message>").arg(fileUrl).arg(result.message);
break;
case "success":
messageDialog.text = catalog.i18nc("@info:status Don't translate the XML tag <filename>!", "Successfully exported material to <filename>%1</filename>").arg(result.path);
break;
}
messageDialog.open();
CuraApplication.setDefaultPath("dialog_material_path", folder);
}
}
}
}

View file

@ -1,128 +1,138 @@
// Copyright (c) 2018 Ultimaker B.V.
// Copyright (c) 2022 Ultimaker B.V.
// Cura is released under the terms of the LGPLv3 or higher.
import QtQuick 2.7
import QtQuick.Controls 1.4
import QtQuick.Controls.Styles 1.4
import QtQuick.Controls 2.1
import QtQuick.Layouts 1.3
import QtQuick.Dialogs 1.2
import UM 1.2 as UM
import Cura 1.0 as Cura
import UM 1.5 as UM
import Cura 1.5 as Cura
// A single material row, typically used in a MaterialsBrandSection
Rectangle
{
id: materialSlot
property var material: null
property var hovered: false
property var is_favorite: material != null && material.is_favorite
height: UM.Theme.getSize("favorites_row").height
property var material: null
property bool hovered: false
property bool isActive: material != null && Cura.MachineManager.currentRootMaterialId[Cura.ExtruderManager.activeExtruderIndex] == material.root_material_id
height: UM.Theme.getSize("preferences_page_list_item").height
width: parent.width
//color: material != null ? (base.currentItem.root_material_id == material.root_material_id ? UM.Theme.getColor("favorites_row_selected") : "transparent") : "transparent"
color:
{
if(material !== null && base.currentItem !== null)
color: UM.Theme.getColor("main_background")
states:
[
State
{
if(base.currentItem.root_material_id === material.root_material_id)
{
return UM.Theme.getColor("favorites_row_selected")
}
name: "selected"
when: material !== null && base.currentItem !== null && base.currentItem.root_material_id === material.root_material_id
PropertyChanges { target: materialSlot; color: UM.Theme.getColor("background_3") }
},
State
{
name: "hovered"
when: hovered
PropertyChanges { target: materialSlot; color: UM.Theme.getColor("background_3") }
}
return "transparent"
}
]
Rectangle
{
id: swatch
color: material != null ? material.color_code : "transparent"
border.width: UM.Theme.getSize("default_lining").width
border.color: "black"
width: UM.Theme.getSize("favorites_button_icon").width
height: UM.Theme.getSize("favorites_button_icon").height
width: UM.Theme.getSize("icon_indicator").width
height: UM.Theme.getSize("icon_indicator").height
radius: width / 2
anchors.verticalCenter: materialSlot.verticalCenter
anchors.left: materialSlot.left
anchors.leftMargin: UM.Theme.getSize("default_margin").width
anchors.leftMargin: 2 * UM.Theme.getSize("default_margin").width
}
Label
UM.Label
{
text: material != null ? material.brand + " " + material.name : ""
id: materialLabel
text: material != null ? `${material.brand} ${material.name}` : ""
font: isActive ? UM.Theme.getFont("default_italic") : UM.Theme.getFont("default")
elide: Text.ElideRight
wrapMode: Text.NoWrap
verticalAlignment: Text.AlignVCenter
height: parent.height
anchors.left: swatch.right
anchors.right: favoriteButton.left
anchors.leftMargin: UM.Theme.getSize("default_margin").width
anchors.rightMargin: UM.Theme.getSize("narrow_margin").width
anchors.verticalCenter: materialSlot.verticalCenter
anchors.leftMargin: UM.Theme.getSize("narrow_margin").width
font.italic: material != null && Cura.MachineManager.currentRootMaterialId[Cura.ExtruderManager.activeExtruderIndex] == material.root_material_id
}
MouseArea
UM.TooltipArea
{
anchors.fill: parent
text: material != null ? `${material.brand} ${material.name}` : ""
acceptedButtons: Qt.LeftButton
onClicked:
{
materialList.currentBrand = material.brand
materialList.currentType = material.brand + "_" + material.material
base.setExpandedActiveMaterial(material.root_material_id)
materialList.currentBrand = material.brand;
materialList.currentType = `${material.brand}_${material.material}`;
base.setExpandedActiveMaterial(material.root_material_id);
}
hoverEnabled: true
onEntered: { materialSlot.hovered = true }
onExited: { materialSlot.hovered = false }
}
Button
Item
{
id: favorite_button
text: ""
implicitWidth: UM.Theme.getSize("favorites_button").width
implicitHeight: UM.Theme.getSize("favorites_button").height
visible: materialSlot.hovered || materialSlot.is_favorite || favorite_button.hovered
anchors
{
right: materialSlot.right
verticalCenter: materialSlot.verticalCenter
}
onClicked:
{
if (materialSlot.is_favorite)
id: favoriteButton
states:
[
State
{
CuraApplication.getMaterialManagementModel().removeFavorite(material.root_material_id)
}
else
name: "favorite"
when: material !== null && material.is_favorite
PropertyChanges { target: favoriteIndicator; source: UM.Theme.getIcon("StarFilled");}
PropertyChanges { target: favoriteButton; visible: true }
},
State
{
CuraApplication.getMaterialManagementModel().addFavorite(material.root_material_id)
name: "hovered"
when: hovered
PropertyChanges { target: favoriteButton; visible: true }
}
}
style: ButtonStyle
{
background: Item { }
}
]
implicitHeight: parent.height
implicitWidth: height
anchors.right: materialSlot.right
visible: false
UM.RecolorImage
{
anchors
id: favoriteIndicator
anchors.centerIn: parent
width: UM.Theme.getSize("small_button_icon").width
height: UM.Theme.getSize("small_button_icon").height
color: UM.Theme.getColor("primary")
source: UM.Theme.getIcon("Star")
}
MouseArea
{
anchors.fill: parent
onClicked:
{
verticalCenter: favorite_button.verticalCenter
horizontalCenter: favorite_button.horizontalCenter
}
width: UM.Theme.getSize("favorites_button_icon").width
height: UM.Theme.getSize("favorites_button_icon").height
color:
{
if (favorite_button.hovered)
if (material !== null)
{
return UM.Theme.getColor("primary_hover")
}
else
{
if (materialSlot.is_favorite)
if (material.is_favorite)
{
return UM.Theme.getColor("primary")
CuraApplication.getMaterialManagementModel().removeFavorite(material.root_material_id)
}
else
{
UM.Theme.getColor("text_inactive")
CuraApplication.getMaterialManagementModel().addFavorite(material.root_material_id)
}
}
}
source: materialSlot.is_favorite ? UM.Theme.getIcon("StarFilled") : UM.Theme.getIcon("Star")
}
}
}

View file

@ -1,4 +1,4 @@
//Copyright (c) 2021 Ultimaker B.V.
//Copyright (c) 2022 Ultimaker B.V.
//Cura is released under the terms of the LGPLv3 or higher.
import QtQuick 2.15
@ -7,7 +7,7 @@ import QtQuick.Dialogs 1.2
import QtQuick.Layouts 1.15
import QtQuick.Window 2.1
import Cura 1.1 as Cura
import UM 1.4 as UM
import UM 1.5 as UM
Window
{
@ -20,6 +20,7 @@ Window
width: minimumWidth
height: minimumHeight
modality: Qt.ApplicationModal
color: UM.Theme.getColor("main_background")
property variant syncModel
property alias pageIndex: swipeView.currentIndex
@ -32,82 +33,78 @@ Window
anchors.fill: parent
interactive: false
Rectangle
Item
{
id: introPage
color: UM.Theme.getColor("main_background")
Column
ColumnLayout
{
spacing: UM.Theme.getSize("default_margin").height
anchors.fill: parent
anchors.margins: UM.Theme.getSize("default_margin").width
Label
UM.Label
{
text: catalog.i18nc("@title:header", "Sync materials with printers")
font: UM.Theme.getFont("large_bold")
color: UM.Theme.getColor("text")
Layout.fillWidth: true
}
Label
UM.Label
{
text: catalog.i18nc("@text", "Following a few simple steps, you will be able to synchronize all your material profiles with your printers.")
font: UM.Theme.getFont("medium")
color: UM.Theme.getColor("text")
wrapMode: Text.Wrap
width: parent.width
Layout.fillWidth: true
}
Image
{
Layout.fillWidth: true
Layout.fillHeight: true
source: UM.Theme.getImage("material_ecosystem")
width: parent.width
fillMode: Image.PreserveAspectFit
sourceSize.width: width
}
}
Cura.PrimaryButton
{
id: startButton
anchors
Item
{
right: parent.right
rightMargin: UM.Theme.getSize("default_margin").width
bottom: parent.bottom
bottomMargin: UM.Theme.getSize("default_margin").height
}
text: catalog.i18nc("@button", "Start")
onClicked:
{
if(Cura.API.account.isLoggedIn)
Layout.preferredHeight: childrenRect.height
Layout.alignment: Qt.AlignBottom
Layout.fillWidth: true
Cura.TertiaryButton
{
swipeView.currentIndex += 2; //Skip sign in page.
text: catalog.i18nc("@button", "Why do I need to sync material profiles?")
iconSource: UM.Theme.getIcon("LinkExternal")
isIconOnRightSide: true
onClicked: Qt.openUrlExternally("https://support.ultimaker.com/hc/en-us/articles/360013137919?utm_source=cura&utm_medium=software&utm_campaign=sync-material-printer-why")
}
else
Cura.PrimaryButton
{
swipeView.currentIndex += 1;
anchors.right: parent.right
text: catalog.i18nc("@button", "Start")
onClicked:
{
if(Cura.API.account.isLoggedIn)
{
swipeView.currentIndex += 2; //Skip sign in page.
}
else
{
swipeView.currentIndex += 1;
}
}
}
}
}
Cura.TertiaryButton
{
anchors
{
left: parent.left
leftMargin: UM.Theme.getSize("default_margin").width
verticalCenter: startButton.verticalCenter
}
text: catalog.i18nc("@button", "Why do I need to sync material profiles?")
iconSource: UM.Theme.getIcon("LinkExternal")
isIconOnRightSide: true
onClicked: Qt.openUrlExternally("https://support.ultimaker.com/hc/en-us/articles/360013137919?utm_source=cura&utm_medium=software&utm_campaign=sync-material-printer-why")
}
}
Rectangle
Item
{
id: signinPage
color: UM.Theme.getColor("main_background")
Connections //While this page is active, continue to the next page if the user logs in.
// While this page is active, continue to the next page if the user logs in.
Connections
{
target: Cura.API.account
function onLoginStateChanged(is_logged_in)
@ -125,40 +122,35 @@ Window
anchors.fill: parent
anchors.margins: UM.Theme.getSize("default_margin").width
Label
UM.Label
{
text: catalog.i18nc("@title:header", "Sign in")
font: UM.Theme.getFont("large_bold")
color: UM.Theme.getColor("text")
Layout.preferredHeight: height
Layout.fillWidth: true
}
Label
UM.Label
{
text: catalog.i18nc("@text", "To automatically sync the material profiles with all your printers connected to Digital Factory you need to be signed in in Cura.")
font: UM.Theme.getFont("medium")
color: UM.Theme.getColor("text")
wrapMode: Text.Wrap
width: parent.width
Layout.maximumWidth: width
Layout.preferredHeight: height
Layout.fillWidth: true
}
Item
Image
{
Layout.preferredWidth: parent.width
Layout.alignment: Qt.AlignCenter
Layout.preferredWidth: parent.width / 2
source: UM.Theme.getImage("first_run_ultimaker_cloud")
Layout.fillHeight: true
Image
{
source: UM.Theme.getImage("first_run_ultimaker_cloud")
width: parent.width / 2
sourceSize.width: width
anchors.centerIn: parent
}
sourceSize.width: width
fillMode: Image.PreserveAspectFit
}
Item
{
width: parent.width
height: childrenRect.height
Layout.preferredHeight: height
Layout.preferredHeight: childrenRect.height
Layout.alignment: Qt.AlignBottom
Layout.fillWidth: true
Cura.SecondaryButton
{
anchors.left: parent.left
@ -175,10 +167,9 @@ Window
}
}
Rectangle
Item
{
id: printerListPage
color: UM.Theme.getColor("main_background")
ColumnLayout
{
@ -189,7 +180,6 @@ Window
Row
{
Layout.preferredHeight: childrenRect.height
spacing: UM.Theme.getSize("default_margin").width
states: [
@ -220,244 +210,225 @@ Window
{
id: printerListHeaderIcon
width: UM.Theme.getSize("section_icon").width
height: width
height: UM.Theme.getSize("section_icon").height
anchors.verticalCenter: parent.verticalCenter
}
Label
UM.Label
{
id: printerListHeader
anchors.verticalCenter: parent.verticalCenter
//Text is always defined by the states above.
font: UM.Theme.getFont("large_bold")
color: UM.Theme.getColor("text")
}
}
Row
{
Layout.preferredWidth: parent.width
Layout.fillWidth: true
Layout.preferredHeight: childrenRect.height
Label
UM.Label
{
id: syncStatusLabel
width: parent.width - UM.Theme.getSize("default_margin").width - troubleshootingLink.width
anchors.left: parent.left
wrapMode: Text.Wrap
elide: Text.ElideRight
visible: text !== ""
text: ""
color: UM.Theme.getColor("text")
font: UM.Theme.getFont("medium")
}
Cura.TertiaryButton
{
id: troubleshootingLink
anchors.right: parent.right
text: catalog.i18nc("@button", "Troubleshooting")
visible: typeof syncModel !== "undefined" && syncModel.exportUploadStatus == "error"
iconSource: UM.Theme.getIcon("LinkExternal")
onClicked: Qt.openUrlExternally("https://support.ultimaker.com/hc/en-us/articles/360012019239?utm_source=cura&utm_medium=software&utm_campaign=sync-material-wizard-troubleshoot-cloud-printer")
}
}
ScrollView
ListView
{
id: printerListScrollView
width: parent.width
Layout.preferredWidth: width
id: printerList
Layout.fillWidth: true
Layout.fillHeight: true
clip: true
ScrollBar.horizontal.policy: ScrollBar.AlwaysOff
ListView
ScrollBar.vertical: UM.ScrollBar
{
id: printerList
width: parent.width
spacing: UM.Theme.getSize("default_margin").height
id: printerListScrollBar
}
spacing: UM.Theme.getSize("default_margin").height
model: cloudPrinterList
delegate: Rectangle
model: cloudPrinterList
delegate: Rectangle
{
id: delegateContainer
color: "transparent"
border.color: UM.Theme.getColor("lining")
border.width: UM.Theme.getSize("default_lining").width
width: printerList.width - printerListScrollBar.width
height: UM.Theme.getSize("machine_selector_icon").height + 2 * UM.Theme.getSize("default_margin").height
property string syncStatus:
{
id: delegateContainer
color: "transparent"
border.color: UM.Theme.getColor("lining")
border.width: UM.Theme.getSize("default_lining").width
width: printerListScrollView.width
height: UM.Theme.getSize("card").height
property string syncStatus:
var printer_id = model.metadata["host_guid"]
if(syncModel.printerStatus[printer_id] === undefined) //No status information available. Could be added after we started syncing.
{
var printer_id = model.metadata["host_guid"]
if(syncModel.printerStatus[printer_id] === undefined) //No status information available. Could be added after we started syncing.
{
return "idle";
}
return syncModel.printerStatus[printer_id];
return "idle";
}
return syncModel.printerStatus[printer_id];
}
Cura.IconWithText
{
anchors
{
verticalCenter: parent.verticalCenter
left: parent.left
leftMargin: Math.round(parent.height - height) / 2 //Equal margin on the left as above and below.
right: parent.right
rightMargin: Math.round(parent.height - height) / 2
}
Cura.IconWithText
{
anchors
{
verticalCenter: parent.verticalCenter
left: parent.left
leftMargin: Math.round(parent.height - height) / 2 //Equal margin on the left as above and below.
right: parent.right
rightMargin: Math.round(parent.height - height) / 2
}
text: model.name
font: UM.Theme.getFont("medium")
text: model.name
font: UM.Theme.getFont("medium")
source: UM.Theme.getIcon("Printer", "medium")
iconColor: UM.Theme.getColor("machine_selector_printer_icon")
iconSize: UM.Theme.getSize("machine_selector_icon").width
//Printer status badge (always cloud, but whether it's online or offline).
UM.RecolorImage
{
width: UM.Theme.getSize("printer_status_icon").width
height: UM.Theme.getSize("printer_status_icon").height
anchors
{
bottom: parent.bottom
bottomMargin: -Math.round(height / 6)
left: parent.left
leftMargin: parent.iconSize - Math.round(width * 5 / 6)
}
source: UM.Theme.getIcon("CloudBadge", "low")
color: UM.Theme.getColor("primary")
//Make a themeable circle in the background so we can change it in other themes.
Rectangle
{
anchors.centerIn: parent
width: parent.width - 1.5 //1.5 pixels smaller (at least sqrt(2), regardless of pixel scale) so that the circle doesn't show up behind the icon due to anti-aliasing.
height: parent.height - 1.5
radius: width / 2
color: UM.Theme.getColor("connection_badge_background")
z: parent.z - 1
}
}
}
source: UM.Theme.getIcon("Printer", "medium")
iconColor: UM.Theme.getColor("machine_selector_printer_icon")
iconSize: UM.Theme.getSize("machine_selector_icon").width
//Printer status badge (always cloud, but whether it's online or offline).
UM.RecolorImage
{
id: printerSpinner
width: UM.Theme.getSize("section_icon").width
height: width
anchors.verticalCenter: parent.verticalCenter
anchors.right: parent.right
anchors.rightMargin: Math.round((parent.height - height) / 2) //Same margin on the right as above and below.
width: UM.Theme.getSize("printer_status_icon").width
height: UM.Theme.getSize("printer_status_icon").height
anchors
{
bottom: parent.bottom
bottomMargin: -Math.round(height / 6)
left: parent.left
leftMargin: parent.iconSize - Math.round(width * 5 / 6)
}
visible: delegateContainer.syncStatus === "uploading"
source: UM.Theme.getIcon("ArrowDoubleCircleRight")
source: UM.Theme.getIcon("CloudBadge", "low")
color: UM.Theme.getColor("primary")
RotationAnimator
//Make a themeable circle in the background so we can change it in other themes.
Rectangle
{
target: printerSpinner
from: 0
to: 360
duration: 1000
loops: Animation.Infinite
running: true
anchors.centerIn: parent
width: parent.width - 1.5 //1.5 pixels smaller (at least sqrt(2), regardless of pixel scale) so that the circle doesn't show up behind the icon due to anti-aliasing.
height: parent.height - 1.5
radius: width / 2
color: UM.Theme.getColor("connection_badge_background")
z: parent.z - 1
}
}
UM.StatusIcon
{
width: UM.Theme.getSize("section_icon").width
height: width
anchors.verticalCenter: parent.verticalCenter
anchors.right: parent.right
anchors.rightMargin: Math.round((parent.height - height) / 2) //Same margin on the right as above and below.
visible: delegateContainer.syncStatus === "failed" || delegateContainer.syncStatus === "success"
status: delegateContainer.syncStatus === "success" ? UM.StatusIcon.Status.POSITIVE : UM.StatusIcon.Status.ERROR
}
}
footer: Item
UM.RecolorImage
{
width: printerListScrollView.width
height: {
if(!visible)
{
return 0;
}
let h = UM.Theme.getSize("card").height + printerListTroubleshooting.height + UM.Theme.getSize("default_margin").height * 2; //1 margin between content and footer, 1 for troubleshooting link.
return h;
}
visible: includeOfflinePrinterList.count - cloudPrinterList.count > 0 && typeof syncModel !== "undefined" && syncModel.exportUploadStatus === "idle"
Rectangle
id: printerSpinner
width: UM.Theme.getSize("section_icon").width
height: width
anchors.verticalCenter: parent.verticalCenter
anchors.right: parent.right
anchors.rightMargin: Math.round((parent.height - height) / 2) //Same margin on the right as above and below.
visible: delegateContainer.syncStatus === "uploading"
source: UM.Theme.getIcon("ArrowDoubleCircleRight")
color: UM.Theme.getColor("primary")
RotationAnimator
{
anchors.fill: parent
anchors.topMargin: UM.Theme.getSize("default_margin").height
target: printerSpinner
from: 0
to: 360
duration: 1000
loops: Animation.Infinite
running: true
}
}
UM.StatusIcon
{
width: UM.Theme.getSize("section_icon").width
height: width
anchors.verticalCenter: parent.verticalCenter
anchors.right: parent.right
anchors.rightMargin: Math.round((parent.height - height) / 2) //Same margin on the right as above and below.
border.color: UM.Theme.getColor("lining")
border.width: UM.Theme.getSize("default_lining").width
color: "transparent"
visible: delegateContainer.syncStatus === "failed" || delegateContainer.syncStatus === "success"
status: delegateContainer.syncStatus === "success" ? UM.StatusIcon.Status.POSITIVE : UM.StatusIcon.Status.ERROR
}
}
Row
footer: Item
{
width: printerList.width - printerListScrollBar.width
height: childrenRect.height + UM.Theme.getSize("default_margin").height
visible: includeOfflinePrinterList.count - cloudPrinterList.count > 0 && typeof syncModel !== "undefined" && syncModel.exportUploadStatus === "idle"
Rectangle
{
anchors.top: parent.top
anchors.left: parent.left
anchors.right: parent.right
border.color: UM.Theme.getColor("lining")
border.width: UM.Theme.getSize("default_lining").width
anchors.topMargin: UM.Theme.getSize("default_margin").height
height: childrenRect.height + 2 * UM.Theme.getSize("thick_margin").height
color: "transparent"
GridLayout
{
columns: 3
rows: 2
anchors.top: parent.top
anchors.left: parent.left
anchors.right: parent.right
anchors.leftMargin: UM.Theme.getSize("thick_margin").width
anchors.rightMargin: UM.Theme.getSize("thick_margin").width
anchors.topMargin: UM.Theme.getSize("thick_margin").height
anchors.bottomMargin: UM.Theme.getSize("thick_margin").height
columnSpacing: UM.Theme.getSize("default_margin").width
rowSpacing: UM.Theme.getSize("default_margin").height
UM.StatusIcon
{
anchors
{
fill: parent
margins: Math.round(UM.Theme.getSize("card").height - UM.Theme.getSize("machine_selector_icon").width) / 2 //Same margin as in other cards.
}
spacing: UM.Theme.getSize("default_margin").width
Layout.preferredWidth: UM.Theme.getSize("section_icon").width
Layout.preferredHeight: UM.Theme.getSize("section_icon").height
status: UM.StatusIcon.Status.WARNING
}
UM.StatusIcon
{
id: infoIcon
width: UM.Theme.getSize("section_icon").width
height: width
//Fake anchor.verticalCenter: printersMissingText.verticalCenter, since we can't anchor to things that aren't siblings.
anchors.top: parent.top
anchors.topMargin: Math.round(printersMissingText.height / 2 - height / 2)
UM.Label
{
Layout.fillWidth: true
Layout.alignment: Qt.AlignVCenter
text: catalog.i18nc("@text Asking the user whether printers are missing in a list.", "Printers missing?")
+ "\n"
+ catalog.i18nc("@text", "Make sure all your printers are turned ON and connected to Digital Factory.")
font: UM.Theme.getFont("medium")
elide: Text.ElideRight
}
status: UM.StatusIcon.Status.WARNING
}
Cura.SecondaryButton
{
id: refreshListButton
Layout.alignment: Qt.AlignVCenter
text: catalog.i18nc("@button", "Refresh List")
iconSource: UM.Theme.getIcon("ArrowDoubleCircleRight")
onClicked: Cura.API.account.sync(true)
}
Column
{
//Fill the total width. Can't use layouts because we need the anchors for vertical alignment.
width: parent.width - infoIcon.width - refreshListButton.width - parent.spacing * 2
spacing: UM.Theme.getSize("default_margin").height
Label
{
id: printersMissingText
text: catalog.i18nc("@text Asking the user whether printers are missing in a list.", "Printers missing?")
+ "\n"
+ catalog.i18nc("@text", "Make sure all your printers are turned ON and connected to Digital Factory.")
font: UM.Theme.getFont("medium")
color: UM.Theme.getColor("text")
elide: Text.ElideRight
}
Cura.TertiaryButton
{
id: printerListTroubleshooting
leftPadding: 0 //Want to visually align this to the text.
text: catalog.i18nc("@button", "Troubleshooting")
iconSource: UM.Theme.getIcon("LinkExternal")
onClicked: Qt.openUrlExternally("https://support.ultimaker.com/hc/en-us/articles/360012019239?utm_source=cura&utm_medium=software&utm_campaign=sync-material-wizard-troubleshoot-cloud-printer")
}
}
Cura.SecondaryButton
{
id: refreshListButton
//Fake anchor.verticalCenter: printersMissingText.verticalCenter, since we can't anchor to things that aren't siblings.
anchors.top: parent.top
anchors.topMargin: Math.round(printersMissingText.height / 2 - height / 2)
text: catalog.i18nc("@button", "Refresh List")
iconSource: UM.Theme.getIcon("ArrowDoubleCircleRight")
onClicked: Cura.API.account.sync(true)
}
Cura.TertiaryButton
{
id: printerListTroubleshooting
Layout.column: 1
Layout.row: 1
Layout.fillWidth: true
leftPadding: 0
text: catalog.i18nc("@button", "Troubleshooting")
iconSource: UM.Theme.getIcon("LinkExternal")
onClicked: Qt.openUrlExternally("https://support.ultimaker.com/hc/en-us/articles/360012019239?utm_source=cura&utm_medium=software&utm_campaign=sync-material-wizard-troubleshoot-cloud-printer")
}
}
}
@ -465,10 +436,9 @@ Window
}
Item
{
width: parent.width
height: childrenRect.height
Layout.preferredWidth: width
Layout.preferredHeight: height
Layout.fillWidth: true
Layout.preferredHeight: childrenRect.height
Layout.alignment: Qt.AlignBottom
Cura.SecondaryButton
{
@ -540,7 +510,7 @@ Window
running: true
}
}
Label
UM.Label
{
id: syncingLabel
anchors.left: syncingIcon.right
@ -554,56 +524,62 @@ Window
}
}
ColumnLayout //Placeholder for when the user has no cloud printers.
// Placeholder for when the user has no cloud printers.
ColumnLayout
{
spacing: UM.Theme.getSize("default_margin").height
anchors.fill: parent
anchors.margins: UM.Theme.getSize("default_margin").width
visible: cloudPrinterList.count == 0
Label
UM.Label
{
text: catalog.i18nc("@title:header", "No printers found")
font: UM.Theme.getFont("large_bold")
color: UM.Theme.getColor("text")
Layout.preferredWidth: width
Layout.preferredHeight: height
}
Image
{
source: UM.Theme.getImage("3d_printer_faded")
sourceSize.width: width
fillMode: Image.PreserveAspectFit
Layout.alignment: Qt.AlignHCenter
Layout.preferredWidth: parent.width / 3
}
Label
{
text: catalog.i18nc("@text", "It seems like you don't have any compatible printers connected to Digital Factory. Make sure your printer is connected and it's running the latest firmware.")
width: parent.width
horizontalAlignment: Text.AlignHCenter
wrapMode: Text.Wrap
Layout.preferredWidth: width
Layout.preferredHeight: height
Layout.fillWidth: true
}
Item
{
Layout.preferredWidth: parent.width
Layout.fillWidth: true
Layout.fillHeight: true
Image
{
anchors.fill: parent
source: UM.Theme.getImage("3d_printer_faded")
sourceSize.width: width
fillMode: Image.PreserveAspectFit
}
}
UM.Label
{
text: catalog.i18nc("@text", "It seems like you don't have any compatible printers connected to Digital Factory. Make sure your printer is connected and it's running the latest firmware.")
Layout.fillWidth: true
horizontalAlignment: Text.AlignHCenter
wrapMode: Text.Wrap
}
Item
{
Layout.fillWidth: true
Layout.preferredHeight: parent.height / 4
Cura.TertiaryButton
{
text: catalog.i18nc("@button", "Learn how to connect your printer to Digital Factory")
iconSource: UM.Theme.getIcon("LinkExternal")
onClicked: Qt.openUrlExternally("https://support.ultimaker.com/hc/en-us/articles/360012019239?utm_source=cura&utm_medium=software&utm_campaign=sync-material-wizard-add-cloud-printer")
anchors.horizontalCenter: parent.horizontalCenter
maximumWidth: parent.width
}
}
Item
{
width: parent.width
height: childrenRect.height
Layout.preferredWidth: width
Layout.preferredHeight: height
Layout.preferredHeight: childrenRect.height
Layout.alignment: Qt.AlignBottom
Layout.fillWidth: true
Cura.SecondaryButton
{
@ -611,30 +587,34 @@ Window
text: catalog.i18nc("@button", "Sync materials with USB")
onClicked: swipeView.currentIndex = removableDriveSyncPage.SwipeView.index
}
Cura.PrimaryButton
RowLayout
{
id: disabledSyncButton
anchors.right: parent.right
text: catalog.i18nc("@button", "Sync")
enabled: false //If there are no printers, always disable this button.
}
Cura.SecondaryButton
{
anchors.right: disabledSyncButton.left
anchors.rightMargin: UM.Theme.getSize("default_margin").width
text: catalog.i18nc("@button", "Refresh")
iconSource: UM.Theme.getIcon("ArrowDoubleCircleRight")
outlineColor: "transparent"
onClicked: Cura.API.account.sync(true)
spacing: UM.Theme.getSize("default_margin").width
Cura.SecondaryButton
{
text: catalog.i18nc("@button", "Refresh")
iconSource: UM.Theme.getIcon("ArrowDoubleCircleRight")
outlineColor: "transparent"
onClicked: Cura.API.account.sync(true)
}
Cura.PrimaryButton
{
id: disabledSyncButton
text: catalog.i18nc("@button", "Sync")
enabled: false // If there are no printers, always disable this button.
}
}
}
}
}
Rectangle
Item
{
id: removableDriveSyncPage
color: UM.Theme.getColor("main_background")
ColumnLayout
{
@ -642,53 +622,56 @@ Window
anchors.fill: parent
anchors.margins: UM.Theme.getSize("default_margin").width
Label
UM.Label
{
text: catalog.i18nc("@title:header", "Sync material profiles via USB")
font: UM.Theme.getFont("large_bold")
color: UM.Theme.getColor("text")
Layout.preferredHeight: height
Layout.fillWidth: true
}
Label
UM.Label
{
text: catalog.i18nc("@text In the UI this is followed by a list of steps the user needs to take.", "Follow the following steps to load the new material profiles to your printer.")
font: UM.Theme.getFont("medium")
color: UM.Theme.getColor("text")
wrapMode: Text.Wrap
width: parent.width
Layout.maximumWidth: width
Layout.preferredHeight: height
Layout.fillWidth: true
}
Row
RowLayout
{
width: parent.width
Layout.preferredWidth: width
Layout.fillWidth: true
Layout.fillHeight: true
spacing: UM.Theme.getSize("default_margin").width
Image
Item
{
source: UM.Theme.getImage("insert_usb")
width: parent.width / 3
height: width
anchors.verticalCenter: parent.verticalCenter
sourceSize.width: width
Layout.preferredWidth: parent.width / 3
Layout.fillHeight: true
Image
{
anchors.fill: parent
source: UM.Theme.getImage("insert_usb")
verticalAlignment: Image.AlignVCenter
horizontalAlignment: Image.AlignHCenter
fillMode: Image.PreserveAspectFit
sourceSize.width: width
}
}
Label
UM.Label
{
Layout.alignment: Qt.AlignCenter
Layout.fillWidth: true
text: "1. " + catalog.i18nc("@text", "Click the export material archive button.")
+ "\n2. " + catalog.i18nc("@text", "Save the .umm file on a USB stick.")
+ "\n3. " + catalog.i18nc("@text", "Insert the USB stick into your printer and launch the procedure to load new material profiles.")
font: UM.Theme.getFont("medium")
color: UM.Theme.getColor("text")
wrapMode: Text.Wrap
width: parent.width * 2 / 3 - UM.Theme.getSize("default_margin").width
anchors.verticalCenter: parent.verticalCenter
}
}
Cura.TertiaryButton
{
Layout.fillWidth: true
text: catalog.i18nc("@button", "How to load new material profiles to my printer")
iconSource: UM.Theme.getIcon("LinkExternal")
onClicked: Qt.openUrlExternally("https://support.ultimaker.com/hc/en-us/articles/4403319801106/?utm_source=cura&utm_medium=software&utm_campaign=add-material-profiles-via-usb")
@ -696,10 +679,9 @@ Window
Item
{
width: parent.width
height: childrenRect.height
Layout.preferredWidth: width
Layout.preferredHeight: height
Layout.preferredHeight: childrenRect.height
Layout.alignment: Qt.AlignBottom
Layout.fillWidth: true
Cura.SecondaryButton
{
@ -732,24 +714,22 @@ Window
}
}
Cura.GlobalStacksModel
property variant cloudPrinterList: Cura.GlobalStacksModel
{
id: cloudPrinterList
filterConnectionType: 3 //Only show cloud connections.
filterOnlineOnly: true //Only show printers that are online.
filterCapabilities: ["import_material"] //Only show printers that can receive the material profiles.
}
Cura.GlobalStacksModel
property variant includeOfflinePrinterList: Cura.GlobalStacksModel
{
//In order to show a refresh button only when there are offline cloud printers, we need to know if there are any offline printers.
//A global stacks model without the filter for online-only printers allows this.
id: includeOfflinePrinterList
filterConnectionType: 3 //Still only show cloud connections.
}
FileDialog
property variant exportUsbDialog: FileDialog
{
id: exportUsbDialog
title: catalog.i18nc("@title:window", "Export All Materials")
selectExisting: false
nameFilters: ["Material archives (*.umm)", "All files (*)"]

View file

@ -1,116 +1,53 @@
// Copyright (c) 2018 Ultimaker B.V.
// Copyright (c) 2022 Ultimaker B.V.
// Uranium is released under the terms of the LGPLv3 or higher.
import QtQuick 2.7
import QtQuick.Controls 1.4
import QtQuick.Controls.Styles 1.4
import QtQuick.Layouts 1.3
import QtQuick.Dialogs 1.2
import UM 1.2 as UM
import UM 1.5 as UM
import Cura 1.0 as Cura
Item
Column
{
id: material_type_section
property var materialType
property var materialType: null
property string materialBrand: materialType !== null ? materialType.brand : ""
property string materialName: materialType !== null ? materialType.name : ""
property bool expanded: materialList.expandedTypes.indexOf(`${materialBrand}_${materialName}`) !== -1
property var colorsModel: materialType !== null ? materialType.colors : null
property alias indented: categoryButton.indented
width: parent.width
property string materialBrand: materialType != null ? materialType.brand : ""
property string materialName: materialType != null ? materialType.name : ""
property var expanded: materialList.expandedTypes.indexOf(materialBrand + "_" + materialName) > -1
property var colorsModel: materialType != null ? materialType.colors: null
height: childrenRect.height
width: parent ? parent.width :undefined
anchors.left: parent ? parent.left : undefined
Rectangle
Cura.CategoryButton
{
id: material_type_header_background
color:
id: categoryButton
width: parent.width
height: UM.Theme.getSize("preferences_page_list_item").height
labelText: materialName
labelFont: UM.Theme.getFont("default")
expanded: material_type_section.expanded
onClicked:
{
if(!expanded && materialBrand + "_" + materialName == materialList.currentType)
const identifier = `${materialBrand}_${materialName}`;
const i = materialList.expandedTypes.indexOf(identifier);
if (i !== -1)
{
return UM.Theme.getColor("favorites_row_selected")
materialList.expandedTypes.splice(i, 1); // remove
}
else
{
return "transparent"
}
}
width: parent.width
height: material_type_header.height
}
Rectangle
{
id: material_type_header_border
color: UM.Theme.getColor("favorites_header_bar")
anchors.bottom: material_type_header.bottom
anchors.left: material_type_header.left
height: UM.Theme.getSize("default_lining").height
width: material_type_header.width
}
Row
{
id: material_type_header
width: parent.width
leftPadding: UM.Theme.getSize("default_margin").width
anchors
{
left: parent ? parent.left : undefined
}
Label
{
text: materialName
height: UM.Theme.getSize("favorites_row").height
width: parent.width - parent.leftPadding - UM.Theme.getSize("favorites_button").width
id: material_type_name
verticalAlignment: Text.AlignVCenter
}
Item // this one causes lots of warnings
{
implicitWidth: UM.Theme.getSize("favorites_button").width
implicitHeight: UM.Theme.getSize("favorites_button").height
UM.RecolorImage {
anchors
{
verticalCenter: parent ? parent.verticalCenter : undefined
horizontalCenter: parent ? parent.horizontalCenter : undefined
}
width: UM.Theme.getSize("standard_arrow").width
height: UM.Theme.getSize("standard_arrow").height
color: "black"
source: material_type_section.expanded ? UM.Theme.getIcon("ChevronSingleDown") : UM.Theme.getIcon("ChevronSingleLeft")
}
}
}
MouseArea // causes lots of warnings
{
anchors.fill: material_type_header
onPressed:
{
const identifier = materialBrand + "_" + materialName;
const i = materialList.expandedTypes.indexOf(identifier)
if (i > -1)
{
// Remove it
materialList.expandedTypes.splice(i, 1)
material_type_section.expanded = false
}
else
{
// Add it
materialList.expandedTypes.push(identifier)
material_type_section.expanded = true
materialList.expandedTypes.push(identifier); // add
}
UM.Preferences.setValue("cura/expanded_types", materialList.expandedTypes.join(";"));
}
}
Column
{
height: material_type_section.expanded ? childrenRect.height : 0
visible: material_type_section.expanded
width: parent.width
anchors.top: material_type_header.bottom
Repeater
{
model: colorsModel
@ -131,7 +68,7 @@ Item
return;
}
expanded = materialList.expandedTypes.indexOf(materialBrand + "_" + materialName) > -1
material_type_section.expanded = materialList.expandedTypes.indexOf(`${materialBrand}_${materialName}`) !== -1;
}
}
}

View file

@ -1,16 +1,15 @@
// Copyright (c) 2017 Ultimaker B.V.
// Copyright (c) 2022 Ultimaker B.V.
// Cura is released under the terms of the LGPLv3 or higher.
import QtQuick 2.7
import QtQuick.Controls 1.4
import QtQuick.Controls 2.15
import QtQuick.Dialogs 1.2
import QtQuick.Layouts 1.3
import UM 1.2 as UM
import UM 1.5 as UM
import Cura 1.0 as Cura
import ".." // Access to ReadOnlyTextArea.qml
TabView
Item
{
id: base
@ -19,8 +18,6 @@ TabView
property bool editingEnabled: false
property string currency: UM.Preferences.getValue("cura/currency") ? UM.Preferences.getValue("cura/currency") : "€"
property real firstColumnWidth: (width * 0.50) | 0
property real secondColumnWidth: (width * 0.40) | 0
property string containerId: ""
property var materialPreferenceValues: UM.Preferences.getValue("cura/material_settings") ? JSON.parse(UM.Preferences.getValue("cura/material_settings")) : {}
property var materialManagementModel: CuraApplication.getMaterialManagementModel()
@ -67,47 +64,69 @@ TabView
}
}
Tab
Rectangle
{
title: catalog.i18nc("@title", "Information")
color: UM.Theme.getColor("main_background")
anchors.margins: UM.Theme.getSize("default_margin").width
anchors
{
top: pageSelectorTabRow.bottom
topMargin: -UM.Theme.getSize("default_lining").width
left: parent.left
right: parent.right
bottom: parent.bottom
}
border.width: UM.Theme.getSize("default_lining").width
border.color: UM.Theme.getColor("border_main")
ScrollView
{
id: scrollView
anchors.fill: parent
horizontalScrollBarPolicy: Qt.ScrollBarAlwaysOff
flickableItem.flickableDirection: Flickable.VerticalFlick
frameVisible: true
property real columnWidth: (viewport.width * 0.5 - UM.Theme.getSize("default_margin").width) | 0
Flow
id: informationPage
anchors
{
id: containerGrid
fill: parent
topMargin: UM.Theme.getSize("thin_margin").height
bottomMargin: UM.Theme.getSize("thin_margin").height
leftMargin: UM.Theme.getSize("thin_margin").width
rightMargin: UM.Theme.getSize("thin_margin").width
}
x: UM.Theme.getSize("default_margin").width
y: UM.Theme.getSize("default_lining").height
ScrollBar.vertical: UM.ScrollBar
{
id: scrollBar
parent: informationPage
anchors
{
top: parent.top
right: parent.right
bottom: parent.bottom
}
}
ScrollBar.horizontal.policy: ScrollBar.AlwaysOff
clip: true
visible: pageSelectorTabRow.currentItem.activeView === "information"
width: base.width
property real rowHeight: brandTextField.height + UM.Theme.getSize("default_lining").height
property real columnWidth: Math.floor((width - scrollBar.width - UM.Theme.getSize("narrow_margin").width) / 2)
property real rowHeight: UM.Theme.getSize("setting_control").height
MessageDialog
Column
{
width: informationPage.width
spacing: UM.Theme.getSize("narrow_margin").height
Cura.MessageDialog
{
id: confirmDiameterChangeDialog
icon: StandardIcon.Question;
title: catalog.i18nc("@title:window", "Confirm Diameter Change")
text: catalog.i18nc("@label (%1 is a number)", "The new filament diameter is set to %1 mm, which is not compatible with the current extruder. Do you wish to continue?".arg(new_diameter_value))
standardButtons: StandardButton.Yes | StandardButton.No
modality: Qt.ApplicationModal
standardButtons: Dialog.Yes | Dialog.No
property var new_diameter_value: null;
property var old_diameter_value: null;
property var old_approximate_diameter_value: null;
property var new_diameter_value: null
property var old_diameter_value: null
property var old_approximate_diameter_value: null
onYes:
onAccepted:
{
base.setMetaDataEntry("approximate_diameter", old_approximate_diameter_value, getApproximateDiameter(new_diameter_value).toString());
base.setMetaDataEntry("properties/diameter", properties.diameter, new_diameter_value);
@ -116,209 +135,337 @@ TabView
base.resetSelectedMaterial()
}
onNo:
onRejected:
{
base.properties.diameter = old_diameter_value;
diameterSpinBox.value = Qt.binding(function() { return base.properties.diameter })
diameterTextField.valueText = Qt.binding(function() { return base.properties.diameter })
}
onRejected: no()
}
Label { width: scrollView.columnWidth; height: parent.rowHeight; verticalAlignment: Qt.AlignVCenter; text: catalog.i18nc("@label", "Display Name") }
ReadOnlyTextField
{
id: displayNameTextField;
width: scrollView.columnWidth;
text: properties.name;
readOnly: !base.editingEnabled;
onEditingFinished: base.updateMaterialDisplayName(properties.name, text)
}
Label { width: scrollView.columnWidth; height: parent.rowHeight; verticalAlignment: Qt.AlignVCenter; text: catalog.i18nc("@label", "Brand") }
ReadOnlyTextField
{
id: brandTextField;
width: scrollView.columnWidth;
text: properties.brand;
readOnly: !base.editingEnabled;
onEditingFinished: base.updateMaterialBrand(properties.brand, text)
}
Label { width: scrollView.columnWidth; height: parent.rowHeight; verticalAlignment: Qt.AlignVCenter; text: catalog.i18nc("@label", "Material Type") }
ReadOnlyTextField
{
id: materialTypeField;
width: scrollView.columnWidth;
text: properties.material;
readOnly: !base.editingEnabled;
onEditingFinished: base.updateMaterialType(properties.material, text)
}
Label { width: scrollView.columnWidth; height: parent.rowHeight; verticalAlignment: Qt.AlignVCenter; text: catalog.i18nc("@label", "Color") }
Row
{
width: scrollView.columnWidth
height: parent.rowHeight
spacing: Math.round(UM.Theme.getSize("default_margin").width / 2)
// color indicator square
Rectangle
spacing: UM.Theme.getSize("narrow_margin").width
UM.Label
{
id: colorSelector
color: properties.color_code
height: informationPage.rowHeight
width: informationPage.columnWidth
text: catalog.i18nc("@label", "Display Name")
}
Cura.TextField
{
id: displayNameTextField
width: informationPage.columnWidth
text: properties.name
enabled: base.editingEnabled
onEditingFinished: base.updateMaterialDisplayName(properties.name, text)
}
}
width: Math.round(colorLabel.height * 0.75)
height: Math.round(colorLabel.height * 0.75)
border.width: UM.Theme.getSize("default_lining").height
Row
{
spacing: UM.Theme.getSize("narrow_margin").width
UM.Label
{
height: informationPage.rowHeight
width: informationPage.columnWidth
text: catalog.i18nc("@label", "Brand")
}
Cura.TextField
{
id: brandTextField
width: informationPage.columnWidth
text: properties.brand
enabled: base.editingEnabled
onEditingFinished: base.updateMaterialBrand(properties.brand, text)
}
}
anchors.verticalCenter: parent.verticalCenter
Row
{
spacing: UM.Theme.getSize("narrow_margin").width
UM.Label
{
height: informationPage.rowHeight
width: informationPage.columnWidth
text: catalog.i18nc("@label", "Material Type")
}
Cura.TextField
{
id: materialTypeField
width: informationPage.columnWidth
text: properties.material
enabled: base.editingEnabled
onEditingFinished: base.updateMaterialType(properties.material, text)
}
}
// open the color selection dialog on click
MouseArea
Row
{
spacing: UM.Theme.getSize("narrow_margin").width
UM.Label
{
height: informationPage.rowHeight
width: informationPage.columnWidth
verticalAlignment: Qt.AlignVCenter; text: catalog.i18nc("@label", "Color")
}
Row
{
width: informationPage.columnWidth
spacing: Math.round(UM.Theme.getSize("default_margin").width / 2)
// color indicator square
Item
{
anchors.fill: parent
onClicked: colorDialog.open()
id: colorSelector
anchors.verticalCenter: parent.verticalCenter
width: colorSelectorBackground.width + 2 * UM.Theme.getSize("narrow_margin").width
height: colorSelectorBackground.height + 2 * UM.Theme.getSize("narrow_margin").height
Rectangle
{
id: colorSelectorBackground
color: properties.color_code
width: UM.Theme.getSize("icon_indicator").width
height: UM.Theme.getSize("icon_indicator").height
radius: width / 2
anchors.centerIn: parent
}
// open the color selection dialog on click
MouseArea
{
anchors.fill: parent
onClicked: colorDialog.open()
enabled: base.editingEnabled
}
}
// pretty color name text field
Cura.TextField
{
id: colorLabel;
width: parent.width - colorSelector.width - parent.spacing
text: properties.color_name;
enabled: base.editingEnabled
onEditingFinished: base.setMetaDataEntry("color_name", properties.color_name, text)
}
}
// pretty color name text field
ReadOnlyTextField
{
id: colorLabel;
width: parent.width - colorSelector.width - parent.spacing
text: properties.color_name;
readOnly: !base.editingEnabled
onEditingFinished: base.setMetaDataEntry("color_name", properties.color_name, text)
}
// popup dialog to select a new color
// if successful it sets the properties.color_code value to the new color
ColorDialog
{
id: colorDialog
color: properties.color_code
onAccepted: base.setMetaDataEntry("color_code", properties.color_code, color)
}
}
Item { width: parent.width; height: UM.Theme.getSize("default_margin").height }
Label { width: parent.width; height: parent.rowHeight; font.bold: true; verticalAlignment: Qt.AlignVCenter; text: catalog.i18nc("@label", "Properties") }
Label { width: scrollView.columnWidth; height: parent.rowHeight; verticalAlignment: Qt.AlignVCenter; text: catalog.i18nc("@label", "Density") }
ReadOnlySpinBox
{
id: densitySpinBox
width: scrollView.columnWidth
value: properties.density
decimals: 2
suffix: " g/cm³"
stepSize: 0.01
readOnly: !base.editingEnabled
onEditingFinished: base.setMetaDataEntry("properties/density", properties.density, value)
onValueChanged: updateCostPerMeter()
}
Label { width: scrollView.columnWidth; height: parent.rowHeight; verticalAlignment: Qt.AlignVCenter; text: catalog.i18nc("@label", "Diameter") }
ReadOnlySpinBox
{
id: diameterSpinBox
width: scrollView.columnWidth
value: properties.diameter
decimals: 2
suffix: " mm"
stepSize: 0.01
readOnly: !base.editingEnabled
onEditingFinished:
{
// This does not use a SettingPropertyProvider, because we need to make the change to all containers
// which derive from the same base_file
var old_diameter = Cura.ContainerManager.getContainerMetaDataEntry(base.containerId, "properties/diameter");
var old_approximate_diameter = Cura.ContainerManager.getContainerMetaDataEntry(base.containerId, "approximate_diameter");
var new_approximate_diameter = getApproximateDiameter(value);
if (new_approximate_diameter != Cura.ExtruderManager.getActiveExtruderStack().approximateMaterialDiameter)
// popup dialog to select a new color
// if successful it sets the properties.color_code value to the new color
Cura.ColorDialog
{
confirmDiameterChangeDialog.old_diameter_value = old_diameter;
confirmDiameterChangeDialog.new_diameter_value = value;
confirmDiameterChangeDialog.old_approximate_diameter_value = old_approximate_diameter;
confirmDiameterChangeDialog.open()
}
else {
base.setMetaDataEntry("approximate_diameter", old_approximate_diameter, getApproximateDiameter(value).toString());
base.setMetaDataEntry("properties/diameter", properties.diameter, value);
id: colorDialog
title: catalog.i18nc("@title", "Material color picker")
color: properties.color_code
onAccepted: base.setMetaDataEntry("color_code", properties.color_code, color)
}
}
onValueChanged: updateCostPerMeter()
}
Label { width: scrollView.columnWidth; height: parent.rowHeight; verticalAlignment: Qt.AlignVCenter; text: catalog.i18nc("@label", "Filament Cost") }
SpinBox
UM.Label
{
id: spoolCostSpinBox
width: scrollView.columnWidth
value: base.getMaterialPreferenceValue(properties.guid, "spool_cost")
prefix: base.currency + " "
decimals: 2
maximumValue: 100000000
width: parent.width
height: parent.rowHeight
font: UM.Theme.getFont("default_bold")
verticalAlignment: Qt.AlignVCenter
text: catalog.i18nc("@label", "Properties")
}
onValueChanged:
Row
{
height: parent.rowHeight
spacing: UM.Theme.getSize("narrow_margin").width
UM.Label
{
base.setMaterialPreferenceValue(properties.guid, "spool_cost", parseFloat(value))
updateCostPerMeter()
height: informationPage.rowHeight
width: informationPage.columnWidth
text: catalog.i18nc("@label", "Density")
}
Cura.NumericTextFieldWithUnit
{
id: densityTextField
enabled: base.editingEnabled
valueText: properties.density
controlWidth: informationPage.columnWidth
controlHeight: informationPage.rowHeight
spacing: 0
unitText: "g/cm³"
decimals: 2
maximum: 1000
editingFinishedFunction: function()
{
var modified_text = valueText.replace(",", ".");
base.setMetaDataEntry("properties/density", properties.density, modified_text)
}
onValueTextChanged: updateCostPerMeter()
}
}
Label { width: scrollView.columnWidth; height: parent.rowHeight; verticalAlignment: Qt.AlignVCenter; text: catalog.i18nc("@label", "Filament weight") }
SpinBox
Row
{
id: spoolWeightSpinBox
width: scrollView.columnWidth
value: base.getMaterialPreferenceValue(properties.guid, "spool_weight", Cura.ContainerManager.getContainerMetaDataEntry(properties.container_id, "properties/weight"))
suffix: " g"
stepSize: 100
decimals: 0
maximumValue: 10000
onValueChanged:
height: parent.rowHeight
spacing: UM.Theme.getSize("narrow_margin").width
UM.Label
{
base.setMaterialPreferenceValue(properties.guid, "spool_weight", parseFloat(value))
updateCostPerMeter()
height: informationPage.rowHeight
width: informationPage.columnWidth
text: catalog.i18nc("@label", "Diameter")
}
Cura.NumericTextFieldWithUnit
{
id: diameterTextField
enabled: base.editingEnabled
valueText: properties.diameter
controlWidth: informationPage.columnWidth
controlHeight: informationPage.rowHeight
spacing: 0
unitText: "mm"
decimals: 2
maximum: 1000
editingFinishedFunction: function()
{
// This does not use a SettingPropertyProvider, because we need to make the change to all containers
// which derive from the same base_file
var old_diameter = Cura.ContainerManager.getContainerMetaDataEntry(base.containerId, "properties/diameter");
var old_approximate_diameter = Cura.ContainerManager.getContainerMetaDataEntry(base.containerId, "approximate_diameter");
var modified_value = valueText.replace(",", ".");
var new_approximate_diameter = getApproximateDiameter(modified_value);
if (new_approximate_diameter != Cura.ExtruderManager.getActiveExtruderStack().approximateMaterialDiameter)
{
confirmDiameterChangeDialog.old_diameter_value = old_diameter;
confirmDiameterChangeDialog.new_diameter_value = modified_value;
confirmDiameterChangeDialog.old_approximate_diameter_value = old_approximate_diameter;
confirmDiameterChangeDialog.open()
}
else {
base.setMetaDataEntry("approximate_diameter", old_approximate_diameter, new_approximate_diameter);
base.setMetaDataEntry("properties/diameter", properties.diameter, modified_value);
}
}
onValueTextChanged: updateCostPerMeter()
}
}
Label { width: scrollView.columnWidth; height: parent.rowHeight; verticalAlignment: Qt.AlignVCenter; text: catalog.i18nc("@label", "Filament length") }
Label
Row
{
width: scrollView.columnWidth
text: "~ %1 m".arg(Math.round(base.spoolLength))
verticalAlignment: Qt.AlignVCenter
height: parent.rowHeight
spacing: UM.Theme.getSize("narrow_margin").width
UM.Label
{
height: informationPage.rowHeight
width: informationPage.columnWidth
text: catalog.i18nc("@label", "Filament Cost")
}
Cura.NumericTextFieldWithUnit
{
id: spoolCostTextField
valueText: base.getMaterialPreferenceValue(properties.guid, "spool_cost")
controlWidth: informationPage.columnWidth
controlHeight: informationPage.rowHeight
spacing: 0
unitText: base.currency
decimals: 2
maximum: 100000000
editingFinishedFunction: function()
{
var modified_text = valueText.replace(",", ".");
base.setMaterialPreferenceValue(properties.guid, "spool_cost", modified_text);
}
onValueTextChanged: updateCostPerMeter()
}
}
Label { width: scrollView.columnWidth; height: parent.rowHeight; verticalAlignment: Qt.AlignVCenter; text: catalog.i18nc("@label", "Cost per Meter") }
Label
Row
{
width: scrollView.columnWidth
text: "~ %1 %2/m".arg(base.costPerMeter.toFixed(2)).arg(base.currency)
verticalAlignment: Qt.AlignVCenter
height: parent.rowHeight
spacing: UM.Theme.getSize("narrow_margin").width
UM.Label
{
height: informationPage.rowHeight
width: informationPage.columnWidth
text: catalog.i18nc("@label", "Filament weight")
}
Cura.NumericTextFieldWithUnit
{
id: spoolWeightTextField
valueText: base.getMaterialPreferenceValue(properties.guid, "spool_weight", Cura.ContainerManager.getContainerMetaDataEntry(properties.container_id, "properties/weight"))
controlWidth: informationPage.columnWidth
controlHeight: informationPage.rowHeight
spacing: 0
unitText: " g"
decimals: 0
maximum: 10000
editingFinishedFunction: function()
{
var modified_text = valueText.replace(",", ".")
base.setMaterialPreferenceValue(properties.guid, "spool_weight", modified_text)
}
onValueTextChanged: updateCostPerMeter()
}
}
Item { width: parent.width; height: UM.Theme.getSize("default_margin").height; visible: unlinkMaterialButton.visible }
Label
Row
{
width: 2 * scrollView.columnWidth
verticalAlignment: Qt.AlignVCenter
height: parent.rowHeight
spacing: UM.Theme.getSize("narrow_margin").width
UM.Label
{
height: informationPage.rowHeight
width: informationPage.columnWidth
text: catalog.i18nc("@label", "Filament length")
}
UM.Label
{
width: informationPage.columnWidth
text: "~ %1 m".arg(Math.round(base.spoolLength))
height: informationPage.rowHeight
}
}
Row
{
height: parent.rowHeight
spacing: UM.Theme.getSize("narrow_margin").width
UM.Label
{
height: informationPage.rowHeight
width: informationPage.columnWidth
text: catalog.i18nc("@label", "Cost per Meter")
}
UM.Label
{
height: informationPage.rowHeight
width: informationPage.columnWidth
text: "~ %1 %2/m".arg(base.costPerMeter.toFixed(2)).arg(base.currency)
}
}
UM.Label
{
height: parent.rowHeight
width: informationPage.width
text: catalog.i18nc("@label", "This material is linked to %1 and shares some of its properties.").arg(base.linkedMaterialNames)
wrapMode: Text.WordWrap
visible: unlinkMaterialButton.visible
}
Button
Cura.SecondaryButton
{
id: unlinkMaterialButton
text: catalog.i18nc("@label", "Unlink Material")
@ -330,141 +477,183 @@ TabView
}
}
Item { width: parent.width; height: UM.Theme.getSize("default_margin").height }
Label { width: parent.width; height: parent.rowHeight; verticalAlignment: Qt.AlignVCenter; text: catalog.i18nc("@label", "Description") }
ReadOnlyTextArea
UM.Label
{
text: properties.description;
width: 2 * scrollView.columnWidth
width: informationPage.width
height: parent.rowHeight
text: catalog.i18nc("@label", "Description")
}
Cura.ReadOnlyTextArea
{
text: properties.description
width: informationPage.width - scrollBar.width
height: 0.4 * informationPage.width
wrapMode: Text.WordWrap
readOnly: !base.editingEnabled;
readOnly: !base.editingEnabled
onEditingFinished: base.setMetaDataEntry("description", properties.description, text)
}
Label { width: parent.width; height: parent.rowHeight; verticalAlignment: Qt.AlignVCenter; text: catalog.i18nc("@label", "Adhesion Information") }
ReadOnlyTextArea
UM.Label
{
text: properties.adhesion_info;
width: 2 * scrollView.columnWidth
wrapMode: Text.WordWrap
width: informationPage.width
height: parent.rowHeight
text: catalog.i18nc("@label", "Adhesion Information")
}
readOnly: !base.editingEnabled;
Cura.ReadOnlyTextArea
{
text: properties.adhesion_info
width: informationPage.width - scrollBar.width
height: 0.4 * informationPage.width
wrapMode: Text.WordWrap
readOnly: !base.editingEnabled
onEditingFinished: base.setMetaDataEntry("adhesion_info", properties.adhesion_info, text)
}
}
}
Item { width: parent.width; height: UM.Theme.getSize("default_margin").height }
ListView
{
id: settingsPage
visible: pageSelectorTabRow.currentItem.activeView === "settings"
clip: true
anchors
{
fill: parent
topMargin: UM.Theme.getSize("thin_margin").height
bottomMargin: UM.Theme.getSize("thin_margin").height
leftMargin: UM.Theme.getSize("thin_margin").width
rightMargin: UM.Theme.getSize("thin_margin").width
}
function updateCostPerMeter()
width: settingsPage.width
spacing: UM.Theme.getSize("narrow_margin").height
ScrollBar.vertical: UM.ScrollBar
{
base.spoolLength = calculateSpoolLength(diameterSpinBox.value, densitySpinBox.value, spoolWeightSpinBox.value);
base.costPerMeter = calculateCostPerMeter(spoolCostSpinBox.value);
id: settingScrollBar
parent: settingsPage
anchors
{
top: parent.top
right: parent.right
bottom: parent.bottom
}
}
property real columnWidth: Math.floor((width - settingScrollBar.width - UM.Theme.getSize("narrow_margin").width) / 2)
model: UM.SettingDefinitionsModel
{
containerId: Cura.MachineManager.activeMachine != null ? Cura.MachineManager.activeMachine.definition.id: ""
visibilityHandler: Cura.MaterialSettingsVisibilityHandler { }
expanded: ["*"]
}
delegate: UM.TooltipArea
{
width: childrenRect.width
height: childrenRect.height
UM.TooltipArea
{
anchors.fill: parent
text: model.description
}
UM.Label
{
id: label
width: settingsPage.columnWidth
height: spinBox.height + UM.Theme.getSize("default_lining").height
text: model.label
elide: Text.ElideRight
verticalAlignment: Qt.AlignVCenter
}
Cura.SpinBox
{
id: spinBox
anchors.left: label.right
value:
{
// In case the setting is not in the material...
if (!isNaN(parseFloat(materialPropertyProvider.properties.value)))
{
return parseFloat(materialPropertyProvider.properties.value);
}
// ... we search in the variant, and if it is not there...
if (!isNaN(parseFloat(variantPropertyProvider.properties.value)))
{
return parseFloat(variantPropertyProvider.properties.value);
}
// ... then look in the definition container.
if (!isNaN(parseFloat(machinePropertyProvider.properties.value)))
{
return parseFloat(machinePropertyProvider.properties.value);
}
return 0;
}
width: settingsPage.columnWidth
suffix: " " + model.unit
to: 99999
decimals: model.unit == "mm" ? 2 : 0
onEditingFinished: materialPropertyProvider.setPropertyValue("value", value)
}
UM.ContainerPropertyProvider
{
id: materialPropertyProvider
containerId: base.containerId
watchedProperties: [ "value" ]
key: model.key
}
UM.ContainerPropertyProvider
{
id: variantPropertyProvider
containerId: Cura.MachineManager.activeStack.variant.id
watchedProperties: [ "value" ]
key: model.key
}
UM.ContainerPropertyProvider
{
id: machinePropertyProvider
containerId: Cura.MachineManager.activeMachine != null ? Cura.MachineManager.activeMachine.definition.id: ""
watchedProperties: ["value"]
key: model.key
}
}
}
}
Tab
UM.TabRow
{
title: catalog.i18nc("@label", "Print settings")
anchors
id: pageSelectorTabRow
UM.TabRowButton
{
leftMargin: UM.Theme.getSize("default_margin").width
topMargin: UM.Theme.getSize("default_margin").height
bottomMargin: UM.Theme.getSize("default_margin").height
rightMargin: 0
text: catalog.i18nc("@title", "Information")
property string activeView: "information" //To determine which page gets displayed.
}
ScrollView
UM.TabRowButton
{
anchors.fill: parent;
ListView
{
model: UM.SettingDefinitionsModel
{
containerId: Cura.MachineManager.activeMachine != null ? Cura.MachineManager.activeMachine.definition.id: ""
visibilityHandler: Cura.MaterialSettingsVisibilityHandler { }
expanded: ["*"]
}
delegate: UM.TooltipArea
{
width: childrenRect.width
height: childrenRect.height
text: model.description
Label
{
id: label
width: base.firstColumnWidth;
height: spinBox.height + UM.Theme.getSize("default_lining").height
text: model.label
elide: Text.ElideRight
verticalAlignment: Qt.AlignVCenter
}
ReadOnlySpinBox
{
id: spinBox
anchors.left: label.right
value:
{
// In case the setting is not in the material...
if (!isNaN(parseFloat(materialPropertyProvider.properties.value)))
{
return parseFloat(materialPropertyProvider.properties.value);
}
// ... we search in the variant, and if it is not there...
if (!isNaN(parseFloat(variantPropertyProvider.properties.value)))
{
return parseFloat(variantPropertyProvider.properties.value);
}
// ... then look in the definition container.
if (!isNaN(parseFloat(machinePropertyProvider.properties.value)))
{
return parseFloat(machinePropertyProvider.properties.value);
}
return 0;
}
width: base.secondColumnWidth
readOnly: !base.editingEnabled
suffix: " " + model.unit
maximumValue: 99999
decimals: model.unit == "mm" ? 2 : 0
onEditingFinished: materialPropertyProvider.setPropertyValue("value", value)
}
UM.ContainerPropertyProvider
{
id: materialPropertyProvider
containerId: base.containerId
watchedProperties: [ "value" ]
key: model.key
}
UM.ContainerPropertyProvider
{
id: variantPropertyProvider
containerId: Cura.MachineManager.activeStack.variant.id
watchedProperties: [ "value" ]
key: model.key
}
UM.ContainerPropertyProvider
{
id: machinePropertyProvider
containerId: Cura.MachineManager.activeMachine != null ? Cura.MachineManager.activeMachine.definition.id: ""
watchedProperties: [ "value" ]
key: model.key
}
}
}
text: catalog.i18nc("@label", "Print settings")
property string activeView: "settings"
}
}
function updateCostPerMeter()
{
var modified_weight = spoolWeightTextField.valueText.replace(",", ".")
var modified_cost = spoolCostTextField.valueText.replace(",", ".")
var modified_diameter = diameterTextField.valueText.replace(",", ".")
var modified_density = densityTextField.valueText.replace(",", ".")
base.spoolLength = calculateSpoolLength(modified_diameter, modified_density, parseInt(modified_weight));
base.costPerMeter = calculateCostPerMeter(parseFloat(modified_cost));
}
function calculateSpoolLength(diameter, density, spoolWeight)
{
if(!diameter)

View file

@ -1,118 +0,0 @@
// Copyright (c) 2018 Ultimaker B.V.
// Cura is released under the terms of the LGPLv3 or higher.
import QtQuick 2.7
import QtQuick.Controls 1.4
import UM 1.2 as UM
import Cura 1.0 as Cura
Tab
{
id: base
property int extruderPosition: -1 //Denotes the global stack.
property var qualityItem: null
property bool isQualityItemCurrentlyActivated:
{
if (qualityItem == null)
{
return false;
}
return qualityItem.name == Cura.MachineManager.activeQualityOrQualityChangesName;
}
TableView
{
anchors.fill: parent
anchors.margins: UM.Theme.getSize("default_margin").width
id: profileSettingsView
Component
{
id: itemDelegate
UM.TooltipArea
{
property var setting: qualitySettings.getItem(styleData.row)
height: childrenRect.height
width: (parent != null) ? parent.width : 0
text:
{
if (styleData.value === undefined)
{
return ""
}
return (styleData.value.substr(0,1) == "=") ? styleData.value : ""
}
Label
{
anchors.left: parent.left
anchors.leftMargin: UM.Theme.getSize("default_margin").width
anchors.right: parent.right
text:
{
if (styleData.value === undefined)
{
return ""
}
return (styleData.value.substr(0,1) == "=") ? catalog.i18nc("@info:status", "Calculated") : styleData.value
}
font.strikeout: styleData.column == 1 && setting.user_value != "" && base.isQualityItemCurrentlyActivated
font.italic: setting.profile_value_source == "quality_changes" || (setting.user_value != "" && base.isQualityItemCurrentlyActivated)
opacity: font.strikeout ? 0.5 : 1
color: styleData.textColor
elide: Text.ElideRight
}
}
}
TableViewColumn
{
role: "label"
title: catalog.i18nc("@title:column", "Setting")
width: (parent.width * 0.4) | 0
delegate: itemDelegate
}
TableViewColumn
{
role: "profile_value"
title: catalog.i18nc("@title:column", "Profile")
width: (parent.width * 0.18) | 0
delegate: itemDelegate
}
TableViewColumn
{
role: "user_value"
title: catalog.i18nc("@title:column", "Current");
visible: base.isQualityItemCurrentlyActivated
width: (parent.width * 0.18) | 0
delegate: itemDelegate
}
TableViewColumn
{
role: "unit"
title: catalog.i18nc("@title:column", "Unit")
width: (parent.width * 0.14) | 0
delegate: itemDelegate
}
section.property: "category"
section.delegate: Label
{
text: section
font.bold: true
}
model: Cura.QualitySettingsModel
{
id: qualitySettings
selectedPosition: base.extruderPosition
selectedQualityItem: base.qualityItem == null ? {} : base.qualityItem
}
SystemPalette { id: palette }
}
}

View file

@ -1,51 +1,29 @@
// Copyright (c) 2019 Ultimaker B.V.
// Uranium is released under the terms of the LGPLv3 or higher.
//Copyright (c) 2022 Ultimaker B.V.
//Cura is released under the terms of the LGPLv3 or higher.
import QtQuick 2.7
import QtQuick.Controls 1.4
import QtQuick.Controls 2.15
import QtQuick.Layouts 1.3
import QtQuick.Dialogs 1.2
import UM 1.2 as UM
import UM 1.5 as UM
import Cura 1.6 as Cura
Item
UM.ManagementPage
{
id: base
property var resetEnabled: false // Keep PreferencesDialog happy
property var extrudersModel: CuraApplication.getExtrudersModel()
property var qualityManagementModel: CuraApplication.getQualityManagementModel()
property bool hasCurrentItem: base.currentItem != null
UM.I18nCatalog { id: catalog; name: "cura"; }
property var currentItem: objectList.currentIndex == -1 ? null : base.qualityManagementModel.getItem(objectList.currentIndex)
Label
{
id: titleLabel
anchors
{
top: parent.top
left: parent.left
right: parent.right
margins: 5 * screenScaleFactor
}
font.pointSize: 18
text: catalog.i18nc("@title:tab", "Profiles")
}
property string currentItemName: hasCurrentItem ? base.currentItem.name : ""
property string currentItemDisplayName: hasCurrentItem ? base.qualityManagementModel.getQualityItemDisplayName(base.currentItem) : ""
property var hasCurrentItem: base.currentItem != null
property var currentItem:
{
var current_index = qualityListView.currentIndex;
return (current_index == -1) ? null : base.qualityManagementModel.getItem(current_index);
}
property var currentItemName: hasCurrentItem ? base.currentItem.name : ""
property var currentItemDisplayName: hasCurrentItem ? base.qualityManagementModel.getQualityItemDisplayName(base.currentItem) : ""
property var isCurrentItemActivated:
property bool isCurrentItemActivated:
{
if (!base.currentItem)
{
@ -61,133 +39,13 @@ Item
}
}
property var canCreateProfile:
{
return isCurrentItemActivated && Cura.MachineManager.hasUserSettings;
}
property bool canCreateProfile: Cura.MachineManager.hasUserSettings
Row // Button Row
{
id: buttonRow
anchors
{
left: parent.left
right: parent.right
top: titleLabel.bottom
}
height: childrenRect.height
signal createProfile() // Click create profile from ... in Profile context menu
// Activate button
Button
{
id: activateMenuButton
text: catalog.i18nc("@action:button", "Activate")
iconName: "list-activate"
enabled: !isCurrentItemActivated && base.currentItem
onClicked:
{
if(base.currentItem.is_read_only)
{
Cura.IntentManager.selectIntent(base.currentItem.intent_category, base.currentItem.quality_type);
}
else
{
Cura.MachineManager.setQualityChangesGroup(base.currentItem.quality_changes_group);
}
}
}
property string newQualityNameToSelect: ""
property bool toActivateNewQuality: false
// Create button
Button
{
id: createMenuButton
text: catalog.i18nc("@label", "Create")
iconName: "list-add"
enabled: base.canCreateProfile && !Cura.MachineManager.stacksHaveErrors
visible: base.canCreateProfile
onClicked:
{
createQualityDialog.object = Cura.ContainerManager.makeUniqueName(base.currentItem.name);
createQualityDialog.open();
createQualityDialog.selectText();
}
}
// Duplicate button
Button
{
id: duplicateMenuButton
text: catalog.i18nc("@label", "Duplicate")
iconName: "list-add"
enabled: !base.canCreateProfile
visible: !base.canCreateProfile
onClicked:
{
duplicateQualityDialog.object = Cura.ContainerManager.makeUniqueName(base.currentItem.name);
duplicateQualityDialog.open();
duplicateQualityDialog.selectText();
}
}
// Remove button
Button
{
id: removeMenuButton
text: catalog.i18nc("@action:button", "Remove")
iconName: "list-remove"
enabled: base.hasCurrentItem && !base.currentItem.is_read_only && !base.isCurrentItemActivated
onClicked:
{
forceActiveFocus();
confirmRemoveQualityDialog.open();
}
}
// Rename button
Button
{
id: renameMenuButton
text: catalog.i18nc("@action:button", "Rename")
iconName: "edit-rename"
enabled: base.hasCurrentItem && !base.currentItem.is_read_only
onClicked:
{
renameQualityDialog.object = base.currentItem.name;
renameQualityDialog.open();
renameQualityDialog.selectText();
}
}
// Import button
Button
{
id: importMenuButton
text: catalog.i18nc("@action:button", "Import")
iconName: "document-import"
onClicked:
{
importDialog.open();
}
}
// Export button
Button
{
id: exportMenuButton
text: catalog.i18nc("@action:button", "Export")
iconName: "document-export"
enabled: base.hasCurrentItem && !base.currentItem.is_read_only
onClicked:
{
exportDialog.open();
}
}
}
// Click create profile from ... in Profile context menu
signal createProfile()
onCreateProfile:
{
createQualityDialog.object = Cura.ContainerManager.makeUniqueName(Cura.MachineManager.activeQualityOrQualityChangesName);
@ -195,433 +53,377 @@ Item
createQualityDialog.selectText();
}
// Dialog to request a name when creating a new profile
UM.RenameDialog
{
id: createQualityDialog
title: catalog.i18nc("@title:window", "Create Profile")
object: "<new name>"
explanation: catalog.i18nc("@info", "Please provide a name for this profile.")
onAccepted:
title: catalog.i18nc("@title:tab", "Profiles")
detailsPlaneCaption: base.currentItemDisplayName
scrollviewCaption: catalog.i18nc("@label", "Profiles compatible with active printer:") + "<br><b>" + Cura.MachineManager.activeMachine.name + "</b>"
hamburgerButtonVisible: hasCurrentItem
onHamburgeButtonClicked: {
const hamburerButtonHeight = hamburger_button.height;
menu.popup(hamburger_button, -menu.width + hamburger_button.width / 2, hamburger_button.height);
// for some reason the height of the hamburger changes when opening the popup
// reset height to initial heigt
hamburger_button.height = hamburerButtonHeight;
}
isActiveModelFunction: function(model, id) {
if (model.is_read_only)
{
base.newQualityNameToSelect = newName; // We want to switch to the new profile once it's created
base.toActivateNewQuality = true;
base.qualityManagementModel.createQualityChanges(newName);
return (model.name == Cura.MachineManager.activeQualityOrQualityChangesName) && (model.intent_category == Cura.MachineManager.activeIntentCategory);
}
else
{
return model.name == Cura.MachineManager.activeQualityOrQualityChangesName;
}
}
property string newQualityNameToSelect: ""
property bool toActivateNewQuality: false
sectionRole: "section_name"
// This connection makes sure that we will switch to the correct quality after the model gets updated
Connections
{
target: base.qualityManagementModel
function onItemsChanged()
model: qualityManagementModel
buttons: [
Cura.SecondaryButton
{
var toSelectItemName = base.currentItem == null ? "" : base.currentItem.name;
if (newQualityNameToSelect != "")
text: catalog.i18nc("@action:button", "Import")
onClicked:importDialog.open()
},
Cura.SecondaryButton
{
id: createMenuButton
text: catalog.i18nc("@action:button", "Create new")
enabled: !Cura.MachineManager.stacksHaveErrors
visible: base.canCreateProfile
tooltip: catalog.i18nc("@action:tooltip", "Create new profile from current settings/overrides")
onClicked:
{
toSelectItemName = newQualityNameToSelect;
createQualityDialog.object = Cura.ContainerManager.makeUniqueName("<new name>")
createQualityDialog.open()
createQualityDialog.selectText()
}
}
]
Column
{
id: detailsPanelHeaderColumn
anchors
{
left: parent.left
right: parent.right
top: parent.top
}
spacing: UM.Theme.getSize("default_margin").height
visible: base.currentItem != null
UM.Label
{
anchors.left: parent.left
anchors.right: parent.right
text: catalog.i18nc("@action:label", "Some settings from current profile were overwritten.")
visible: currentSettingsActions.visible
}
Flow
{
id: currentSettingsActions
width: parent.width
visible: base.hasCurrentItem && base.currentItem.name == Cura.MachineManager.activeQualityOrQualityChangesName && base.currentItem.intent_category == Cura.MachineManager.activeIntentCategory
spacing: UM.Theme.getSize("default_margin").width
Cura.SecondaryButton
{
text: catalog.i18nc("@action:button", "Update profile.")
enabled: Cura.MachineManager.hasUserSettings && objectList.currentIndex && !objectList.currentIndex.is_read_only
onClicked: Cura.ContainerManager.updateQualityChanges()
tooltip: catalog.i18nc("@action:tooltip", "Update profile with current settings/overrides")
}
var newIdx = -1; // Default to nothing if nothing can be found
if (toSelectItemName != "")
Cura.SecondaryButton
{
// Select the required quality name if given
for (var idx = 0; idx < base.qualityManagementModel.count; ++idx)
text: catalog.i18nc("@action:button", "Discard current changes")
enabled: Cura.MachineManager.hasUserSettings
onClicked: Cura.ContainerManager.clearUserContainers()
}
}
UM.Label
{
id: defaultsMessage
visible: false
text: catalog.i18nc("@action:label", "This profile uses the defaults specified by the printer, so it has no settings/overrides in the list below.")
width: parent.width
}
UM.Label
{
id: noCurrentSettingsMessage
visible: base.isCurrentItemActivated && !Cura.MachineManager.hasUserSettings
text: catalog.i18nc("@action:label", "Your current settings match the selected profile.")
width: parent.width
}
UM.TabRow
{
id: profileExtruderTabs
// One extra tab for the global settings.
UM.TabRowButton
{
text: catalog.i18nc("@title:tab", "Global Settings")
}
Repeater
{
model: base.extrudersModel
UM.TabRowButton
{
var item = base.qualityManagementModel.getItem(idx);
if (item && item.name == toSelectItemName)
{
// Switch to the newly created profile if needed
newIdx = idx;
if (base.toActivateNewQuality)
{
// Activate this custom quality if required
if(item.quality_changes_group)
{
Cura.MachineManager.setQualityChangesGroup(item.quality_changes_group);
}
}
break;
}
text: model.name
}
}
qualityListView.currentIndex = newIdx;
// Reset states
base.newQualityNameToSelect = "";
base.toActivateNewQuality = false;
}
}
// Dialog to request a name when duplicating a new profile
UM.RenameDialog
Rectangle
{
id: duplicateQualityDialog
title: catalog.i18nc("@title:window", "Duplicate Profile")
object: "<new name>"
onAccepted:
{
base.qualityManagementModel.duplicateQualityChanges(newName, base.currentItem);
}
}
// Confirmation dialog for removing a profile
MessageDialog
{
id: confirmRemoveQualityDialog
icon: StandardIcon.Question;
title: catalog.i18nc("@title:window", "Confirm Remove")
text: catalog.i18nc("@label (%1 is object name)", "Are you sure you wish to remove %1? This cannot be undone!").arg(base.currentItemName)
standardButtons: StandardButton.Yes | StandardButton.No
modality: Qt.ApplicationModal
onYes:
{
base.qualityManagementModel.removeQualityChangesGroup(base.currentItem.quality_changes_group);
// reset current item to the first if available
qualityListView.currentIndex = -1; // Reset selection.
}
}
// Dialog to rename a quality profile
UM.RenameDialog
{
id: renameQualityDialog
title: catalog.i18nc("@title:window", "Rename Profile")
object: "<new name>"
onAccepted:
{
var actualNewName = base.qualityManagementModel.renameQualityChangesGroup(base.currentItem.quality_changes_group, newName);
base.newQualityNameToSelect = actualNewName; // Select the new name after the model gets updated
}
}
// Dialog for importing a quality profile
FileDialog
{
id: importDialog
title: catalog.i18nc("@title:window", "Import Profile")
selectExisting: true
nameFilters: base.qualityManagementModel.getFileNameFilters("profile_reader")
folder: CuraApplication.getDefaultPath("dialog_profile_path")
onAccepted:
{
var result = Cura.ContainerManager.importProfile(fileUrl);
messageDialog.text = result.message;
if (result.status == "ok")
{
messageDialog.icon = StandardIcon.Information;
}
else if (result.status == "warning" || result.status == "duplicate")
{
messageDialog.icon = StandardIcon.Warning;
}
else
{
messageDialog.icon = StandardIcon.Critical;
}
messageDialog.open();
CuraApplication.setDefaultPath("dialog_profile_path", folder);
}
}
// Dialog for exporting a quality profile
FileDialog
{
id: exportDialog
title: catalog.i18nc("@title:window", "Export Profile")
selectExisting: false
nameFilters: base.qualityManagementModel.getFileNameFilters("profile_writer")
folder: CuraApplication.getDefaultPath("dialog_profile_path")
onAccepted:
{
var result = Cura.ContainerManager.exportQualityChangesGroup(base.currentItem.quality_changes_group,
fileUrl, selectedNameFilter);
if (result && result.status == "error")
{
messageDialog.icon = StandardIcon.Critical;
messageDialog.text = result.message;
messageDialog.open();
}
// else pop-up Message thing from python code
CuraApplication.setDefaultPath("dialog_profile_path", folder);
}
}
Item
{
id: contentsItem
color: UM.Theme.getColor("main_background")
anchors
{
top: titleLabel.bottom
top: detailsPanelHeaderColumn.bottom
topMargin: -UM.Theme.getSize("default_lining").width
left: parent.left
right: parent.right
bottom: parent.bottom
margins: 5 * screenScaleFactor
bottomMargin: 0
}
clip: true
border.width: UM.Theme.getSize("default_lining").width
border.color: UM.Theme.getColor("thick_lining")
visible: base.hasCurrentItem
}
Item
Cura.ProfileOverview
{
anchors
{
top: buttonRow.bottom
topMargin: UM.Theme.getSize("default_margin").height
top: detailsPanelHeaderColumn.bottom
margins: UM.Theme.getSize("default_margin").height
left: parent.left
right: parent.right
bottom: parent.bottom
}
SystemPalette
visible: detailsPanelHeaderColumn.visible
qualityItem: base.currentItem
extruderPosition: profileExtruderTabs.currentIndex - 1
}
Item
{
id: content_item
anchors.fill: parent
// This connection makes sure that we will switch to the correct quality after the model gets updated
Connections
{
id: palette
}
Label
{
id: captionLabel
anchors
target: base.qualityManagementModel
function onItemsChanged()
{
top: parent.top
left: parent.left
}
visible: text != ""
text: catalog.i18nc("@label %1 is printer name", "Printer: %1").arg(Cura.MachineManager.activeMachine.name)
width: profileScrollView.width
elide: Text.ElideRight
}
ScrollView
{
id: profileScrollView
anchors
{
top: captionLabel.visible ? captionLabel.bottom : parent.top
topMargin: captionLabel.visible ? UM.Theme.getSize("default_margin").height : 0
bottom: parent.bottom
left: parent.left
}
Rectangle
{
parent: viewport
anchors.fill: parent
color: palette.light
}
width: true ? (parent.width * 0.4) | 0 : parent.width
frameVisible: true
clip: true
ListView
{
id: qualityListView
model: base.qualityManagementModel
Component.onCompleted:
var toSelectItemName = base.currentItem == null ? "" : base.currentItem.name;
if (newQualityNameToSelect != "")
{
var selectedItemName = Cura.MachineManager.activeQualityOrQualityChangesName;
toSelectItemName = newQualityNameToSelect;
}
var newIdx = -1; // Default to nothing if nothing can be found
if (toSelectItemName != "")
{
// Select the required quality name if given
for (var idx = 0; idx < base.qualityManagementModel.count; idx++)
for (var idx = 0; idx < base.qualityManagementModel.count; ++idx)
{
var item = base.qualityManagementModel.getItem(idx);
if (item.name == selectedItemName)
if (item && item.name == toSelectItemName)
{
currentIndex = idx;
// Switch to the newly created profile if needed
newIdx = idx;
if (base.toActivateNewQuality)
{
// Activate this custom quality if required
if(item.quality_changes_group)
{
Cura.MachineManager.setQualityChangesGroup(item.quality_changes_group);
}
}
break;
}
}
}
objectList.currentIndex = newIdx;
section.property: "section_name"
section.delegate: Rectangle
{
height: childrenRect.height
// Reset states
base.newQualityNameToSelect = "";
base.toActivateNewQuality = false;
}
}
Cura.MessageDialog
{
id: messageDialog
standardButtons: Dialog.Ok
}
Label
{
anchors.left: parent.left
anchors.leftMargin: UM.Theme.getSize("default_lining").width
text: section
font.bold: true
}
}
delegate: Rectangle
{
width: profileScrollView.width
height: childrenRect.height
// Added this property to identify custom profiles in automated system tests (Squish)
property bool isReadOnly: model.is_read_only
property bool isCurrentItem: ListView.isCurrentItem
color: isCurrentItem ? palette.highlight : (model.index % 2) ? palette.base : palette.alternateBase
Label
{
anchors.left: parent.left
anchors.leftMargin: UM.Theme.getSize("default_margin").width
anchors.right: parent.right
width: Math.floor((parent.width * 0.8))
text: model.name
elide: Text.ElideRight
font.italic:
{
if (model.is_read_only)
{
// For built-in qualities, it needs to match both the intent category and the quality name
return model.name == Cura.MachineManager.activeQualityOrQualityChangesName && model.intent_category == Cura.MachineManager.activeIntentCategory
}
else
{
// For custom qualities, it only needs to match the name
return model.name == Cura.MachineManager.activeQualityOrQualityChangesName
}
}
color: parent.isCurrentItem ? palette.highlightedText : palette.text
}
MouseArea
{
anchors.fill: parent
onClicked:
{
parent.ListView.view.currentIndex = model.index;
}
}
}
// Dialog to request a name when creating a new profile
Cura.RenameDialog
{
id: createQualityDialog
title: catalog.i18nc("@title:window", "Create Profile")
object: "<new name>"
explanation: catalog.i18nc("@info", "Please provide a name for this profile.")
onAccepted:
{
base.newQualityNameToSelect = newName; // We want to switch to the new profile once it's created
base.toActivateNewQuality = true;
base.qualityManagementModel.createQualityChanges(newName);
}
}
// details panel on the right
Item
Cura.Menu
{
id: detailsPanel
anchors
id: menu
Cura.MenuItem
{
left: profileScrollView.right
leftMargin: UM.Theme.getSize("default_margin").width
top: parent.top
bottom: parent.bottom
right: parent.right
text: catalog.i18nc("@action:button", "Activate")
enabled: !isCurrentItemActivated && base.currentItem
onTriggered:
{
if(base.currentItem.is_read_only)
{
Cura.IntentManager.selectIntent(base.currentItem.intent_category, base.currentItem.quality_type)
}
else
{
Cura.MachineManager.setQualityChangesGroup(base.currentItem.quality_changes_group)
}
}
}
Item
Cura.MenuItem
{
anchors.fill: parent
visible: base.currentItem != null
Item // Profile title Label
text: catalog.i18nc("@action:button", "Duplicate")
enabled: base.hasCurrentItem
onTriggered:
{
id: profileName
forceActiveFocus()
duplicateQualityDialog.open()
}
}
Cura.MenuItem
{
text: catalog.i18nc("@action:button", "Remove")
enabled: base.hasCurrentItem && !base.currentItem.is_read_only && !base.isCurrentItemActivated
onTriggered:
{
forceActiveFocus()
confirmRemoveQualityDialog.open()
}
}
Cura.MenuItem
{
text: catalog.i18nc("@action:button", "Rename")
enabled: base.hasCurrentItem && !base.currentItem.is_read_only
onTriggered:
{
renameQualityDialog.object = base.currentItem.name
renameQualityDialog.open()
renameQualityDialog.selectText()
}
}
Cura.MenuItem
{
text: catalog.i18nc("@action:button", "Export")
enabled: base.hasCurrentItem && !base.currentItem.is_read_only
onTriggered: exportDialog.open()
}
}
width: parent.width
height: childrenRect.height
// Dialog for exporting a quality profile
FileDialog
{
id: exportDialog
title: catalog.i18nc("@title:window", "Export Profile")
selectExisting: false
nameFilters: base.qualityManagementModel.getFileNameFilters("profile_writer")
folder: CuraApplication.getDefaultPath("dialog_profile_path")
onAccepted:
{
var result = Cura.ContainerManager.exportQualityChangesGroup(base.currentItem.quality_changes_group,
fileUrl, selectedNameFilter);
Label
{
anchors.left: parent.left
anchors.right: parent.right
text: base.currentItemDisplayName
font: UM.Theme.getFont("large_bold")
elide: Text.ElideRight
renderType: Text.NativeRendering
}
if (result && result.status == "error")
{
messageDialog.title = catalog.i18nc("@title:window", "Export Profile")
messageDialog.text = result.message;
messageDialog.open();
}
Flow
{
id: currentSettingsActions
visible: base.hasCurrentItem && base.currentItem.name == Cura.MachineManager.activeQualityOrQualityChangesName && base.currentItem.intent_category == Cura.MachineManager.activeIntentCategory
anchors.left: parent.left
anchors.right: parent.right
anchors.top: profileName.bottom
anchors.topMargin: UM.Theme.getSize("default_margin").height
// else pop-up Message thing from python code
CuraApplication.setDefaultPath("dialog_profile_path", folder);
}
}
Button
{
text: catalog.i18nc("@action:button", "Update profile with current settings/overrides")
enabled: Cura.MachineManager.hasUserSettings && !base.currentItem.is_read_only
onClicked: Cura.ContainerManager.updateQualityChanges()
}
// Dialog to request a name when duplicating a new profile
Cura.RenameDialog
{
id: duplicateQualityDialog
title: catalog.i18nc("@title:window", "Duplicate Profile")
object: "<new name>"
onAccepted: base.qualityManagementModel.duplicateQualityChanges(newName, base.currentItem)
}
Button
{
text: catalog.i18nc("@action:button", "Discard current changes");
enabled: Cura.MachineManager.hasUserSettings
onClicked: Cura.ContainerManager.clearUserContainers();
}
}
// Confirmation dialog for removing a profile
Cura.MessageDialog
{
id: confirmRemoveQualityDialog
Column
{
id: profileNotices
anchors.top: currentSettingsActions.visible ? currentSettingsActions.bottom : currentSettingsActions.anchors.top
anchors.topMargin: UM.Theme.getSize("default_margin").height
anchors.left: parent.left
anchors.right: parent.right
spacing: UM.Theme.getSize("default_margin").height
title: catalog.i18nc("@title:window", "Confirm Remove")
text: catalog.i18nc("@label (%1 is object name)", "Are you sure you wish to remove %1? This cannot be undone!").arg(base.currentItemName)
standardButtons: StandardButton.Yes | StandardButton.No
modal: true
Label
{
id: defaultsMessage
visible: false
text: catalog.i18nc("@action:label", "This profile uses the defaults specified by the printer, so it has no settings/overrides in the list below.")
wrapMode: Text.WordWrap
width: parent.width
}
Label
{
id: noCurrentSettingsMessage
visible: base.isCurrentItemActivated && !Cura.MachineManager.hasUserSettings
text: catalog.i18nc("@action:label", "Your current settings match the selected profile.")
wrapMode: Text.WordWrap
width: parent.width
}
}
onAccepted:
{
base.qualityManagementModel.removeQualityChangesGroup(base.currentItem.quality_changes_group);
// reset current item to the first if available
qualityListView.currentIndex = -1; // Reset selection.
}
}
TabView
{
anchors.left: parent.left
anchors.top: profileNotices.visible ? profileNotices.bottom : profileNotices.anchors.top
anchors.topMargin: UM.Theme.getSize("default_margin").height
anchors.right: parent.right
anchors.bottom: parent.bottom
// Dialog to rename a quality profile
Cura.RenameDialog
{
id: renameQualityDialog
title: catalog.i18nc("@title:window", "Rename Profile")
object: "<new name>"
onAccepted:
{
var actualNewName = base.qualityManagementModel.renameQualityChangesGroup(base.currentItem.quality_changes_group, newName);
base.newQualityNameToSelect = actualNewName; // Select the new name after the model gets updated
}
}
currentIndex: 0
ProfileTab
{
title: catalog.i18nc("@title:tab", "Global Settings")
qualityItem: base.currentItem
}
Repeater
{
model: base.extrudersModel
ProfileTab
{
title: model.name
extruderPosition: model.index
qualityItem: base.currentItem
}
}
}
// Dialog for importing a quality profile
FileDialog
{
id: importDialog
title: catalog.i18nc("@title:window", "Import Profile")
selectExisting: true
nameFilters: base.qualityManagementModel.getFileNameFilters("profile_reader")
folder: CuraApplication.getDefaultPath("dialog_profile_path")
onAccepted:
{
var result = Cura.ContainerManager.importProfile(fileUrl);
messageDialog.title = catalog.i18nc("@title:window", "Import Profile")
messageDialog.text = result.message;
messageDialog.open();
CuraApplication.setDefaultPath("dialog_profile_path", folder);
}
}
}

View file

@ -1,54 +0,0 @@
// Copyright (c) 2016 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.Dialogs 1.2
Item
{
id: base
property alias value: spinBox.value
property alias minimumValue: spinBox.minimumValue
property alias maximumValue: spinBox.maximumValue
property alias stepSize: spinBox.stepSize
property alias prefix: spinBox.prefix
property alias suffix: spinBox.suffix
property alias decimals: spinBox.decimals
signal editingFinished();
property bool readOnly: false
width: spinBox.width
height: spinBox.height
SpinBox
{
id: spinBox
enabled: !base.readOnly
opacity: base.readOnly ? 0.5 : 1.0
anchors.fill: parent
onEditingFinished: base.editingFinished()
Keys.onEnterPressed: spinBox.focus = false
Keys.onReturnPressed: spinBox.focus = false
}
Label
{
visible: base.readOnly
text: base.prefix + base.value.toFixed(spinBox.decimals) + base.suffix
anchors.verticalCenter: parent.verticalCenter
anchors.left: parent.left
anchors.leftMargin: spinBox.__style ? spinBox.__style.padding.left : 0
color: palette.buttonText
}
SystemPalette { id: palette }
}

View file

@ -2,9 +2,10 @@
// Cura is released under the terms of the LGPLv3 or higher.
import QtQuick 2.1
import QtQuick.Controls 1.1
import QtQuick.Controls 2.15
import UM 1.5 as UM
Item
ScrollView
{
id: base
@ -15,27 +16,22 @@ Item
property bool readOnly: false
width: textArea.width
height: textArea.height
TextArea
{
id: textArea
enabled: !base.readOnly
opacity: base.readOnly ? 0.5 : 1.0
selectByMouse: true
anchors.fill: parent
background: UM.UnderlineBackground { id: backgroundRectangle }
Keys.onReturnPressed:
{
base.editingFinished()
}
color: UM.Theme.getColor("text")
selectionColor: UM.Theme.getColor("text_selection")
font: UM.Theme.getFont("default")
Keys.onEnterPressed:
{
base.editingFinished()
}
Keys.onReturnPressed: base.editingFinished()
Keys.onEnterPressed: base.editingFinished()
onActiveFocusChanged:
{

View file

@ -1,49 +0,0 @@
// Copyright (c) 2016 Ultimaker B.V.
// Cura is released under the terms of the LGPLv3 or higher.
// Different than the name suggests, it is not always read-only.
import QtQuick 2.1
import QtQuick.Controls 1.1
import QtQuick.Dialogs 1.2
Item
{
id: base
property alias text: textField.text
signal editingFinished();
property bool readOnly: false
width: textField.width
height: textField.height
TextField
{
id: textField
enabled: !base.readOnly
opacity: base.readOnly ? 0.5 : 1.0
anchors.fill: parent
onEditingFinished: base.editingFinished()
Keys.onEnterPressed: base.editingFinished()
Keys.onReturnPressed: base.editingFinished()
}
Label
{
visible: base.readOnly
text: textField.text
anchors.verticalCenter: parent.verticalCenter
anchors.left: parent.left
anchors.leftMargin: textField.__panel ? textField.__panel.leftMargin : 0
color: palette.buttonText
}
SystemPalette { id: palette }
}

View file

@ -0,0 +1,86 @@
// Copyright (c) 2022 Ultimaker B.V.
// Uranium is released under the terms of the LGPLv3 or higher.
import QtQuick 2.1
import QtQuick.Controls 2.0
import QtQuick.Window 2.1
import UM 1.5 as UM
import Cura 1.0 as Cura
UM.Dialog
{
id: base
buttonSpacing: UM.Theme.getSize("default_margin").width
property string object: ""
property alias newName: nameField.text
property bool validName: true
property string validationError
property string dialogTitle: catalog.i18nc("@title:window", "Rename")
property string explanation: catalog.i18nc("@info", "Please provide a new name.")
title: dialogTitle
minimumWidth: UM.Theme.getSize("small_popup_dialog").width
minimumHeight: UM.Theme.getSize("small_popup_dialog").height
width: minimumWidth
height: minimumHeight
property variant catalog: UM.I18nCatalog { name: "cura" }
signal textChanged(string text)
signal selectText()
onSelectText:
{
nameField.selectAll();
nameField.focus = true;
}
Column
{
anchors.fill: parent
UM.Label
{
text: base.explanation + "\n" //Newline to make some space using system theming.
width: parent.width
wrapMode: Text.WordWrap
}
Cura.TextField
{
id: nameField
width: parent.width
text: base.object
maximumLength: 40
selectByMouse: true
onTextChanged: base.textChanged(text)
}
UM.Label
{
visible: !base.validName
text: base.validationError
}
}
rightButtons: [
Cura.SecondaryButton
{
id: cancelButton
text: catalog.i18nc("@action:button","Cancel")
onClicked: base.reject()
},
Cura.PrimaryButton
{
id: okButton
text: catalog.i18nc("@action:button", "OK")
onClicked: base.accept()
enabled: base.validName
}
]
}

View file

@ -0,0 +1,23 @@
// Copyright (c) 2022 Ultimaker B.V.
// Uranium is released under the terms of the LGPLv3 or higher.
import QtQuick 2.2
import QtQuick.Controls 2.1
import UM 1.5 as UM
import Cura 1.5 as Cura
Cura.CategoryButton
{
id: base
categoryIcon: definition ? UM.Theme.getIcon(definition.icon) : ""
labelText: definition ? definition.label : ""
expanded: definition ? definition.expanded : false
signal showTooltip(string text)
signal hideTooltip()
signal contextMenuRequested()
onClicked: expanded ? settingDefinitionsModel.collapseRecursive(definition.key) : settingDefinitionsModel.expandRecursive(definition.key)
}

View file

@ -0,0 +1,99 @@
// Copyright (c) 2022 Ultimaker B.V.
// Uranium is released under the terms of the LGPLv3 or higher.
import QtQuick 2.1
import QtQuick.Controls 2.1
import UM 1.5 as UM
Item
{
// Use the depth of the model to move the item, but also leave space for the visibility / enabled exclamation mark.
// Align checkbox with SettingVisibilityCategory icon with + 5
x: definition ? definition.depth * UM.Theme.getSize("narrow_margin").width : UM.Theme.getSize("default_margin").width
UM.TooltipArea
{
text: definition ? definition.description : ""
width: childrenRect.width;
height: childrenRect.height;
id: checkboxTooltipArea
UM.CheckBox
{
id: check
text: definition ? definition.label: ""
checked: definition ? definition.visible: false
enabled: definition ? !definition.prohibited: false
MouseArea
{
anchors.fill: parent
onClicked: definitionsModel.setVisible(definition.key, !check.checked)
}
}
}
UM.TooltipArea
{
width: height
height: check.height
anchors.left: checkboxTooltipArea.right
anchors.leftMargin: 2 * screenScaleFactor
text:
{
if(provider.properties.enabled == "True")
{
return ""
}
var key = definition ? definition.key : ""
var requires = settingDefinitionsModel.getRequires(key, "enabled")
if (requires.length == 0)
{
return catalog.i18nc("@item:tooltip", "This setting has been hidden by the active machine and will not be visible.");
}
else
{
var requires_text = ""
for (var i in requires)
{
if (requires_text == "")
{
requires_text = requires[i].label
}
else
{
requires_text += ", " + requires[i].label
}
}
return catalog.i18ncp("@item:tooltip %1 is list of setting names", "This setting has been hidden by the value of %1. Change the value of that setting to make this setting visible.", "This setting has been hidden by the values of %1. Change the values of those settings to make this setting visible.", requires.length) .arg(requires_text);
}
}
UM.RecolorImage
{
anchors.centerIn: parent
width: Math.round(check.height * 0.75) | 0
height: width
source: UM.Theme.getIcon("Information")
color: UM.Theme.getColor("primary_button_text")
}
visible: provider.properties.enabled == "False"
}
UM.SettingPropertyProvider
{
id: provider
containerStackId: "global"
watchedProperties: [ "enabled" ]
key: definition ? definition.key : ""
}
}

View file

@ -1,11 +1,8 @@
// Copyright (c) 2016 Ultimaker B.V.
// Copyright (c) 2022 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.Controls 2.3 as NewControls
import QtQuick.Controls 2.15
import UM 1.5 as UM
@ -13,12 +10,20 @@ import Cura 1.0 as Cura
UM.PreferencesPage
{
title: catalog.i18nc("@title:tab", "Setting Visibility");
title: catalog.i18nc("@title:tab", "Setting Visibility")
property QtObject settingVisibilityPresetsModel: CuraApplication.getSettingVisibilityPresetsModel()
property int scrollToIndex: 0
buttons: [
Cura.SecondaryButton
{
text: catalog.i18nc("@action:button", "Defaults")
onClicked: reset()
}
]
signal scrollToSection( string key )
onScrollToSection:
{
@ -33,16 +38,16 @@ UM.PreferencesPage
Item
{
id: base;
anchors.fill: parent;
id: base
anchors.fill: parent
UM.CheckBox
{
id: toggleVisibleSettings
anchors
{
verticalCenter: filter.verticalCenter;
left: parent.left;
verticalCenter: filter.verticalCenter
left: parent.left
leftMargin: UM.Theme.getSize("default_margin").width
}
text: catalog.i18nc("@label:textbox", "Check all")
@ -61,13 +66,13 @@ UM.PreferencesPage
return Qt.PartiallyChecked
}
}
tristate: true
MouseArea
{
anchors.fill: parent;
onClicked:
{
if(parent.checkState == Qt.Unchecked || parent.checkState == Qt.PartiallyChecked)
if (parent.checkState == Qt.Unchecked || parent.checkState == Qt.PartiallyChecked)
{
definitionsModel.setAllExpandedVisible(true)
}
@ -79,9 +84,9 @@ UM.PreferencesPage
}
}
TextField
Cura.TextField
{
id: filter;
id: filter
anchors
{
@ -97,15 +102,15 @@ UM.PreferencesPage
onTextChanged: definitionsModel.filter = {"i18n_label|i18n_description": "*" + text}
}
NewControls.ComboBox
Cura.ComboBox
{
id: visibilityPreset
width: 150 * screenScaleFactor
width: UM.Theme.getSize("action_button").width
anchors
{
top: parent.top
right: parent.right
bottom: scrollView.top
verticalCenter: filter.verticalCenter
}
model: settingVisibilityPresetsModel.items
@ -132,76 +137,58 @@ UM.PreferencesPage
}
}
ScrollView
ListView
{
id: scrollView
frameVisible: true
id: settingsListView
anchors
{
top: filter.bottom;
top: filter.bottom
topMargin: UM.Theme.getSize("default_margin").height
left: parent.left;
right: parent.right;
bottom: parent.bottom;
left: parent.left
right: parent.right
bottom: parent.bottom
}
ListView
clip: true
ScrollBar.vertical: UM.ScrollBar { id: scrollBar }
model: UM.SettingDefinitionsModel
{
id: settingsListView
id: definitionsModel
containerId: Cura.MachineManager.activeMachine != null ? Cura.MachineManager.activeMachine.definition.id: ""
showAll: true
exclude: ["machine_settings", "command_line_settings"]
showAncestors: true
expanded: ["*"]
visibilityHandler: UM.SettingPreferenceVisibilityHandler {}
}
model: UM.SettingDefinitionsModel
property Component settingVisibilityCategory: Cura.SettingVisibilityCategory {}
property Component settingVisibilityItem: Cura.SettingVisibilityItem {}
delegate: Loader
{
id: loader
width: settingsListView.width - scrollBar.width
height: model.type != undefined ? UM.Theme.getSize("section").height : 0
property var definition: model
property var settingDefinitionsModel: definitionsModel
asynchronous: true
active: model.type != undefined
sourceComponent:
{
id: definitionsModel
containerId: Cura.MachineManager.activeMachine != null ? Cura.MachineManager.activeMachine.definition.id: ""
showAll: true
exclude: ["machine_settings", "command_line_settings"]
showAncestors: true
expanded: ["*"]
visibilityHandler: UM.SettingPreferenceVisibilityHandler {}
}
delegate: Loader
{
id: loader
width: settingsListView.width
height: model.type != undefined ? UM.Theme.getSize("section").height : 0
property var definition: model
property var settingDefinitionsModel: definitionsModel
asynchronous: true
active: model.type != undefined
sourceComponent:
switch (model.type)
{
switch(model.type)
{
case "category":
return settingVisibilityCategory
default:
return settingVisibilityItem
}
case "category":
return settingsListView.settingVisibilityCategory
default:
return settingsListView.settingVisibilityItem
}
}
}
}
UM.I18nCatalog { name: "cura"; }
SystemPalette { id: palette; }
Component
{
id: settingVisibilityCategory;
UM.SettingVisibilityCategory { }
}
Component
{
id: settingVisibilityItem;
UM.SettingVisibilityItem { }
}
}
}
}