Skip to content

Commit

Permalink
Add more docstrings and stule changes
Browse files Browse the repository at this point in the history
  • Loading branch information
DanicaSTFC committed Feb 15, 2024
1 parent 595c960 commit 8e806c8
Show file tree
Hide file tree
Showing 3 changed files with 144 additions and 65 deletions.
111 changes: 66 additions & 45 deletions eqt/ui/FormDialog.py
Original file line number Diff line number Diff line change
Expand Up @@ -325,23 +325,35 @@ def applyWidgetStates(self, states):


class AdvancedFormDialog(FormDialog):
def __init__(self, parent=None, title=None, button_name=None):
"""Creates a form dialog. Adds a default button to the vertical layout,
located between the form layout and the buttons `ok` and `cancel`, and connects it.
def __init__(self, parent=None, title=None, parent_button_name=None):
"""
Constructs an advanced form dialog that adds widgets in its parent.
Creates a form dialog and adds a default button to the vertical layout.
The default button is located between the form layout and the buttons 'ok' and 'cancel'.
The default button is connected to the 'setDefaultValues' method.
Parameters
--------------------
parent : qwidget or None
The parent widget of the advanced form dialog
title : str or None
----------
parent : QWidget 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.
button_name : str or None
the name of the button opening the advanced form dialog in the parent"""
if parent is not None:
self.dialog_parent = parent
self.display_on_parent_dict = {}
if button_name is not None:
self.button_widget_row = self.dialog_parent.getWidgetRow(button_name)
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_dict = {}
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
Expand All @@ -351,33 +363,33 @@ def __init__(self, parent=None, title=None, button_name=None):

def _onOk(self):
"""
Called when the dialog's "Ok" button is clicked.
It is redifined from Form Dialog.
When the ok button in the advanced configuration dialog is clicked,
the selected parameters are visualised in the parent only
if they are not the default values.
Saves the widget states and calls `onOk`
Called when the "Ok" button is clicked in the advanced dialog.
It saves the widget states, calls `onOk`, sets the default widgets
to visible and closes the dialog. Adds or updates or removes widgets from the
parent based on the values of the widgets in the advanced dialog.
"""
self.saveAllWidgetStates()
self.onOk()
self.formWidget.setDefaultWidgetStatesVisibleTrue()
self.close()

if hasattr(self, 'display_on_parent_dict'):
if self.display_on_parent_dict:
if self.getWidgetStates() == self.getDefaultWidgetStates():
self._removeWidgetsFromParent()
else:
self._addWidgetsToParent()

def _addWidgetsToParent(self):
i = 0
for name in self.display_on_parent_dict.keys():
i += 1
if hasattr(self, 'button_widget_row'):
widget_row = self.button_widget_row + i
else:
widget_row = -1
self._addOrUpdateWidgetsInParent()

def _addOrUpdateWidgetsInParent(self):
"""
Adds or updates widgets in the parent form.
This method iterates over the display_on_parent_dict 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_dict, start=1):
widget_row = self.parent_button_row + index if self.parent_button_row != -1 else -1
value = str(self.getWidgetStates()[f'{name}_field']['value'])
if f'{name}_field' not in self.dialog_parent.getWidgets():
label = str(self.getWidgetStates()[f'{name}_label']['value'])
Expand All @@ -386,29 +398,38 @@ def _addWidgetsToParent(self):
self.dialog_parent.getWidget(name, 'field').setText(value)

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

def add_tooltip(self, name, value):
advanced_default_tooltip_text = f'Default values are `{name}` = {value}.'
self.getWidget('Advanced_default').setToolTip(advanced_default_tooltip_text)

def setDefaultValues(self):
"""
Sets the widgets in the advanced dialog to their default states.
Makes the default widget states visible and applies the widget states
to the widgets in the form.
"""
self.formWidget.setDefaultWidgetStatesVisibleTrue()
self.applyWidgetStates(self.formWidget.default_widget_states)

def addToDictionaryDisplayOnParent(self, name):
"""
Raises an error if the parent is None.
Otherwise, adds they name in the dictionary with value 'None'.
The dictionary is used to preserve the ordering of the widgets
between the dialog and the parent.
Adds `name` in a dictionary. The order in which names are added to this
dictionary 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 not hasattr(self, 'dialog_parent'):
raise KeyError('''The advanced-dialog-form parent is None.
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_dict[name] = None

def getDisplayOnParentDictionary(self):
return self.display_on_parent_dict
6 changes: 3 additions & 3 deletions examples/advanced_dialog_example.py
Original file line number Diff line number Diff line change
Expand Up @@ -11,14 +11,14 @@ def __init__(self, parent=None):
FormWidget.__init__(self, parent)

pb = QtWidgets.QPushButton(self)
pb.setText("Open Advanced Dialog with form layout")
pb.setText("Open Advanced Dialog")
pb.clicked.connect(lambda: self.openFormDialog())
self.addSpanningWidget(pb, 'buttadv')
pb2 = QtWidgets.QPushButton(self)
pb2.setText("b2")
self.addSpanningWidget(pb2, 'buttadv2')
# dialog = AdvancedFormDialog(parent=self, title='Example')
dialog = AdvancedFormDialog(parent=self, title='Example', button_name='buttadv')
dialog = AdvancedFormDialog(parent=self, title='Example', parent_button_name='buttadv')


dialog.Ok.clicked.connect(lambda: self.accepted())
# Example on how to add elements to the FormDialog
Expand Down
92 changes: 75 additions & 17 deletions test/test__formUI_status_test.py
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,10 @@ class FormsCommonTests(metaclass=abc.ABCMeta):
"""Common tests for all Form types"""
@abc.abstractmethod
def setUp(self):
"""
Set up the test environment by initialising the necessary objects and widgets.
This method is executed before each test case.
"""
self.form = None # stop mypy [attr-defined] error
raise NotImplementedError

Expand Down Expand Up @@ -441,6 +445,10 @@ def test_getAllWidgetStates(self):
@skip_ci
class FormDialogStatusTest(FormsCommonTests, unittest.TestCase):
def setUp(self):
"""
Set up the test environment by initialising the necessary objects and widgets.
This method is executed before each test case.
"""
self.form = FormDialog()
self.add_every_widget()
self.add_every_spanning_widget()
Expand All @@ -450,9 +458,19 @@ def setUp(self):
self.vertical_layout = self.form.formWidget.uiElements['verticalLayout']

def click_Ok(self):
"""
Clicks the ok button on the form.
This method simulates a mouse click on the ok button in the form.
"""
QTest.mouseClick(self.form.Ok, Qt.LeftButton)

def click_Cancel(self):
"""
Clicks the cancel button on the form.
This method simulates a mouse click on the cancel button in the form.
"""
QTest.mouseClick(self.form.Cancel, Qt.LeftButton)

def add_every_widget_to_vertical_layout(self):
Expand Down Expand Up @@ -591,6 +609,10 @@ def test_restoreAllSavedWidgetStates(self):
@skip_ci
class FormWidgetStateTest(FormsCommonTests, unittest.TestCase):
def setUp(self):
"""
Set up the test environment by initialising the necessary objects and widgets.
This method is executed before each test case.
"""
self.form = FormWidget()
self.add_every_widget()
self.add_every_spanning_widget()
Expand Down Expand Up @@ -674,6 +696,10 @@ def test_restoreAllSavedWidgetStates(self):
@skip_ci
class FormDockWidgetStateTest(FormsCommonTests, unittest.TestCase):
def setUp(self):
"""
Set up the test environment by initialising the necessary objects and widgets.
This method is executed before each test case.
"""
self.form = FormDockWidget()
self.add_every_widget()
self.add_every_spanning_widget()
Expand Down Expand Up @@ -747,22 +773,34 @@ def test_restoreAllSavedWidgetStates(self):
@skip_ci
class AdvancedFormDialogStatusTest(FormDialogStatusTest):
def setUp(self):
"""
Set up the test environment by initialising the necessary objects and widgets.
This method is executed before each test case.
"""
self.form_parent = FormWidget()
self.form_parent.addSpanningWidget(QtWidgets.QPushButton("Open Advanced Dialog"),
'butt_adv')
self.form = AdvancedFormDialog(parent=self.form_parent, title='Advanced form dialog',
button_name='butt_adv')

self.form_without_parent = AdvancedFormDialog()
parent_button_name='butt_adv')

self.layout = self.form.formWidget.uiElements['groupBoxFormLayout']
self.vertical_layout = self.form.formWidget.uiElements['verticalLayout']
self.add_every_widget()
for key in self.list_all_widgets.keys():
for key in self.list_all_widgets:
self.form.addToDictionaryDisplayOnParent(key)

self.form_without_parent = AdvancedFormDialog()

self.simple_form = AdvancedFormDialog()
self.add_two_widgets()
self.layout = self.form.formWidget.uiElements['groupBoxFormLayout']
self.vertical_layout = self.form.formWidget.uiElements['verticalLayout']


def click_default_button(self):
"""
Clicks the default button on the form.
This method simulates a mouse click on the default button of the form.
"""
QTest.mouseClick(self.form.default_button, Qt.LeftButton)

def test_position_default_button(self):
Expand All @@ -776,6 +814,14 @@ def test_position_default_button(self):
self.assertEqual(index, 1)

def test_dialog_ok_button_behaviour(self):
"""
Test the behavior of the Ok button on the advanced dialog.
This test case verifies the button's behavior in different scenarios:
1. Click the Ok button without changing any states and verify that the parent widget states remain unchanged.
2. Change the states and click the OK button, then verify that the parent widget states are updated correctly.
3. Click the default button and then the OK button, and verify that the parent widget states are restored to their initial values.
"""
# click ok first
parent_initial_states = self.form_parent.getAllWidgetStates()
self.form.open()
Expand All @@ -788,10 +834,10 @@ def test_dialog_ok_button_behaviour(self):
self.form.open()
self.click_Ok()
parent_states = self.form_parent.getAllWidgetStates()
for key in self.list_all_widgets:
self.assertEqual(parent_states[f'{key}_field']['value'],
str(self.exampleState[i][f'{key}_value']))
self.assertEqual(parent_states[f'{key}_label']['value'], key)
for name in self.list_all_widgets:
self.assertEqual(parent_states[f'{name}_field']['value'],
str(self.exampleState[i][f'{name}_value']))
self.assertEqual(parent_states[f'{name}_label']['value'], name)
# click default and then ok
self.form.open()
self.click_default_button()
Expand All @@ -800,30 +846,42 @@ def test_dialog_ok_button_behaviour(self):
self.assertEqual(parent_states, parent_initial_states)

def test_dialog_cancel_button_behaviour(self):
"""
Test the behavior of the Cancel button on the advanced dialog.
This test case verifies the button's behavior in different scenarios:
1. Open the dialog, click the Cancel button without changing any states and verify that the
parent-widget states remain unchanged.
2. Open the dialog, update the widgets and click the Cancel button. Verify that the parent-widget states remain unchanged.
3. Open the dialog, update the widgets and click the Ok button. Then reopen the dialog, change the states and click the Cancel button.
Verify that the parent widget states are those set before reopening the dialog.
4. Open the dialog, click the default button and then the Cancel button. Verify that the parent widget
states remain unchanged.
"""
# click cancel first
parent_initial_states = self.form_parent.getAllWidgetStates()
self.form.open()
self.click_Cancel()
parent_states = self.form_parent.getAllWidgetStates()
self.assertEqual(parent_states, parent_initial_states)
# change states and click Cancel
self.set_state(0)
self.form.open()
self.set_state(0)
self.click_Cancel()
parent_states = self.form_parent.getAllWidgetStates()
self.assertEqual(parent_states, parent_initial_states)
# change states and click Ok then chance states and click cancel
self.set_state(0)
self.form.open()
self.set_state(0)
self.click_Ok()
self.set_state(1)
self.form.open()
self.set_state(1)
self.click_Cancel()
parent_states = self.form_parent.getAllWidgetStates()
for key in self.list_all_widgets.keys():
self.assertEqual(parent_states[f'{key}_field']['value'],
str(self.exampleState[0][f'{key}_value']))
self.assertEqual(parent_states[f'{key}_label']['value'], key)
for name in self.list_all_widgets:
self.assertEqual(parent_states[f'{name}_field']['value'],
str(self.exampleState[0][f'{name}_value']))
self.assertEqual(parent_states[f'{name}_label']['value'], name)
# click default and then Cancel
self.form.open()
self.click_default_button()
Expand Down

0 comments on commit 8e806c8

Please sign in to comment.