def generate_panel(self, formset): """ Generate a panel for the module form with all the controls formset format example: [('_video', '_arenas', '_run'), {"Player":['_threshold', "_player", "=", "_results", "_query"], "Background image":[(' ', '_selectBackground', '_paintBackground'), '_image']}, "_progress"] tuple: will display the controls in the same horizontal line list: will display the controls in the same vertical line dict: will display the controls in a tab widget '||': will plit the controls in a horizontal line '=': will plit the controls in a vertical line @param formset: Form configuration @type formset: list """ control = None if '=' in formset or isinstance(formset, hsplitter): control = QSplitter(QtCore.Qt.Vertical) index = list(formset).index('=') first_panel = self.generate_panel(formset[0:index]) second_panel = self.generate_panel(formset[index + 1:]) control.addWidget(first_panel) control.addWidget(second_panel) self._splitters.append(control) return control elif '||' in formset or isinstance(formset, vsplitter): control = QSplitter(QtCore.Qt.Horizontal) index = list(formset).index('||') first_panel = self.generate_panel(formset[0:index]) second_panel = self.generate_panel(formset[index + 1:]) control.addWidget(first_panel) control.addWidget(second_panel) if isinstance(formset, vsplitter): sizes = [formset.left_width, formset.right_width] control.setSizes(sizes) self._splitters.append(control) return control control = QFrame(self) layout = None if type(formset) is tuple: layout = QHBoxLayout() for row in formset: if isinstance(row, (list, tuple, vsplitter, hsplitter)): panel = self.generate_panel(row) layout.addWidget(panel) elif row == " ": spacer = QSpacerItem(40, 20, QSizePolicy.Expanding, QSizePolicy.Minimum) layout.addItem(spacer) elif type(row) is dict: c = self.generate_tabs(row) layout.addWidget(c) self._tabs.append(c) else: param = self.controls.get(row, None) if param is None: label = QLabel() label.setSizePolicy(QSizePolicy.Maximum, QSizePolicy.Maximum) # layout.addWidget( label ) if row.startswith('info:'): label.setText(row[5:]) font = QFont() font.setPointSize(10) label.setFont(font) label.setAccessibleName('info') elif row.startswith('h1:'): label.setText(row[3:]) font = QFont() font.setPointSize(17) font.setBold(True) label.setFont(font) label.setAccessibleName('h1') elif row.startswith('h2:'): label.setText(row[3:]) font = QFont() font.setPointSize(16) font.setBold(True) label.setFont(font) label.setAccessibleName('h2') elif row.startswith('h3:'): label.setText(row[3:]) font = QFont() font.setPointSize(15) font.setBold(True) label.setFont(font) label.setAccessibleName('h3') elif row.startswith('h4:'): label.setText(row[3:]) font = QFont() font.setPointSize(14) font.setBold(True) label.setFont(font) label.setAccessibleName('h4') elif row.startswith('h5:'): label.setText(row[3:]) font = QFont() font.setPointSize(12) font.setBold(True) label.setFont(font) label.setAccessibleName('h5') else: label.setText(row) font = QFont() font.setPointSize(10) label.setFont(font) label.setAccessibleName('msg') label.setToolTip(label.text()) layout.addWidget(label) else: param.parent = self param.name = row layout.addWidget(param.form) elif type(formset) is list: layout = QVBoxLayout() for row in formset: if isinstance(row, (list, tuple, vsplitter, hsplitter)): panel = self.generate_panel(row) layout.addWidget(panel) elif row == " ": spacer = QSpacerItem(20, 40, QSizePolicy.Minimum, QSizePolicy.Expanding) layout.addItem(spacer) elif type(row) is dict: c = self.generate_tabs(row) layout.addWidget(c) self._tabs.append(c) else: param = self.controls.get(row, None) if param is None: label = QLabel() label.setSizePolicy(QSizePolicy.Maximum, QSizePolicy.Maximum) label.resize(30, 30) # layout.addWidget( label ) if row.startswith('info:'): label.setText(row[5:]) font = QFont() font.setPointSize(10) label.setFont(font) label.setAccessibleName('info') elif row.startswith('h1:'): label.setText(row[3:]) font = QFont() font.setPointSize(17) font.setBold(True) label.setFont(font) label.setAccessibleName('h1') elif row.startswith('h2:'): label.setText(row[3:]) font = QFont() font.setPointSize(16) font.setBold(True) label.setFont(font) label.setAccessibleName('h2') elif row.startswith('h3:'): label.setText(row[3:]) font = QFont() font.setPointSize(15) font.setBold(True) label.setFont(font) label.setAccessibleName('h3') elif row.startswith('h4:'): label.setText(row[3:]) font = QFont() font.setPointSize(14) font.setBold(True) label.setFont(font) label.setAccessibleName('h4') elif row.startswith('h5:'): label.setText(row[3:]) font = QFont() font.setPointSize(12) font.setBold(True) label.setFont(font) label.setAccessibleName('h5') else: label.setText(row) font = QFont() font.setPointSize(10) label.setFont(font) label.setAccessibleName('msg') label.setToolTip(label.text()) layout.addWidget(label) else: param.parent = self param.name = row layout.addWidget(param.form) if _api.USED_API == _api.QT_API_PYQT5: layout.setContentsMargins(0, 0, 0, 0) elif _api.USED_API == _api.QT_API_PYQT4: layout.setMargin(0) control.setLayout(layout) return control
class ControlBoundingSlider(ControlBase): """ .. image:: https://raw.githubusercontent.com/UmSenhorQualquer/pyforms/master/tutorials/Controls4Docs/ControlBoundingSlider.png """ def __init__(self, *args, **kwargs): """ :param tupple default: The default value is a list containing in the first element the lower value and in the second element the upper value. Default = [20,40]. :param bool horizontal: Flag indicating if the Bounding slider should be draw horizontally or vertically. Default = True. :param bool show_spinboxes: Show or hide the spinboxes. Default = True :param float minimum: Defines the minimum value that can be selected. :param float maximum: Defines the maximum value that can be selected. :param bool convert_2_int: Flag to define if the control should return floats or integers. """ self._horizontal = kwargs.get('horizontal', True) self._show_spinboxes = kwargs.get('show_spinboxes', True) ControlBase.__init__(self, *args, **kwargs) self.min = kwargs.get('min', kwargs.get('minimum', 0)) self.max = kwargs.get('max', kwargs.get('maximum', 100)) self.value = kwargs.get('default', [10,20]) self.convert_2_int = kwargs.get('convert_2_int', False) self.__update() def init_form(self): self._boundingbox = GaugeWidgetHorizontal() if self._horizontal else GaugeWidgetVertical() self._boundingbox.changed_event = self.__update if self._show_spinboxes: self._form = hwidget = QWidget() if self._horizontal: hlayout = QHBoxLayout() else: hlayout = QVBoxLayout() if _api.USED_API == _api.QT_API_PYQT5: hlayout.setContentsMargins(0,0,0,0) elif _api.USED_API == _api.QT_API_PYQT4: hlayout.setMargin(0) if self._label is not None: self._controllabel = QLabel(self.form) hlayout.addWidget(self._controllabel) self._controllabel.setAccessibleName('ControlBoundingSlider-label') self.label = self._label else: self._controllabel = None hwidget.setLayout(hlayout) self._min_spinbox = QSpinBox() self._min_spinbox.valueChanged.connect(self.__min_spinbox_changed) self._min_spinbox.setMaximumWidth(95) self._max_spinbox = QSpinBox() self._max_spinbox.valueChanged.connect(self.__max_spinbox_changed) self._max_spinbox.setMaximumWidth(95) if self._horizontal: hlayout.addWidget(self._min_spinbox) else: hlayout.addWidget(self._max_spinbox) hlayout.addWidget(self._boundingbox) if self._horizontal: hlayout.addWidget(self._max_spinbox) else: hlayout.addWidget(self._min_spinbox) else: self._form = self._boundingbox super(ControlBoundingSlider, self).init_form() def __max_spinbox_changed(self, value): if value < self._boundingbox._minVal: return if hasattr(self, '_is_updating_spinboxes'): return self.scale = self.__find_scale_factor(value) self._boundingbox._maxVal = value self._boundingbox.repaint() self.changed_event() def __min_spinbox_changed(self, value): if value > self._boundingbox._maxVal: return if hasattr(self, '_is_updating_spinboxes'): return self.scale = self.__find_scale_factor(value) self._boundingbox._minVal = value self._boundingbox.repaint() self.changed_event() def __update(self): l, h = self._boundingbox._minVal, self._boundingbox._maxVal self._is_updating_spinboxes = True if self._show_spinboxes: self._min_spinbox.setValue(l) self._max_spinbox.setValue(h) del self._is_updating_spinboxes self.changed_event() def changed_event(self): pass def __find_scale_factor(self, value): scale = 1.0 new_value = value while abs(new_value) < 0.0: scale *= 10.0 new_value = value * scale return scale def load_form(self, data, path=None): """ Load a value from the dict variable @param data: dictionary with the value of the Control """ self.convert_2_int = data.get('convert-int', self.convert_2_int) self.scale = data.get('scale', self.scale) self.max = data.get('max', self.max) self.min = data.get('min', self.min) self.value = data.get('value', self.value) def save_form(self, data, path=None): """ Save a value to dict variable @param data: dictionary with to where the value of the Control will be added """ data['value'] = self.value data['max'] = self.max data['min'] = self.min data['scale'] = self.scale data['convert-int'] = self.convert_2_int return data ########################################################################## ############ Properties ################################################## ########################################################################## @property def label(self): return self._controllabel.getText() @label.setter def label(self, value): self._controllabel.setText(value) @property def value(self): """ Sets and gets the control value. It should be a list or tuple of 2 values. """ return self._boundingbox._minVal, self._boundingbox._maxVal @value.setter def value(self, value): self.scale = self.__find_scale_factor(value[0]) self._boundingbox._minVal, self._boundingbox._maxVal = value[0], value[1] if hasattr(self, '_min_spinbox'): self._min_spinbox.setValue(value[0]) if hasattr(self, '_max_spinbox'): self._max_spinbox.setValue(value[1]) ControlBase.value.fset(self, value) self._boundingbox.repaint() @property def min(self): """ Sets and gets the minimum value possible. """ return self._boundingbox._lower @min.setter def min(self, value): self._boundingbox._lower = value self._boundingbox.repaint() if hasattr(self, '_min_spinbox'): self._min_spinbox.setMinimum(value) if hasattr(self, '_max_spinbox'): self._max_spinbox.setMinimum(value) @property def max(self): """ Sets and gets the maximum value possible. """ return self._boundingbox._higher @max.setter def max(self, value): self._boundingbox._higher = value self._boundingbox.repaint() if hasattr(self, '_min_spinbox'): self._min_spinbox.setMaximum(value) if hasattr(self, '_max_spinbox'): self._max_spinbox.setMaximum(value) @property def scale(self): """ Sets and gets the scale value. """ return self._boundingbox.scale @scale.setter def scale(self, value): self._boundingbox.scale = value @property def convert_2_int(self): """ Flag to define if the control should return floats or integers. """ return not self._boundingbox._use_float @convert_2_int.setter def convert_2_int(self, value): self._boundingbox._use_float = not value
class ControlCombo(ControlBase, QWidget): """This class represents a wrapper to the combo box""" def __init__(self, label='', default=None, helptext=None): QWidget.__init__(self) ControlBase.__init__(self, label, default, helptext) ########################################################################## ############ Functions ################################################### ########################################################################## def init_form(self): self._layout = QHBoxLayout() self._combo = QComboBox(self.form) if self._label is not None: self._combolabel = QLabel(self.form) self._layout.addWidget(self._combolabel) self._combolabel.setAccessibleName('ControlCombo-label') self.label = self._label else: self._combolabel = None self._layout.addWidget(self._combo) self.form.setLayout(self._layout) self._combo.setSizePolicy(QSizePolicy.Expanding, QSizePolicy.Fixed) self._layout.setContentsMargins(0, 0, 0, 0) self.form.setContentsMargins(0, 0, 0, 0) self.form.setMinimumHeight(38) self.form.setMaximumHeight(38) self.form.setSizePolicy(QSizePolicy.Preferred, QSizePolicy.Fixed) self._combo.currentIndexChanged.connect(self._currentIndexChanged) self._combo.activated.connect(self._activated) self._combo.highlighted.connect(self._highlighted) self._combo.editTextChanged.connect(self._editTextChanged) self._items = {} self._addingItem = False def clear(self): self._items = {} self._value = None self._combo.clear() def add_item(self, label, value=None): self._addingItem = True if value is not None: if not (value in self._items.values()): self._combo.addItem(label) else: if not (label in self._items.keys()): self._combo.addItem(label) firstValue = False if self._items == {}: firstValue = True if value is None: self._items[str(label)] = label else: self._items[str(label)] = value self._addingItem = False if firstValue: self.value = self._items[label] def __add__(self, val): if isinstance(val, tuple): self.add_item(val[0], val[1]) else: self.add_item(val) return self def get_item_index_by_name(self, item_name): """ Returns the index of the item containing the given name :param item_name: item name in combo box :type item_name: string """ return self._combo.findText(item_name) def count(self): return self._combo.count() def show(self): """ Show the control """ QWidget.show(self) def hide(self): """ Hide the control """ QWidget.hide(self) ########################################################################## ############ Events ###################################################### ########################################################################## def current_index_changed_event(self, index): """Called when the user chooses an item in the combobox and the selected choice is different from the last one selected. @index: item's index """ pass def activated_event(self, index): """Called when the user chooses an item in the combobox. Note that this signal happens even when the choice is not changed @index: item's index """ pass def highlighted_event(self, index): pass def edittext_changed_event(self, text): pass ########################################################################## ############ PROPERTIES ################################################## ########################################################################## @property def form(self): return self @property def current_index(self): return self._combo.currentIndex() @current_index.setter def current_index(self, value): self._combo.setCurrentIndex(value) @property def items(self): return self._items.items() @property def value(self): return self._value @value.setter def value(self, value): for key, val in self.items: if value == val: index = self._combo.findText(key) self._combo.setCurrentIndex(index) if self._value != value: self.changed_event() self._value = val @property def text(self): return str(self._combo.currentText()) @text.setter def text(self, value): for key, val in self.items: if value == key: self.value = val break @property def label(self): if self._combolabel: return self._combolabel.text() else: return None @label.setter def label(self, value): """ Label of the control, if applies @type value: string """ if self._combolabel: self._combolabel.setText(value) ########################################################################## ############ Private functions ########################################### ########################################################################## def _activated(self, index): if not self._addingItem: item = self._combo.currentText() if len(item) >= 1: ControlBase.value.fset(self, self._items[str(item)]) self.activated_event(index) def _highlighted(self, index): """Called when an item in the combobox popup list is highlighted by the user. @index: item's index """ self.highlighted_event(index) def _editTextChanged(self, text): self.edittext_changed_event(text) def _currentIndexChanged(self, index): if not self._addingItem: item = self._combo.currentText() if len(item) >= 1: ControlBase.value.fset(self, self._items[str(item)]) self.current_index_changed_event(index)
def _handle_text(self, layout, row): param = self.controls.get(row, None) if param is None: label = QLabel() label.setOpenExternalLinks(True) label.setSizePolicy(QSizePolicy.Maximum, QSizePolicy.Maximum) if row.startswith('info:'): label.setText(row[5:]) font = QFont() font.setPointSize(10) label.setFont(font) label.setAccessibleName('info') elif row.startswith('h1:'): label.setText(row[3:]) font = QFont() font.setPointSize(17) font.setBold(True) label.setFont(font) label.setAccessibleName('h1') elif row.startswith('h2:'): label.setText(row[3:]) font = QFont() font.setPointSize(16) font.setBold(True) label.setFont(font) label.setAccessibleName('h2') elif row.startswith('h3:'): label.setText(row[3:]) font = QFont() font.setPointSize(15) font.setBold(True) label.setFont(font) label.setAccessibleName('h3') elif row.startswith('h4:'): label.setText(row[3:]) font = QFont() font.setPointSize(14) font.setBold(True) label.setFont(font) label.setAccessibleName('h4') elif row.startswith('h5:'): label.setText(row[3:]) font = QFont() font.setPointSize(12) font.setBold(True) label.setFont(font) label.setAccessibleName('h5') else: label.setText(row) label.setAccessibleName('msg') label.setToolTip(label.text()) layout.addWidget(label) else: param.parent = self param.name = row layout.addWidget(param.form)