WhatsNewPagesModel.py 4.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113
  1. # Copyright (c) 2021 Ultimaker B.V.
  2. # Cura is released under the terms of the LGPLv3 or higher.
  3. import os
  4. from typing import Optional, Dict, List, Tuple, TYPE_CHECKING
  5. from PyQt6.QtCore import pyqtProperty, pyqtSlot
  6. from UM.Logger import Logger
  7. from UM.Resources import Resources
  8. from cura.UI.WelcomePagesModel import WelcomePagesModel
  9. if TYPE_CHECKING:
  10. from PyQt6.QtCore import QObject
  11. from cura.CuraApplication import CuraApplication
  12. class WhatsNewPagesModel(WelcomePagesModel):
  13. """
  14. This Qt ListModel is more or less the same the WelcomePagesModel, except that this model is only for showing the
  15. "what's new" page. This is also used in the "Help" menu to show the changes log.
  16. """
  17. image_formats = [".png", ".jpg", ".jpeg", ".gif", ".svg"]
  18. text_formats = [".txt", ".htm", ".html"]
  19. image_key = "image"
  20. text_key = "text"
  21. def __init__(self, application: "CuraApplication", parent: Optional["QObject"] = None) -> None:
  22. super().__init__(application, parent)
  23. self._subpages: List[Dict[str, Optional[str]]] = []
  24. @staticmethod
  25. def _collectOrdinalFiles(resource_type: int, include: List[str]) -> Tuple[Dict[int, str], int]:
  26. result = {} # type: Dict[int, str]
  27. highest = -1
  28. try:
  29. folder_path = Resources.getPath(resource_type, "whats_new")
  30. for _, _, files in os.walk(folder_path):
  31. for filename in files:
  32. basename = os.path.basename(filename)
  33. base, ext = os.path.splitext(basename)
  34. if ext.lower() not in include or not base.isdigit():
  35. continue
  36. page_no = int(base)
  37. highest = max(highest, page_no)
  38. result[page_no] = os.path.join(folder_path, filename)
  39. except FileNotFoundError:
  40. Logger.logException("w", "Could not find 'whats_new' folder for resource-type {0}".format(resource_type))
  41. return result, highest
  42. @staticmethod
  43. def _loadText(filename: str) -> str:
  44. result = ""
  45. try:
  46. with open(filename, "r", encoding="utf-8") as file:
  47. result = file.read()
  48. except OSError:
  49. Logger.logException("w", "Could not open {0}".format(filename))
  50. return result
  51. def initialize(self) -> None:
  52. self._pages = []
  53. try:
  54. self._pages.append({"id": "whats_new",
  55. "page_url": self._getBuiltinWelcomePagePath("WhatsNewContent.qml"),
  56. "next_page_button_text": self._catalog.i18nc("@action:button", "Skip"),
  57. "next_page_id": "changelog"
  58. })
  59. except FileNotFoundError:
  60. Logger.warning("Unable to find what's new page")
  61. try:
  62. self._pages.append({"id": "changelog",
  63. "page_url": self._getBuiltinWelcomePagePath("ChangelogContent.qml"),
  64. "next_page_button_text": self._catalog.i18nc("@action:button", "Close"),
  65. })
  66. except FileNotFoundError:
  67. Logger.warning("Unable to find changelog page")
  68. self.setItems(self._pages)
  69. images, max_image = WhatsNewPagesModel._collectOrdinalFiles(Resources.Images, WhatsNewPagesModel.image_formats)
  70. texts, max_text = WhatsNewPagesModel._collectOrdinalFiles(Resources.Texts, WhatsNewPagesModel.text_formats)
  71. highest = max(max_image, max_text)
  72. self._subpages = []
  73. for n in range(0, highest + 1):
  74. self._subpages.append({
  75. WhatsNewPagesModel.image_key: None if n not in images else images[n],
  76. WhatsNewPagesModel.text_key: None if n not in texts else self._loadText(texts[n])
  77. })
  78. if len(self._subpages) == 0:
  79. self._subpages.append({WhatsNewPagesModel.text_key: "~ There Is Nothing New Under The Sun ~"})
  80. def _getSubpageItem(self, page: int, item: str) -> Optional[str]:
  81. if 0 <= page < self.subpageCount and item in self._subpages[page]:
  82. return self._subpages[page][item]
  83. else:
  84. return None
  85. @pyqtProperty(int, constant = True)
  86. def subpageCount(self) -> int:
  87. return len(self._subpages)
  88. @pyqtSlot(int, result = str)
  89. def getSubpageImageSource(self, page: int) -> str:
  90. result = self._getSubpageItem(page, WhatsNewPagesModel.image_key)
  91. return "file:///" + (result if result else Resources.getPath(Resources.Images, "cura-icon.png"))
  92. @pyqtSlot(int, result = str)
  93. def getSubpageText(self, page: int) -> str:
  94. result = self._getSubpageItem(page, WhatsNewPagesModel.text_key)
  95. return result if result else "* * *"