2020-05-03 03:18:10 +00:00
|
|
|
from typing import Union, Sequence
|
2020-05-02 01:12:09 +00:00
|
|
|
|
2020-05-02 00:11:31 +00:00
|
|
|
from PyQt5 import QtWidgets
|
2020-05-02 03:09:07 +00:00
|
|
|
from flatcamGUI.GUIElements import RadioSet, FCCheckBox, FCButton, FCComboBox, FCEntry, FCSpinner, FCColorEntry, \
|
2020-05-03 01:27:17 +00:00
|
|
|
FCSliderWithSpinner, FCDoubleSpinner
|
2020-05-02 00:11:31 +00:00
|
|
|
|
|
|
|
import gettext
|
|
|
|
import FlatCAMTranslation as fcTranslate
|
|
|
|
import builtins
|
|
|
|
fcTranslate.apply_language('strings')
|
|
|
|
if '_' not in builtins.__dict__:
|
|
|
|
_ = gettext.gettext
|
|
|
|
|
|
|
|
|
|
|
|
class OptionUI:
|
|
|
|
|
|
|
|
def __init__(self, option: str):
|
|
|
|
self.option = option
|
|
|
|
|
|
|
|
def add_to_grid(self, grid: QtWidgets.QGridLayout, row: int) -> int:
|
|
|
|
"""
|
|
|
|
Adds the necessary widget to the grid, starting at the supplied row.
|
|
|
|
Returns the number of rows used (normally 1)
|
|
|
|
"""
|
|
|
|
raise NotImplementedError()
|
|
|
|
|
|
|
|
def get_field(self):
|
|
|
|
raise NotImplementedError()
|
|
|
|
|
|
|
|
|
|
|
|
class BasicOptionUI(OptionUI):
|
|
|
|
"""Abstract OptionUI that has a label on the left then some other widget on the right"""
|
2020-05-03 14:38:26 +00:00
|
|
|
def __init__(self, option: str, label_text: str, label_tooltip: Union[str, None] = None, label_bold: bool = False, label_red: bool = False):
|
2020-05-02 00:11:31 +00:00
|
|
|
super().__init__(option=option)
|
|
|
|
self.label_text = label_text
|
|
|
|
self.label_tooltip = label_tooltip
|
2020-05-03 14:38:26 +00:00
|
|
|
self.label_bold = label_bold
|
|
|
|
self.label_red = label_red
|
2020-05-02 00:11:31 +00:00
|
|
|
self.label_widget = self.build_label_widget()
|
|
|
|
self.entry_widget = self.build_entry_widget()
|
|
|
|
|
|
|
|
def build_label_widget(self) -> QtWidgets.QLabel:
|
2020-05-03 14:38:26 +00:00
|
|
|
fmt = "%s:"
|
|
|
|
if self.label_bold:
|
|
|
|
fmt = "<b>%s</b>" % fmt
|
|
|
|
if self.label_red:
|
|
|
|
fmt = "<span style=\"color:red;\">%s</span>" % fmt
|
|
|
|
label_widget = QtWidgets.QLabel(fmt % _(self.label_text))
|
2020-05-02 00:11:31 +00:00
|
|
|
if self.label_tooltip is not None:
|
|
|
|
label_widget.setToolTip(_(self.label_tooltip))
|
|
|
|
return label_widget
|
|
|
|
|
|
|
|
def build_entry_widget(self) -> QtWidgets.QWidget:
|
|
|
|
raise NotImplementedError()
|
|
|
|
|
|
|
|
def add_to_grid(self, grid: QtWidgets.QGridLayout, row: int) -> int:
|
|
|
|
grid.addWidget(self.label_widget, row, 0)
|
|
|
|
grid.addWidget(self.entry_widget, row, 1)
|
|
|
|
return 1
|
|
|
|
|
|
|
|
def get_field(self):
|
|
|
|
return self.entry_widget
|
|
|
|
|
|
|
|
|
|
|
|
class RadioSetOptionUI(BasicOptionUI):
|
|
|
|
|
2020-05-03 14:38:26 +00:00
|
|
|
def __init__(self, option: str, label_text: str, choices: list, orientation='horizontal', **kwargs):
|
2020-05-02 00:11:31 +00:00
|
|
|
self.choices = choices
|
|
|
|
self.orientation = orientation
|
2020-05-03 14:38:26 +00:00
|
|
|
super().__init__(option=option, label_text=label_text, **kwargs)
|
2020-05-02 00:11:31 +00:00
|
|
|
|
|
|
|
def build_entry_widget(self) -> QtWidgets.QWidget:
|
|
|
|
return RadioSet(choices=self.choices, orientation=self.orientation)
|
|
|
|
|
|
|
|
|
|
|
|
class CheckboxOptionUI(OptionUI):
|
|
|
|
|
|
|
|
def __init__(self, option: str, label_text: str, label_tooltip: str):
|
|
|
|
super().__init__(option=option)
|
|
|
|
self.label_text = label_text
|
|
|
|
self.label_tooltip = label_tooltip
|
|
|
|
self.checkbox_widget = self.build_checkbox_widget()
|
|
|
|
|
|
|
|
def build_checkbox_widget(self):
|
|
|
|
checkbox = FCCheckBox('%s' % _(self.label_text))
|
|
|
|
checkbox.setToolTip(_(self.label_tooltip))
|
|
|
|
return checkbox
|
|
|
|
|
|
|
|
def add_to_grid(self, grid: QtWidgets.QGridLayout, row: int) -> int:
|
|
|
|
grid.addWidget(self.checkbox_widget, row, 0, 1, 3)
|
|
|
|
return 1
|
|
|
|
|
|
|
|
def get_field(self):
|
|
|
|
return self.checkbox_widget
|
|
|
|
|
|
|
|
|
|
|
|
class ComboboxOptionUI(BasicOptionUI):
|
|
|
|
|
2020-05-03 14:38:26 +00:00
|
|
|
def __init__(self, option: str, label_text: str, choices: Sequence, **kwargs):
|
2020-05-02 00:11:31 +00:00
|
|
|
self.choices = choices
|
2020-05-03 14:38:26 +00:00
|
|
|
super().__init__(option=option, label_text=label_text, **kwargs)
|
2020-05-02 00:11:31 +00:00
|
|
|
|
|
|
|
def build_entry_widget(self):
|
|
|
|
combo = FCComboBox()
|
|
|
|
for choice in self.choices:
|
|
|
|
# don't translate the QCombo items as they are used in QSettings and identified by name
|
|
|
|
combo.addItem(choice)
|
|
|
|
return combo
|
|
|
|
|
|
|
|
|
|
|
|
class ColorOptionUI(BasicOptionUI):
|
|
|
|
def build_entry_widget(self) -> QtWidgets.QWidget:
|
2020-05-02 02:08:42 +00:00
|
|
|
entry = FCColorEntry()
|
|
|
|
return entry
|
2020-05-02 00:11:31 +00:00
|
|
|
|
|
|
|
|
2020-05-02 03:09:07 +00:00
|
|
|
class SliderWithSpinnerOptionUI(BasicOptionUI):
|
2020-05-03 14:38:26 +00:00
|
|
|
def __init__(self, option: str, label_text: str, min_value=0, max_value=100, step=1, **kwargs):
|
2020-05-03 01:27:17 +00:00
|
|
|
self.min_value = min_value
|
|
|
|
self.max_value = max_value
|
2020-05-02 03:09:07 +00:00
|
|
|
self.step = step
|
2020-05-03 14:38:26 +00:00
|
|
|
super().__init__(option=option, label_text=label_text, **kwargs)
|
2020-05-02 03:09:07 +00:00
|
|
|
|
|
|
|
def build_entry_widget(self) -> QtWidgets.QWidget:
|
2020-05-03 01:27:17 +00:00
|
|
|
entry = FCSliderWithSpinner(min=self.min_value, max=self.max_value, step=self.step)
|
|
|
|
return entry
|
|
|
|
|
|
|
|
|
2020-05-03 03:18:10 +00:00
|
|
|
class SpinnerOptionUI(BasicOptionUI):
|
2020-05-03 14:38:26 +00:00
|
|
|
def __init__(self, option: str, label_text: str, min_value: int, max_value: int, step: int = 1, **kwargs):
|
2020-05-03 03:18:10 +00:00
|
|
|
self.min_value = min_value
|
|
|
|
self.max_value = max_value
|
|
|
|
self.step = step
|
2020-05-03 14:38:26 +00:00
|
|
|
super().__init__(option=option, label_text=label_text, **kwargs)
|
2020-05-03 03:18:10 +00:00
|
|
|
|
|
|
|
def build_entry_widget(self) -> QtWidgets.QWidget:
|
|
|
|
entry = FCSpinner()
|
|
|
|
entry.set_range(self.min_value, self.max_value)
|
|
|
|
entry.set_step(self.step)
|
|
|
|
entry.setWrapping(True)
|
|
|
|
return entry
|
|
|
|
|
|
|
|
|
2020-05-03 01:27:17 +00:00
|
|
|
class DoubleSpinnerOptionUI(BasicOptionUI):
|
2020-05-03 14:38:26 +00:00
|
|
|
def __init__(self, option: str, label_text: str, step: float, decimals: int, min_value=None, max_value=None, **kwargs):
|
2020-05-03 01:27:17 +00:00
|
|
|
self.min_value = min_value
|
|
|
|
self.max_value = max_value
|
|
|
|
self.step = step
|
|
|
|
self.decimals = decimals
|
2020-05-03 14:38:26 +00:00
|
|
|
super().__init__(option=option, label_text=label_text, **kwargs)
|
2020-05-03 01:27:17 +00:00
|
|
|
|
|
|
|
def build_entry_widget(self) -> QtWidgets.QWidget:
|
|
|
|
entry = FCDoubleSpinner()
|
|
|
|
entry.set_precision(self.decimals)
|
|
|
|
entry.setSingleStep(self.step)
|
|
|
|
if self.min_value is None:
|
|
|
|
self.min_value = entry.minimum()
|
|
|
|
else:
|
|
|
|
entry.setMinimum(self.min_value)
|
|
|
|
if self.max_value is None:
|
|
|
|
self.max_value = entry.maximum()
|
|
|
|
else:
|
|
|
|
entry.setMaximum(self.max_value)
|
2020-05-02 03:09:07 +00:00
|
|
|
return entry
|
|
|
|
|
|
|
|
|
2020-05-02 00:11:31 +00:00
|
|
|
class HeadingOptionUI(OptionUI):
|
2020-05-03 14:38:26 +00:00
|
|
|
def __init__(self, label_text: str, label_tooltip: Union[str, None] = None):
|
2020-05-02 00:11:31 +00:00
|
|
|
super().__init__(option="__heading")
|
|
|
|
self.label_text = label_text
|
|
|
|
self.label_tooltip = label_tooltip
|
|
|
|
|
|
|
|
def build_heading_widget(self):
|
|
|
|
heading = QtWidgets.QLabel('<b>%s</b>' % _(self.label_text))
|
|
|
|
heading.setToolTip(_(self.label_tooltip))
|
|
|
|
return heading
|
|
|
|
|
|
|
|
def add_to_grid(self, grid: QtWidgets.QGridLayout, row: int) -> int:
|
|
|
|
grid.addWidget(self.build_heading_widget(), row, 0, 1, 2)
|
|
|
|
return 1
|
|
|
|
|
|
|
|
def get_field(self):
|
|
|
|
return None
|
|
|
|
|
|
|
|
|
|
|
|
class SeparatorOptionUI(OptionUI):
|
|
|
|
|
|
|
|
def __init__(self):
|
|
|
|
super().__init__(option="__separator")
|
|
|
|
|
|
|
|
def build_separator_widget(self):
|
|
|
|
separator = QtWidgets.QFrame()
|
|
|
|
separator.setFrameShape(QtWidgets.QFrame.HLine)
|
|
|
|
separator.setFrameShadow(QtWidgets.QFrame.Sunken)
|
|
|
|
return separator
|
|
|
|
|
|
|
|
def add_to_grid(self, grid: QtWidgets.QGridLayout, row: int) -> int:
|
|
|
|
grid.addWidget(self.build_separator_widget(), row, 0, 1, 2)
|
|
|
|
return 1
|
|
|
|
|
|
|
|
def get_field(self):
|
|
|
|
return None
|
|
|
|
|
|
|
|
|
|
|
|
class FullWidthButtonOptionUI(OptionUI):
|
|
|
|
def __init__(self, option: str, label_text: str, label_tooltip: str):
|
|
|
|
super().__init__(option=option)
|
|
|
|
self.label_text = label_text
|
|
|
|
self.label_tooltip = label_tooltip
|
|
|
|
self.button_widget = self.build_button_widget()
|
|
|
|
|
|
|
|
def build_button_widget(self):
|
|
|
|
button = FCButton(_(self.label_text))
|
|
|
|
button.setToolTip(_(self.label_tooltip))
|
|
|
|
return button
|
|
|
|
|
|
|
|
def add_to_grid(self, grid: QtWidgets.QGridLayout, row: int) -> int:
|
|
|
|
grid.addWidget(self.button_widget, row, 0, 1, 3)
|
|
|
|
return 1
|
|
|
|
|
|
|
|
def get_field(self):
|
|
|
|
return self.button_widget
|