diff --git a/plugins/Marketplace/LocalPackageList.py b/plugins/Marketplace/LocalPackageList.py index 6bd22ee918..ea259dbdc7 100644 --- a/plugins/Marketplace/LocalPackageList.py +++ b/plugins/Marketplace/LocalPackageList.py @@ -48,9 +48,8 @@ class LocalPackageList(PackageList): self.setIsLoading(True) # Obtain and sort the local packages - Logger.debug(f"Number of local packages: {len(self._manager.local_packages)} -> {[p['package_id'] for p in self._manager.local_packages]}") self.setItems([{"package": p} for p in [self._makePackageModel(p) for p in self._manager.local_packages]]) - self.sort(attrgetter("sectionTitle", "canUpdate", "displayName"), key = "package", reverse = True) + self.sort(attrgetter("sectionTitle", "can_update", "displayName"), key = "package", reverse = True) self.checkForUpdates(self._manager.local_packages) self.setIsLoading(False) @@ -90,8 +89,8 @@ class LocalPackageList(PackageList): return for package_data in response_data["data"]: - package = self._getPackageModel(package_data["package_id"]) + package = self.getPackageModel(package_data["package_id"]) package.download_url = package_data.get("download_url", "") package.canUpdate = True - self.sort(attrgetter("sectionTitle", "canUpdate", "displayName"), key = "package", reverse = True) + self.sort(attrgetter("sectionTitle", "can_update", "displayName"), key = "package", reverse = True) diff --git a/plugins/Marketplace/PackageList.py b/plugins/Marketplace/PackageList.py index 8c9bcdb963..5ad2c50ddb 100644 --- a/plugins/Marketplace/PackageList.py +++ b/plugins/Marketplace/PackageList.py @@ -112,19 +112,26 @@ class PackageList(ListModel): :return: ``True`` if a Footer should be displayed in the ListView, e.q.: paginated lists, ``False`` Otherwise""" return self._has_footer - def _connectManageButtonSignals(self, package: PackageModel) -> None: - package.installPackageTriggered.connect(self.installPackage) - package.uninstallPackageTriggered.connect(self.uninstallPackage) - package.updatePackageTriggered.connect(self.installPackage) - package.enablePackageTriggered.connect(self.enablePackage) - package.disablePackageTriggered.connect(self.disablePackage) - - def _getPackageModel(self, package_id: str) -> PackageModel: + def getPackageModel(self, package_id: str) -> PackageModel: index = self.find("package", package_id) return self.getItem(index)["package"] canInstallChanged = pyqtSignal(str, bool) + def _install(self, package_id: str, update: bool = False) -> None: + package_path = self._to_install.pop(package_id) + Logger.debug(f"Installing {package_id}") + to_be_installed = self._manager.installPackage(package_path) is not None + package = self.getPackageModel(package_id) + if package.can_update and to_be_installed: + package.can_update = False + if update: + package.is_updating = False + else: + package.is_recently_installed = True + package.is_installing = False + self.subscribeUserToPackage(package_id, str(package.sdk_version)) + def download(self, package_id: str, url: str, update: bool = False) -> None: def downloadFinished(reply: "QNetworkReply") -> None: @@ -159,34 +166,13 @@ class PackageList(ListModel): if reply: reply_string = bytes(reply.readAll()).decode() Logger.error(f"Failed to download package: {package_id} due to {reply_string}") - package = self._getPackageModel(package_id) + package = self.getPackageModel(package_id) if update: - package.setIsUpdating(False) + package.is_updating = False else: - package.setIsInstalling(False) + package.is_installing = False - @pyqtSlot(str) - def installPackage(self, package_id: str) -> None: - package = self._getPackageModel(package_id) - url = package.download_url - Logger.debug(f"Trying to download and install {package_id} from {url}") - self.download(package_id, url) - - def _install(self, package_id: str, update: bool = False) -> None: - package_path = self._to_install.pop(package_id) - Logger.debug(f"Installing {package_id}") - to_be_installed = self._manager.installPackage(package_path) is not None - package = self._getPackageModel(package_id) - if package.canUpdate and to_be_installed: - package.canUpdate = False - package.setManageInstallState(to_be_installed) - if update: - package.setIsUpdating(False) - else: - package.setIsInstalling(False) - self._subscribe(package_id, str(package.sdk_version)) - - def _subscribe(self, package_id: str, sdk_version: str) -> None: + def subscribeUserToPackage(self, package_id: str, sdk_version: str) -> None: if self._account.isLoggedIn: Logger.debug(f"Subscribing the user for package: {package_id}") HttpRequestManager.getInstance().put( @@ -195,32 +181,58 @@ class PackageList(ListModel): scope = self._scope ) - @pyqtSlot(str) - def uninstallPackage(self, package_id: str) -> None: - Logger.debug(f"Uninstalling {package_id}") - package = self._getPackageModel(package_id) - self._manager.removePackage(package_id) - package.setIsInstalling(False) - package.setManageInstallState(False) - self._unsunscribe(package_id) - - def _unsunscribe(self, package_id: str) -> None: + def unsunscribeUserFromPackage(self, package_id: str) -> None: if self._account.isLoggedIn: Logger.debug(f"Unsubscribing the user for package: {package_id}") HttpRequestManager.getInstance().delete(url = f"{USER_PACKAGES_URL}/{package_id}", scope = self._scope) + # --- Handle the manage package buttons --- + + def _connectManageButtonSignals(self, package: PackageModel) -> None: + package.installPackageTriggered.connect(self.installPackage) + package.uninstallPackageTriggered.connect(self.uninstallPackage) + package.updatePackageTriggered.connect(self.installPackage) + package.enablePackageTriggered.connect(self.enablePackage) + package.disablePackageTriggered.connect(self.disablePackage) + + @pyqtSlot(str) + def installPackage(self, package_id: str) -> None: + package = self.getPackageModel(package_id) + package.is_installing = True + url = package.download_url + Logger.debug(f"Trying to download and install {package_id} from {url}") + self.download(package_id, url) + + @pyqtSlot(str) + def uninstallPackage(self, package_id: str) -> None: + Logger.debug(f"Uninstalling {package_id}") + package = self.getPackageModel(package_id) + package.is_installing = True + self._manager.removePackage(package_id) + package.is_installing = False + self.unsunscribeUserFromPackage(package_id) + @pyqtSlot(str) def updatePackage(self, package_id: str) -> None: + package = self.getPackageModel(package_id) + package.is_updating = True self._manager.removePackage(package_id, force_add = True) - package = self._getPackageModel(package_id) url = package.download_url Logger.debug(f"Trying to download and update {package_id} from {url}") self.download(package_id, url, True) @pyqtSlot(str) def enablePackage(self, package_id: str) -> None: + package = self.getPackageModel(package_id) + package.is_enabling = True Logger.debug(f"Enabling {package_id}") + # TODO: implement enabling functionality + package.is_enabling = False @pyqtSlot(str) def disablePackage(self, package_id: str) -> None: + package = self.getPackageModel(package_id) + package.is_enabling = True Logger.debug(f"Disabling {package_id}") + # TODO: implement disabling functionality + package.is_enabling = False diff --git a/plugins/Marketplace/PackageModel.py b/plugins/Marketplace/PackageModel.py index 4a8254de7d..8ba712c19d 100644 --- a/plugins/Marketplace/PackageModel.py +++ b/plugins/Marketplace/PackageModel.py @@ -61,9 +61,11 @@ class PackageModel(QObject): if not self._icon_url or self._icon_url == "": self._icon_url = author_data.get("icon_url", "") - self._can_update = False self._is_installing = False + self.is_recently_installed = False + self._can_update = False self._is_updating = False + self._is_enabling = False self._section_title = section_title 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. @@ -262,88 +264,9 @@ class PackageModel(QObject): def isCompatibleAirManager(self) -> bool: return self._is_compatible_air_manager - isInstallingChanged = pyqtSignal() + # --- manage buttons signals --- - def setIsInstalling(self, value: bool) -> None: - if value != self._is_installing: - self._is_installing = value - self.isInstallingChanged.emit() - - @pyqtProperty(bool, fset = setIsInstalling, notify = isInstallingChanged) - def isInstalling(self) -> bool: - return self._is_installing - - isUpdatingChanged = pyqtSignal() - - def setIsUpdating(self, value: bool) -> None: - if value != self._is_updating: - self._is_updating = value - self.isUpdatingChanged.emit() - - @pyqtProperty(bool, fset = setIsUpdating, notify = isUpdatingChanged) - def isUpdating(self) -> bool: - return self._is_updating - - isInstalledChanged = pyqtSignal() - - @pyqtProperty(bool, notify = isInstalledChanged) - def isInstalled(self): - return self._is_installed - - isEnabledChanged = pyqtSignal() - - @pyqtProperty(bool, notify = isEnabledChanged) - def isEnabled(self) -> bool: - return self._is_active - - manageEnableStateChanged = pyqtSignal() - - @pyqtProperty(str, notify = manageEnableStateChanged) - def manageEnableState(self) -> str: - # TODO: Handle manual installed packages - if self._is_installed: - if self._is_active: - return "secondary" - else: - return "primary" - else: - return "hidden" - - manageInstallStateChanged = pyqtSignal() - - def setManageInstallState(self, value: bool) -> None: - if value != self._is_installed: - self._is_installed = value - self.manageInstallStateChanged.emit() - self.manageEnableStateChanged.emit() - - @pyqtProperty(str, notify = manageInstallStateChanged) - def manageInstallState(self) -> str: - if self._is_installed: - if self._is_bundled: - return "hidden" - else: - return "secondary" - else: - return "primary" - - manageUpdateStateChanged = pyqtSignal() - - @pyqtProperty(str, notify = manageUpdateStateChanged) - def manageUpdateState(self) -> str: - if self._can_update: - return "primary" - return "hidden" - - @property - def canUpdate(self) -> bool: - return self._can_update - - @canUpdate.setter - def canUpdate(self, value): - if value != self._can_update: - self._can_update = value - self.manageUpdateStateChanged.emit() + stateManageButtonChanged = pyqtSignal() installPackageTriggered = pyqtSignal(str) @@ -354,3 +277,162 @@ class PackageModel(QObject): enablePackageTriggered = pyqtSignal(str) disablePackageTriggered = pyqtSignal(str) + + # --- enabling --- + + @pyqtProperty(str, notify = stateManageButtonChanged) + def stateManageEnableButton(self) -> str: + if self._is_enabling: + return "busy" + if self.is_recently_installed: + return "hidden" + if self._package_type == "material": + if self._is_bundled: # TODO: Check if a bundled material can/should be un-/install en-/disabled + return "secondary" + return "hidden" + if not self._is_installed: + return "hidden" + if self._is_installed and self._is_active: + return "secondary" + return "primary" + + @property + def is_enabling(self) -> bool: + return self._is_enabling + + @is_enabling.setter + def is_enabling(self, value: bool) -> None: + if value != self._is_enabling: + self._is_enabling = value + self.stateManageButtonChanged.emit() + + # --- Installing --- + + @pyqtProperty(str, notify = stateManageButtonChanged) + def stateManageInstallButton(self) -> str: + if self._is_installing: + return "busy" + if self.is_recently_installed: + return "secondary" + if self._is_installed: + if self._is_bundled: + return "hidden" + else: + return "secondary" + else: + return "primary" + + @property + def is_installing(self) -> bool: + return self._is_installing + + @is_installing.setter + def is_installing(self, value: bool) -> None: + if value != self._is_installing: + self._is_installing = value + self.stateManageButtonChanged.emit() + + # --- Updating --- + + @pyqtProperty(str, notify = stateManageButtonChanged) + def stateManageUpdateButton(self) -> str: + if self._is_updating: + return "busy" + if self._can_update: + return "primary" + return "hidden" + + @property + def is_updating(self) -> bool: + return self._is_updating + + @is_updating.setter + def is_updating(self, value: bool) -> None: + if value != self._is_updating: + self._is_updating = value + self.stateManageButtonChanged.emit() + + @property + def can_update(self) -> bool: + return self._can_update + + @can_update.setter + def can_update(self, value: bool) -> None: + if value != self._can_update: + self._can_update = value + self.stateManageButtonChanged.emit() + + # ---- + + + + + + + + + + + # isInstalledChanged = pyqtSignal() + # + # @pyqtProperty(bool, notify = isInstalledChanged) + # def isInstalled(self): + # return self._is_installed + # + # isEnabledChanged = pyqtSignal() + # + # + #f + # @pyqtProperty(bool, notify = isEnabledChanged) + # def isEnabled(self) -> bool: + # return self._is_active + # + # + # + # isManageEnableStateChanged = pyqtSignalf() + # + # @pyqtProperty(str, notify = isManageEnableStateChanged) + # def isManageEnableState(self) -> str: + # if self.isEnabling: + # return "busy" + # if self. + # + # manageEnableStateChanged = pyqtSignal() + # + # @pyqtProperty(str, notify = manageEnableStateChanged) + # def manageEnableState(self) -> str: + # # TODO: Handle manual installed packages + # if self._is_installed: + # if self._is_active: + # return "secondary" + # else: + # return "primary" + # else: + # return "hidden" + # + # manageInstallStateChanged = pyqtSignal() + # + # def setManageInstallState(self, value: bool) -> None: + # if value != self._is_installed: + # self._is_installed = value + # self.manageInstallStateChanged.emit() + # self.manageEnableStateChanged.emit() + # + # @pyqtProperty(str, notify = manageInstallStateChanged) + # def manageInstallState(self) -> str: + # if self._is_installed: + # if self._is_bundled: + # return "hidden" + # else: + # return "secondary" + # else: + # return "primary" + # + # manageUpdateStateChanged = pyqtSignal() + # + # @pyqtProperty(str, notify = manageUpdateStateChanged) + # def manageUpdateState(self) -> str: + # if self._can_update: + # return "primary" + # return "hidden" + # diff --git a/plugins/Marketplace/resources/qml/ManageButton.qml b/plugins/Marketplace/resources/qml/ManageButton.qml index 797e83830f..dd17d07d01 100644 --- a/plugins/Marketplace/resources/qml/ManageButton.qml +++ b/plugins/Marketplace/resources/qml/ManageButton.qml @@ -17,7 +17,7 @@ RowLayout property string busySecondaryText: busyMessageText.text property string mainState: "primary" property bool enabled: true - property bool busy: false + property bool busy signal clicked(bool primary_action) diff --git a/plugins/Marketplace/resources/qml/PackageCard.qml b/plugins/Marketplace/resources/qml/PackageCard.qml index 6331c9f58c..89ae6091fc 100644 --- a/plugins/Marketplace/resources/qml/PackageCard.qml +++ b/plugins/Marketplace/resources/qml/PackageCard.qml @@ -355,12 +355,12 @@ Rectangle ManageButton { id: enableManageButton + state: packageData.stateManageEnableButton Layout.alignment: Qt.AlignTop primaryText: catalog.i18nc("@button", "Enable") busyPrimaryText: catalog.i18nc("@button", "enabling...") secondaryText: catalog.i18nc("@button", "Disable") busySecondaryText: catalog.i18nc("@button", "disabling...") - mainState: packageData.manageEnableState enabled: !(installManageButton.busy || updateManageButton.busy) } Connections @@ -382,13 +382,12 @@ Rectangle ManageButton { id: installManageButton + state: packageData.stateManageInstallButton Layout.alignment: Qt.AlignTop primaryText: catalog.i18nc("@button", "Install") busyPrimaryText: catalog.i18nc("@button", "installing...") secondaryText: catalog.i18nc("@button", "Uninstall") busySecondaryText: catalog.i18nc("@button", "uninstalling...") - mainState: packageData.manageInstallState - busy: packageData.isInstalling enabled: !(enableManageButton.busy || updateManageButton.busy) } Connections @@ -396,7 +395,6 @@ Rectangle target: installManageButton function onClicked(primary_action) { - packageData.isInstalling = true if (primary_action) { packageData.installPackageTriggered(packageData.packageId) @@ -411,11 +409,10 @@ Rectangle ManageButton { id: updateManageButton + state: packageData.stateManageUpdateButton Layout.alignment: Qt.AlignTop primaryText: catalog.i18nc("@button", "Update") busyPrimaryText: catalog.i18nc("@button", "updating...") - mainState: packageData.manageUpdateState - busy: packageData.isUpdating enabled: !(installManageButton.busy || enableManageButton.busy) } Connections @@ -423,7 +420,6 @@ Rectangle target: updateManageButton function onClicked(primary_action) { - packageData.isUpdating = true packageData.updatePackageTriggered(packageData.packageId) } }