mirror of
https://github.com/Ultimaker/Cura.git
synced 2025-07-16 03:07:53 -06:00
Add Install Pending Updates button to Account popup
CURA-7473
This commit is contained in:
parent
f35ca0eb7d
commit
4f1a18f102
3 changed files with 64 additions and 12 deletions
|
@ -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, Union
|
from typing import 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
|
||||||
|
|
||||||
|
@ -56,6 +56,7 @@ class Account(QObject):
|
||||||
lastSyncDateTimeChanged = pyqtSignal()
|
lastSyncDateTimeChanged = pyqtSignal()
|
||||||
syncStateChanged = pyqtSignal(int) # because SyncState is an int Enum
|
syncStateChanged = pyqtSignal(int) # because SyncState is an int Enum
|
||||||
manualSyncEnabledChanged = pyqtSignal(bool)
|
manualSyncEnabledChanged = pyqtSignal(bool)
|
||||||
|
updatePackagesEnabledChanged = pyqtSignal(bool)
|
||||||
|
|
||||||
def __init__(self, application: "CuraApplication", parent = None) -> None:
|
def __init__(self, application: "CuraApplication", parent = None) -> None:
|
||||||
super().__init__(parent)
|
super().__init__(parent)
|
||||||
|
@ -66,6 +67,8 @@ class Account(QObject):
|
||||||
self._logged_in = False
|
self._logged_in = False
|
||||||
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_action = None # type: Callable
|
||||||
self._last_sync_str = "-"
|
self._last_sync_str = "-"
|
||||||
|
|
||||||
self._callback_port = 32118
|
self._callback_port = 32118
|
||||||
|
@ -143,6 +146,18 @@ class Account(QObject):
|
||||||
if not self._update_timer.isActive():
|
if not self._update_timer.isActive():
|
||||||
self._update_timer.start()
|
self._update_timer.start()
|
||||||
|
|
||||||
|
def setUpdatePackagesAction(self, action: Callable):
|
||||||
|
""" Set the callback which will be invoked when the user clicks the update packages button
|
||||||
|
|
||||||
|
Should be invoked after your service sets the sync state to SYNCING and before setting the
|
||||||
|
sync state to SUCCESS.
|
||||||
|
|
||||||
|
Action will be reset to None when the next sync starts
|
||||||
|
"""
|
||||||
|
self._update_packages_action = action
|
||||||
|
self._update_packages_enabled = True
|
||||||
|
self.updatePackagesEnabledChanged.emit(self._update_packages_enabled)
|
||||||
|
|
||||||
def _onAccessTokenChanged(self):
|
def _onAccessTokenChanged(self):
|
||||||
self.accessTokenChanged.emit()
|
self.accessTokenChanged.emit()
|
||||||
|
|
||||||
|
@ -185,6 +200,9 @@ class Account(QObject):
|
||||||
sync is currently running, a sync will be requested.
|
sync is currently running, a sync will be requested.
|
||||||
"""
|
"""
|
||||||
|
|
||||||
|
self._update_packages_action = None
|
||||||
|
self._update_packages_enabled = False
|
||||||
|
self.updatePackagesEnabledChanged.emit(self._update_packages_enabled)
|
||||||
if self._update_timer.isActive():
|
if self._update_timer.isActive():
|
||||||
self._update_timer.stop()
|
self._update_timer.stop()
|
||||||
elif self._sync_state == SyncState.SYNCING:
|
elif self._sync_state == SyncState.SYNCING:
|
||||||
|
@ -251,6 +269,10 @@ class Account(QObject):
|
||||||
def manualSyncEnabled(self) -> bool:
|
def manualSyncEnabled(self) -> bool:
|
||||||
return self._manual_sync_enabled
|
return self._manual_sync_enabled
|
||||||
|
|
||||||
|
@pyqtProperty(bool, notify=updatePackagesEnabledChanged)
|
||||||
|
def updatePackagesEnabled(self) -> bool:
|
||||||
|
return self._update_packages_enabled
|
||||||
|
|
||||||
@pyqtSlot()
|
@pyqtSlot()
|
||||||
@pyqtSlot(bool)
|
@pyqtSlot(bool)
|
||||||
def sync(self, user_initiated: bool = False) -> None:
|
def sync(self, user_initiated: bool = False) -> None:
|
||||||
|
@ -259,11 +281,14 @@ class Account(QObject):
|
||||||
|
|
||||||
self._sync()
|
self._sync()
|
||||||
|
|
||||||
|
@pyqtSlot()
|
||||||
|
def update_packages(self):
|
||||||
|
if self._update_packages_action is not None:
|
||||||
|
self._update_packages_action()
|
||||||
|
|
||||||
@pyqtSlot()
|
@pyqtSlot()
|
||||||
def popupOpened(self) -> None:
|
def popupOpened(self) -> None:
|
||||||
self._setManualSyncEnabled(True)
|
self._setManualSyncEnabled(True)
|
||||||
self._sync_state = SyncState.IDLE
|
|
||||||
self.syncStateChanged.emit(self._sync_state)
|
|
||||||
|
|
||||||
@pyqtSlot()
|
@pyqtSlot()
|
||||||
def logout(self) -> None:
|
def logout(self) -> None:
|
||||||
|
|
|
@ -95,10 +95,6 @@ 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.getAllInstalledPackageIDs()
|
user_installed_packages = self._package_manager.getAllInstalledPackageIDs()
|
||||||
|
|
||||||
if user_subscribed_packages == self._last_notified_packages:
|
|
||||||
# already notified user about these
|
|
||||||
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)
|
||||||
|
@ -109,7 +105,15 @@ class CloudPackageChecker(QObject):
|
||||||
|
|
||||||
# We check if there are packages installed in Web Marketplace but not in Cura marketplace
|
# We check if there are packages installed in Web Marketplace but not in Cura marketplace
|
||||||
package_discrepancy = list(user_subscribed_packages.difference(user_installed_packages))
|
package_discrepancy = list(user_subscribed_packages.difference(user_installed_packages))
|
||||||
|
|
||||||
if package_discrepancy:
|
if package_discrepancy:
|
||||||
|
account = self._application.getCuraAPI().account
|
||||||
|
account.setUpdatePackagesAction(lambda: self._onSyncButtonClicked(None, None))
|
||||||
|
|
||||||
|
if user_subscribed_packages == self._last_notified_packages:
|
||||||
|
# already notified user about these
|
||||||
|
return
|
||||||
|
|
||||||
Logger.log("d", "Discrepancy found between Cloud subscribed packages and Cura installed packages")
|
Logger.log("d", "Discrepancy found between Cloud subscribed packages and Cura installed packages")
|
||||||
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)
|
||||||
|
@ -144,7 +148,8 @@ class CloudPackageChecker(QObject):
|
||||||
self._message.hide()
|
self._message.hide()
|
||||||
self._message = None
|
self._message = None
|
||||||
|
|
||||||
def _onSyncButtonClicked(self, sync_message: Message, sync_message_action: str) -> None:
|
def _onSyncButtonClicked(self, sync_message: Optional[Message], sync_message_action: Optional[str]) -> None:
|
||||||
sync_message.hide()
|
if sync_message is not None:
|
||||||
|
sync_message.hide()
|
||||||
self._hideSyncMessage() # Should be the same message, but also sets _message to None
|
self._hideSyncMessage() # Should be the same message, but also sets _message to None
|
||||||
self.discrepancies.emit(self._model)
|
self.discrepancies.emit(self._model)
|
||||||
|
|
|
@ -49,7 +49,7 @@ Row // Sync state icon + message
|
||||||
width: 20 * screenScaleFactor
|
width: 20 * screenScaleFactor
|
||||||
height: width
|
height: width
|
||||||
|
|
||||||
source: Cura.API.account.manualSyncEnabled ? UM.Theme.getIcon("update") : UM.Theme.getIcon("checked")
|
// source is determined by State
|
||||||
color: UM.Theme.getColor("account_sync_state_icon")
|
color: UM.Theme.getColor("account_sync_state_icon")
|
||||||
|
|
||||||
RotationAnimator
|
RotationAnimator
|
||||||
|
@ -80,14 +80,36 @@ Row // Sync state icon + message
|
||||||
Label
|
Label
|
||||||
{
|
{
|
||||||
id: stateLabel
|
id: stateLabel
|
||||||
text: catalog.i18nc("@state", catalog.i18nc("@label", "Account synced"))
|
// text is determined by State
|
||||||
color: UM.Theme.getColor("text")
|
color: UM.Theme.getColor("text")
|
||||||
font: UM.Theme.getFont("medium")
|
font: UM.Theme.getFont("medium")
|
||||||
renderType: Text.NativeRendering
|
renderType: Text.NativeRendering
|
||||||
width: contentWidth + UM.Theme.getSize("default_margin").height
|
width: contentWidth + UM.Theme.getSize("default_margin").height
|
||||||
height: contentHeight
|
height: contentHeight
|
||||||
verticalAlignment: Text.AlignVCenter
|
verticalAlignment: Text.AlignVCenter
|
||||||
visible: !Cura.API.account.manualSyncEnabled
|
visible: !Cura.API.account.manualSyncEnabled && !Cura.API.account.updatePackagesEnabled
|
||||||
|
}
|
||||||
|
|
||||||
|
Label
|
||||||
|
{
|
||||||
|
id: updatePackagesButton
|
||||||
|
text: catalog.i18nc("@button", "Install pending updates")
|
||||||
|
color: UM.Theme.getColor("secondary_button_text")
|
||||||
|
font: UM.Theme.getFont("medium")
|
||||||
|
renderType: Text.NativeRendering
|
||||||
|
verticalAlignment: Text.AlignVCenter
|
||||||
|
height: contentHeight
|
||||||
|
width: contentWidth + UM.Theme.getSize("default_margin").height
|
||||||
|
visible: Cura.API.account.updatePackagesEnabled
|
||||||
|
|
||||||
|
MouseArea
|
||||||
|
{
|
||||||
|
anchors.fill: parent
|
||||||
|
onClicked: Cura.API.account.update_packages()
|
||||||
|
hoverEnabled: true
|
||||||
|
onEntered: updatePackagesButton.font.underline = true
|
||||||
|
onExited: updatePackagesButton.font.underline = false
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Label
|
Label
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue