mirror of
https://github.com/Ultimaker/Cura.git
synced 2025-07-07 15:07:28 -06:00
Moved busy/confirmed logic to QML
COntributes to CURA-8587
This commit is contained in:
parent
d876b85259
commit
e72655cc22
3 changed files with 132 additions and 97 deletions
|
@ -165,7 +165,7 @@ class PackageList(ListModel):
|
||||||
if dialog is not None:
|
if dialog is not None:
|
||||||
dialog.deleteLater()
|
dialog.deleteLater()
|
||||||
# reset package card
|
# reset package card
|
||||||
package = self.getPackageModel(package_id)
|
self._manager.packageInstallingFailed.emit(package_id)
|
||||||
|
|
||||||
def _requestInstall(self, package_id: str, update: bool = False) -> None:
|
def _requestInstall(self, package_id: str, update: bool = False) -> None:
|
||||||
package_path = self._to_install[package_id]
|
package_path = self._to_install[package_id]
|
||||||
|
@ -182,8 +182,9 @@ class PackageList(ListModel):
|
||||||
def _install(self, package_id: str, update: bool = False) -> None:
|
def _install(self, package_id: str, update: bool = False) -> None:
|
||||||
package_path = self._to_install.pop(package_id)
|
package_path = self._to_install.pop(package_id)
|
||||||
to_be_installed = self._manager.installPackage(package_path) is not None
|
to_be_installed = self._manager.installPackage(package_path) is not None
|
||||||
|
if not to_be_installed:
|
||||||
|
return
|
||||||
package = self.getPackageModel(package_id)
|
package = self.getPackageModel(package_id)
|
||||||
# TODO handle failure
|
|
||||||
self.subscribeUserToPackage(package_id, str(package.sdk_version))
|
self.subscribeUserToPackage(package_id, str(package.sdk_version))
|
||||||
|
|
||||||
def download(self, package_id: str, url: str, update: bool = False) -> None:
|
def download(self, package_id: str, url: str, update: bool = False) -> None:
|
||||||
|
@ -231,14 +232,7 @@ class PackageList(ListModel):
|
||||||
if reply:
|
if reply:
|
||||||
reply_string = bytes(reply.readAll()).decode()
|
reply_string = bytes(reply.readAll()).decode()
|
||||||
Logger.error(f"Failed to download package: {package_id} due to {reply_string}")
|
Logger.error(f"Failed to download package: {package_id} due to {reply_string}")
|
||||||
try:
|
self._manager.packageInstallingFailed.emit(package_id)
|
||||||
package = self.getPackageModel(package_id)
|
|
||||||
# TODO: handle error
|
|
||||||
except RuntimeError:
|
|
||||||
# Setting the ownership of this object to not qml can still result in a RuntimeError. Which can occur when quickly toggling
|
|
||||||
# between de-/constructing Remote or Local PackageLists. This try-except is here to prevent a hard crash when the wrapped C++ object
|
|
||||||
# was deleted when it was still parsing the response
|
|
||||||
return
|
|
||||||
|
|
||||||
def subscribeUserToPackage(self, package_id: str, sdk_version: str) -> None:
|
def subscribeUserToPackage(self, package_id: str, sdk_version: str) -> None:
|
||||||
"""Subscribe the user (if logged in) to the package for a given SDK
|
"""Subscribe the user (if logged in) to the package for a given SDK
|
||||||
|
|
|
@ -16,6 +16,7 @@ from UM.PluginRegistry import PluginRegistry
|
||||||
|
|
||||||
catalog = i18nCatalog("cura")
|
catalog = i18nCatalog("cura")
|
||||||
|
|
||||||
|
|
||||||
class PackageModel(QObject):
|
class PackageModel(QObject):
|
||||||
"""
|
"""
|
||||||
Represents a package, containing all the relevant information to be displayed about a package.
|
Represents a package, containing all the relevant information to be displayed about a package.
|
||||||
|
@ -38,7 +39,8 @@ class PackageModel(QObject):
|
||||||
self._icon_url = package_data.get("icon_url", "")
|
self._icon_url = package_data.get("icon_url", "")
|
||||||
self._display_name = package_data.get("display_name", catalog.i18nc("@label:property", "Unknown Package"))
|
self._display_name = package_data.get("display_name", catalog.i18nc("@label:property", "Unknown Package"))
|
||||||
tags = package_data.get("tags", [])
|
tags = package_data.get("tags", [])
|
||||||
self._is_checked_by_ultimaker = (self._package_type == "plugin" and "verified" in tags) or (self._package_type == "material" and "certified" in tags)
|
self._is_checked_by_ultimaker = (self._package_type == "plugin" and "verified" in tags) or (
|
||||||
|
self._package_type == "material" and "certified" in tags)
|
||||||
self._package_version = package_data.get("package_version", "") # Display purpose, no need for 'UM.Version'.
|
self._package_version = package_data.get("package_version", "") # Display purpose, no need for 'UM.Version'.
|
||||||
self._package_info_url = package_data.get("website", "") # Not to be confused with 'download_url'.
|
self._package_info_url = package_data.get("website", "") # Not to be confused with 'download_url'.
|
||||||
self._download_count = package_data.get("download_count", 0)
|
self._download_count = package_data.get("download_count", 0)
|
||||||
|
@ -63,38 +65,32 @@ class PackageModel(QObject):
|
||||||
if not self._icon_url or self._icon_url == "":
|
if not self._icon_url or self._icon_url == "":
|
||||||
self._icon_url = author_data.get("icon_url", "")
|
self._icon_url = author_data.get("icon_url", "")
|
||||||
|
|
||||||
self._is_installing = False
|
|
||||||
self._recently_installed = False
|
|
||||||
self._install_status_changing = False
|
|
||||||
|
|
||||||
self._can_update = False
|
self._can_update = False
|
||||||
self._is_updating = False
|
|
||||||
self._recently_updated = False
|
|
||||||
self._section_title = section_title
|
self._section_title = section_title
|
||||||
self.sdk_version = package_data.get("sdk_version_semver", "")
|
self.sdk_version = package_data.get("sdk_version_semver", "")
|
||||||
# Note that there's a lot more info in the package_data than just these specified here.
|
# Note that there's a lot more info in the package_data than just these specified here.
|
||||||
|
|
||||||
self.enablePackageTriggered.connect(self._plugin_registry.enablePlugin)
|
self.enablePackageTriggered.connect(self._plugin_registry.enablePlugin)
|
||||||
self.disablePackageTriggered.connect(self._plugin_registry.disablePlugin)
|
self.disablePackageTriggered.connect(self._plugin_registry.disablePlugin)
|
||||||
self.installPackageTriggered.connect(lambda pkg_id, url: self.setIsInstalling(True))
|
|
||||||
self.uninstallPackageTriggered.connect(lambda pkg_id: self.setIsInstalling(True))
|
|
||||||
self.updatePackageTriggered.connect(lambda pkg_id: self.setIsUpdating(True))
|
|
||||||
|
|
||||||
def finished_installed():
|
self._is_updating = False
|
||||||
if self.isInstalling:
|
self._is_recently_updated = self._getRecentlyUpdated()
|
||||||
self._recently_installed = True
|
|
||||||
self.setIsInstalling(False)
|
self._is_installing = False
|
||||||
if self.isUpdating:
|
self._is_uninstalling = False
|
||||||
self._recently_updated = True
|
self._is_recently_installed = self._getRecentlyInstalled()
|
||||||
self._can_update = not self._package_id in self._package_manager.getPackagesToInstall()
|
|
||||||
self.setIsUpdating(False)
|
self.updatePackageTriggered.connect(lambda pkg: self._setIsUpdating(True))
|
||||||
|
self.installPackageTriggered.connect(lambda pkg, url: self._setIsInstalling(True))
|
||||||
|
self.uninstallPackageTriggered.connect(lambda pkg: self._setIsUninstalling(True))
|
||||||
|
|
||||||
self._package_manager.installedPackagesChanged.connect(finished_installed)
|
|
||||||
self._plugin_registry.hasPluginsEnabledOrDisabledChanged.connect(self.stateManageButtonChanged)
|
self._plugin_registry.hasPluginsEnabledOrDisabledChanged.connect(self.stateManageButtonChanged)
|
||||||
|
self._package_manager.packageInstalled.connect(lambda pkg_id: self._packageInstalled(pkg_id, True))
|
||||||
|
self._package_manager.packageUninstalled.connect(lambda pkg_id: self._packageInstalled(pkg_id, True))
|
||||||
|
self._package_manager.packageInstallingFailed.connect(lambda pkg_id: self._packageInstalled(pkg_id, False))
|
||||||
self._package_manager.packagesWithUpdateChanged.connect(lambda: self.setCanUpdate(self._package_id in self._package_manager.packagesWithUpdate))
|
self._package_manager.packagesWithUpdateChanged.connect(lambda: self.setCanUpdate(self._package_id in self._package_manager.packagesWithUpdate))
|
||||||
|
|
||||||
def __eq__(self, other: object):
|
def __eq__(self, other: object) -> bool:
|
||||||
if isinstance(other, PackageModel):
|
if isinstance(other, PackageModel):
|
||||||
return other == self
|
return other == self
|
||||||
elif isinstance(other, str):
|
elif isinstance(other, str):
|
||||||
|
@ -102,7 +98,7 @@ class PackageModel(QObject):
|
||||||
else:
|
else:
|
||||||
return False
|
return False
|
||||||
|
|
||||||
def __repr__(self):
|
def __repr__(self) -> str:
|
||||||
return f"<{self._package_id} : {self._package_version} : {self._section_title}>"
|
return f"<{self._package_id} : {self._package_version} : {self._section_title}>"
|
||||||
|
|
||||||
def _findLink(self, subdata: Dict[str, Any], link_type: str) -> str:
|
def _findLink(self, subdata: Dict[str, Any], link_type: str) -> str:
|
||||||
|
@ -219,7 +215,7 @@ class PackageModel(QObject):
|
||||||
return self._package_type
|
return self._package_type
|
||||||
|
|
||||||
@pyqtProperty(str, constant = True)
|
@pyqtProperty(str, constant = True)
|
||||||
def iconUrl(self):
|
def iconUrl(self) -> str:
|
||||||
return self._icon_url
|
return self._icon_url
|
||||||
|
|
||||||
@pyqtProperty(str, constant = True)
|
@pyqtProperty(str, constant = True)
|
||||||
|
@ -231,19 +227,19 @@ class PackageModel(QObject):
|
||||||
return self._is_checked_by_ultimaker
|
return self._is_checked_by_ultimaker
|
||||||
|
|
||||||
@pyqtProperty(str, constant = True)
|
@pyqtProperty(str, constant = True)
|
||||||
def packageVersion(self):
|
def packageVersion(self) -> str:
|
||||||
return self._package_version
|
return self._package_version
|
||||||
|
|
||||||
@pyqtProperty(str, constant = True)
|
@pyqtProperty(str, constant = True)
|
||||||
def packageInfoUrl(self):
|
def packageInfoUrl(self) -> str:
|
||||||
return self._package_info_url
|
return self._package_info_url
|
||||||
|
|
||||||
@pyqtProperty(int, constant = True)
|
@pyqtProperty(int, constant = True)
|
||||||
def downloadCount(self):
|
def downloadCount(self) -> str:
|
||||||
return self._download_count
|
return self._download_count
|
||||||
|
|
||||||
@pyqtProperty(str, constant = True)
|
@pyqtProperty(str, constant = True)
|
||||||
def description(self):
|
def description(self) -> str:
|
||||||
return self._description
|
return self._description
|
||||||
|
|
||||||
@pyqtProperty(str, constant = True)
|
@pyqtProperty(str, constant = True)
|
||||||
|
@ -251,11 +247,11 @@ class PackageModel(QObject):
|
||||||
return self._formatted_description
|
return self._formatted_description
|
||||||
|
|
||||||
@pyqtProperty(str, constant = True)
|
@pyqtProperty(str, constant = True)
|
||||||
def authorName(self):
|
def authorName(self) -> str:
|
||||||
return self._author_name
|
return self._author_name
|
||||||
|
|
||||||
@pyqtProperty(str, constant = True)
|
@pyqtProperty(str, constant = True)
|
||||||
def authorInfoUrl(self):
|
def authorInfoUrl(self) -> str:
|
||||||
return self._author_info_url
|
return self._author_info_url
|
||||||
|
|
||||||
@pyqtProperty(str, constant = True)
|
@pyqtProperty(str, constant = True)
|
||||||
|
@ -312,49 +308,62 @@ class PackageModel(QObject):
|
||||||
|
|
||||||
disablePackageTriggered = pyqtSignal(str)
|
disablePackageTriggered = pyqtSignal(str)
|
||||||
|
|
||||||
@pyqtProperty(bool, notify = stateManageButtonChanged)
|
installedPackagesChanged = pyqtSignal(bool)
|
||||||
def isActive(self):
|
|
||||||
return not self._package_id in self._plugin_registry.getDisabledPlugins()
|
|
||||||
|
|
||||||
def setIsInstalling(self, value: bool) -> None:
|
uninstalledPackagesChanged = pyqtSignal(bool)
|
||||||
if value != self._is_installing:
|
|
||||||
|
updatePackagesChanged = pyqtSignal(bool)
|
||||||
|
|
||||||
|
def _setIsUpdating(self, value: bool) -> None:
|
||||||
|
self._is_updating = value
|
||||||
|
|
||||||
|
def _setIsInstalling(self, value: bool) -> None:
|
||||||
self._is_installing = value
|
self._is_installing = value
|
||||||
self.stateManageButtonChanged.emit()
|
|
||||||
|
|
||||||
@pyqtProperty(bool, fset = setIsInstalling, notify = stateManageButtonChanged)
|
def _setIsUninstalling(self, value: bool) -> None:
|
||||||
def isInstalling(self) -> bool:
|
self._is_uninstalling = value
|
||||||
return self._is_installing
|
|
||||||
|
def _packageInstalled(self, package_id: str, success: bool) -> None:
|
||||||
|
if self._package_id != package_id:
|
||||||
|
return
|
||||||
|
if self._is_updating:
|
||||||
|
self.updatePackagesChanged.emit(success)
|
||||||
|
self._is_updating = False
|
||||||
|
if self._is_installing:
|
||||||
|
self.installedPackagesChanged.emit(success)
|
||||||
|
self._is_installing = False
|
||||||
|
if self._is_uninstalling:
|
||||||
|
self.uninstalledPackagesChanged.emit(success)
|
||||||
|
self._is_uninstalling = False
|
||||||
|
|
||||||
|
def _getRecentlyInstalled(self) -> bool:
|
||||||
|
return (self._package_id in self._package_manager.getPackagesToInstall() or self._package_id in self._package_manager.getPackagesToRemove()) \
|
||||||
|
and self._package_id not in self._package_manager.package_infosWithUpdate
|
||||||
|
|
||||||
|
@pyqtProperty(bool, constant = True)
|
||||||
|
def isRecentlyInstalledChanged(self) -> bool:
|
||||||
|
return self._is_recently_installed
|
||||||
|
|
||||||
|
def _getRecentlyUpdated(self) -> bool:
|
||||||
|
return self._package_id in self._package_manager.package_infosWithUpdate and self._package_id in self._package_manager.getPackagesToInstall()
|
||||||
|
|
||||||
|
@pyqtProperty(bool, constant = True)
|
||||||
|
def isRecentlyUpdatedChanged(self) -> bool:
|
||||||
|
return self._is_recently_updated
|
||||||
|
|
||||||
@pyqtProperty(bool, notify = stateManageButtonChanged)
|
@pyqtProperty(bool, notify = stateManageButtonChanged)
|
||||||
def isInstalled(self) -> bool:
|
def isInstalled(self) -> bool:
|
||||||
return self._package_id in self._package_manager.local_packages_id
|
return self._package_id in self._package_manager.local_packages_id
|
||||||
|
|
||||||
@pyqtProperty(bool, notify = stateManageButtonChanged)
|
@pyqtProperty(bool, notify = stateManageButtonChanged)
|
||||||
def isRecentlyInstalled(self) -> bool:
|
def isActive(self) -> bool:
|
||||||
return self._recently_installed and self._package_id in self._package_manager.getPackagesToInstall()
|
return not self._package_id in self._plugin_registry.getDisabledPlugins()
|
||||||
|
|
||||||
@pyqtProperty(bool, notify = stateManageButtonChanged)
|
|
||||||
def isRecentlyUninstalled(self) -> bool:
|
|
||||||
return self._package_id in self._package_manager.getPackagesToRemove()
|
|
||||||
|
|
||||||
@pyqtProperty(bool, notify = stateManageButtonChanged)
|
@pyqtProperty(bool, notify = stateManageButtonChanged)
|
||||||
def canDowngrade(self) -> bool:
|
def canDowngrade(self) -> bool:
|
||||||
"""Flag if the installed package can be downgraded to a bundled version"""
|
"""Flag if the installed package can be downgraded to a bundled version"""
|
||||||
return self._package_manager.canDowngrade(self._package_id)
|
return self._package_manager.canDowngrade(self._package_id)
|
||||||
|
|
||||||
def setIsUpdating(self, value):
|
|
||||||
if value != self._is_updating:
|
|
||||||
self._is_updating = value
|
|
||||||
self.stateManageButtonChanged.emit()
|
|
||||||
|
|
||||||
@pyqtProperty(bool, fset = setIsUpdating, notify = stateManageButtonChanged)
|
|
||||||
def isUpdating(self):
|
|
||||||
return self._is_updating
|
|
||||||
|
|
||||||
@pyqtProperty(bool, notify = stateManageButtonChanged)
|
|
||||||
def isRecentlyUpdated(self):
|
|
||||||
return self._recently_updated and self._package_id in self._package_manager.getPackagesToInstall()
|
|
||||||
|
|
||||||
def setCanUpdate(self, value: bool) -> None:
|
def setCanUpdate(self, value: bool) -> None:
|
||||||
if value != self._can_update:
|
if value != self._can_update:
|
||||||
self._can_update = value
|
self._can_update = value
|
||||||
|
|
|
@ -209,45 +209,62 @@ Item
|
||||||
{
|
{
|
||||||
id: installManageButton
|
id: installManageButton
|
||||||
visible: (showManageButtons || confirmed) && ((packageData.isBundled && packageData.canDowngrade) || !packageData.isBundled) && !updateManageButton.confirmed
|
visible: (showManageButtons || confirmed) && ((packageData.isBundled && packageData.canDowngrade) || !packageData.isBundled) && !updateManageButton.confirmed
|
||||||
|
enabled: !updateManageButton.busy
|
||||||
|
|
||||||
enabled: !packageData.isUpdating
|
busy: false
|
||||||
|
confirmed: { packageData.isRecentlyInstalledChanged }
|
||||||
|
|
||||||
busy: packageData.isInstalling
|
button_style: confirmed ? packageData.isInstalled : !packageData.isInstalled
|
||||||
confirmed: packageData.isRecentlyInstalled || packageData.isRecentlyUninstalled
|
|
||||||
|
|
||||||
button_style: !packageData.isInstalled
|
|
||||||
Layout.alignment: Qt.AlignTop
|
Layout.alignment: Qt.AlignTop
|
||||||
|
|
||||||
text:
|
text:
|
||||||
{
|
{
|
||||||
if (packageData.canDowngrade) { return catalog.i18nc("@button", "Downgrade"); }
|
|
||||||
if (packageData.isRecentlyInstalled) { return catalog.i18nc("@button", "Installed"); }
|
|
||||||
if (packageData.isRecentlyUninstalled)
|
|
||||||
{
|
|
||||||
if (packageData.canDowngrade) { return catalog.i18nc("@button", "Downgraded") }
|
|
||||||
else { return catalog.i18nc("@button", "Uninstalled"); } }
|
|
||||||
if (button_style)
|
if (button_style)
|
||||||
{
|
{
|
||||||
if (packageData.isInstalling) { return catalog.i18nc("@button", "Installing..."); }
|
if (busy) { return catalog.i18nc("@button", "Installing..."); }
|
||||||
|
else if (confirmed) { return catalog.i18nc("@button", "Installed"); }
|
||||||
else { return catalog.i18nc("@button", "Install"); }
|
else { return catalog.i18nc("@button", "Install"); }
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
if (packageData.isInstalling) { return catalog.i18nc("@button", "Uninstalling..."); }
|
if (packageData.canDowngrade)
|
||||||
|
{
|
||||||
|
if (busy) { return catalog.i18nc("@button", "Downgrading..."); }
|
||||||
|
else if (confirmed) { return catalog.i18nc("@button", "Downgraded"); }
|
||||||
|
else { return catalog.i18nc("@button", "Downgrade"); }
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
if (busy) { return catalog.i18nc("@button", "Uninstalling..."); }
|
||||||
|
else if (confirmed) { return catalog.i18nc("@button", "Uninstalled"); }
|
||||||
else { return catalog.i18nc("@button", "Uninstall"); }
|
else { return catalog.i18nc("@button", "Uninstall"); }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
onClicked:
|
onClicked:
|
||||||
{
|
{
|
||||||
if (primary_action)
|
busy = true
|
||||||
{
|
if (primary_action){ packageData.installPackageTriggered(packageData.packageId, packageData.downloadURL); }
|
||||||
packageData.installPackageTriggered(packageData.packageId, packageData.downloadURL)
|
else { packageData.uninstallPackageTriggered(packageData.packageId); }
|
||||||
}
|
}
|
||||||
else
|
|
||||||
|
Connections
|
||||||
{
|
{
|
||||||
packageData.uninstallPackageTriggered(packageData.packageId)
|
target: packageData
|
||||||
|
|
||||||
|
function onInstalledPackagesChanged(success)
|
||||||
|
{
|
||||||
|
installManageButton.busy = false;
|
||||||
|
installManageButton.confirmed = success;
|
||||||
}
|
}
|
||||||
|
function onUninstalledPackagesChanged(success)
|
||||||
|
{
|
||||||
|
installManageButton.busy = false;
|
||||||
|
installManageButton.confirmed = success;
|
||||||
|
installManageButton.button_style = !installManageButton.button_style;
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -257,8 +274,8 @@ Item
|
||||||
visible: (showManageButtons || confirmed) && (packageData.canUpdate || confirmed) && !installManageButton.confirmed
|
visible: (showManageButtons || confirmed) && (packageData.canUpdate || confirmed) && !installManageButton.confirmed
|
||||||
enabled: !installManageButton.busy
|
enabled: !installManageButton.busy
|
||||||
|
|
||||||
busy: packageData.isUpdating
|
busy: false
|
||||||
confirmed: packageData.isRecentlyUpdated
|
confirmed: { packageData.isRecentlyUpdatedChanged }
|
||||||
|
|
||||||
button_style: true
|
button_style: true
|
||||||
Layout.alignment: Qt.AlignTop
|
Layout.alignment: Qt.AlignTop
|
||||||
|
@ -270,7 +287,22 @@ Item
|
||||||
else { return catalog.i18nc("@button", "Update"); }
|
else { return catalog.i18nc("@button", "Update"); }
|
||||||
}
|
}
|
||||||
|
|
||||||
onClicked: packageData.updatePackageTriggered(packageData.packageId)
|
onClicked:
|
||||||
|
{
|
||||||
|
busy = true;
|
||||||
|
packageData.updatePackageTriggered(packageData.packageId);
|
||||||
|
}
|
||||||
|
|
||||||
|
Connections
|
||||||
|
{
|
||||||
|
target: packageData
|
||||||
|
|
||||||
|
function onUpdatePackagesChanged(succes)
|
||||||
|
{
|
||||||
|
updateManageButton.busy = false;
|
||||||
|
updateManageButton.confirmed = succes;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue