Only show certain App Switcher icons when account has DF access

Added a dictionary where additional user rights can be set.
A plugin such as the DigitalFactory can update this dictionary
if certain account rights change. The `account.additionalRights`
is intended to allow us some flexibility, without breaking the API
in the future.

The Application Switcher now queries the additional account rights,
which is updated by the DF plugin to only show `My printers`,
`Digital Library` and `Print jobs` when the user has access to the
DF.

Contributes to CURA-8624
This commit is contained in:
Jelle Spijker 2021-10-18 15:35:17 +02:00
parent 629f695ef7
commit 666880ad20
No known key found for this signature in database
GPG key ID: 6662DC033BE6B99A
3 changed files with 31 additions and 14 deletions

View file

@ -1,7 +1,7 @@
# Copyright (c) 2018 Ultimaker B.V. # Copyright (c) 2018 Ultimaker B.V.
# Cura is released under the terms of the LGPLv3 or higher. # Cura is released under the terms of the LGPLv3 or higher.
from datetime import datetime 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 from PyQt5.QtCore import QObject, pyqtSignal, pyqtSlot, pyqtProperty, QTimer, Q_ENUMS
@ -46,6 +46,9 @@ class Account(QObject):
loginStateChanged = pyqtSignal(bool) loginStateChanged = pyqtSignal(bool)
"""Signal emitted when user logged in or out""" """Signal emitted when user logged in or out"""
additionalRightsChanged = pyqtSignal("QVariantMap")
"""Signal emitted when a users additional rights change"""
accessTokenChanged = pyqtSignal() accessTokenChanged = pyqtSignal()
syncRequested = pyqtSignal() syncRequested = pyqtSignal()
"""Sync services may connect to this signal to receive sync triggers. """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._error_message = None # type: Optional[Message]
self._logged_in = False self._logged_in = False
self._additional_rights: Dict[str, Any] = {}
self._sync_state = SyncState.IDLE self._sync_state = SyncState.IDLE
self._manual_sync_enabled = False self._manual_sync_enabled = False
self._update_packages_enabled = False self._update_packages_enabled = False
@ -301,3 +305,14 @@ class Account(QObject):
return # Nothing to do, user isn't logged in. return # Nothing to do, user isn't logged in.
self._authorization_service.deleteAuthData() 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

View file

@ -67,10 +67,12 @@ class DigitalFactoryApiClient:
def callbackWrap(response: Optional[Any] = None, *args, **kwargs) -> None: def callbackWrap(response: Optional[Any] = None, *args, **kwargs) -> None:
if (response is not None and isinstance(response, DigitalFactoryFeatureBudgetResponse) and if (response is not None and isinstance(response, DigitalFactoryFeatureBudgetResponse) and
response.library_max_private_projects is not None): response.library_max_private_projects is not None):
callback( # A user has DF access when library_max_private_projects is either -1 (unlimited) or bigger then 0
response.library_max_private_projects == -1 or # Note: -1 is unlimited has_access = response.library_max_private_projects == -1 or response.library_max_private_projects > 0
response.library_max_private_projects > 0) callback(has_access)
self._library_max_private_projects = response.library_max_private_projects 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: else:
Logger.warning(f"Digital Factory: Response is not a feature budget, likely an error: {str(response)}") Logger.warning(f"Digital Factory: Response is not a feature budget, likely an error: {str(response)}")
callback(False) callback(False)

View file

@ -33,63 +33,63 @@ Popup
thumbnail: UM.Theme.getIcon("PrinterTriple", "high"), thumbnail: UM.Theme.getIcon("PrinterTriple", "high"),
description: catalog.i18nc("@tooltip:button", "Monitor printers in Ultimaker Digital Factory."), 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", 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. displayName: "Digital Library", //Not translated, since it's a brand name.
thumbnail: UM.Theme.getIcon("Library", "high"), thumbnail: UM.Theme.getIcon("Library", "high"),
description: catalog.i18nc("@tooltip:button", "Create print projects in Digital Library."), 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", 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"), displayName: catalog.i18nc("@label:button", "Print jobs"),
thumbnail: UM.Theme.getIcon("FoodBeverages"), thumbnail: UM.Theme.getIcon("FoodBeverages"),
description: catalog.i18nc("@tooltip:button", "Monitor print jobs and reprint from your print history."), 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", 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. displayName: "Ultimaker Marketplace", //Not translated, since it's a brand name.
thumbnail: UM.Theme.getIcon("Shop", "high"), thumbnail: UM.Theme.getIcon("Shop", "high"),
description: catalog.i18nc("@tooltip:button", "Extend Ultimaker Cura with plugins and material profiles."), 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", 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. displayName: "Ultimaker Academy", //Not translated, since it's a brand name.
thumbnail: UM.Theme.getIcon("Knowledge"), thumbnail: UM.Theme.getIcon("Knowledge"),
description: catalog.i18nc("@tooltip:button", "Become a 3D printing expert with Ultimaker e-learning."), 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", 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"), displayName: catalog.i18nc("@label:button", "Ultimaker support"),
thumbnail: UM.Theme.getIcon("Help", "high"), thumbnail: UM.Theme.getIcon("Help", "high"),
description: catalog.i18nc("@tooltip:button", "Learn how to get started with Ultimaker Cura."), 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", 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"), displayName: catalog.i18nc("@label:button", "Ask a question"),
thumbnail: UM.Theme.getIcon("Speak", "high"), thumbnail: UM.Theme.getIcon("Speak", "high"),
description: catalog.i18nc("@tooltip:button", "Consult the Ultimaker Community."), description: catalog.i18nc("@tooltip:button", "Consult the Ultimaker Community."),
link: "https://community.ultimaker.com/?utm_source=cura&utm_medium=software&utm_campaign=switcher-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"), displayName: catalog.i18nc("@label:button", "Report a bug"),
thumbnail: UM.Theme.getIcon("Bug", "high"), thumbnail: UM.Theme.getIcon("Bug", "high"),
description: catalog.i18nc("@tooltip:button", "Let developers know that something is going wrong."), description: catalog.i18nc("@tooltip:button", "Let developers know that something is going wrong."),
link: "https://github.com/Ultimaker/Cura/issues/new/choose", link: "https://github.com/Ultimaker/Cura/issues/new/choose",
dfRequired: false DFAccessRequired: false
}, },
{ {
displayName: "Ultimaker.com", //Not translated, since it's a URL. displayName: "Ultimaker.com", //Not translated, since it's a URL.
thumbnail: UM.Theme.getIcon("Browser"), thumbnail: UM.Theme.getIcon("Browser"),
description: catalog.i18nc("@tooltip:button", "Visit the Ultimaker website."), description: catalog.i18nc("@tooltip:button", "Visit the Ultimaker website."),
link: "https://ultimaker.com/?utm_source=cura&utm_medium=software&utm_campaign=switcher-umwebsite", 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 iconSource: modelData.thumbnail
tooltipText: modelData.description tooltipText: modelData.description
isExternalLink: true 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) onClicked: Qt.openUrlExternally(modelData.link)
} }