mirror of
https://github.com/Ultimaker/Cura.git
synced 2025-07-07 15:07:28 -06:00
Also check for package updates automatically
Moves the 30-second sync timer from CloudOutputDeviceManager to Account and subscribes CloudPackageChecker to the timer. CURA-7290
This commit is contained in:
parent
637a241d99
commit
88ff68e40c
3 changed files with 37 additions and 29 deletions
|
@ -3,9 +3,8 @@
|
||||||
from datetime import datetime
|
from datetime import datetime
|
||||||
from typing import Optional, Dict, TYPE_CHECKING
|
from typing import Optional, Dict, TYPE_CHECKING
|
||||||
|
|
||||||
from PyQt5.QtCore import QObject, pyqtSignal, pyqtSlot, pyqtProperty
|
from PyQt5.QtCore import QObject, pyqtSignal, pyqtSlot, pyqtProperty, QTimer
|
||||||
|
|
||||||
from UM.Logger import Logger
|
|
||||||
from UM.Message import Message
|
from UM.Message import Message
|
||||||
from UM.i18n import i18nCatalog
|
from UM.i18n import i18nCatalog
|
||||||
from cura.OAuth2.AuthorizationService import AuthorizationService
|
from cura.OAuth2.AuthorizationService import AuthorizationService
|
||||||
|
@ -28,11 +27,14 @@ i18n_catalog = i18nCatalog("cura")
|
||||||
# api.account.userProfile # Who is logged in``
|
# api.account.userProfile # Who is logged in``
|
||||||
#
|
#
|
||||||
class Account(QObject):
|
class Account(QObject):
|
||||||
|
# The interval with which the remote clusters are checked
|
||||||
|
SYNC_INTERVAL = 30.0 # seconds
|
||||||
|
|
||||||
# Signal emitted when user logged in or out.
|
# Signal emitted when user logged in or out.
|
||||||
loginStateChanged = pyqtSignal(bool)
|
loginStateChanged = pyqtSignal(bool)
|
||||||
accessTokenChanged = pyqtSignal()
|
accessTokenChanged = pyqtSignal()
|
||||||
cloudPrintersDetectedChanged = pyqtSignal(bool)
|
cloudPrintersDetectedChanged = pyqtSignal(bool)
|
||||||
manualSyncRequested = pyqtSignal()
|
syncRequested = pyqtSignal()
|
||||||
lastSyncDateTimeChanged = pyqtSignal()
|
lastSyncDateTimeChanged = pyqtSignal()
|
||||||
syncStateChanged = pyqtSignal(str)
|
syncStateChanged = pyqtSignal(str)
|
||||||
|
|
||||||
|
@ -66,6 +68,13 @@ class Account(QObject):
|
||||||
|
|
||||||
self._authorization_service = AuthorizationService(self._oauth_settings)
|
self._authorization_service = AuthorizationService(self._oauth_settings)
|
||||||
|
|
||||||
|
# Create a timer for automatic account sync
|
||||||
|
self._update_timer = QTimer()
|
||||||
|
self._update_timer.setInterval(int(self.SYNC_INTERVAL * 1000))
|
||||||
|
# The timer is restarted explicitly after an update was processed. This prevents 2 concurrent updates
|
||||||
|
self._update_timer.setSingleShot(True)
|
||||||
|
self._update_timer.timeout.connect(self.syncRequested)
|
||||||
|
|
||||||
self._sync_clients = {}
|
self._sync_clients = {}
|
||||||
"""contains entries "client_name" : "state["success"|"error|"syncing"]"""
|
"""contains entries "client_name" : "state["success"|"error|"syncing"]"""
|
||||||
|
|
||||||
|
@ -77,9 +86,9 @@ class Account(QObject):
|
||||||
self._authorization_service.loadAuthDataFromPreferences()
|
self._authorization_service.loadAuthDataFromPreferences()
|
||||||
|
|
||||||
def setSyncState(self, service_name: str, state: str) -> None:
|
def setSyncState(self, service_name: str, state: str) -> None:
|
||||||
""" Can be used to register and update account sync states
|
""" Can be used to register sync services and update account sync states
|
||||||
|
|
||||||
Example: `setSyncState("packages", "syncing")`
|
Example: `setSyncState("PluginSyncService", "syncing")`
|
||||||
:param service_name: A unique name for your service, such as `plugins` or `backups`
|
:param service_name: A unique name for your service, such as `plugins` or `backups`
|
||||||
:param state: One of Account.SYNC_STATES
|
:param state: One of Account.SYNC_STATES
|
||||||
"""
|
"""
|
||||||
|
@ -105,6 +114,11 @@ class Account(QObject):
|
||||||
self._last_sync_str = datetime.now().strftime("%d/%m/%Y %H:%M")
|
self._last_sync_str = datetime.now().strftime("%d/%m/%Y %H:%M")
|
||||||
self.lastSyncDateTimeChanged.emit()
|
self.lastSyncDateTimeChanged.emit()
|
||||||
|
|
||||||
|
if self._sync_state != "syncing":
|
||||||
|
# schedule new auto update after syncing completed (for whatever reason)
|
||||||
|
if not self._update_timer.isActive():
|
||||||
|
self._update_timer.start()
|
||||||
|
|
||||||
def _onAccessTokenChanged(self):
|
def _onAccessTokenChanged(self):
|
||||||
self.accessTokenChanged.emit()
|
self.accessTokenChanged.emit()
|
||||||
|
|
||||||
|
@ -181,7 +195,7 @@ class Account(QObject):
|
||||||
def sync(self) -> None:
|
def sync(self) -> None:
|
||||||
"""Checks for new cloud printers"""
|
"""Checks for new cloud printers"""
|
||||||
|
|
||||||
self.manualSyncRequested.emit()
|
self.syncRequested.emit()
|
||||||
|
|
||||||
@pyqtSlot()
|
@pyqtSlot()
|
||||||
def logout(self) -> None:
|
def logout(self) -> None:
|
||||||
|
|
|
@ -35,6 +35,9 @@ class CloudPackageChecker(QObject):
|
||||||
self._application.initializationFinished.connect(self._onAppInitialized)
|
self._application.initializationFinished.connect(self._onAppInitialized)
|
||||||
self._i18n_catalog = i18nCatalog("cura")
|
self._i18n_catalog = i18nCatalog("cura")
|
||||||
self._sdk_version = ApplicationMetadata.CuraSDKVersion
|
self._sdk_version = ApplicationMetadata.CuraSDKVersion
|
||||||
|
self._last_check_packages = []
|
||||||
|
"""Result from a previous check within the same user session.
|
||||||
|
Used to prevent duplicate notifications"""
|
||||||
|
|
||||||
# This is a plugin, so most of the components required are not ready when
|
# This is a plugin, so most of the components required are not ready when
|
||||||
# this is initialized. Therefore, we wait until the application is ready.
|
# this is initialized. Therefore, we wait until the application is ready.
|
||||||
|
@ -43,8 +46,13 @@ class CloudPackageChecker(QObject):
|
||||||
# initial check
|
# initial check
|
||||||
self._getPackagesIfLoggedIn()
|
self._getPackagesIfLoggedIn()
|
||||||
|
|
||||||
self._application.getCuraAPI().account.loginStateChanged.connect(self._getPackagesIfLoggedIn)
|
self._application.getCuraAPI().account.loginStateChanged.connect(self._onLoginStateChanged)
|
||||||
self._application.getCuraAPI().account.manualSyncRequested.connect(self._getPackagesIfLoggedIn)
|
self._application.getCuraAPI().account.syncRequested.connect(self._getPackagesIfLoggedIn)
|
||||||
|
|
||||||
|
def _onLoginStateChanged(self) -> None:
|
||||||
|
# reset session
|
||||||
|
self._last_check_packages = []
|
||||||
|
self._getPackagesIfLoggedIn()
|
||||||
|
|
||||||
def _getPackagesIfLoggedIn(self) -> None:
|
def _getPackagesIfLoggedIn(self) -> None:
|
||||||
if self._application.getCuraAPI().account.isLoggedIn:
|
if self._application.getCuraAPI().account.isLoggedIn:
|
||||||
|
@ -87,6 +95,10 @@ class CloudPackageChecker(QObject):
|
||||||
user_subscribed_packages = [plugin["package_id"] for plugin in subscribed_packages_payload]
|
user_subscribed_packages = [plugin["package_id"] for plugin in subscribed_packages_payload]
|
||||||
user_installed_packages = self._package_manager.getUserInstalledPackages()
|
user_installed_packages = self._package_manager.getUserInstalledPackages()
|
||||||
|
|
||||||
|
if user_subscribed_packages == self._last_check_packages:
|
||||||
|
# nothing new here
|
||||||
|
return
|
||||||
|
|
||||||
# We need to re-evaluate the dismissed packages
|
# We need to re-evaluate the dismissed packages
|
||||||
# (i.e. some package might got updated to the correct SDK version in the meantime,
|
# (i.e. some package might got updated to the correct SDK version in the meantime,
|
||||||
# hence remove them from the Dismissed Incompatible list)
|
# hence remove them from the Dismissed Incompatible list)
|
||||||
|
@ -102,6 +114,7 @@ class CloudPackageChecker(QObject):
|
||||||
self._model.addDiscrepancies(package_discrepancy)
|
self._model.addDiscrepancies(package_discrepancy)
|
||||||
self._model.initialize(self._package_manager, subscribed_packages_payload)
|
self._model.initialize(self._package_manager, subscribed_packages_payload)
|
||||||
self._showSyncMessage()
|
self._showSyncMessage()
|
||||||
|
self._last_check_packages = user_subscribed_packages
|
||||||
|
|
||||||
def _showSyncMessage(self) -> None:
|
def _showSyncMessage(self) -> None:
|
||||||
"""Show the message if it is not already shown"""
|
"""Show the message if it is not already shown"""
|
||||||
|
|
|
@ -29,9 +29,6 @@ class CloudOutputDeviceManager:
|
||||||
META_NETWORK_KEY = "um_network_key"
|
META_NETWORK_KEY = "um_network_key"
|
||||||
SYNC_SERVICE_NAME = "CloudOutputDeviceManager"
|
SYNC_SERVICE_NAME = "CloudOutputDeviceManager"
|
||||||
|
|
||||||
# The interval with which the remote clusters are checked
|
|
||||||
CHECK_CLUSTER_INTERVAL = 30.0 # seconds
|
|
||||||
|
|
||||||
# The translation catalog for this device.
|
# The translation catalog for this device.
|
||||||
I18N_CATALOG = i18nCatalog("cura")
|
I18N_CATALOG = i18nCatalog("cura")
|
||||||
|
|
||||||
|
@ -45,13 +42,6 @@ class CloudOutputDeviceManager:
|
||||||
self._api = CloudApiClient(self._account, on_error = lambda error: Logger.log("e", str(error)))
|
self._api = CloudApiClient(self._account, on_error = lambda error: Logger.log("e", str(error)))
|
||||||
self._account.loginStateChanged.connect(self._onLoginStateChanged)
|
self._account.loginStateChanged.connect(self._onLoginStateChanged)
|
||||||
|
|
||||||
# Create a timer to update the remote cluster list
|
|
||||||
self._update_timer = QTimer()
|
|
||||||
self._update_timer.setInterval(int(self.CHECK_CLUSTER_INTERVAL * 1000))
|
|
||||||
# The timer is restarted explicitly after an update was processed. This prevents 2 concurrent updates
|
|
||||||
self._update_timer.setSingleShot(True)
|
|
||||||
self._update_timer.timeout.connect(self._getRemoteClusters)
|
|
||||||
|
|
||||||
# Ensure we don't start twice.
|
# Ensure we don't start twice.
|
||||||
self._running = False
|
self._running = False
|
||||||
|
|
||||||
|
@ -65,11 +55,9 @@ class CloudOutputDeviceManager:
|
||||||
if not self._account.isLoggedIn:
|
if not self._account.isLoggedIn:
|
||||||
return
|
return
|
||||||
self._running = True
|
self._running = True
|
||||||
if not self._update_timer.isActive():
|
|
||||||
self._update_timer.start()
|
|
||||||
self._getRemoteClusters()
|
self._getRemoteClusters()
|
||||||
|
|
||||||
self._account.manualSyncRequested.connect(self._getRemoteClusters)
|
self._account.syncRequested.connect(self._getRemoteClusters)
|
||||||
|
|
||||||
def stop(self):
|
def stop(self):
|
||||||
"""Stops running the cloud output device manager."""
|
"""Stops running the cloud output device manager."""
|
||||||
|
@ -77,8 +65,6 @@ class CloudOutputDeviceManager:
|
||||||
if not self._running:
|
if not self._running:
|
||||||
return
|
return
|
||||||
self._running = False
|
self._running = False
|
||||||
if self._update_timer.isActive():
|
|
||||||
self._update_timer.stop()
|
|
||||||
self._onGetRemoteClustersFinished([]) # Make sure we remove all cloud output devices.
|
self._onGetRemoteClustersFinished([]) # Make sure we remove all cloud output devices.
|
||||||
|
|
||||||
def refreshConnections(self) -> None:
|
def refreshConnections(self) -> None:
|
||||||
|
@ -100,8 +86,7 @@ class CloudOutputDeviceManager:
|
||||||
if self._syncing:
|
if self._syncing:
|
||||||
return
|
return
|
||||||
|
|
||||||
if self._update_timer.isActive():
|
Logger.info("Syncing cloud printer clusters")
|
||||||
self._update_timer.stop()
|
|
||||||
|
|
||||||
self._syncing = True
|
self._syncing = True
|
||||||
self._account.setSyncState(self.SYNC_SERVICE_NAME, "syncing")
|
self._account.setSyncState(self.SYNC_SERVICE_NAME, "syncing")
|
||||||
|
@ -135,14 +120,10 @@ class CloudOutputDeviceManager:
|
||||||
|
|
||||||
self._syncing = False
|
self._syncing = False
|
||||||
self._account.setSyncState(self.SYNC_SERVICE_NAME, "success")
|
self._account.setSyncState(self.SYNC_SERVICE_NAME, "success")
|
||||||
# Schedule a new update
|
|
||||||
self._update_timer.start()
|
|
||||||
|
|
||||||
def _onGetRemoteClusterFailed(self):
|
def _onGetRemoteClusterFailed(self):
|
||||||
self._syncing = False
|
self._syncing = False
|
||||||
self._account.setSyncState(self.SYNC_SERVICE_NAME, "error")
|
self._account.setSyncState(self.SYNC_SERVICE_NAME, "error")
|
||||||
# Schedule a new update
|
|
||||||
self._update_timer.start()
|
|
||||||
|
|
||||||
def _onDevicesDiscovered(self, clusters: List[CloudClusterResponse]) -> None:
|
def _onDevicesDiscovered(self, clusters: List[CloudClusterResponse]) -> None:
|
||||||
"""**Synchronously** create machines for discovered devices
|
"""**Synchronously** create machines for discovered devices
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue