PackageList.py 3.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101
  1. # Copyright (c) 2021 Ultimaker B.V.
  2. # Cura is released under the terms of the LGPLv3 or higher.
  3. from PyQt5.QtCore import pyqtProperty, pyqtSignal, pyqtSlot, Qt
  4. from typing import Optional, TYPE_CHECKING
  5. from UM.i18n import i18nCatalog
  6. from UM.Qt.ListModel import ListModel
  7. from UM.TaskManagement.HttpRequestScope import JsonDecoratorScope # To request JSON responses from the API.
  8. from UM.TaskManagement.HttpRequestManager import HttpRequestData # To request the package list from the API.
  9. from cura.CuraApplication import CuraApplication
  10. from cura.UltimakerCloud.UltimakerCloudScope import UltimakerCloudScope # To make requests to the Ultimaker API with correct authorization.
  11. if TYPE_CHECKING:
  12. from PyQt5.QtCore import QObject
  13. catalog = i18nCatalog("cura")
  14. class PackageList(ListModel):
  15. """ A List model for Packages, this class serves as parent class for more detailed implementations.
  16. such as Packages obtained from Remote or Local source
  17. """
  18. PackageRole = Qt.UserRole + 1
  19. def __init__(self, parent: Optional["QObject"] = None) -> None:
  20. super().__init__(parent)
  21. self._error_message = ""
  22. self.addRoleName(self.PackageRole, "package")
  23. self._is_loading = False
  24. self._has_more = False
  25. self._has_footer = True
  26. self._ongoing_request: Optional[HttpRequestData] = None
  27. self._scope = JsonDecoratorScope(UltimakerCloudScope(CuraApplication.getInstance()))
  28. @pyqtSlot()
  29. def updatePackages(self) -> None:
  30. """ A Qt slot which will update the List from a source. Actual implementation should be done in the child class"""
  31. pass
  32. @pyqtSlot()
  33. def abortUpdating(self) -> None:
  34. """ A Qt slot which allows the update process to be aborted. Override this for child classes with async/callback
  35. updatePackges methods"""
  36. pass
  37. def reset(self) -> None:
  38. """ Resets and clears the list"""
  39. self.clear()
  40. isLoadingChanged = pyqtSignal()
  41. def setIsLoading(self, value: bool) -> None:
  42. if self._is_loading != value:
  43. self._is_loading = value
  44. self.isLoadingChanged.emit()
  45. @pyqtProperty(bool, fset = setIsLoading, notify = isLoadingChanged)
  46. def isLoading(self) -> bool:
  47. """ Indicating if the the packages are loading
  48. :return" ``True`` if the list is being obtained, otherwise ``False``
  49. """
  50. return self._is_loading
  51. hasMoreChanged = pyqtSignal()
  52. def setHasMore(self, value: bool) -> None:
  53. if self._has_more != value:
  54. self._has_more = value
  55. self.hasMoreChanged.emit()
  56. @pyqtProperty(bool, fset = setHasMore, notify = hasMoreChanged)
  57. def hasMore(self) -> bool:
  58. """ Indicating if there are more packages available to load.
  59. :return: ``True`` if there are more packages to load, or ``False``.
  60. """
  61. return self._has_more
  62. errorMessageChanged = pyqtSignal()
  63. def setErrorMessage(self, error_message: str) -> None:
  64. if self._error_message != error_message:
  65. self._error_message = error_message
  66. self.errorMessageChanged.emit()
  67. @pyqtProperty(str, notify = errorMessageChanged, fset = setErrorMessage)
  68. def errorMessage(self) -> str:
  69. """ If an error occurred getting the list of packages, an error message will be held here.
  70. If no error occurred (yet), this will be an empty string.
  71. :return: An error message, if any, or an empty string if everything went okay.
  72. """
  73. return self._error_message
  74. @pyqtProperty(bool, constant = True)
  75. def hasFooter(self) -> bool:
  76. """ Indicating if the PackageList should have a Footer visible. For paginated PackageLists
  77. :return: ``True`` if a Footer should be displayed in the ListView, e.q.: paginated lists, ``False`` Otherwise"""
  78. return self._has_footer