Browse Source

Refactor missing packages dialog into model (MissingPackageList) and controller (InstallMissingPackagesDialog.qml)

Rename classes and files to have unified naming.

CURA-6990
j.delarago 2 years ago
parent
commit
0df21e6073

+ 7 - 0
plugins/3MFReader/WorkspaceDialog.py

@@ -9,6 +9,7 @@ from UM.Application import Application
 from UM.i18n import i18nCatalog
 from UM.Settings.ContainerRegistry import ContainerRegistry
 from cura.Settings.GlobalStack import GlobalStack
+from plugins.Marketplace.InstallMissingPackagesDialog import InstallMissingPackageDialog
 from .UpdatableMachinesModel import UpdatableMachinesModel
 
 import os
@@ -60,6 +61,8 @@ class WorkspaceDialog(QObject):
         self._is_printer_group = False
         self._updatable_machines_model = UpdatableMachinesModel(self)
         self._missing_package_metadata: List[Dict[str, str]] = []
+        self._plugin_registry: PluginRegistry = CuraApplication.getInstance().getPluginRegistry()
+        self._install_missing_package_dialog: Optional[QObject] = None
 
     machineConflictChanged = pyqtSignal()
     qualityChangesConflictChanged = pyqtSignal()
@@ -284,6 +287,10 @@ class WorkspaceDialog(QObject):
     def missingPackages(self):
         return self._missing_package_metadata
 
+    @pyqtSlot()
+    def installMissingPackages(self):
+        self._install_missing_package_dialog = InstallMissingPackageDialog(self._missing_package_metadata)
+        self._install_missing_package_dialog.show()
 
     def getResult(self) -> Dict[str, Optional[str]]:
         if "machine" in self._result and self.updatableMachinesModel.count <= 1:

+ 1 - 1
plugins/3MFReader/WorkspaceDialog.qml

@@ -469,7 +469,7 @@ UM.Dialog
         {
             visible: buttonWarning
             text: catalog.i18nc("@action:button", "Install missing Material")
-            onClicked: accept()
+            onClicked: manager.installMissingPackages()
         }
     ]
 

+ 60 - 0
plugins/Marketplace/InstallMissingPackagesDialog.py

@@ -0,0 +1,60 @@
+import os
+
+from PyQt6.QtCore import QObject, pyqtSignal, pyqtProperty
+from typing import Optional, List, Dict, cast
+from cura.CuraApplication import CuraApplication
+from UM.PluginRegistry import PluginRegistry
+from cura.CuraPackageManager import CuraPackageManager
+
+from plugins.Marketplace.MissingPackageList import MissingPackageList
+
+
+class InstallMissingPackageDialog(QObject):
+    """Dialog used to display packages that need to be installed to load 3mf file materials"""
+    def __init__(self, packages_metadata: List[Dict[str, str]]):
+        """Initialize
+
+        :param packages_metadata: List of dictionaries containing information about missing packages.
+        """
+        super().__init__()
+
+        self._plugin_registry: PluginRegistry = CuraApplication.getInstance().getPluginRegistry()
+        self._package_manager: CuraPackageManager = cast(CuraPackageManager, CuraApplication.getInstance().getPackageManager())
+        self._package_manager.installedPackagesChanged.connect(self.checkIfRestartNeeded)
+
+        self._dialog: Optional[QObject] = None
+        self._restart_needed = False
+        self._package_metadata: List[Dict[str, str]] = packages_metadata
+
+        self._package_model = MissingPackageList()
+        self._package_model.setPackageIds(packages_metadata)
+
+    def show(self):
+        plugin_path = self._plugin_registry.getPluginPath("Marketplace")
+        if plugin_path is None:
+            plugin_path = os.path.dirname(__file__)
+
+        # create a QML component for the license dialog
+        license_dialog_component_path = os.path.join(plugin_path, "resources", "qml", "InstallMissingPackagesDialog.qml")
+        self._dialog = CuraApplication.getInstance().createQmlComponent(license_dialog_component_path, {"manager": self})
+        self._dialog.show()
+
+    def checkIfRestartNeeded(self) -> None:
+        if self._dialog is None:
+            return
+
+        if self._package_manager.hasPackagesToRemoveOrInstall:
+            self._restart_needed = True
+        else:
+            self._restart_needed = False
+        self.showRestartChanged.emit()
+
+    showRestartChanged = pyqtSignal()
+
+    @pyqtProperty(bool, notify=showRestartChanged)
+    def showRestartNotification(self) -> bool:
+        return self._restart_needed
+
+    @pyqtProperty(QObject)
+    def model(self):
+        return self._package_model

+ 32 - 0
plugins/Marketplace/MissingPackageList.py

@@ -0,0 +1,32 @@
+#  Copyright (c) 2022 Ultimaker B.V.
+#  Cura is released under the terms of the LGPLv3 or higher.
+
+from typing import Optional, TYPE_CHECKING, Dict, List
+
+from .Constants import PACKAGES_URL
+from .PackageModel import PackageModel
+from .RemotePackageList import RemotePackageList
+from PyQt6.QtCore import pyqtSignal, QObject, pyqtProperty, QCoreApplication
+
+from UM.TaskManagement.HttpRequestManager import HttpRequestManager  # To request the package list from the API.
+from UM.i18n import i18nCatalog
+
+if TYPE_CHECKING:
+    from PyQt6.QtCore import QObject, pyqtProperty, pyqtSignal
+
+catalog = i18nCatalog("cura")
+
+class MissingPackageList(RemotePackageList):
+    def __init__(self, parent: Optional["QObject"] = None) -> None:
+        super().__init__(parent)
+        self._package_metadata: List[Dict[str, str]] = []
+        # self.packageTypeFilter = None # This will be our new filter
+        self._package_type_filter = "material"
+
+    def setPackageIds(self, packages: List[Dict[str, str]]) -> None:
+        self._package_metadata = packages
+        search_string = ", ".join(map(lambda package: package["id"], packages))
+        # self.setSearchString(search_string)
+        self.setSearchString("ABS")
+
+

+ 158 - 0
plugins/Marketplace/resources/qml/InstallMissingPackagesDialog.qml

@@ -0,0 +1,158 @@
+// Copyright (c) 2021 Ultimaker B.V.
+// Cura is released under the terms of the LGPLv3 or higher.
+
+import QtQuick 2.15
+import QtQuick.Controls 2.15
+import QtQuick.Layouts 1.15
+import QtQuick.Window 2.2
+
+import UM 1.5 as UM
+import Cura 1.6 as Cura
+
+Window
+{
+    id: marketplaceDialog
+
+    property variant catalog: UM.I18nCatalog { name: "cura" }
+
+    signal searchStringChanged(string new_search)
+
+    minimumWidth: UM.Theme.getSize("modal_window_minimum").width
+    minimumHeight: UM.Theme.getSize("modal_window_minimum").height
+    width: minimumWidth
+    height: minimumHeight
+
+    onVisibleChanged:
+    {
+        while(contextStack.depth > 1)
+        {
+            contextStack.pop(); //Do NOT use the StackView.Immediate transition here, since it causes the window to stay empty. Seemingly a Qt bug: https://bugreports.qt.io/browse/QTBUG-60670?
+        }
+    }
+
+    Connections
+    {
+        target: Cura.API.account
+        function onLoginStateChanged()
+        {
+            close();
+        }
+    }
+
+    title: catalog.i18nc("@title", "Install missing Materials")
+    modality: Qt.ApplicationModal
+
+    // Background color
+    Rectangle
+    {
+        anchors.fill: parent
+        color: UM.Theme.getColor("main_background")
+    }
+    //The Marketplace can have a page in front of everything with package details. The stack view controls its visibility.
+    StackView
+    {
+        id: contextStack
+        anchors.fill: parent
+
+        initialItem: packageBrowse
+
+        ColumnLayout
+        {
+            id: packageBrowse
+
+            spacing: UM.Theme.getSize("narrow_margin").height
+
+            // Page title.
+            Item
+            {
+                Layout.preferredWidth: parent.width
+                Layout.preferredHeight: childrenRect.height + UM.Theme.getSize("default_margin").height
+
+                UM.Label
+                {
+                    id: pageTitle
+                    anchors
+                    {
+                        left: parent.left
+                        leftMargin: UM.Theme.getSize("default_margin").width
+                        right: parent.right
+                        rightMargin: UM.Theme.getSize("default_margin").width
+                        bottom: parent.bottom
+                    }
+
+                    font: UM.Theme.getFont("large")
+                    text: content.item ? content.item.pageTitle: catalog.i18nc("@title", "Loading...")
+                }
+            }
+
+            // Page contents.
+            Rectangle
+            {
+                Layout.preferredWidth: parent.width
+                Layout.fillHeight: true
+                color: UM.Theme.getColor("detail_background")
+
+                // Page contents.
+                Loader
+                {
+                    id: content
+                    anchors.fill: parent
+                    anchors.margins: UM.Theme.getSize("default_margin").width
+                    source: "MissingPackages.qml"
+                }
+            }
+        }
+    }
+
+    Rectangle
+    {
+        height: quitButton.height + 2 * UM.Theme.getSize("default_margin").width
+        color: UM.Theme.getColor("primary")
+        visible: manager.showRestartNotification
+        anchors
+        {
+            left: parent.left
+            right: parent.right
+            bottom: parent.bottom
+        }
+
+        RowLayout
+        {
+            anchors
+            {
+                left: parent.left
+                right: parent.right
+                verticalCenter: parent.verticalCenter
+                margins: UM.Theme.getSize("default_margin").width
+            }
+            spacing: UM.Theme.getSize("default_margin").width
+            UM.ColorImage
+            {
+                id: bannerIcon
+                source: UM.Theme.getIcon("Plugin")
+
+                color: UM.Theme.getColor("primary_button_text")
+                implicitWidth: UM.Theme.getSize("banner_icon_size").width
+                implicitHeight: UM.Theme.getSize("banner_icon_size").height
+            }
+            Text
+            {
+                color: UM.Theme.getColor("primary_button_text")
+                text: catalog.i18nc("@button", "In order to use the package you will need to restart Cura")
+                font: UM.Theme.getFont("default")
+                renderType: Text.NativeRendering
+                Layout.fillWidth: true
+            }
+            Cura.SecondaryButton
+            {
+                id: quitButton
+                text: catalog.i18nc("@info:button, %1 is the application name", "Quit %1").arg(CuraApplication.applicationDisplayName)
+                onClicked:
+                {
+                    marketplaceDialog.hide();
+                    CuraApplication.closeApplication();
+                }
+            }
+        }
+    }
+}

+ 15 - 0
plugins/Marketplace/resources/qml/MissingPackages.qml

@@ -0,0 +1,15 @@
+// Copyright (c) 2021 Ultimaker B.V.
+// Cura is released under the terms of the LGPLv3 or higher.
+
+import UM 1.4 as UM
+
+Packages
+{
+    pageTitle: catalog.i18nc("@header", "Install Materials")
+
+    bannerVisible: false
+    showUpdateButton: false
+    showInstallButton: true
+
+    model: manager.model
+}