From 0f0b6a9712592a81b0b8e95af703c0da27921387 Mon Sep 17 00:00:00 2001 From: Jack Ha Date: Mon, 14 May 2018 16:01:59 +0200 Subject: [PATCH 1/4] Fix/Implement update in toolbox --- cura/CuraPackageManager.py | 26 ++++++------ .../resources/qml/ToolboxInstalledTile.qml | 2 +- .../qml/ToolboxInstalledTileActions.qml | 7 +++- plugins/Toolbox/src/Toolbox.py | 41 ++++++++++++++++--- resources/packages.json | 2 +- 5 files changed, 57 insertions(+), 21 deletions(-) diff --git a/cura/CuraPackageManager.py b/cura/CuraPackageManager.py index 2b91081e4d..4b21096c2f 100644 --- a/cura/CuraPackageManager.py +++ b/cura/CuraPackageManager.py @@ -136,14 +136,14 @@ class CuraPackageManager(QObject): all_installed_ids = all_installed_ids.union(set(self._bundled_package_dict.keys())) if self._installed_package_dict.keys(): all_installed_ids = all_installed_ids.union(set(self._installed_package_dict.keys())) + all_installed_ids = all_installed_ids.difference(self._to_remove_package_set) + # If it's going to be installed and to be removed, then the package is being updated and it should be listed. if self._to_install_package_dict.keys(): all_installed_ids = all_installed_ids.union(set(self._to_install_package_dict.keys())) - all_installed_ids = all_installed_ids.difference(self._to_remove_package_set) # map of -> -> installed_packages_dict = {} for package_id in all_installed_ids: - # Skip required plugins as they should not be tampered with if package_id in Application.getInstance().getRequiredPlugins(): continue @@ -194,10 +194,10 @@ class CuraPackageManager(QObject): return package_id = package_info["package_id"] - # Check the delayed installation and removal lists first - if package_id in self._to_remove_package_set: - self._to_remove_package_set.remove(package_id) - has_changes = True + # # Check the delayed installation and removal lists first + # if package_id in self._to_remove_package_set: + # self._to_remove_package_set.remove(package_id) + # has_changes = True # Check if it is installed installed_package_info = self.getInstalledPackageInfo(package_info["package_id"]) @@ -235,20 +235,22 @@ class CuraPackageManager(QObject): self.installedPackagesChanged.emit() # Schedules the given package to be removed upon the next start. + # \param package_id id of the package + # \param force_add is used when updating. In that case you actually want to uninstall & install @pyqtSlot(str) - def removePackage(self, package_id: str) -> None: + def removePackage(self, package_id: str, force_add: bool = False) -> None: # Check the delayed installation and removal lists first if not self.isPackageInstalled(package_id): Logger.log("i", "Attempt to remove package [%s] that is not installed, do nothing.", package_id) return - # Remove from the delayed installation list if present - if package_id in self._to_install_package_dict: + if package_id not in self._to_install_package_dict or force_add: + # Schedule for a delayed removal: + self._to_remove_package_set.add(package_id) + else: + # Remove from the delayed installation list if present del self._to_install_package_dict[package_id] - # Schedule for a delayed removal: - self._to_remove_package_set.add(package_id) - self._saveManagementData() self.installedPackagesChanged.emit() diff --git a/plugins/Toolbox/resources/qml/ToolboxInstalledTile.qml b/plugins/Toolbox/resources/qml/ToolboxInstalledTile.qml index 6004832a57..e788c3788c 100644 --- a/plugins/Toolbox/resources/qml/ToolboxInstalledTile.qml +++ b/plugins/Toolbox/resources/qml/ToolboxInstalledTile.qml @@ -102,4 +102,4 @@ Item onMetadataChanged: canUpdate = toolbox.canUpdate(model.id) } } -} \ No newline at end of file +} diff --git a/plugins/Toolbox/resources/qml/ToolboxInstalledTileActions.qml b/plugins/Toolbox/resources/qml/ToolboxInstalledTileActions.qml index 1921bcb58e..d63326288d 100644 --- a/plugins/Toolbox/resources/qml/ToolboxInstalledTileActions.qml +++ b/plugins/Toolbox/resources/qml/ToolboxInstalledTileActions.qml @@ -37,7 +37,10 @@ Column font: UM.Theme.getFont("default_bold") } } - onClicked: toolbox.update(model.id) + onClicked: { + // Must do all stuff in 1 function as the current ToolboxInstalledTile object is going to disappear... + toolbox.update(model.id) + } } ProgressBar { @@ -90,4 +93,4 @@ Column } onClicked: toolbox.uninstall(model.id) } -} \ No newline at end of file +} diff --git a/plugins/Toolbox/src/Toolbox.py b/plugins/Toolbox/src/Toolbox.py index 3ee6787cf4..3dd1ec90ec 100644 --- a/plugins/Toolbox/src/Toolbox.py +++ b/plugins/Toolbox/src/Toolbox.py @@ -61,6 +61,7 @@ class Toolbox(QObject, Extension): "plugins_showcase": QUrl("{base_url}/showcase".format(base_url = self._api_url)), "materials_showcase": QUrl("{base_url}/showcase".format(base_url = self._api_url)) } + self._to_update = [] # Package_ids that are waiting to be updated # Data: self._metadata = { @@ -216,13 +217,29 @@ class Toolbox(QObject, Extension): @pyqtSlot(str) def uninstall(self, plugin_id: str) -> None: - self._package_manager.removePackage(plugin_id) + self._package_manager.removePackage(plugin_id, force_add = True) self.installChanged.emit() self._updateInstalledModels() self.metadataChanged.emit() self._restart_required = True self.restartRequiredChanged.emit() + ## Actual update packages that are in self._to_update + def _update(self) -> None: + if self._to_update: + plugin_id = self._to_update.pop(0) + Logger.log("d", "Updating package [%s]..." % plugin_id) + self.uninstall(plugin_id) + self.startDownload(self.getRemotePackageURL(plugin_id)) + if self._to_update: + self._application.callLater(self._update) + + ## Update a plugin by plugin_id + @pyqtSlot(str) + def update(self, plugin_id: str) -> None: + self._to_update.append(plugin_id) + self._application.callLater(self._update) + @pyqtSlot(str) def enable(self, plugin_id: str) -> None: self._plugin_registry.enablePlugin(plugin_id) @@ -251,6 +268,23 @@ class Toolbox(QObject, Extension): def restart(self): CuraApplication.getInstance().windowClosed() + def getRemotePackage(self, package_id: str) -> Optional[Dict]: + # TODO: make the lookup in a dict, not a loop. canUpdate is called for every item. + remote_package = None + for package in self._metadata["packages"]: + if package["package_id"] == package_id: + remote_package = package + break + return remote_package + + @pyqtSlot(str, result = str) + def getRemotePackageURL(self, package_id: str) -> str: + remote_package = self.getRemotePackage(package_id) + if remote_package: + return remote_package["download_url"] + else: + return "" + # Checks # -------------------------------------------------------------------------- @pyqtSlot(str, result = bool) @@ -259,10 +293,7 @@ class Toolbox(QObject, Extension): if local_package is None: return False - remote_package = None - for package in self._metadata["packages"]: - if package["package_id"] == package_id: - remote_package = package + remote_package = self.getRemotePackage(package_id) if remote_package is None: return False diff --git a/resources/packages.json b/resources/packages.json index 8d58f226b0..acda5e0a9e 100644 --- a/resources/packages.json +++ b/resources/packages.json @@ -736,7 +736,7 @@ "package_type": "material", "display_name": "Dagoma Chromatik PLA", "description": "Filament testé et approuvé pour les imprimantes 3D Dagoma. Chromatik est l'idéal pour débuter et suivre les tutoriels premiers pas. Il vous offre qualité et résistance pour chacune de vos impressions.", - "package_version": "1.0.0", + "package_version": "0.9.5", "cura_version": 4, "website": "https://dagoma.fr/boutique/filaments.html", "author": { From 1f088aabc4b02ac050647e0a6e75318293ab3c37 Mon Sep 17 00:00:00 2001 From: Jack Ha Date: Mon, 14 May 2018 16:11:44 +0200 Subject: [PATCH 2/4] Cleanup and simplify toolbox plugin update --- cura/CuraPackageManager.py | 5 ----- .../qml/ToolboxInstalledTileActions.qml | 5 +---- plugins/Toolbox/src/Toolbox.py | 20 +++++++++---------- 3 files changed, 10 insertions(+), 20 deletions(-) diff --git a/cura/CuraPackageManager.py b/cura/CuraPackageManager.py index 4b21096c2f..41718a9e3b 100644 --- a/cura/CuraPackageManager.py +++ b/cura/CuraPackageManager.py @@ -194,11 +194,6 @@ class CuraPackageManager(QObject): return package_id = package_info["package_id"] - # # Check the delayed installation and removal lists first - # if package_id in self._to_remove_package_set: - # self._to_remove_package_set.remove(package_id) - # has_changes = True - # Check if it is installed installed_package_info = self.getInstalledPackageInfo(package_info["package_id"]) to_install_package = installed_package_info is None # Install if the package has not been installed diff --git a/plugins/Toolbox/resources/qml/ToolboxInstalledTileActions.qml b/plugins/Toolbox/resources/qml/ToolboxInstalledTileActions.qml index d63326288d..07f4ed632c 100644 --- a/plugins/Toolbox/resources/qml/ToolboxInstalledTileActions.qml +++ b/plugins/Toolbox/resources/qml/ToolboxInstalledTileActions.qml @@ -37,10 +37,7 @@ Column font: UM.Theme.getFont("default_bold") } } - onClicked: { - // Must do all stuff in 1 function as the current ToolboxInstalledTile object is going to disappear... - toolbox.update(model.id) - } + onClicked: toolbox.update(model.id) } ProgressBar { diff --git a/plugins/Toolbox/src/Toolbox.py b/plugins/Toolbox/src/Toolbox.py index 3dd1ec90ec..81046b51ce 100644 --- a/plugins/Toolbox/src/Toolbox.py +++ b/plugins/Toolbox/src/Toolbox.py @@ -228,9 +228,15 @@ class Toolbox(QObject, Extension): def _update(self) -> None: if self._to_update: plugin_id = self._to_update.pop(0) - Logger.log("d", "Updating package [%s]..." % plugin_id) - self.uninstall(plugin_id) - self.startDownload(self.getRemotePackageURL(plugin_id)) + remote_package = self.getRemotePackage(plugin_id) + if remote_package: + download_url = remote_package["download_url"] + Logger.log("d", "Updating package [%s]..." % plugin_id) + self.uninstall(plugin_id) + self.startDownload(download_url) + else: + Logger.log("e", "Could not update package [%s] because there is no remote package info available.", plugin_id) + if self._to_update: self._application.callLater(self._update) @@ -277,14 +283,6 @@ class Toolbox(QObject, Extension): break return remote_package - @pyqtSlot(str, result = str) - def getRemotePackageURL(self, package_id: str) -> str: - remote_package = self.getRemotePackage(package_id) - if remote_package: - return remote_package["download_url"] - else: - return "" - # Checks # -------------------------------------------------------------------------- @pyqtSlot(str, result = bool) From 0547ad38bdee8899642ab733b325080ea9b867a2 Mon Sep 17 00:00:00 2001 From: Jack Ha Date: Mon, 14 May 2018 16:17:14 +0200 Subject: [PATCH 3/4] Undo setting testing version --- resources/packages.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/resources/packages.json b/resources/packages.json index acda5e0a9e..8d58f226b0 100644 --- a/resources/packages.json +++ b/resources/packages.json @@ -736,7 +736,7 @@ "package_type": "material", "display_name": "Dagoma Chromatik PLA", "description": "Filament testé et approuvé pour les imprimantes 3D Dagoma. Chromatik est l'idéal pour débuter et suivre les tutoriels premiers pas. Il vous offre qualité et résistance pour chacune de vos impressions.", - "package_version": "0.9.5", + "package_version": "1.0.0", "cura_version": 4, "website": "https://dagoma.fr/boutique/filaments.html", "author": { From 49c4f66d9526d0caeee8f14e682ced5f047e45d7 Mon Sep 17 00:00:00 2001 From: Jack Ha Date: Tue, 15 May 2018 10:50:33 +0200 Subject: [PATCH 4/4] Ugly fix for uninstalling installed packages, but not uninstalling bundled packages. --- cura/CuraPackageManager.py | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/cura/CuraPackageManager.py b/cura/CuraPackageManager.py index 41718a9e3b..cb6ce307fb 100644 --- a/cura/CuraPackageManager.py +++ b/cura/CuraPackageManager.py @@ -239,12 +239,18 @@ class CuraPackageManager(QObject): Logger.log("i", "Attempt to remove package [%s] that is not installed, do nothing.", package_id) return + # Temp hack + if package_id not in self._installed_package_dict and package_id in self._bundled_package_dict: + Logger.log("i", "Not uninstalling [%s] because it is a bundled package.") + return + if package_id not in self._to_install_package_dict or force_add: # Schedule for a delayed removal: self._to_remove_package_set.add(package_id) else: - # Remove from the delayed installation list if present - del self._to_install_package_dict[package_id] + if package_id in self._to_install_package_dict: + # Remove from the delayed installation list if present + del self._to_install_package_dict[package_id] self._saveManagementData() self.installedPackagesChanged.emit()