From 4e8534b93b1be06d25f647a1f6da1032d71379dc Mon Sep 17 00:00:00 2001 From: Nino van Hooff Date: Fri, 17 Jan 2020 11:10:29 +0100 Subject: [PATCH 1/3] Unsubscribe from package when a license is declined (cloud flow) CURA-6984 --- plugins/Toolbox/src/CloudApiModel.py | 8 ++++++++ plugins/Toolbox/src/CloudSync/CloudPackageManager.py | 5 +++++ plugins/Toolbox/src/CloudSync/SyncOrchestrator.py | 3 +-- 3 files changed, 14 insertions(+), 2 deletions(-) diff --git a/plugins/Toolbox/src/CloudApiModel.py b/plugins/Toolbox/src/CloudApiModel.py index 31c3139262..556d54cf88 100644 --- a/plugins/Toolbox/src/CloudApiModel.py +++ b/plugins/Toolbox/src/CloudApiModel.py @@ -18,3 +18,11 @@ class CloudApiModel: cloud_api_root=cloud_api_root, cloud_api_version=cloud_api_version, ) + + ## https://api.ultimaker.com/cura-packages/v1/user/packages/{package_id} + @classmethod + def userPackageUrl(cls, package_id: str) -> str: + + return (CloudApiModel.api_url_user_packages + "/{package_id}").format( + package_id=package_id + ) diff --git a/plugins/Toolbox/src/CloudSync/CloudPackageManager.py b/plugins/Toolbox/src/CloudSync/CloudPackageManager.py index ee57a1b90d..0cbc9eaa7a 100644 --- a/plugins/Toolbox/src/CloudSync/CloudPackageManager.py +++ b/plugins/Toolbox/src/CloudSync/CloudPackageManager.py @@ -16,3 +16,8 @@ class CloudPackageManager: data=data.encode(), scope=self._scope ) + + def unsubscribe(self, package_id: str) -> None: + url = CloudApiModel.userPackageUrl(package_id) + self._request_manager.delete(url=url, scope=self._scope) + diff --git a/plugins/Toolbox/src/CloudSync/SyncOrchestrator.py b/plugins/Toolbox/src/CloudSync/SyncOrchestrator.py index 674fb68729..abde4e4072 100644 --- a/plugins/Toolbox/src/CloudSync/SyncOrchestrator.py +++ b/plugins/Toolbox/src/CloudSync/SyncOrchestrator.py @@ -83,8 +83,7 @@ class SyncOrchestrator(Extension): self._cloud_package_manager.subscribe(item["package_id"]) has_changes = True else: - # todo unsubscribe declined packages - pass + self._cloud_package_manager.unsubscribe(item["package_id"]) # delete temp file os.remove(item["package_path"]) From 9dd50c88046128bd77dcd4cd7a02b7180a4fd580 Mon Sep 17 00:00:00 2001 From: Nino van Hooff Date: Fri, 17 Jan 2020 11:44:57 +0100 Subject: [PATCH 2/3] Replace buttons by PrimaryButtons for cloud sync dialogs CURA-6984 --- .../qml/dialogs/CompatibilityDialog.qml | 4 +++- .../qml/dialogs/ToolboxLicenseDialog.qml | 21 ++++++++++++------- resources/themes/cura-light/theme.json | 1 + 3 files changed, 17 insertions(+), 9 deletions(-) diff --git a/plugins/Toolbox/resources/qml/dialogs/CompatibilityDialog.qml b/plugins/Toolbox/resources/qml/dialogs/CompatibilityDialog.qml index 06c1102811..32b4da4823 100644 --- a/plugins/Toolbox/resources/qml/dialogs/CompatibilityDialog.qml +++ b/plugins/Toolbox/resources/qml/dialogs/CompatibilityDialog.qml @@ -152,7 +152,7 @@ UM.Dialog{ } // End of ScrollView - Cura.ActionButton + Cura.PrimaryButton { id: nextButton anchors.bottom: parent.bottom @@ -160,6 +160,8 @@ UM.Dialog{ anchors.margins: UM.Theme.getSize("default_margin").height text: catalog.i18nc("@button", "Next") onClicked: accept() + leftPadding: UM.Theme.getSize("dialog_primary_button_padding").width + rightPadding: UM.Theme.getSize("dialog_primary_button_padding").width } } } diff --git a/plugins/Toolbox/resources/qml/dialogs/ToolboxLicenseDialog.qml b/plugins/Toolbox/resources/qml/dialogs/ToolboxLicenseDialog.qml index 2c88ac6d5f..3e7cdc9df8 100644 --- a/plugins/Toolbox/resources/qml/dialogs/ToolboxLicenseDialog.qml +++ b/plugins/Toolbox/resources/qml/dialogs/ToolboxLicenseDialog.qml @@ -10,6 +10,7 @@ import QtQuick.Controls.Styles 1.4 // TODO: Switch to QtQuick.Controls 2.x and remove QtQuick.Controls.Styles import UM 1.1 as UM +import Cura 1.6 as Cura UM.Dialog { @@ -51,18 +52,22 @@ UM.Dialog } rightButtons: [ - Button + Cura.PrimaryButton { - id: acceptButton - anchors.margins: UM.Theme.getSize("default_margin").width - text: catalog.i18nc("@action:button", "Accept") + leftPadding: UM.Theme.getSize("dialog_primary_button_padding").width + rightPadding: UM.Theme.getSize("dialog_primary_button_padding").width + + text: catalog.i18nc("@button", "Agree") onClicked: { handler.onLicenseAccepted() } - }, - Button + } + ] + + leftButtons: + [ + Cura.SecondaryButton { id: declineButton - anchors.margins: UM.Theme.getSize("default_margin").width - text: catalog.i18nc("@action:button", "Decline") + text: catalog.i18nc("@button", "Decline and remove from account") onClicked: { handler.onLicenseDeclined() } } ] diff --git a/resources/themes/cura-light/theme.json b/resources/themes/cura-light/theme.json index e5009d8633..de4c9ccb42 100644 --- a/resources/themes/cura-light/theme.json +++ b/resources/themes/cura-light/theme.json @@ -520,6 +520,7 @@ "action_button": [15.0, 2.5], "action_button_icon": [1.0, 1.0], "action_button_radius": [0.15, 0.15], + "dialog_primary_button_padding": [3.0, 0], "radio_button": [1.3, 1.3], From b03be75a1338cab6ef0ce79a88b01199c4fe977b Mon Sep 17 00:00:00 2001 From: Nino van Hooff Date: Fri, 17 Jan 2020 12:21:18 +0100 Subject: [PATCH 3/3] Show error messages for cloud flow errors - failed downloads - failed installs CURA-6984 --- plugins/Toolbox/src/CloudSync/SyncOrchestrator.py | 15 +++++++++++++-- 1 file changed, 13 insertions(+), 2 deletions(-) diff --git a/plugins/Toolbox/src/CloudSync/SyncOrchestrator.py b/plugins/Toolbox/src/CloudSync/SyncOrchestrator.py index abde4e4072..e97bdbcbc4 100644 --- a/plugins/Toolbox/src/CloudSync/SyncOrchestrator.py +++ b/plugins/Toolbox/src/CloudSync/SyncOrchestrator.py @@ -1,8 +1,10 @@ import os from typing import List, Dict, Any, cast +from UM import i18n_catalog from UM.Extension import Extension from UM.Logger import Logger +from UM.Message import Message from UM.PluginRegistry import PluginRegistry from cura.CuraApplication import CuraApplication from .CloudPackageChecker import CloudPackageChecker @@ -64,7 +66,10 @@ class SyncOrchestrator(Extension): # \param success_items: Dict[package_id, file_path] # \param error_items: List[package_id] def _onDownloadFinished(self, success_items: Dict[str, str], error_items: List[str]) -> None: - # todo handle error items + if error_items: + message = i18n_catalog.i18nc("@info:generic", "{} plugins failed to download".format(len(error_items))) + self._showErrorMessage(message) + plugin_path = cast(str, PluginRegistry.getInstance().getPluginPath(self.getPluginId())) self._license_presenter.present(plugin_path, success_items) @@ -78,7 +83,8 @@ class SyncOrchestrator(Extension): if item["accepted"]: # install and subscribe packages if not self._package_manager.installPackage(item["package_path"]): - Logger.error("could not install {}".format(item["package_id"])) + message = "Could not install {}".format(item["package_id"]) + self._showErrorMessage(message) continue self._cloud_package_manager.subscribe(item["package_id"]) has_changes = True @@ -89,3 +95,8 @@ class SyncOrchestrator(Extension): if has_changes: self._restart_presenter.present() + + ## Logs an error and shows it to the user + def _showErrorMessage(self, text: str): + Logger.error(text) + Message(text, lifetime=0).show()