Skip to content

Commit

Permalink
Add-advanced-dialog (#124)
Browse files Browse the repository at this point in the history
- Adds the class `AdvancedDialogForm` & tests/example;
- Deprecates `getWidgetStates` to be `getSavedWidgetStates`.
  • Loading branch information
DanicaSTFC authored Mar 25, 2024
1 parent 7063e68 commit b0e70df
Show file tree
Hide file tree
Showing 7 changed files with 620 additions and 178 deletions.
18 changes: 9 additions & 9 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,13 +1,13 @@
# Version 1.0.0
- Edits 'contributing.md' and 'README.md (#131, #133).
- Adds unit test for `addWidget` and `addSpanningWidget`; - Adds `getIndexFromVerticalLayout`
to `FormDialog` (#123).
- Initialises `widget_states` in init (#132).
- Adds methods to insert widgets in the forms & tests/example
Removes `_addWidget`
Adds `getWidgetRow`and updates states dictionary and related methods
Adds `getNameAndRole*`.
Changes `num_widgets` to be a property (#109)
- Adds the class `AdvancedDialogForm` & tests/example;
deprecates `getWidgetStates` to be `getSavedWidgetStates` (#124)
- Edits 'contributing.md' and 'README.md (#131, #133)
- Adds unit test for `addWidget` and `addSpanningWidget`; adds `getIndexFromVerticalLayout`
to `FormDialog` (#123)
- Initialises `widget_states` in init (#132)
- Adds methods to insert widgets in the forms & tests/example; removes `_addWidget`;
adds `getWidgetRow`and updates states dictionary and related methods; adds
`getNameAndRole*`; changes `num_widgets` to be a property (#109)
- Reinstates changelog (#99)
- Adds `title` to `FormDockWidget` & update tests/examples (#102)
- Stops `pre-commit` committing corrections to user PRs (#112)
Expand Down
121 changes: 119 additions & 2 deletions eqt/ui/FormDialog.py
Original file line number Diff line number Diff line change
Expand Up @@ -203,7 +203,6 @@ def getNumWidgets(self):
def getWidget(self, name, role='field'):
'''
Returns the widget by the name with which it has been added.
By default it returns the widget that is the field in the form.
The user can get the label by specifying the role to be label.
Raises ValueError if the role is not field or label.
Expand Down Expand Up @@ -242,9 +241,13 @@ def saveAllWidgetStates(self):
self.formWidget.saveAllWidgetStates()

def getWidgetStates(self):
'''Returns the saved widget states.'''
'''Deprecated. Use `getSavedWidgetStates`.'''
return self.formWidget.getWidgetStates()

def getSavedWidgetStates(self):
'''Returns the saved widget states.'''
return self.formWidget.getSavedWidgetStates()

def getDefaultWidgetStates(self):
'''Returns the saved default widget states.'''
return self.formWidget.getDefaultWidgetStates()
Expand Down Expand Up @@ -325,3 +328,117 @@ def applyWidgetStates(self, states):
'widget2': {'value': 2, 'enabled': False, 'visible': False, 'widget_row': 1}}.
'''
return self.formWidget.applyWidgetStates(states)


class AdvancedFormDialog(FormDialog):
def __init__(self, parent=None, title=None, parent_button_name=None):
"""
Constructs an advanced form dialog that adds widgets on its parent.
To add widgets to the parent, call `displayWidgetValueOnParent` after creating an instance
of the class. The advanced form dialog has a default button in its vertical layout, which
is located between the form layout and the buttons 'ok' and 'cancel'. This button sets the
widgets to their default values.
Parameters
----------
parent : UIFormWidget or None, optional
The parent widget of the advanced form dialog.
If None, the dialog is created without a parent.
title : str or None, optional
The title of the advanced form dialog.
parent_button_name : str or None, optional
The name of the button opening the advanced form dialog in the parent.
If passed, the extra widgets will be added under this button in the parent,
otherwise they are added at the end.
"""
self.dialog_parent = parent
self.display_on_parent = []
if parent_button_name is None:
self.parent_button_row = -1
elif parent is None:
raise ValueError(
'The parent is None. Set the parent if you want to set the parent button name.')
else:
self.parent_button_row = self.dialog_parent.getWidgetRow(parent_button_name)

FormDialog.__init__(self, parent, title)

# add default button to vertical layout
self.default_button = QtWidgets.QPushButton("Set default values")
self.insertWidgetToVerticalLayout(1, self.default_button)
self.default_button.clicked.connect(lambda: self._setDefaultValues())

def _onOk(self):
"""
Called when the "Ok" button is clicked in the advanced dialog.
Calls the super-class method `_onOk`, sets the default widgets
to visible, and adds/updates/removes widgets from the
parent depending on the the widgets in the advanced dialog.
"""
super()._onOk()
self.formWidget.setDefaultWidgetStatesVisibleTrue()
if self.display_on_parent:
if self.getSavedWidgetStates() == self.getDefaultWidgetStates():
self._removeWidgetsFromParent()
else:
self._addOrUpdateWidgetsInParent()

def _addOrUpdateWidgetsInParent(self):
"""
Adds or updates widgets in the parent form.
This method iterates over the display_on_parent and adds the widgets to the parent
form. If a widget already exists in the parent form, it is updated with the most current
value set in the advanced dialog.
"""
for index, name in enumerate(self.display_on_parent, start=1):
widget_row = self.parent_button_row + index if self.parent_button_row != -1 else -1
value = self.getSavedWidgetStates()[f'{name}_field']['value']
qwidget = self.getWidget(name, 'field')
if isinstance(qwidget, QtWidgets.QComboBox):
value = qwidget.itemText(value)
if f'{name}_field' not in self.dialog_parent.getWidgets():
label = str(self.getSavedWidgetStates()[f'{name}_label']['value'])
self.dialog_parent.insertWidget(widget_row, name, QtWidgets.QLabel(str(value)),
label)
else:
self.dialog_parent.getWidget(name, 'field').setText(str(value))

def _removeWidgetsFromParent(self):
"""
Removes widgets from the parent form.
This method iterates over the display_on_parent and removes
the widgets from the parent.
"""
for name in self.display_on_parent:
if f'{name}_field' in self.dialog_parent.getWidgets():
self.dialog_parent.removeWidget(name)

def _setDefaultValues(self):
"""
Sets the widgets in the advanced dialog to their default states.
Makes the default widget states visible, as often the default states are saved while the
widgets are not visible. Applies the widget states to the widgets in the form.
"""
self.formWidget.setDefaultWidgetStatesVisibleTrue()
self.applyWidgetStates(self.formWidget.default_widget_states)

def displayWidgetValueOnParent(self, name):
"""
Adds `name` in a list. The order in which names are added to this
list reflects the order in which the widgets are added to the parent.
Raises an error if the parent of the advanced dialog is `None`.
Parameters
----------
name : str
The name of the widget in the advanced dialog to be displayed in the parent.
"""
if self.dialog_parent is None:
raise KeyError('''The advanced-dialog parent is None.
Set the parent if you want to add widgets to it.''')
self.display_on_parent.append(name)
14 changes: 13 additions & 1 deletion eqt/ui/UIFormWidget.py
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
from warnings import warn

from PySide2 import QtWidgets

from .UISliderWidget import UISliderWidget
Expand Down Expand Up @@ -465,6 +467,12 @@ def saveAllWidgetStates(self):
self.widget_states = self.getAllWidgetStates()

def getWidgetStates(self):
'''Deprecated. Use `getSavedWidgetStates`.'''
warn('The method `getWidgetStates` is deprecated, use `getSavedWidgetStates`.',
DeprecationWarning, stacklevel=2)
return self.getSavedWidgetStates()

def getSavedWidgetStates(self):
'''Returns the saved widget states.'''
return self.widget_states

Expand Down Expand Up @@ -623,9 +631,13 @@ def saveAllWidgetStates(self):
self.widget().saveAllWidgetStates()

def getWidgetStates(self):
'''Returns the saved widget states.'''
'''Deprecated. Use `getSavedWidgetStates`.'''
return self.widget().getWidgetStates()

def getSavedWidgetStates(self):
'''Returns the saved widget states.'''
return self.widget().getSavedWidgetStates()

def getDefaultWidgetStates(self):
'''Returns the saved default widget states.'''
return self.widget().getDefaultWidgetStates()
Expand Down
35 changes: 35 additions & 0 deletions examples/advanced_dialog_example.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
import sys

import utilitiesForExamples
from PySide2 import QtWidgets

from eqt.ui.FormDialog import AdvancedFormDialog
from eqt.ui.UIFormWidget import FormWidget


def run_example():
parent = FormWidget(parent=None)
# open advanced dialog button
pb = QtWidgets.QPushButton(parent)
pb.setText("Open Advanced Dialog")
pb.clicked.connect(lambda: advanced_dialog.exec())
parent.addSpanningWidget(pb, 'button_advanced')
# extra button
extra_button = QtWidgets.QPushButton(parent)
extra_button.setText("Extra button")
parent.addSpanningWidget(extra_button, 'extra_button')
# create dialog
advanced_dialog = AdvancedFormDialog(parent=parent, title='Example',
parent_button_name='button_advanced')
# all widgets
utilitiesForExamples.addWidgetsToExample(advanced_dialog)
for name in utilitiesForExamples.list_all_widgets():
advanced_dialog.displayWidgetValueOnParent(name)
# show
parent.show()


if __name__ == "__main__":
app = QtWidgets.QApplication(sys.argv)
run_example()
sys.exit(app.exec_())
19 changes: 17 additions & 2 deletions examples/utilitiesForExamples.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,20 @@
from eqt.ui.UISliderWidget import UISliderWidget


def list_all_widgets():
list_all_widgets = {
'label': QtWidgets.QLabel('test label'), 'checkBox': QtWidgets.QCheckBox('test checkbox'),
'comboBox': QtWidgets.QComboBox(), 'doubleSpinBox': QtWidgets.QDoubleSpinBox(),
'spinBox': QtWidgets.QSpinBox(), 'slider': QtWidgets.QSlider(),
'uiSliderWidget': UISliderWidget(QtWidgets.QLabel()),
'radioButton': QtWidgets.QRadioButton('test radio button'),
'textEdit': QtWidgets.QTextEdit('test text edit'),
'plainTextEdit': QtWidgets.QPlainTextEdit('test plain text edit'),
'lineEdit': QtWidgets.QLineEdit('test line edit'),
'button': QtWidgets.QPushButton('test push button')}
return list_all_widgets


def addWidgetsToExample(form):
'''
Adds a spanning widget and every type of widget to a form
Expand All @@ -12,9 +26,10 @@ def addWidgetsToExample(form):
# add all widgets
form.addWidget(QtWidgets.QLabel('Label'), 'Label: ', 'label')
form.addWidget(QtWidgets.QCheckBox('check me'), 'CheckBox: ', 'checkBox')
qwidget = QtWidgets.QComboBox()
combobox_list = ['choice 1', 'choice 2']
form.addWidget(QtWidgets.QComboBox(), 'ComboBox: ', 'comboBox')
form.getWidget('comboBox').addItems(combobox_list)
qwidget.addItems(combobox_list)
form.addWidget(qwidget, 'ComboBox: ', 'comboBox')
form.addWidget(QtWidgets.QDoubleSpinBox(), 'DoubleSpinBox: ', 'doubleSpinBox')
form.addWidget(QtWidgets.QSpinBox(), 'SpinBox: ', 'spinBox')
form.addWidget(QtWidgets.QSlider(), 'Slider: ', 'slider')
Expand Down
4 changes: 3 additions & 1 deletion test/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,9 @@

from eqt.ui import FormDialog

if any(os.getenv(var, '0').lower() in ('1', 'true') for var in ('CONDA_BUILD', 'CI')):
is_ci = any(os.getenv(var, '0').lower() in ('1', 'true') for var in ('CONDA_BUILD', 'CI'))

if is_ci:

def skip_ci(_):
def inner(*_, **__):
Expand Down
Loading

0 comments on commit b0e70df

Please sign in to comment.