From 9df7ccd5cc10ee08f2cd01ec3cdc2aa61fafae6b Mon Sep 17 00:00:00 2001 From: Jaime van Kessel Date: Fri, 18 Feb 2022 14:20:16 +0100 Subject: [PATCH] Let profiles page use ManagementPage No idea why it didn't in the first place. This caused a lot of code duplication. CURA-8949 --- resources/qml/Preferences/ProfilesPage.qml | 788 ++++++++------------- 1 file changed, 280 insertions(+), 508 deletions(-) diff --git a/resources/qml/Preferences/ProfilesPage.qml b/resources/qml/Preferences/ProfilesPage.qml index a1a88a4c0b..0d2b811f8b 100644 --- a/resources/qml/Preferences/ProfilesPage.qml +++ b/resources/qml/Preferences/ProfilesPage.qml @@ -10,35 +10,24 @@ 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() - UM.I18nCatalog { id: catalog; name: "cura"; } + scrollviewCaption: catalog.i18nc("@label", "Profiles compatible with active printer:") + "" + Cura.MachineManager.activeMachine.name + "" + + onHamburgeButtonClicked: menu.popup(content_item, content_item.width - menu.width, hamburger_button.height) - 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 var hasCurrentItem: base.currentItem != null + sectionRole: "section_name" property var currentItem: { - var current_index = qualityListView.currentIndex; + var current_index = objectList.currentIndex; return (current_index == -1) ? null : base.qualityManagementModel.getItem(current_index); } @@ -66,125 +55,29 @@ Item return isCurrentItemActivated && Cura.MachineManager.hasUserSettings; } - Row // Button Row - { - id: buttonRow - anchors + model: qualityManagementModel + buttons: [ + Cura.SecondaryButton { - left: parent.left - right: parent.right - top: titleLabel.bottom - } - height: childrenRect.height - - // Activate button - Button - { - id: activateMenuButton - text: catalog.i18nc("@action:button", "Activate") - icon.name: "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); - } - } - } - - // Create button - Button + text: catalog.i18nc("@action:button", "Import") + onClicked:importDialog.open() + }, + Cura.SecondaryButton { id: createMenuButton - text: catalog.i18nc("@label", "Create") - icon.name: "list-add" - enabled: base.canCreateProfile && !Cura.MachineManager.stacksHaveErrors + text: catalog.i18nc("@action:button", "Create new") + + enabled: !Cura.MachineManager.stacksHaveErrors visible: base.canCreateProfile onClicked: { - createQualityDialog.object = Cura.ContainerManager.makeUniqueName(base.currentItem.name); - createQualityDialog.open(); - createQualityDialog.selectText(); + createQualityDialog.object = Cura.ContainerManager.makeUniqueName(base.currentItem.name) + createQualityDialog.open() + createQualityDialog.selectText() } } - - // Duplicate button - Button - { - id: duplicateMenuButton - text: catalog.i18nc("@label", "Duplicate") - icon.name: "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") - icon.name: "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") - icon.name: "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") - icon.name: "document-import" - onClicked: - { - importDialog.open(); - } - } - - // Export button - Button - { - id: exportMenuButton - text: catalog.i18nc("@action:button", "Export") - icon.name: "document-export" - enabled: base.hasCurrentItem && !base.currentItem.is_read_only - onClicked: - { - exportDialog.open(); - } - } - } + ] // Click create profile from ... in Profile context menu signal createProfile() @@ -195,186 +88,209 @@ 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: "" - 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); - } - } - property string newQualityNameToSelect: "" property bool toActivateNewQuality: false - // This connection makes sure that we will switch to the correct quality after the model gets updated - Connections + Item { - target: base.qualityManagementModel - function onItemsChanged() + id: content_item + anchors.fill: parent + // This connection makes sure that we will switch to the correct quality after the model gets updated + Connections { - var toSelectItemName = base.currentItem == null ? "" : base.currentItem.name; - if (newQualityNameToSelect != "") + target: base.qualityManagementModel + function onItemsChanged() { - 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) + var toSelectItemName = base.currentItem == null ? "" : base.currentItem.name; + if (newQualityNameToSelect != "") { - var item = base.qualityManagementModel.getItem(idx); - if (item && item.name == toSelectItemName) + 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) { - // Switch to the newly created profile if needed - newIdx = idx; - if (base.toActivateNewQuality) + var item = base.qualityManagementModel.getItem(idx); + if (item && item.name == toSelectItemName) { - // Activate this custom quality if required - if(item.quality_changes_group) + // Switch to the newly created profile if needed + newIdx = idx; + if (base.toActivateNewQuality) { - Cura.MachineManager.setQualityChangesGroup(item.quality_changes_group); + // Activate this custom quality if required + if(item.quality_changes_group) + { + Cura.MachineManager.setQualityChangesGroup(item.quality_changes_group); + } } + break; } - break; + } + } + objectList.currentIndex = newIdx; + + // Reset states + base.newQualityNameToSelect = ""; + base.toActivateNewQuality = false; + } + } + UM.MessageDialog + { + id: messageDialog + standardButtons: Dialog.Ok + } + + // Dialog to request a name when creating a new profile + UM.RenameDialog + { + id: createQualityDialog + title: catalog.i18nc("@title:window", "Create Profile") + object: "" + 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); + } + } + + Cura.Menu + { + id: menu + Cura.MenuItem + { + 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) } } } - qualityListView.currentIndex = newIdx; - - // Reset states - base.newQualityNameToSelect = ""; - base.toActivateNewQuality = false; - } - } - - // Dialog to request a name when duplicating a new profile - UM.RenameDialog - { - id: duplicateQualityDialog - title: catalog.i18nc("@title:window", "Duplicate Profile") - object: "" - onAccepted: - { - base.qualityManagementModel.duplicateQualityChanges(newName, base.currentItem); - } - } - - // Confirmation dialog for removing a profile - UM.MessageDialog - { - id: confirmRemoveQualityDialog - - 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 - - onAccepted: - { - 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: "" - 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.title = catalog.i18nc("@title:window", "Import Profile") - messageDialog.text = result.message; - 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") + Cura.MenuItem { - messageDialog.title = catalog.i18nc("@title:window", "Export Profile") + 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() + } + } + + // 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.title = catalog.i18nc("@title:window", "Export Profile") + messageDialog.text = result.message; + messageDialog.open(); + } + + // else pop-up Message thing from python code + CuraApplication.setDefaultPath("dialog_profile_path", folder); + } + } + + // Dialog to request a name when duplicating a new profile + UM.RenameDialog + { + id: duplicateQualityDialog + title: catalog.i18nc("@title:window", "Duplicate Profile") + object: "" + onAccepted: + { + base.qualityManagementModel.duplicateQualityChanges(newName, base.currentItem); + } + } + + // Confirmation dialog for removing a profile + UM.MessageDialog + { + id: confirmRemoveQualityDialog + + 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 + + onAccepted: + { + 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: "" + 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.title = catalog.i18nc("@title:window", "Import Profile") messageDialog.text = result.message; messageDialog.open(); + CuraApplication.setDefaultPath("dialog_profile_path", folder); } - - // else pop-up Message thing from python code - CuraApplication.setDefaultPath("dialog_profile_path", folder); - } - } - - //Dialogue box for showing the result of importing or exporting profiles. - UM.MessageDialog - { - id: messageDialog - standardButtons: Dialog.Ok - } - - Item - { - id: contentsItem - - anchors - { - top: titleLabel.bottom - left: parent.left - right: parent.right - bottom: parent.bottom - margins: 5 * screenScaleFactor - bottomMargin: 0 - } - - clip: true - } - - Item - { - anchors - { - top: buttonRow.bottom - topMargin: UM.Theme.getSize("default_margin").height - left: parent.left - right: parent.right - bottom: parent.bottom } SystemPalette @@ -382,241 +298,97 @@ Item id: palette } - Label + Column { - id: captionLabel + id: detailsPanelHeaderColumn anchors { - top: parent.top left: parent.left - } - visible: text != "" - text: catalog.i18nc("@label %1 is printer name", "Printer: %1").arg(Cura.MachineManager.activeMachine.name) - width: profileBackground.width - elide: Text.ElideRight - } - - Rectangle - { - id: profileBackground - anchors - { - top: captionLabel.visible ? captionLabel.bottom : parent.top - topMargin: captionLabel.visible ? UM.Theme.getSize("default_margin").height : 0 - bottom: parent.bottom - left: parent.left - } - width: (parent.width * 0.4) | 0 - - color: palette.light - - ListView - { - id: qualityListView - anchors.fill: parent - - ScrollBar.vertical: UM.ScrollBar - { - id: profileScrollBar - } - clip: true - model: base.qualityManagementModel - - Component.onCompleted: - { - var selectedItemName = Cura.MachineManager.activeQualityOrQualityChangesName; - - // Select the required quality name if given - for (var idx = 0; idx < base.qualityManagementModel.count; idx++) - { - var item = base.qualityManagementModel.getItem(idx); - if (item.name == selectedItemName) - { - currentIndex = idx; - break; - } - } - } - - section.property: "section_name" - section.delegate: Rectangle - { - height: childrenRect.height - - Label - { - anchors.left: parent.left - anchors.leftMargin: UM.Theme.getSize("default_lining").width - text: section - font.bold: true - } - } - - delegate: Rectangle - { - width: profileBackground.width - profileScrollBar.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; - } - } - } - } - } - - // details panel on the right - Item - { - id: detailsPanel - - anchors - { - left: profileBackground.right - leftMargin: UM.Theme.getSize("default_margin").width - top: parent.top - bottom: parent.bottom right: parent.right + top: parent.top } - Column + spacing: UM.Theme.getSize("default_margin").height + visible: base.currentItem != null + UM.Label { - id: detailsPanelHeaderColumn - anchors - { - left: parent.left - right: parent.right - top: parent.top - } - - spacing: UM.Theme.getSize("default_margin").height - visible: base.currentItem != null - - Item // Profile title Label - { - id: profileName - - width: parent.width - height: childrenRect.height - - Label - { - anchors.left: parent.left - anchors.right: parent.right - text: base.currentItemDisplayName - font: UM.Theme.getFont("large_bold") - elide: Text.ElideRight - renderType: Text.NativeRendering - } - } - - Flow - { - id: currentSettingsActions - width: parent.width - - visible: base.hasCurrentItem && base.currentItem.name == Cura.MachineManager.activeQualityOrQualityChangesName && base.currentItem.intent_category == Cura.MachineManager.activeIntentCategory - - Button - { - text: catalog.i18nc("@action:button", "Update profile with current settings/overrides") - enabled: Cura.MachineManager.hasUserSettings && qualityListView.currentItem && !qualityListView.currentItem.is_read_only - onClicked: Cura.ContainerManager.updateQualityChanges() - } - - Button - { - text: catalog.i18nc("@action:button", "Discard current changes"); - enabled: Cura.MachineManager.hasUserSettings - onClicked: Cura.ContainerManager.clearUserContainers(); - } - } - - 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 - } - - UM.TabRow - { - id: profileExtruderTabs - UM.TabRowButton //One extra tab for the global settings. - { - text: catalog.i18nc("@title:tab", "Global Settings") - } - - Repeater - { - model: base.extrudersModel - - UM.TabRowButton - { - text: model.name - } - } - } + anchors.left: parent.left + anchors.right: parent.right + text: base.currentItemDisplayName + font: UM.Theme.getFont("large_bold") + elide: Text.ElideRight } - Cura.ProfileOverview + Flow { - anchors + id: currentSettingsActions + width: parent.width + + visible: base.hasCurrentItem && base.currentItem.name == Cura.MachineManager.activeQualityOrQualityChangesName && base.currentItem.intent_category == Cura.MachineManager.activeIntentCategory + + Cura.SecondaryButton { - top: detailsPanelHeaderColumn.bottom - left: parent.left - right: parent.right - bottom: parent.bottom + text: catalog.i18nc("@action:button", "Update profile with current settings/overrides") + enabled: Cura.MachineManager.hasUserSettings && objectList.currentIndex && !objectList.currentIndex.is_read_only + onClicked: Cura.ContainerManager.updateQualityChanges() } - visible: detailsPanelHeaderColumn.visible - qualityItem: base.currentItem - extruderPosition: profileExtruderTabs.currentIndex - 1 + Cura.SecondaryButton + { + 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 + UM.TabRowButton //One extra tab for the global settings. + { + text: catalog.i18nc("@title:tab", "Global Settings") + } + + Repeater + { + model: base.extrudersModel + + UM.TabRowButton + { + text: model.name + } + } + } + } + + Cura.ProfileOverview + { + anchors + { + top: detailsPanelHeaderColumn.bottom + left: parent.left + right: parent.right + bottom: parent.bottom + } + + visible: detailsPanelHeaderColumn.visible + qualityItem: base.currentItem + extruderPosition: profileExtruderTabs.currentIndex - 1 } } }