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/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..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,15 +83,20 @@ 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 else: - # todo unsubscribe declined packages - pass + self._cloud_package_manager.unsubscribe(item["package_id"]) # delete temp file os.remove(item["package_path"]) 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() 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],