Browse Source

Merge branch 'master' of https://github.com/Ultimaker/Cura

Matt Jani 5 years ago
parent
commit
35aadad747

+ 6 - 2
cura/CuraApplication.py

@@ -191,8 +191,6 @@ class CuraApplication(QtApplication):
 
 
         self._cura_formula_functions = None  # type: Optional[CuraFormulaFunctions]
         self._cura_formula_functions = None  # type: Optional[CuraFormulaFunctions]
 
 
-        self._cura_package_manager = None
-
         self._machine_action_manager = None  # type: Optional[MachineActionManager.MachineActionManager]
         self._machine_action_manager = None  # type: Optional[MachineActionManager.MachineActionManager]
 
 
         self.empty_container = None  # type: EmptyInstanceContainer
         self.empty_container = None  # type: EmptyInstanceContainer
@@ -632,6 +630,12 @@ class CuraApplication(QtApplication):
     def showPreferences(self) -> None:
     def showPreferences(self) -> None:
         self.showPreferencesWindow.emit()
         self.showPreferencesWindow.emit()
 
 
+    # This is called by drag-and-dropping curapackage files.
+    @pyqtSlot(QUrl)
+    def installPackageViaDragAndDrop(self, file_url: str) -> Optional[str]:
+        filename = QUrl(file_url).toLocalFile()
+        return self._package_manager.installPackage(filename)
+
     @override(Application)
     @override(Application)
     def getGlobalContainerStack(self) -> Optional["GlobalStack"]:
     def getGlobalContainerStack(self) -> Optional["GlobalStack"]:
         return self._global_container_stack
         return self._global_container_stack

+ 39 - 11
plugins/Toolbox/src/CloudSync/CloudPackageManager.py

@@ -1,23 +1,51 @@
+from UM.Logger import Logger
+from UM.TaskManagement.HttpRequestManager import HttpRequestManager
 from cura.CuraApplication import CuraApplication
 from cura.CuraApplication import CuraApplication
 from ..CloudApiModel import CloudApiModel
 from ..CloudApiModel import CloudApiModel
 from ..UltimakerCloudScope import UltimakerCloudScope
 from ..UltimakerCloudScope import UltimakerCloudScope
 
 
 
 
-## Manages Cloud subscriptions. When a package is added to a user's account, the user is 'subscribed' to that package
-# Whenever the user logs in on another instance of Cura, these subscriptions can be used to sync the user's plugins
 class CloudPackageManager:
 class CloudPackageManager:
+    """Manages Cloud subscriptions
+
+    When a package is added to a user's account, the user is 'subscribed' to that package.
+    Whenever the user logs in on another instance of Cura, these subscriptions can be used to sync the user's plugins
+
+    Singleton: use CloudPackageManager.getInstance() instead of CloudPackageManager()
+    """
+
+    __instance = None
+
+    @classmethod
+    def getInstance(cls, app: CuraApplication):
+        if not cls.__instance:
+            cls.__instance = CloudPackageManager(app)
+        return cls.__instance
+
     def __init__(self, app: CuraApplication) -> None:
     def __init__(self, app: CuraApplication) -> None:
-        self._request_manager = app.getHttpRequestManager()
-        self._scope = UltimakerCloudScope(app)
+        if self.__instance is not None:
+            raise RuntimeError("This is a Singleton. use getInstance()")
 
 
-    def subscribe(self, package_id: str) -> None:
-        data = "{\"data\": {\"package_id\": \"%s\", \"sdk_version\": \"%s\"}}" % (package_id, CloudApiModel.sdk_version)
-        self._request_manager.put(url=CloudApiModel.api_url_user_packages,
-                                  data=data.encode(),
-                                  scope=self._scope
-                                  )
+        self._scope = UltimakerCloudScope(app)  # type: UltimakerCloudScope
+
+        app.getPackageManager().packageInstalled.connect(self._onPackageInstalled)
 
 
     def unsubscribe(self, package_id: str) -> None:
     def unsubscribe(self, package_id: str) -> None:
         url = CloudApiModel.userPackageUrl(package_id)
         url = CloudApiModel.userPackageUrl(package_id)
-        self._request_manager.delete(url=url, scope=self._scope)
+        HttpRequestManager.getInstance().delete(url = url, scope = self._scope)
+
+    def _subscribe(self, package_id: str) -> None:
+        """You probably don't want to use this directly. All installed packages will be automatically subscribed."""
+
+        Logger.debug("Subscribing to {}", package_id)
+        data = "{\"data\": {\"package_id\": \"%s\", \"sdk_version\": \"%s\"}}" % (package_id, CloudApiModel.sdk_version)
+        HttpRequestManager.getInstance().put(
+            url = CloudApiModel.api_url_user_packages,
+            data = data.encode(),
+            scope = self._scope
+        )
 
 
+    def _onPackageInstalled(self, package_id: str):
+        if CuraApplication.getInstance().getCuraAPI().account.isLoggedIn:
+            # We might already be subscribed, but checking would take one extra request. Instead, simply subscribe
+            self._subscribe(package_id)

+ 2 - 2
plugins/Toolbox/src/CloudSync/SyncOrchestrator.py

@@ -38,7 +38,8 @@ class SyncOrchestrator(Extension):
         self._name = "SyncOrchestrator"
         self._name = "SyncOrchestrator"
 
 
         self._package_manager = app.getPackageManager()
         self._package_manager = app.getPackageManager()
-        self._cloud_package_manager = CloudPackageManager(app)
+        # Keep a reference to the CloudPackageManager. it watches for installed packages and subscribes to them
+        self._cloud_package_manager = CloudPackageManager.getInstance(app)  # type: CloudPackageManager
 
 
         self._checker = CloudPackageChecker(app)  # type: CloudPackageChecker
         self._checker = CloudPackageChecker(app)  # type: CloudPackageChecker
         self._checker.discrepancies.connect(self._onDiscrepancies)
         self._checker.discrepancies.connect(self._onDiscrepancies)
@@ -84,7 +85,6 @@ class SyncOrchestrator(Extension):
                     message = "Could not install {}".format(item["package_id"])
                     message = "Could not install {}".format(item["package_id"])
                     self._showErrorMessage(message)
                     self._showErrorMessage(message)
                     continue
                     continue
-                self._cloud_package_manager.subscribe(item["package_id"])
                 has_changes = True
                 has_changes = True
             else:
             else:
                 self._cloud_package_manager.unsubscribe(item["package_id"])
                 self._cloud_package_manager.unsubscribe(item["package_id"])

+ 0 - 8
plugins/Toolbox/src/Toolbox.py

@@ -21,7 +21,6 @@ from cura.Machines.ContainerTree import ContainerTree
 
 
 from .CloudApiModel import CloudApiModel
 from .CloudApiModel import CloudApiModel
 from .AuthorsModel import AuthorsModel
 from .AuthorsModel import AuthorsModel
-from .CloudSync.CloudPackageManager import CloudPackageManager
 from .CloudSync.LicenseModel import LicenseModel
 from .CloudSync.LicenseModel import LicenseModel
 from .PackagesModel import PackagesModel
 from .PackagesModel import PackagesModel
 from .UltimakerCloudScope import UltimakerCloudScope
 from .UltimakerCloudScope import UltimakerCloudScope
@@ -44,7 +43,6 @@ class Toolbox(QObject, Extension):
         self._sdk_version = ApplicationMetadata.CuraSDKVersion  # type: Union[str, int]
         self._sdk_version = ApplicationMetadata.CuraSDKVersion  # type: Union[str, int]
 
 
         # Network:
         # Network:
-        self._cloud_package_manager = CloudPackageManager(application)  # type: CloudPackageManager
         self._download_request_data = None  # type: Optional[HttpRequestData]
         self._download_request_data = None  # type: Optional[HttpRequestData]
         self._download_progress = 0  # type: float
         self._download_progress = 0  # type: float
         self._is_downloading = False  # type: bool
         self._is_downloading = False  # type: bool
@@ -147,10 +145,6 @@ class Toolbox(QObject, Extension):
 
 
         self._application.getHttpRequestManager().put(url, data = data.encode(), scope = self._scope)
         self._application.getHttpRequestManager().put(url, data = data.encode(), scope = self._scope)
 
 
-    @pyqtSlot(str)
-    def subscribe(self, package_id: str) -> None:
-        self._cloud_package_manager.subscribe(package_id)
-
     def getLicenseDialogPluginFileLocation(self) -> str:
     def getLicenseDialogPluginFileLocation(self) -> str:
         return self._license_dialog_plugin_file_location
         return self._license_dialog_plugin_file_location
 
 
@@ -377,7 +371,6 @@ class Toolbox(QObject, Extension):
     def onLicenseAccepted(self):
     def onLicenseAccepted(self):
         self.closeLicenseDialog.emit()
         self.closeLicenseDialog.emit()
         package_id = self.install(self.getLicenseDialogPluginFileLocation())
         package_id = self.install(self.getLicenseDialogPluginFileLocation())
-        self.subscribe(package_id)
 
 
 
 
     @pyqtSlot()
     @pyqtSlot()
@@ -681,7 +674,6 @@ class Toolbox(QObject, Extension):
         installed_id = self.install(file_path)
         installed_id = self.install(file_path)
         if installed_id != package_id:
         if installed_id != package_id:
             Logger.error("Installed package {} does not match {}".format(installed_id, package_id))
             Logger.error("Installed package {} does not match {}".format(installed_id, package_id))
-        self.subscribe(installed_id)
 
 
     # Getter & Setters for Properties:
     # Getter & Setters for Properties:
     # --------------------------------------------------------------------------
     # --------------------------------------------------------------------------

+ 1 - 1
resources/qml/Cura.qml

@@ -238,7 +238,7 @@ UM.MainWindow
                             if (filename.toLowerCase().endsWith(".curapackage"))
                             if (filename.toLowerCase().endsWith(".curapackage"))
                             {
                             {
                                 // Try to install plugin & close.
                                 // Try to install plugin & close.
-                                CuraApplication.getPackageManager().installPackageViaDragAndDrop(filename);
+                                CuraApplication.installPackageViaDragAndDrop(filename);
                                 packageInstallDialog.text = catalog.i18nc("@label", "This package will be installed after restarting.");
                                 packageInstallDialog.text = catalog.i18nc("@label", "This package will be installed after restarting.");
                                 packageInstallDialog.icon = StandardIcon.Information;
                                 packageInstallDialog.icon = StandardIcon.Information;
                                 packageInstallDialog.open();
                                 packageInstallDialog.open();