From 2da8040e5afc7201d0130dc3387229c39acd5fef Mon Sep 17 00:00:00 2001 From: Nino van Hooff Date: Fri, 10 Jan 2020 15:49:18 +0100 Subject: [PATCH] Show a restart dialog at the end of the cloud sync flow CURA-6983 --- .../CloudSync/RestartApplicationPresenter.py | 49 +++++++++++++++++++ .../Toolbox/src/CloudSync/SyncOrchestrator.py | 27 +++++----- 2 files changed, 65 insertions(+), 11 deletions(-) create mode 100644 plugins/Toolbox/src/CloudSync/RestartApplicationPresenter.py diff --git a/plugins/Toolbox/src/CloudSync/RestartApplicationPresenter.py b/plugins/Toolbox/src/CloudSync/RestartApplicationPresenter.py new file mode 100644 index 0000000000..e0d26cbf7a --- /dev/null +++ b/plugins/Toolbox/src/CloudSync/RestartApplicationPresenter.py @@ -0,0 +1,49 @@ +import os +import tempfile +from functools import reduce +from typing import Dict, List, Optional, Any + +from PyQt5.QtNetwork import QNetworkReply + +from UM import i18n_catalog, i18nCatalog +from UM.Logger import Logger +from UM.Message import Message +from UM.Signal import Signal +from UM.TaskManagement.HttpRequestManager import HttpRequestManager +from cura.CuraApplication import CuraApplication +from plugins.Toolbox.src.UltimakerCloudScope import UltimakerCloudScope +from plugins.Toolbox.src.CloudSync.SubscribedPackagesModel import SubscribedPackagesModel + + +## Presents a dialog telling the user that a restart is required to apply changes +# Since we cannot restart Cura, the app is closed instead when the button is clicked +class RestartApplicationPresenter: + + def __init__(self, app: CuraApplication): + # Emits (Dict[str, str], List[str]) # (success_items, error_items) + # Dict{success_package_id, temp_file_path} + # List[errored_package_id] + self.done = Signal() + + self._app = app + self._i18n_catalog = i18nCatalog("cura") + + def present(self): + app_name = self._app.getApplicationDisplayName() + + message = Message(title=self._i18n_catalog.i18nc( + "@info:generic", + "You need to quit and restart {} before changes have effect.", app_name + )) + + message.addAction("quit", + name="Quit " + app_name, + icon = "", + description="Close the application", + button_align=Message.ActionButtonAlignment.ALIGN_RIGHT) + + message.actionTriggered.connect(self._quitClicked) + message.show() + + def _quitClicked(self, *_): + self._app.windowClosed() diff --git a/plugins/Toolbox/src/CloudSync/SyncOrchestrator.py b/plugins/Toolbox/src/CloudSync/SyncOrchestrator.py index 507de45f55..f740c6dff1 100644 --- a/plugins/Toolbox/src/CloudSync/SyncOrchestrator.py +++ b/plugins/Toolbox/src/CloudSync/SyncOrchestrator.py @@ -11,6 +11,7 @@ from plugins.Toolbox.src.CloudSync.CloudPackageManager import CloudPackageManage from plugins.Toolbox.src.CloudSync.DiscrepanciesPresenter import DiscrepanciesPresenter from plugins.Toolbox.src.CloudSync.DownloadPresenter import DownloadPresenter from plugins.Toolbox.src.CloudSync.LicensePresenter import LicensePresenter +from plugins.Toolbox.src.CloudSync.RestartApplicationPresenter import RestartApplicationPresenter from plugins.Toolbox.src.CloudSync.SubscribedPackagesModel import SubscribedPackagesModel @@ -41,22 +42,24 @@ class SyncOrchestrator(Extension): self._checker = CloudPackageChecker(app) # type: CloudPackageChecker self._checker.discrepancies.connect(self._onDiscrepancies) - self._discrepanciesPresenter = DiscrepanciesPresenter(app) # type: DiscrepanciesPresenter - self._discrepanciesPresenter.packageMutations.connect(self._onPackageMutations) + self._discrepancies_presenter = DiscrepanciesPresenter(app) # type: DiscrepanciesPresenter + self._discrepancies_presenter.packageMutations.connect(self._onPackageMutations) - self._downloadPresenter = DownloadPresenter(app) # type: DownloadPresenter + self._download_Presenter = DownloadPresenter(app) # type: DownloadPresenter - self._licensePresenter = LicensePresenter(app) # type: LicensePresenter - self._licensePresenter.licenseAnswers.connect(self._onLicenseAnswers) + self._license_presenter = LicensePresenter(app) # type: LicensePresenter + self._license_presenter.licenseAnswers.connect(self._onLicenseAnswers) + + self._restart_presenter = RestartApplicationPresenter(app) def _onDiscrepancies(self, model: SubscribedPackagesModel): plugin_path = PluginRegistry.getInstance().getPluginPath(self.getPluginId()) - self._discrepanciesPresenter.present(plugin_path, model) + self._discrepancies_presenter.present(plugin_path, model) def _onPackageMutations(self, mutations: SubscribedPackagesModel): - self._downloadPresenter = self._downloadPresenter.resetCopy() - self._downloadPresenter.done.connect(self._onDownloadFinished) - self._downloadPresenter.download(mutations) + self._download_Presenter = self._download_Presenter.resetCopy() + self._download_Presenter.done.connect(self._onDownloadFinished) + self._download_Presenter.download(mutations) ## Called when a set of packages have finished downloading # \param success_items: Dict[package_id, file_path] @@ -64,7 +67,7 @@ class SyncOrchestrator(Extension): def _onDownloadFinished(self, success_items: Dict[str, str], error_items: List[str]): # todo handle error items plugin_path = PluginRegistry.getInstance().getPluginPath(self.getPluginId()) - self._licensePresenter.present(plugin_path, success_items) + self._license_presenter.present(plugin_path, success_items) # Called when user has accepted / declined all licenses for the downloaded packages def _onLicenseAnswers(self, answers: [Dict[str, Any]]): @@ -80,10 +83,12 @@ class SyncOrchestrator(Extension): else: # todo unsubscribe declined packages pass - # delete temp file os.remove(item["package_path"]) + self._restart_presenter.present() + +