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:
Nino van Hooff 2020-05-04 16:56:09 +02:00
parent 637a241d99
commit 88ff68e40c
3 changed files with 37 additions and 29 deletions

View file

@ -3,9 +3,8 @@
from datetime import datetime
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.i18n import i18nCatalog
from cura.OAuth2.AuthorizationService import AuthorizationService
@ -28,11 +27,14 @@ i18n_catalog = i18nCatalog("cura")
# api.account.userProfile # Who is logged in``
#
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.
loginStateChanged = pyqtSignal(bool)
accessTokenChanged = pyqtSignal()
cloudPrintersDetectedChanged = pyqtSignal(bool)
manualSyncRequested = pyqtSignal()
syncRequested = pyqtSignal()
lastSyncDateTimeChanged = pyqtSignal()
syncStateChanged = pyqtSignal(str)
@ -66,6 +68,13 @@ class Account(QObject):
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 = {}
"""contains entries "client_name" : "state["success"|"error|"syncing"]"""
@ -77,9 +86,9 @@ class Account(QObject):
self._authorization_service.loadAuthDataFromPreferences()
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 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.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):
self.accessTokenChanged.emit()
@ -181,7 +195,7 @@ class Account(QObject):
def sync(self) -> None:
"""Checks for new cloud printers"""
self.manualSyncRequested.emit()
self.syncRequested.emit()
@pyqtSlot()
def logout(self) -> None:

View file

@ -35,6 +35,9 @@ class CloudPackageChecker(QObject):
self._application.initializationFinished.connect(self._onAppInitialized)
self._i18n_catalog = i18nCatalog("cura")
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 initialized. Therefore, we wait until the application is ready.
@ -43,8 +46,13 @@ class CloudPackageChecker(QObject):
# initial check
self._getPackagesIfLoggedIn()
self._application.getCuraAPI().account.loginStateChanged.connect(self._getPackagesIfLoggedIn)
self._application.getCuraAPI().account.manualSyncRequested.connect(self._getPackagesIfLoggedIn)
self._application.getCuraAPI().account.loginStateChanged.connect(self._onLoginStateChanged)
self._application.getCuraAPI().account.syncRequested.connect(self._getPackagesIfLoggedIn)
def _onLoginStateChanged(self) -> None:
# reset session
self._last_check_packages = []
self._getPackagesIfLoggedIn()
def _getPackagesIfLoggedIn(self) -> None:
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_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
# (i.e. some package might got updated to the correct SDK version in the meantime,
# hence remove them from the Dismissed Incompatible list)
@ -102,6 +114,7 @@ class CloudPackageChecker(QObject):
self._model.addDiscrepancies(package_discrepancy)
self._model.initialize(self._package_manager, subscribed_packages_payload)
self._showSyncMessage()
self._last_check_packages = user_subscribed_packages
def _showSyncMessage(self) -> None:
"""Show the message if it is not already shown"""

View file

@ -29,9 +29,6 @@ class CloudOutputDeviceManager:
META_NETWORK_KEY = "um_network_key"
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.
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._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.
self._running = False
@ -65,11 +55,9 @@ class CloudOutputDeviceManager:
if not self._account.isLoggedIn:
return
self._running = True
if not self._update_timer.isActive():
self._update_timer.start()
self._getRemoteClusters()
self._account.manualSyncRequested.connect(self._getRemoteClusters)
self._account.syncRequested.connect(self._getRemoteClusters)
def stop(self):
"""Stops running the cloud output device manager."""
@ -77,8 +65,6 @@ class CloudOutputDeviceManager:
if not self._running:
return
self._running = False
if self._update_timer.isActive():
self._update_timer.stop()
self._onGetRemoteClustersFinished([]) # Make sure we remove all cloud output devices.
def refreshConnections(self) -> None:
@ -100,8 +86,7 @@ class CloudOutputDeviceManager:
if self._syncing:
return
if self._update_timer.isActive():
self._update_timer.stop()
Logger.info("Syncing cloud printer clusters")
self._syncing = True
self._account.setSyncState(self.SYNC_SERVICE_NAME, "syncing")
@ -135,14 +120,10 @@ class CloudOutputDeviceManager:
self._syncing = False
self._account.setSyncState(self.SYNC_SERVICE_NAME, "success")
# Schedule a new update
self._update_timer.start()
def _onGetRemoteClusterFailed(self):
self._syncing = False
self._account.setSyncState(self.SYNC_SERVICE_NAME, "error")
# Schedule a new update
self._update_timer.start()
def _onDevicesDiscovered(self, clusters: List[CloudClusterResponse]) -> None:
"""**Synchronously** create machines for discovered devices