123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101 |
- # Copyright (c) 2021 Ultimaker B.V.
- # Cura is released under the terms of the LGPLv3 or higher.
- from PyQt5.QtCore import pyqtProperty, pyqtSignal, pyqtSlot, Qt
- from typing import Optional, TYPE_CHECKING
- from UM.i18n import i18nCatalog
- from UM.Qt.ListModel import ListModel
- from UM.TaskManagement.HttpRequestScope import JsonDecoratorScope # To request JSON responses from the API.
- from UM.TaskManagement.HttpRequestManager import HttpRequestData # To request the package list from the API.
- from cura.CuraApplication import CuraApplication
- from cura.UltimakerCloud.UltimakerCloudScope import UltimakerCloudScope # To make requests to the Ultimaker API with correct authorization.
- if TYPE_CHECKING:
- from PyQt5.QtCore import QObject
- catalog = i18nCatalog("cura")
- class PackageList(ListModel):
- """ A List model for Packages, this class serves as parent class for more detailed implementations.
- such as Packages obtained from Remote or Local source
- """
- PackageRole = Qt.UserRole + 1
- def __init__(self, parent: Optional["QObject"] = None) -> None:
- super().__init__(parent)
- self._error_message = ""
- self.addRoleName(self.PackageRole, "package")
- self._is_loading = False
- self._has_more = False
- self._has_footer = True
- self._ongoing_request: Optional[HttpRequestData] = None
- self._scope = JsonDecoratorScope(UltimakerCloudScope(CuraApplication.getInstance()))
- @pyqtSlot()
- def updatePackages(self) -> None:
- """ A Qt slot which will update the List from a source. Actual implementation should be done in the child class"""
- pass
- @pyqtSlot()
- def abortUpdating(self) -> None:
- """ A Qt slot which allows the update process to be aborted. Override this for child classes with async/callback
- updatePackges methods"""
- pass
- def reset(self) -> None:
- """ Resets and clears the list"""
- self.clear()
- isLoadingChanged = pyqtSignal()
- def setIsLoading(self, value: bool) -> None:
- if self._is_loading != value:
- self._is_loading = value
- self.isLoadingChanged.emit()
- @pyqtProperty(bool, fset = setIsLoading, notify = isLoadingChanged)
- def isLoading(self) -> bool:
- """ Indicating if the the packages are loading
- :return" ``True`` if the list is being obtained, otherwise ``False``
- """
- return self._is_loading
- hasMoreChanged = pyqtSignal()
- def setHasMore(self, value: bool) -> None:
- if self._has_more != value:
- self._has_more = value
- self.hasMoreChanged.emit()
- @pyqtProperty(bool, fset = setHasMore, notify = hasMoreChanged)
- def hasMore(self) -> bool:
- """ Indicating if there are more packages available to load.
- :return: ``True`` if there are more packages to load, or ``False``.
- """
- return self._has_more
- errorMessageChanged = pyqtSignal()
- def setErrorMessage(self, error_message: str) -> None:
- if self._error_message != error_message:
- self._error_message = error_message
- self.errorMessageChanged.emit()
- @pyqtProperty(str, notify = errorMessageChanged, fset = setErrorMessage)
- def errorMessage(self) -> str:
- """ If an error occurred getting the list of packages, an error message will be held here.
- If no error occurred (yet), this will be an empty string.
- :return: An error message, if any, or an empty string if everything went okay.
- """
- return self._error_message
- @pyqtProperty(bool, constant = True)
- def hasFooter(self) -> bool:
- """ Indicating if the PackageList should have a Footer visible. For paginated PackageLists
- :return: ``True`` if a Footer should be displayed in the ListView, e.q.: paginated lists, ``False`` Otherwise"""
- return self._has_footer
|