Merge branch 'CURA-7290_auto_sync_packages' into CURA-7290_manual_account_sync

# Conflicts:
#	cura/API/Account.py
#	plugins/UM3NetworkPrinting/src/Cloud/CloudOutputDeviceManager.py
This commit is contained in:
Nino van Hooff 2020-05-06 16:03:37 +02:00
commit 9b79b70f2b
3 changed files with 36 additions and 28 deletions

View file

@ -4,7 +4,7 @@ from datetime import datetime
from enum import Enum
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.Message import Message
from UM.i18n import i18nCatalog
@ -28,6 +28,8 @@ 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
class SyncState(Enum):
"""Caution: values used in qml (eg. SyncState.qml)"""
@ -40,7 +42,7 @@ class Account(QObject):
loginStateChanged = pyqtSignal(bool)
accessTokenChanged = pyqtSignal()
cloudPrintersDetectedChanged = pyqtSignal(bool)
manualSyncRequested = pyqtSignal()
syncRequested = pyqtSignal()
lastSyncDateTimeChanged = pyqtSignal()
syncStateChanged = pyqtSignal(str)
@ -72,6 +74,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_services = {} # type: Dict[str, Account.SyncState]
"""contains entries "service_name" : SyncState"""
@ -83,9 +92,9 @@ class Account(QObject):
self._authorization_service.loadAuthDataFromPreferences()
def setSyncState(self, service_name: str, state: SyncState) -> 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", Account.SyncState.SYNCING)`
Example: `setSyncState("PluginSyncService", Account.SyncState.SYNCING)`
:param service_name: A unique name for your service, such as `plugins` or `backups`
:param state: One of Account.SYNC_STATES
"""
@ -108,6 +117,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()
@ -180,7 +194,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

@ -36,6 +36,9 @@ class CloudPackageChecker(QObject):
self._application.initializationFinished.connect(self._onAppInitialized)
self._i18n_catalog = i18nCatalog("cura")
self._sdk_version = ApplicationMetadata.CuraSDKVersion
self._last_check_packages = [] # type: List[str]
"""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.
@ -44,8 +47,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:
@ -88,6 +96,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)
@ -103,6 +115,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, Account.SyncState.SYNCING)
@ -135,14 +120,10 @@ class CloudOutputDeviceManager:
self._syncing = False
self._account.setSyncState(self.SYNC_SERVICE_NAME, Account.SyncState.SUCCESS)
# Schedule a new update
self._update_timer.start()
def _onGetRemoteClusterFailed(self):
self._syncing = False
self._account.setSyncState(self.SYNC_SERVICE_NAME, Account.SyncState.ERROR)
# Schedule a new update
self._update_timer.start()
def _onDevicesDiscovered(self, clusters: List[CloudClusterResponse]) -> None:
"""**Synchronously** create machines for discovered devices