OptionUI.py 7.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222
  1. from typing import Union, Sequence
  2. from PyQt5 import QtWidgets
  3. from flatcamGUI.GUIElements import RadioSet, FCCheckBox, FCButton, FCComboBox, FCEntry, FCSpinner, FCColorEntry, \
  4. FCSliderWithSpinner, FCDoubleSpinner
  5. import gettext
  6. import FlatCAMTranslation as fcTranslate
  7. import builtins
  8. fcTranslate.apply_language('strings')
  9. if '_' not in builtins.__dict__:
  10. _ = gettext.gettext
  11. class OptionUI:
  12. def __init__(self, option: str):
  13. self.option = option
  14. def add_to_grid(self, grid: QtWidgets.QGridLayout, row: int) -> int:
  15. """
  16. Adds the necessary widget to the grid, starting at the supplied row.
  17. Returns the number of rows used (normally 1)
  18. """
  19. raise NotImplementedError()
  20. def get_field(self):
  21. raise NotImplementedError()
  22. class BasicOptionUI(OptionUI):
  23. """Abstract OptionUI that has a label on the left then some other widget on the right"""
  24. def __init__(self, option: str, label_text: str, label_tooltip: Union[str, None] = None, label_bold: bool = False, label_red: bool = False):
  25. super().__init__(option=option)
  26. self.label_text = label_text
  27. self.label_tooltip = label_tooltip
  28. self.label_bold = label_bold
  29. self.label_red = label_red
  30. self.label_widget = self.build_label_widget()
  31. self.entry_widget = self.build_entry_widget()
  32. def build_label_widget(self) -> QtWidgets.QLabel:
  33. fmt = "%s:"
  34. if self.label_bold:
  35. fmt = "<b>%s</b>" % fmt
  36. if self.label_red:
  37. fmt = "<span style=\"color:red;\">%s</span>" % fmt
  38. label_widget = QtWidgets.QLabel(fmt % _(self.label_text))
  39. if self.label_tooltip is not None:
  40. label_widget.setToolTip(_(self.label_tooltip))
  41. return label_widget
  42. def build_entry_widget(self) -> QtWidgets.QWidget:
  43. raise NotImplementedError()
  44. def add_to_grid(self, grid: QtWidgets.QGridLayout, row: int) -> int:
  45. grid.addWidget(self.label_widget, row, 0)
  46. grid.addWidget(self.entry_widget, row, 1)
  47. return 1
  48. def get_field(self):
  49. return self.entry_widget
  50. class RadioSetOptionUI(BasicOptionUI):
  51. def __init__(self, option: str, label_text: str, choices: list, orientation='horizontal', **kwargs):
  52. self.choices = choices
  53. self.orientation = orientation
  54. super().__init__(option=option, label_text=label_text, **kwargs)
  55. def build_entry_widget(self) -> QtWidgets.QWidget:
  56. return RadioSet(choices=self.choices, orientation=self.orientation)
  57. class CheckboxOptionUI(OptionUI):
  58. def __init__(self, option: str, label_text: str, label_tooltip: str):
  59. super().__init__(option=option)
  60. self.label_text = label_text
  61. self.label_tooltip = label_tooltip
  62. self.checkbox_widget = self.build_checkbox_widget()
  63. def build_checkbox_widget(self):
  64. checkbox = FCCheckBox('%s' % _(self.label_text))
  65. checkbox.setToolTip(_(self.label_tooltip))
  66. return checkbox
  67. def add_to_grid(self, grid: QtWidgets.QGridLayout, row: int) -> int:
  68. grid.addWidget(self.checkbox_widget, row, 0, 1, 3)
  69. return 1
  70. def get_field(self):
  71. return self.checkbox_widget
  72. class ComboboxOptionUI(BasicOptionUI):
  73. def __init__(self, option: str, label_text: str, choices: Sequence, **kwargs):
  74. self.choices = choices
  75. super().__init__(option=option, label_text=label_text, **kwargs)
  76. def build_entry_widget(self):
  77. combo = FCComboBox()
  78. for choice in self.choices:
  79. # don't translate the QCombo items as they are used in QSettings and identified by name
  80. combo.addItem(choice)
  81. return combo
  82. class ColorOptionUI(BasicOptionUI):
  83. def build_entry_widget(self) -> QtWidgets.QWidget:
  84. entry = FCColorEntry()
  85. return entry
  86. class SliderWithSpinnerOptionUI(BasicOptionUI):
  87. def __init__(self, option: str, label_text: str, min_value=0, max_value=100, step=1, **kwargs):
  88. self.min_value = min_value
  89. self.max_value = max_value
  90. self.step = step
  91. super().__init__(option=option, label_text=label_text, **kwargs)
  92. def build_entry_widget(self) -> QtWidgets.QWidget:
  93. entry = FCSliderWithSpinner(min=self.min_value, max=self.max_value, step=self.step)
  94. return entry
  95. class SpinnerOptionUI(BasicOptionUI):
  96. def __init__(self, option: str, label_text: str, min_value: int, max_value: int, step: int = 1, **kwargs):
  97. self.min_value = min_value
  98. self.max_value = max_value
  99. self.step = step
  100. super().__init__(option=option, label_text=label_text, **kwargs)
  101. def build_entry_widget(self) -> QtWidgets.QWidget:
  102. entry = FCSpinner()
  103. entry.set_range(self.min_value, self.max_value)
  104. entry.set_step(self.step)
  105. entry.setWrapping(True)
  106. return entry
  107. class DoubleSpinnerOptionUI(BasicOptionUI):
  108. def __init__(self, option: str, label_text: str, step: float, decimals: int, min_value=None, max_value=None, **kwargs):
  109. self.min_value = min_value
  110. self.max_value = max_value
  111. self.step = step
  112. self.decimals = decimals
  113. super().__init__(option=option, label_text=label_text, **kwargs)
  114. def build_entry_widget(self) -> QtWidgets.QWidget:
  115. entry = FCDoubleSpinner()
  116. entry.set_precision(self.decimals)
  117. entry.setSingleStep(self.step)
  118. if self.min_value is None:
  119. self.min_value = entry.minimum()
  120. else:
  121. entry.setMinimum(self.min_value)
  122. if self.max_value is None:
  123. self.max_value = entry.maximum()
  124. else:
  125. entry.setMaximum(self.max_value)
  126. return entry
  127. class HeadingOptionUI(OptionUI):
  128. def __init__(self, label_text: str, label_tooltip: Union[str, None] = None):
  129. super().__init__(option="__heading")
  130. self.label_text = label_text
  131. self.label_tooltip = label_tooltip
  132. def build_heading_widget(self):
  133. heading = QtWidgets.QLabel('<b>%s</b>' % _(self.label_text))
  134. heading.setToolTip(_(self.label_tooltip))
  135. return heading
  136. def add_to_grid(self, grid: QtWidgets.QGridLayout, row: int) -> int:
  137. grid.addWidget(self.build_heading_widget(), row, 0, 1, 2)
  138. return 1
  139. def get_field(self):
  140. return None
  141. class SeparatorOptionUI(OptionUI):
  142. def __init__(self):
  143. super().__init__(option="__separator")
  144. def build_separator_widget(self):
  145. separator = QtWidgets.QFrame()
  146. separator.setFrameShape(QtWidgets.QFrame.HLine)
  147. separator.setFrameShadow(QtWidgets.QFrame.Sunken)
  148. return separator
  149. def add_to_grid(self, grid: QtWidgets.QGridLayout, row: int) -> int:
  150. grid.addWidget(self.build_separator_widget(), row, 0, 1, 2)
  151. return 1
  152. def get_field(self):
  153. return None
  154. class FullWidthButtonOptionUI(OptionUI):
  155. def __init__(self, option: str, label_text: str, label_tooltip: str):
  156. super().__init__(option=option)
  157. self.label_text = label_text
  158. self.label_tooltip = label_tooltip
  159. self.button_widget = self.build_button_widget()
  160. def build_button_widget(self):
  161. button = FCButton(_(self.label_text))
  162. button.setToolTip(_(self.label_tooltip))
  163. return button
  164. def add_to_grid(self, grid: QtWidgets.QGridLayout, row: int) -> int:
  165. grid.addWidget(self.button_widget, row, 0, 1, 3)
  166. return 1
  167. def get_field(self):
  168. return self.button_widget