diff --git a/cura/API/Account.py b/cura/API/Account.py index a85e2c64c5..ab45c4a4be 100644 --- a/cura/API/Account.py +++ b/cura/API/Account.py @@ -1,7 +1,7 @@ # Copyright (c) 2018 Ultimaker B.V. # Cura is released under the terms of the LGPLv3 or higher. from datetime import datetime -from typing import Optional, Dict, TYPE_CHECKING, Callable +from typing import Any, Optional, Dict, TYPE_CHECKING, Callable from PyQt5.QtCore import QObject, pyqtSignal, pyqtSlot, pyqtProperty, QTimer, Q_ENUMS @@ -46,6 +46,9 @@ class Account(QObject): loginStateChanged = pyqtSignal(bool) """Signal emitted when user logged in or out""" + additionalRightsChanged = pyqtSignal("QVariantMap") + """Signal emitted when a users additional rights change""" + accessTokenChanged = pyqtSignal() syncRequested = pyqtSignal() """Sync services may connect to this signal to receive sync triggers. @@ -70,6 +73,7 @@ class Account(QObject): self._error_message = None # type: Optional[Message] self._logged_in = False + self._additional_rights: Dict[str, Any] = {} self._sync_state = SyncState.IDLE self._manual_sync_enabled = False self._update_packages_enabled = False @@ -301,3 +305,14 @@ class Account(QObject): return # Nothing to do, user isn't logged in. self._authorization_service.deleteAuthData() + + def updateAdditionalRight(self, **kwargs) -> None: + """Update the additional rights of the account. + The argument(s) are the rights that need to be set""" + self._additional_rights.update(kwargs) + self.additionalRightsChanged.emit(self._additional_rights) + + @pyqtProperty("QVariantMap", notify = additionalRightsChanged) + def additionalRights(self) -> Dict[str, Any]: + """A dictionary which can be queried for additional account rights.""" + return self._additional_rights diff --git a/plugins/DigitalLibrary/src/DigitalFactoryApiClient.py b/plugins/DigitalLibrary/src/DigitalFactoryApiClient.py index ad87ea9b8a..5301151c5f 100644 --- a/plugins/DigitalLibrary/src/DigitalFactoryApiClient.py +++ b/plugins/DigitalLibrary/src/DigitalFactoryApiClient.py @@ -67,10 +67,12 @@ class DigitalFactoryApiClient: def callbackWrap(response: Optional[Any] = None, *args, **kwargs) -> None: if (response is not None and isinstance(response, DigitalFactoryFeatureBudgetResponse) and response.library_max_private_projects is not None): - callback( - response.library_max_private_projects == -1 or # Note: -1 is unlimited - response.library_max_private_projects > 0) + # A user has DF access when library_max_private_projects is either -1 (unlimited) or bigger then 0 + has_access = response.library_max_private_projects == -1 or response.library_max_private_projects > 0 + callback(has_access) self._library_max_private_projects = response.library_max_private_projects + # update the account with the additional user rights + self._account.updateAdditionalRight(df_access = has_access) else: Logger.warning(f"Digital Factory: Response is not a feature budget, likely an error: {str(response)}") callback(False) diff --git a/resources/qml/ApplicationSwitcher/ApplicationSwitcherPopup.qml b/resources/qml/ApplicationSwitcher/ApplicationSwitcherPopup.qml index bbdc5acde9..ede42fcd5f 100644 --- a/resources/qml/ApplicationSwitcher/ApplicationSwitcherPopup.qml +++ b/resources/qml/ApplicationSwitcher/ApplicationSwitcherPopup.qml @@ -33,63 +33,63 @@ Popup thumbnail: UM.Theme.getIcon("PrinterTriple", "high"), description: catalog.i18nc("@tooltip:button", "Monitor printers in Ultimaker Digital Factory."), link: "https://digitalfactory.ultimaker.com/app/printers?utm_source=cura&utm_medium=software&utm_campaign=switcher-digital-factory-printers", - dfRequired: true + DFAccessRequired: true }, { displayName: "Digital Library", //Not translated, since it's a brand name. thumbnail: UM.Theme.getIcon("Library", "high"), description: catalog.i18nc("@tooltip:button", "Create print projects in Digital Library."), link: "https://digitalfactory.ultimaker.com/app/library?utm_source=cura&utm_medium=software&utm_campaign=switcher-library", - dfRequired: true + DFAccessRequired: true }, { displayName: catalog.i18nc("@label:button", "Print jobs"), thumbnail: UM.Theme.getIcon("FoodBeverages"), description: catalog.i18nc("@tooltip:button", "Monitor print jobs and reprint from your print history."), link: "https://digitalfactory.ultimaker.com/app/print-jobs?utm_source=cura&utm_medium=software&utm_campaign=switcher-digital-factory-printjobs", - dfRequired: true + DFAccessRequired: true }, { displayName: "Ultimaker Marketplace", //Not translated, since it's a brand name. thumbnail: UM.Theme.getIcon("Shop", "high"), description: catalog.i18nc("@tooltip:button", "Extend Ultimaker Cura with plugins and material profiles."), link: "https://marketplace.ultimaker.com/?utm_source=cura&utm_medium=software&utm_campaign=switcher-marketplace-materials", - dfRequired: false + DFAccessRequired: false }, { displayName: "Ultimaker Academy", //Not translated, since it's a brand name. thumbnail: UM.Theme.getIcon("Knowledge"), description: catalog.i18nc("@tooltip:button", "Become a 3D printing expert with Ultimaker e-learning."), link: "https://academy.ultimaker.com/?utm_source=cura&utm_medium=software&utm_campaign=switcher-academy", - dfRequired: false + DFAccessRequired: false }, { displayName: catalog.i18nc("@label:button", "Ultimaker support"), thumbnail: UM.Theme.getIcon("Help", "high"), description: catalog.i18nc("@tooltip:button", "Learn how to get started with Ultimaker Cura."), link: "https://support.ultimaker.com/?utm_source=cura&utm_medium=software&utm_campaign=switcher-support", - dfRequired: false + DFAccessRequired: false }, { displayName: catalog.i18nc("@label:button", "Ask a question"), thumbnail: UM.Theme.getIcon("Speak", "high"), description: catalog.i18nc("@tooltip:button", "Consult the Ultimaker Community."), link: "https://community.ultimaker.com/?utm_source=cura&utm_medium=software&utm_campaign=switcher-community", - dfRequired: false + DFAccessRequired: false }, { displayName: catalog.i18nc("@label:button", "Report a bug"), thumbnail: UM.Theme.getIcon("Bug", "high"), description: catalog.i18nc("@tooltip:button", "Let developers know that something is going wrong."), link: "https://github.com/Ultimaker/Cura/issues/new/choose", - dfRequired: false + DFAccessRequired: false }, { displayName: "Ultimaker.com", //Not translated, since it's a URL. thumbnail: UM.Theme.getIcon("Browser"), description: catalog.i18nc("@tooltip:button", "Visit the Ultimaker website."), link: "https://ultimaker.com/?utm_source=cura&utm_medium=software&utm_campaign=switcher-umwebsite", - dfRequired: false + DFAccessRequired: false } ] @@ -99,7 +99,7 @@ Popup iconSource: modelData.thumbnail tooltipText: modelData.description isExternalLink: true - visible: modelData.dfRequired ? Cura.API.account.isLoggedIn : true + visible: modelData.DFAccessRequired ? Cura.API.account.isLoggedIn & Cura.API.account.additionalRights["df_access"] : true onClicked: Qt.openUrlExternally(modelData.link) }