_viewerpref.py 6.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163
  1. # Copyright (c) 2023, Pubpub-ZZ
  2. #
  3. # All rights reserved.
  4. #
  5. # Redistribution and use in source and binary forms, with or without
  6. # modification, are permitted provided that the following conditions are
  7. # met:
  8. #
  9. # * Redistributions of source code must retain the above copyright notice,
  10. # this list of conditions and the following disclaimer.
  11. # * Redistributions in binary form must reproduce the above copyright notice,
  12. # this list of conditions and the following disclaimer in the documentation
  13. # and/or other materials provided with the distribution.
  14. # * The name of the author may not be used to endorse or promote products
  15. # derived from this software without specific prior written permission.
  16. #
  17. # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
  18. # AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
  19. # IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
  20. # ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
  21. # LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
  22. # CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
  23. # SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
  24. # INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
  25. # CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
  26. # ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
  27. # POSSIBILITY OF SUCH DAMAGE.
  28. from typing import (
  29. Any,
  30. Optional,
  31. )
  32. from ._base import BooleanObject, NameObject, NumberObject, is_null_or_none
  33. from ._data_structures import ArrayObject, DictionaryObject
  34. f_obj = BooleanObject(False)
  35. class ViewerPreferences(DictionaryObject):
  36. def __init__(self, obj: Optional[DictionaryObject] = None) -> None:
  37. super().__init__(self)
  38. if not is_null_or_none(obj):
  39. self.update(obj.items()) # type: ignore
  40. try:
  41. self.indirect_reference = obj.indirect_reference # type: ignore
  42. except AttributeError:
  43. pass
  44. def _get_bool(self, key: str, default: Optional[BooleanObject]) -> Optional[BooleanObject]:
  45. return self.get(key, default)
  46. def _set_bool(self, key: str, v: bool) -> None:
  47. self[NameObject(key)] = BooleanObject(v is True)
  48. def _get_name(self, key: str, default: Optional[NameObject]) -> Optional[NameObject]:
  49. return self.get(key, default)
  50. def _set_name(self, key: str, lst: list[str], v: NameObject) -> None:
  51. if v[0] != "/":
  52. raise ValueError(f"{v} does not start with '/'")
  53. if lst != [] and v not in lst:
  54. raise ValueError(f"{v} is an unacceptable value")
  55. self[NameObject(key)] = NameObject(v)
  56. def _get_arr(self, key: str, default: Optional[list[Any]]) -> Optional[ArrayObject]:
  57. return self.get(key, None if default is None else ArrayObject(default))
  58. def _set_arr(self, key: str, v: Optional[ArrayObject]) -> None:
  59. if v is None:
  60. try:
  61. del self[NameObject(key)]
  62. except KeyError:
  63. pass
  64. return
  65. if not isinstance(v, ArrayObject):
  66. raise ValueError("ArrayObject is expected")
  67. self[NameObject(key)] = v
  68. def _get_int(self, key: str, default: Optional[NumberObject]) -> Optional[NumberObject]:
  69. return self.get(key, default)
  70. def _set_int(self, key: str, v: int) -> None:
  71. self[NameObject(key)] = NumberObject(v)
  72. @property
  73. def PRINT_SCALING(self) -> NameObject:
  74. return NameObject("/PrintScaling")
  75. def __new__(cls: Any, value: Any = None) -> "ViewerPreferences": # noqa: PYI034
  76. def _add_prop_bool(key: str, default: Optional[BooleanObject]) -> property:
  77. return property(
  78. lambda self: self._get_bool(key, default),
  79. lambda self, v: self._set_bool(key, v),
  80. None,
  81. f"""
  82. Returns/Modify the status of {key}, Returns {default} if not defined
  83. """,
  84. )
  85. def _add_prop_name(
  86. key: str, lst: list[str], default: Optional[NameObject]
  87. ) -> property:
  88. return property(
  89. lambda self: self._get_name(key, default),
  90. lambda self, v: self._set_name(key, lst, v),
  91. None,
  92. f"""
  93. Returns/Modify the status of {key}, Returns {default} if not defined.
  94. Acceptable values: {lst}
  95. """,
  96. )
  97. def _add_prop_arr(key: str, default: Optional[ArrayObject]) -> property:
  98. return property(
  99. lambda self: self._get_arr(key, default),
  100. lambda self, v: self._set_arr(key, v),
  101. None,
  102. f"""
  103. Returns/Modify the status of {key}, Returns {default} if not defined
  104. """,
  105. )
  106. def _add_prop_int(key: str, default: Optional[int]) -> property:
  107. return property(
  108. lambda self: self._get_int(key, default),
  109. lambda self, v: self._set_int(key, v),
  110. None,
  111. f"""
  112. Returns/Modify the status of {key}, Returns {default} if not defined
  113. """,
  114. )
  115. cls.hide_toolbar = _add_prop_bool("/HideToolbar", f_obj)
  116. cls.hide_menubar = _add_prop_bool("/HideMenubar", f_obj)
  117. cls.hide_windowui = _add_prop_bool("/HideWindowUI", f_obj)
  118. cls.fit_window = _add_prop_bool("/FitWindow", f_obj)
  119. cls.center_window = _add_prop_bool("/CenterWindow", f_obj)
  120. cls.display_doctitle = _add_prop_bool("/DisplayDocTitle", f_obj)
  121. cls.non_fullscreen_pagemode = _add_prop_name(
  122. "/NonFullScreenPageMode",
  123. ["/UseNone", "/UseOutlines", "/UseThumbs", "/UseOC"],
  124. NameObject("/UseNone"),
  125. )
  126. cls.direction = _add_prop_name(
  127. "/Direction", ["/L2R", "/R2L"], NameObject("/L2R")
  128. )
  129. cls.view_area = _add_prop_name("/ViewArea", [], None)
  130. cls.view_clip = _add_prop_name("/ViewClip", [], None)
  131. cls.print_area = _add_prop_name("/PrintArea", [], None)
  132. cls.print_clip = _add_prop_name("/PrintClip", [], None)
  133. cls.print_scaling = _add_prop_name("/PrintScaling", [], None)
  134. cls.duplex = _add_prop_name(
  135. "/Duplex", ["/Simplex", "/DuplexFlipShortEdge", "/DuplexFlipLongEdge"], None
  136. )
  137. cls.pick_tray_by_pdfsize = _add_prop_bool("/PickTrayByPDFSize", None)
  138. cls.print_pagerange = _add_prop_arr("/PrintPageRange", None)
  139. cls.num_copies = _add_prop_int("/NumCopies", None)
  140. cls.enforce = _add_prop_arr("/Enforce", ArrayObject())
  141. return DictionaryObject.__new__(cls)