From 2462699982f17febc706bd71b86f207a0786c12d Mon Sep 17 00:00:00 2001 From: Jaime van Kessel Date: Tue, 28 Feb 2017 10:25:42 +0100 Subject: [PATCH] Switching profiles now shows a new dialog with all the changes. CURA-3221 --- cura/CuraApplication.py | 15 ++- cura/Settings/MachineManager.py | 5 +- cura/Settings/UserChangesModel.py | 112 ++++++++++++++++ resources/qml/Cura.qml | 15 +++ .../qml/DiscardOrKeepProfileChangesDialog.qml | 126 ++++++++++++++++++ 5 files changed, 270 insertions(+), 3 deletions(-) create mode 100644 cura/Settings/UserChangesModel.py create mode 100644 resources/qml/DiscardOrKeepProfileChangesDialog.qml diff --git a/cura/CuraApplication.py b/cura/CuraApplication.py index add7b4a143..a180c72366 100644 --- a/cura/CuraApplication.py +++ b/cura/CuraApplication.py @@ -53,7 +53,7 @@ from . import MachineActionManager from cura.Settings.MachineManager import MachineManager from cura.Settings.ExtruderManager import ExtruderManager -from cura.Settings.CuraContainerRegistry import CuraContainerRegistry +from cura.Settings.UserChangesModel import UserChangesModel from cura.Settings.ExtrudersModel import ExtrudersModel from cura.Settings.ContainerSettingsModel import ContainerSettingsModel from cura.Settings.MaterialSettingsVisibilityHandler import MaterialSettingsVisibilityHandler @@ -323,11 +323,23 @@ class CuraApplication(QtApplication): ## A reusable dialogbox # showMessageBox = pyqtSignal(str, str, str, str, int, int, arguments = ["title", "text", "informativeText", "detailedText", "buttons", "icon"]) + def messageBox(self, title, text, informativeText = "", detailedText = "", buttons = QMessageBox.Ok, icon = QMessageBox.NoIcon, callback = None, callback_arguments = []): self._message_box_callback = callback self._message_box_callback_arguments = callback_arguments self.showMessageBox.emit(title, text, informativeText, detailedText, buttons, icon) + showDiscardOrKeepProfileChanges = pyqtSignal() + + def discardOrKeepProfileChanges(self, callback = None, callback_arguments = []): + self._discard_or_keep_changes_callback = callback + self._discard_or_keep_changes_callback_arguments = callback_arguments + self.showDiscardOrKeepProfileChanges.emit() + + @pyqtSlot(int) + def discardOrKeepProfileChangesClosed(self, button): + pass + @pyqtSlot(int) def messageBoxClosed(self, button): if self._message_box_callback: @@ -653,6 +665,7 @@ class CuraApplication(QtApplication): qmlRegisterType(MaterialSettingsVisibilityHandler, "Cura", 1, 0, "MaterialSettingsVisibilityHandler") qmlRegisterType(QualitySettingsModel, "Cura", 1, 0, "QualitySettingsModel") qmlRegisterType(MachineNameValidator, "Cura", 1, 0, "MachineNameValidator") + qmlRegisterType(UserChangesModel, "Cura", 1, 1, "UserChangesModel") qmlRegisterSingletonType(ContainerManager, "Cura", 1, 0, "ContainerManager", ContainerManager.createContainerManager) diff --git a/cura/Settings/MachineManager.py b/cura/Settings/MachineManager.py index ce42854d43..38e1ad4d6a 100644 --- a/cura/Settings/MachineManager.py +++ b/cura/Settings/MachineManager.py @@ -957,7 +957,8 @@ class MachineManager(QObject): details = "\n ".join([details_text, ] + details_list) num_changed_settings = len(details_list) - Application.getInstance().messageBox( + Application.getInstance().discardOrKeepProfileChanges() + '''Application.getInstance().messageBox( catalog.i18nc("@window:title", "Switched profiles"), catalog.i18nc( "@label", @@ -968,7 +969,7 @@ class MachineManager(QObject): details, buttons=QMessageBox.Yes + QMessageBox.No, icon=QMessageBox.Question, - callback=self._keepUserSettingsDialogCallback) + callback=self._keepUserSettingsDialogCallback)''' def _keepUserSettingsDialogCallback(self, button): if button == QMessageBox.Yes: diff --git a/cura/Settings/UserChangesModel.py b/cura/Settings/UserChangesModel.py new file mode 100644 index 0000000000..1ff0a486b7 --- /dev/null +++ b/cura/Settings/UserChangesModel.py @@ -0,0 +1,112 @@ +from UM.Qt.ListModel import ListModel + +from PyQt5.QtCore import pyqtSlot, Qt +from UM.Application import Application +from cura.Settings.ExtruderManager import ExtruderManager +from UM.Settings.ContainerRegistry import ContainerRegistry +from UM.i18n import i18nCatalog + +import os + +class UserChangesModel(ListModel): + KeyRole = Qt.UserRole + 1 + LabelRole = Qt.UserRole + 2 + ExtruderRole = Qt.UserRole +3 + OriginalValueRole = Qt.UserRole + 4 + UserValueRole = Qt.UserRole + 6 + CategoryRole = Qt.UserRole + 7 + + def __init__(self, parent = None): + super().__init__(parent = parent) + self.addRoleName(self.KeyRole, "key") + self.addRoleName(self.LabelRole, "label") + self.addRoleName(self.ExtruderRole, "extruder") + self.addRoleName(self.OriginalValueRole, "original_value") + self.addRoleName(self.UserValueRole, "user_value") + self.addRoleName(self.CategoryRole, "category") + + Application.getInstance().globalContainerStackChanged.connect(self._update) + self._i18n_catalog = None + + self._update() + + @pyqtSlot() + def forceUpdate(self): + self._update() + + def _update(self): + items = [] + global_stack = Application.getInstance().getGlobalContainerStack() + stacks = ExtruderManager.getInstance().getUsedExtruderStacks() + + # Ensure that the global stack is in the list of stacks. + if global_stack.getProperty("machine_extruder_count", "value") > 1: + stacks.append(global_stack) + + # Check if the definition container has a translation file and ensure it's loaded. + definition = global_stack.getBottom() + + definition_suffix = ContainerRegistry.getMimeTypeForContainer(type(definition)).preferredSuffix + catalog = i18nCatalog(os.path.basename(definition.getId() + "." + definition_suffix)) + + if catalog.hasTranslationLoaded(): + self._i18n_catalog = catalog + + for file_name in definition.getInheritedFiles(): + catalog = i18nCatalog(os.path.basename(file_name)) + if catalog.hasTranslationLoaded(): + self._i18n_catalog = catalog + + for stack in stacks: + # Make a list of all containers in the stack. + containers = [] + latest_stack = stack + while latest_stack: + containers.extend(latest_stack.getContainers()) + latest_stack = latest_stack.getNextStack() + + # Drop the user container. + user_changes = containers.pop(0) + + for setting_key in user_changes.getAllKeys(): + original_value = None + + # Find the category of the instance by moving up until we find a category. + category = user_changes.getInstance(setting_key).definition + while category.type != "category": + category = category.parent + + # Handle translation (and fallback if we weren't able to find any translation files. + if self._i18n_catalog: + category_label = self._i18n_catalog.i18nc(category.key + " label", category.label) + else: + category_label = category.label + + if self._i18n_catalog: + label = self._i18n_catalog.i18nc(setting_key + " label", stack.getProperty(setting_key, "label")) + else: + label = stack.getProperty(setting_key, "label") + + for container in containers: + if stack == global_stack: + resolve = global_stack.getProperty(setting_key, "resolve") + if resolve is not None: + original_value = resolve + break + + original_value = container.getProperty(setting_key, "value") + if original_value is not None: + break + + item_to_add = {"key": setting_key, + "label": label, + "user_value": user_changes.getProperty(setting_key, "value"), + "original_value": original_value, + "extruder": "", + "category": category_label} + + if stack != global_stack: + item_to_add["extruder"] = stack.getName() + + items.append(item_to_add) + self.setItems(items) \ No newline at end of file diff --git a/resources/qml/Cura.qml b/resources/qml/Cura.qml index b73bd21600..8b70e293b4 100644 --- a/resources/qml/Cura.qml +++ b/resources/qml/Cura.qml @@ -882,6 +882,21 @@ UM.MainWindow } } + DiscardOrKeepProfileChangesDialog + { + id: discardOrKeepProfileChangesDialog + } + + Connections + { + target: Printer + onShowDiscardOrKeepProfileChanges: + { + discardOrKeepProfileChangesDialog.show() + } + + } + Connections { target: Cura.Actions.addMachine diff --git a/resources/qml/DiscardOrKeepProfileChangesDialog.qml b/resources/qml/DiscardOrKeepProfileChangesDialog.qml new file mode 100644 index 0000000000..2744ba3847 --- /dev/null +++ b/resources/qml/DiscardOrKeepProfileChangesDialog.qml @@ -0,0 +1,126 @@ +// Copyright (c) 2017 Ultimaker B.V. +// Cura is released under the terms of the AGPLv3 or higher. + +import QtQuick 2.1 +import QtQuick.Controls 1.1 +import QtQuick.Dialogs 1.2 + +import UM 1.2 as UM +import Cura 1.1 as Cura + +UM.Dialog +{ + id: base + title: catalog.i18nc("@title:window", "Discard or Keep changes") + + width: 500 + height: 500 + property var changesModel: Cura.UserChangesModel{ id: userChangesModel} + onVisibilityChanged: + { + if(visible) + { + changesModel.forceUpdate() + } + } + + Column + { + anchors.fill: parent + + UM.I18nCatalog + { + id: catalog; + name:"cura" + } + Label + { + text: "You have customized some default profile settings. Would you like to keep or discard those settings?" + anchors.margins: UM.Theme.getSize("default_margin").width + anchors.left: parent.left + anchors.right: parent.right + } + + TableView + { + anchors.margins: UM.Theme.getSize("default_margin").width + anchors.left: parent.left + anchors.right: parent.right + height: 200 + id: tableView + Component + { + id: labelDelegate + Label + { + property var extruder_name: userChangesModel.getItem(styleData.row).extruder + anchors.left: parent.left + anchors.leftMargin: UM.Theme.getSize("default_margin").width + font: UM.Theme.getFont("default") + text: + { + var result = styleData.value + if (extruder_name!= "") + { + result += " (" + extruder_name + ")" + } + return result + } + } + } + + Component + { + id: defaultDelegate + Label + { + text: styleData.value + font: UM.Theme.getFont("default") + color: UM.Theme.getColor("setting_control_disabled_text") + } + } + + TableViewColumn + { + role: "label" + title: catalog.i18nc("@title:column", "Profile settings") + delegate: labelDelegate + width: tableView.width * 0.5 + } + + TableViewColumn + { + role: "original_value" + title: "default" + width: tableView.width * 0.25 + delegate: defaultDelegate + } + TableViewColumn + { + role: "user_value" + title: catalog.i18nc("@title:column", "Customized") + width: tableView.width * 0.25 - 1 + } + section.property: "category" + section.delegate: Label + { + text: section + font.bold: true + } + + model: base.changesModel + } + + Row + { + Button + { + text: catalog.i18nc("@action:button", "Keep"); + } + Button + { + text: catalog.i18nc("@action:button", "Discard"); + } + } + } +} \ No newline at end of file