mirror of
https://github.com/Ultimaker/Cura.git
synced 2025-07-08 07:27:29 -06:00
Expose Account.SyncState as an Enum to QML
Provides a single source of truth CURA-7290
This commit is contained in:
parent
8937c63219
commit
1ae050bbc5
5 changed files with 38 additions and 35 deletions
|
@ -1,10 +1,9 @@
|
|||
# Copyright (c) 2018 Ultimaker B.V.
|
||||
# Cura is released under the terms of the LGPLv3 or higher.
|
||||
from datetime import datetime
|
||||
from enum import Enum
|
||||
from typing import Optional, Dict, TYPE_CHECKING
|
||||
|
||||
from PyQt5.QtCore import QObject, pyqtSignal, pyqtSlot, pyqtProperty, QTimer
|
||||
from PyQt5.QtCore import QObject, pyqtSignal, pyqtSlot, pyqtProperty, QTimer, Q_ENUMS
|
||||
|
||||
from UM.Message import Message
|
||||
from UM.i18n import i18nCatalog
|
||||
|
@ -18,6 +17,13 @@ if TYPE_CHECKING:
|
|||
i18n_catalog = i18nCatalog("cura")
|
||||
|
||||
|
||||
class SyncState(QObject):
|
||||
"""QML: Cura.AccountSyncState"""
|
||||
SYNCING = 0
|
||||
SUCCESS = 1
|
||||
ERROR = 2
|
||||
|
||||
|
||||
## The account API provides a version-proof bridge to use Ultimaker Accounts
|
||||
#
|
||||
# Usage:
|
||||
|
@ -30,13 +36,7 @@ i18n_catalog = i18nCatalog("cura")
|
|||
class Account(QObject):
|
||||
# The interval with which the remote clusters are checked
|
||||
SYNC_INTERVAL = 30.0 # seconds
|
||||
|
||||
class SyncState(Enum):
|
||||
"""Caution: values used in qml (eg. SyncState.qml)"""
|
||||
|
||||
SYNCING = "syncing",
|
||||
SUCCESS = "success",
|
||||
ERROR = "error"
|
||||
Q_ENUMS(SyncState)
|
||||
|
||||
# Signal emitted when user logged in or out.
|
||||
loginStateChanged = pyqtSignal(bool)
|
||||
|
@ -44,7 +44,7 @@ class Account(QObject):
|
|||
cloudPrintersDetectedChanged = pyqtSignal(bool)
|
||||
syncRequested = pyqtSignal()
|
||||
lastSyncDateTimeChanged = pyqtSignal()
|
||||
syncStateChanged = pyqtSignal(str)
|
||||
syncStateChanged = pyqtSignal(int) # because it's an int Enum
|
||||
|
||||
def __init__(self, application: "CuraApplication", parent = None) -> None:
|
||||
super().__init__(parent)
|
||||
|
@ -53,7 +53,7 @@ class Account(QObject):
|
|||
|
||||
self._error_message = None # type: Optional[Message]
|
||||
self._logged_in = False
|
||||
self._sync_state = self.SyncState.SUCCESS
|
||||
self._sync_state = SyncState.SUCCESS
|
||||
self._last_sync_str = "-"
|
||||
|
||||
self._callback_port = 32118
|
||||
|
@ -81,7 +81,7 @@ class Account(QObject):
|
|||
self._update_timer.setSingleShot(True)
|
||||
self._update_timer.timeout.connect(self.syncRequested)
|
||||
|
||||
self._sync_services = {} # type: Dict[str, Account.SyncState]
|
||||
self._sync_services = {} # type: Dict[str, SyncState]
|
||||
"""contains entries "service_name" : SyncState"""
|
||||
|
||||
def initialize(self) -> None:
|
||||
|
@ -94,30 +94,30 @@ class Account(QObject):
|
|||
def setSyncState(self, service_name: str, state: SyncState) -> None:
|
||||
""" Can be used to register sync services and update account sync states
|
||||
|
||||
Example: `setSyncState("PluginSyncService", Account.SyncState.SYNCING)`
|
||||
Example: `setSyncState("PluginSyncService", SyncState.SYNCING)`
|
||||
:param service_name: A unique name for your service, such as `plugins` or `backups`
|
||||
:param state: One of Account.SyncState
|
||||
:param state: One of SyncState
|
||||
"""
|
||||
|
||||
prev_state = self._sync_state
|
||||
|
||||
self._sync_services[service_name] = state
|
||||
|
||||
if any(val == self.SyncState.SYNCING for val in self._sync_services.values()):
|
||||
self._sync_state = self.SyncState.SYNCING
|
||||
elif any(val == self.SyncState.ERROR for val in self._sync_services.values()):
|
||||
self._sync_state = self.SyncState.ERROR
|
||||
if any(val == SyncState.SYNCING for val in self._sync_services.values()):
|
||||
self._sync_state = SyncState.SYNCING
|
||||
elif any(val == SyncState.ERROR for val in self._sync_services.values()):
|
||||
self._sync_state = SyncState.ERROR
|
||||
else:
|
||||
self._sync_state = self.SyncState.SUCCESS
|
||||
self._sync_state = SyncState.SUCCESS
|
||||
|
||||
if self._sync_state != prev_state:
|
||||
self.syncStateChanged.emit(self._sync_state.value[0])
|
||||
self.syncStateChanged.emit(self._sync_state)
|
||||
|
||||
if self._sync_state == self.SyncState.SUCCESS:
|
||||
if self._sync_state == SyncState.SUCCESS:
|
||||
self._last_sync_str = datetime.now().strftime("%d/%m/%Y %H:%M")
|
||||
self.lastSyncDateTimeChanged.emit()
|
||||
|
||||
if self._sync_state != self.SyncState.SYNCING:
|
||||
if self._sync_state != SyncState.SYNCING:
|
||||
# schedule new auto update after syncing completed (for whatever reason)
|
||||
if not self._update_timer.isActive():
|
||||
self._update_timer.start()
|
||||
|
|
|
@ -48,6 +48,7 @@ from UM.Workspace.WorkspaceReader import WorkspaceReader
|
|||
from UM.i18n import i18nCatalog
|
||||
from cura import ApplicationMetadata
|
||||
from cura.API import CuraAPI
|
||||
from cura.API.Account import Account
|
||||
from cura.Arranging.Arrange import Arrange
|
||||
from cura.Arranging.ArrangeObjectsAllBuildPlatesJob import ArrangeObjectsAllBuildPlatesJob
|
||||
from cura.Arranging.ArrangeObjectsJob import ArrangeObjectsJob
|
||||
|
@ -1106,6 +1107,7 @@ class CuraApplication(QtApplication):
|
|||
|
||||
from cura.API import CuraAPI
|
||||
qmlRegisterSingletonType(CuraAPI, "Cura", 1, 1, "API", self.getCuraAPI)
|
||||
qmlRegisterUncreatableType(Account, "Cura", 1, 0, "AccountSyncState", "Could not create AccountSyncState")
|
||||
|
||||
# As of Qt5.7, it is necessary to get rid of any ".." in the path for the singleton to work.
|
||||
actions_url = QUrl.fromLocalFile(os.path.abspath(Resources.getPath(CuraApplication.ResourceTypes.QmlFiles, "Actions.qml")))
|
||||
|
|
|
@ -13,7 +13,7 @@ from UM.Logger import Logger
|
|||
from UM.Message import Message
|
||||
from UM.Signal import Signal
|
||||
from UM.TaskManagement.HttpRequestScope import JsonDecoratorScope
|
||||
from cura.API import Account
|
||||
from cura.API.Account import SyncState
|
||||
from cura.CuraApplication import CuraApplication, ApplicationMetadata
|
||||
from cura.UltimakerCloud.UltimakerCloudScope import UltimakerCloudScope
|
||||
from .SubscribedPackagesModel import SubscribedPackagesModel
|
||||
|
@ -62,7 +62,7 @@ class CloudPackageChecker(QObject):
|
|||
self._hideSyncMessage()
|
||||
|
||||
def _getUserSubscribedPackages(self) -> None:
|
||||
self._application.getCuraAPI().account.setSyncState(self.SYNC_SERVICE_NAME, Account.SyncState.SYNCING)
|
||||
self._application.getCuraAPI().account.setSyncState(self.SYNC_SERVICE_NAME, SyncState.SYNCING)
|
||||
Logger.debug("Requesting subscribed packages metadata from server.")
|
||||
url = CloudApiModel.api_url_user_packages
|
||||
self._application.getHttpRequestManager().get(url,
|
||||
|
@ -75,7 +75,7 @@ class CloudPackageChecker(QObject):
|
|||
Logger.log("w",
|
||||
"Requesting user packages failed, response code %s while trying to connect to %s",
|
||||
reply.attribute(QNetworkRequest.HttpStatusCodeAttribute), reply.url())
|
||||
self._application.getCuraAPI().account.setSyncState(self.SYNC_SERVICE_NAME, "error")
|
||||
self._application.getCuraAPI().account.setSyncState(self.SYNC_SERVICE_NAME, SyncState.ERROR)
|
||||
return
|
||||
|
||||
try:
|
||||
|
@ -84,13 +84,13 @@ class CloudPackageChecker(QObject):
|
|||
if "errors" in json_data:
|
||||
for error in json_data["errors"]:
|
||||
Logger.log("e", "%s", error["title"])
|
||||
self._application.getCuraAPI().account.setSyncState(self.SYNC_SERVICE_NAME, "error")
|
||||
self._application.getCuraAPI().account.setSyncState(self.SYNC_SERVICE_NAME, SyncState.ERROR)
|
||||
return
|
||||
self._handleCompatibilityData(json_data["data"])
|
||||
except json.decoder.JSONDecodeError:
|
||||
Logger.log("w", "Received invalid JSON for user subscribed packages from the Web Marketplace")
|
||||
|
||||
self._application.getCuraAPI().account.setSyncState(self.SYNC_SERVICE_NAME, "success")
|
||||
self._application.getCuraAPI().account.setSyncState(self.SYNC_SERVICE_NAME, SyncState.SUCCESS)
|
||||
|
||||
def _handleCompatibilityData(self, subscribed_packages_payload: List[Dict[str, Any]]) -> None:
|
||||
user_subscribed_packages = [plugin["package_id"] for plugin in subscribed_packages_payload]
|
||||
|
|
|
@ -10,6 +10,7 @@ from UM.Logger import Logger # To log errors talking to the API.
|
|||
from UM.Message import Message
|
||||
from UM.Signal import Signal
|
||||
from cura.API import Account
|
||||
from cura.API.Account import SyncState
|
||||
from cura.CuraApplication import CuraApplication
|
||||
from cura.Settings.CuraStackBuilder import CuraStackBuilder
|
||||
from cura.Settings.GlobalStack import GlobalStack
|
||||
|
@ -89,7 +90,7 @@ class CloudOutputDeviceManager:
|
|||
Logger.info("Syncing cloud printer clusters")
|
||||
|
||||
self._syncing = True
|
||||
self._account.setSyncState(self.SYNC_SERVICE_NAME, Account.SyncState.SYNCING)
|
||||
self._account.setSyncState(self.SYNC_SERVICE_NAME, SyncState.SYNCING)
|
||||
self._api.getClusters(self._onGetRemoteClustersFinished, self._onGetRemoteClusterFailed)
|
||||
|
||||
def _onGetRemoteClustersFinished(self, clusters: List[CloudClusterResponse]) -> None:
|
||||
|
@ -119,11 +120,11 @@ class CloudOutputDeviceManager:
|
|||
self._connectToActiveMachine()
|
||||
|
||||
self._syncing = False
|
||||
self._account.setSyncState(self.SYNC_SERVICE_NAME, Account.SyncState.SUCCESS)
|
||||
self._account.setSyncState(self.SYNC_SERVICE_NAME, SyncState.SUCCESS)
|
||||
|
||||
def _onGetRemoteClusterFailed(self):
|
||||
self._syncing = False
|
||||
self._account.setSyncState(self.SYNC_SERVICE_NAME, Account.SyncState.ERROR)
|
||||
self._account.setSyncState(self.SYNC_SERVICE_NAME, SyncState.ERROR)
|
||||
|
||||
def _onDevicesDiscovered(self, clusters: List[CloudClusterResponse]) -> None:
|
||||
"""**Synchronously** create machines for discovered devices
|
||||
|
|
|
@ -82,20 +82,20 @@ Row // sync state icon + message
|
|||
signal syncStateChanged(string newState)
|
||||
|
||||
onSyncStateChanged: {
|
||||
if(newState == "syncing"){
|
||||
if(newState == Cura.AccountSyncState.SYNCING){
|
||||
syncRow.iconSource = UM.Theme.getIcon("update")
|
||||
syncRow.labelText = catalog.i18nc("@label", "Checking...")
|
||||
} else if (newState == "success") {
|
||||
} else if (newState == Cura.AccountSyncState.SUCCESS) {
|
||||
syncRow.iconSource = UM.Theme.getIcon("checked")
|
||||
syncRow.labelText = catalog.i18nc("@label", "You are up to date")
|
||||
} else if (newState == "error") {
|
||||
syncRow.iconSource = UM.Theme.getIcon("warning-light")
|
||||
} else if (newState == Cura.AccountSyncState.ERROR) {
|
||||
syncRow.iconSource = UM.Theme.getIcon("warning_light")
|
||||
syncRow.labelText = catalog.i18nc("@label", "Something went wrong...")
|
||||
} else {
|
||||
print("Error: unexpected sync state: " + newState)
|
||||
}
|
||||
|
||||
if(newState == "syncing"){
|
||||
if(newState == Cura.AccountSyncState.SYNCING){
|
||||
syncRow.animateIconRotation = true
|
||||
syncRow.syncButtonVisible = false
|
||||
} else {
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue