From 906dd7697baedee61f9cc7bc6971a53eb49945c7 Mon Sep 17 00:00:00 2001 From: Danica Sugic Date: Thu, 19 Oct 2023 16:43:27 +0100 Subject: [PATCH 01/96] Add functionality of default saving in a new example --- eqt/ui/FormDialog.py | 15 +++- examples/dialog_example_3_save_default.py | 86 +++++++++++++++++++++++ 2 files changed, 100 insertions(+), 1 deletion(-) create mode 100644 examples/dialog_example_3_save_default.py diff --git a/eqt/ui/FormDialog.py b/eqt/ui/FormDialog.py index 510ff59..a77beba 100644 --- a/eqt/ui/FormDialog.py +++ b/eqt/ui/FormDialog.py @@ -23,8 +23,11 @@ def __init__(self, parent=None, title=None): self.setWindowTitle(title) # add button box to the UI self.formWidget.uiElements['verticalLayout'].addWidget(bb) + bb.button(QtWidgets.QDialogButtonBox.Ok).clicked.connect(self._onOk) bb.button(QtWidgets.QDialogButtonBox.Cancel).clicked.connect(self._onCancel) + + @property def Ok(self): '''returns a reference to the Dialog Ok button to connect its signals''' @@ -35,11 +38,21 @@ def Cancel(self): '''returns a reference to the Dialog Cancel button to connect its signals''' return self.buttonBox.button(QtWidgets.QDialogButtonBox.Cancel) + def _onOk(self): + '''calls `onOk`''' + print("I am _onOk") + self.onOk() + def _onCancel(self): - '''calls onCancel and closes the FormDialog''' + '''calls onCancel and closes the FormDialog''' self.onCancel() self.close() + def onOk(self): + '''Called when the dialog's "Ok" button is clicked. + Can be redefined to add additional functionality on "Ok"''' + pass + def onCancel(self): '''Called when the dialog's "Cancel" button is clicked. Can be redefined to add additional functionality on "Cancel"''' diff --git a/examples/dialog_example_3_save_default.py b/examples/dialog_example_3_save_default.py new file mode 100644 index 0000000..da48f30 --- /dev/null +++ b/examples/dialog_example_3_save_default.py @@ -0,0 +1,86 @@ +import sys + +from PySide2 import QtWidgets + +from eqt.ui import FormDialog + + +class MainUI(QtWidgets.QMainWindow): + def __init__(self, parent=None): + QtWidgets.QMainWindow.__init__(self, parent) + + pb = QtWidgets.QPushButton(self) + pb.setText("Open Dialog with form layout") + + pb.clicked.connect(lambda: self.executedialog()) + + layout = QtWidgets.QHBoxLayout() + layout.addWidget(pb) + widg = QtWidgets.QWidget() + widg.setLayout(layout) + + self.setCentralWidget(widg) + self.dialog = FormDialog(parent=self, title='Example') + + self.openFormDialog() + self.show() + + def openFormDialog(self): + # Example on how to add elements to the FormDialog + # add input 1 as QLineEdit + qlabel = QtWidgets.QLabel(self.dialog.groupBox) + qlabel.setText("Input 1: ") + qwidget = QtWidgets.QLineEdit(self.dialog.groupBox) + qwidget.setClearButtonEnabled(True) + # finally add to the form widget + self.dialog.addSpanningWidget(QtWidgets.QLabel("Input Values: "), 'input_title') + self.dialog.addWidget(qwidget, qlabel, 'input1') + + # add input 2 as QComboBox + qlabel = QtWidgets.QLabel(self.dialog.groupBox) + qlabel.setText("Input 2: ") + qwidget = QtWidgets.QComboBox(self.dialog.groupBox) + qwidget.addItem("option 1") + qwidget.addItem("option 2") + qwidget.setCurrentIndex(0) + qwidget.setEnabled(True) + # finally add to the form widget + self.dialog.addWidget(qwidget, qlabel, 'input2') + self.dialog.addWidget(QtWidgets.QLabel("Example Vertical Layout Text"), layout="vertical") + + # Example of using 'getWidget': + self.dialog.getWidget('input2').setCurrentIndex(1) + + # store a reference + #self.dialog = dialog + self.dialog.onOk = self.accepted + self.dialog.onCancel = self.rejected + + #self.dialog.restoreAllSavedWidgetStates() + if hasattr(self.dialog, 'widget_states'): + print("There are states") + print(self.dialog.widget_states) + + def executedialog(self): + self.dialog.restoreAllSavedWidgetStates() + self.dialog.exec() + + def accepted(self): + self.dialog.widget_states = self.dialog.saveAllWidgetStates() + print("accepted") + print(self.dialog.widgets['input1_field'].text()) + print(self.dialog.widgets['input2_field'].currentText()) + #print(self.widget_states) + print(self.dialog.widget_states) + self.dialog.close() + + def rejected(self): + print("rejected") + + +if __name__ == "__main__": + app = QtWidgets.QApplication(sys.argv) + + window = MainUI() + + sys.exit(app.exec_()) From c143250c26a82f4e688c218289d401e8d305414f Mon Sep 17 00:00:00 2001 From: Danica Sugic Date: Fri, 20 Oct 2023 12:11:48 +0100 Subject: [PATCH 02/96] Save states and restore states as a default in FormDialog --- eqt/ui/FormDialog.py | 11 +++++------ examples/dialog_example_3_save_default.py | 18 +++--------------- 2 files changed, 8 insertions(+), 21 deletions(-) diff --git a/eqt/ui/FormDialog.py b/eqt/ui/FormDialog.py index a77beba..5e3f9cc 100644 --- a/eqt/ui/FormDialog.py +++ b/eqt/ui/FormDialog.py @@ -25,9 +25,7 @@ def __init__(self, parent=None, title=None): self.formWidget.uiElements['verticalLayout'].addWidget(bb) bb.button(QtWidgets.QDialogButtonBox.Ok).clicked.connect(self._onOk) bb.button(QtWidgets.QDialogButtonBox.Cancel).clicked.connect(self._onCancel) - - @property def Ok(self): '''returns a reference to the Dialog Ok button to connect its signals''' @@ -40,22 +38,23 @@ def Cancel(self): def _onOk(self): '''calls `onOk`''' - print("I am _onOk") + self.saveAllWidgetStates() self.onOk() def _onCancel(self): - '''calls onCancel and closes the FormDialog''' + '''calls onCancel and closes the FormDialog''' self.onCancel() + self.restoreAllSavedWidgetStates() self.close() def onOk(self): '''Called when the dialog's "Ok" button is clicked. - Can be redefined to add additional functionality on "Ok"''' + Can be redefined to add additional functionality on "Ok"''' pass def onCancel(self): '''Called when the dialog's "Cancel" button is clicked. - Can be redefined to add additional functionality on "Cancel"''' + Can be redefined to add additional functionality on "Cancel"''' pass @property diff --git a/examples/dialog_example_3_save_default.py b/examples/dialog_example_3_save_default.py index da48f30..8f3be60 100644 --- a/examples/dialog_example_3_save_default.py +++ b/examples/dialog_example_3_save_default.py @@ -26,13 +26,11 @@ def __init__(self, parent=None): self.show() def openFormDialog(self): - # Example on how to add elements to the FormDialog # add input 1 as QLineEdit qlabel = QtWidgets.QLabel(self.dialog.groupBox) qlabel.setText("Input 1: ") qwidget = QtWidgets.QLineEdit(self.dialog.groupBox) qwidget.setClearButtonEnabled(True) - # finally add to the form widget self.dialog.addSpanningWidget(QtWidgets.QLabel("Input Values: "), 'input_title') self.dialog.addWidget(qwidget, qlabel, 'input1') @@ -44,34 +42,24 @@ def openFormDialog(self): qwidget.addItem("option 2") qwidget.setCurrentIndex(0) qwidget.setEnabled(True) - # finally add to the form widget self.dialog.addWidget(qwidget, qlabel, 'input2') self.dialog.addWidget(QtWidgets.QLabel("Example Vertical Layout Text"), layout="vertical") # Example of using 'getWidget': self.dialog.getWidget('input2').setCurrentIndex(1) - # store a reference - #self.dialog = dialog + #redefine the onOk and onCancel functions self.dialog.onOk = self.accepted self.dialog.onCancel = self.rejected - #self.dialog.restoreAllSavedWidgetStates() - if hasattr(self.dialog, 'widget_states'): - print("There are states") - print(self.dialog.widget_states) - + #open dialog function when the parent button is clicked def executedialog(self): - self.dialog.restoreAllSavedWidgetStates() - self.dialog.exec() + self.dialog.open() def accepted(self): - self.dialog.widget_states = self.dialog.saveAllWidgetStates() print("accepted") print(self.dialog.widgets['input1_field'].text()) print(self.dialog.widgets['input2_field'].currentText()) - #print(self.widget_states) - print(self.dialog.widget_states) self.dialog.close() def rejected(self): From 071aa0c0c0ab0d196f723f23ceaea0ddfefa7264 Mon Sep 17 00:00:00 2001 From: Danica Sugic Date: Fri, 20 Oct 2023 18:28:03 +0100 Subject: [PATCH 03/96] Add all widgets to example 3 and set state method --- examples/dialog_example_3_save_default.py | 84 +++++++++++++++++++++++ 1 file changed, 84 insertions(+) diff --git a/examples/dialog_example_3_save_default.py b/examples/dialog_example_3_save_default.py index 8f3be60..65a4291 100644 --- a/examples/dialog_example_3_save_default.py +++ b/examples/dialog_example_3_save_default.py @@ -3,6 +3,7 @@ from PySide2 import QtWidgets from eqt.ui import FormDialog +from eqt.ui.UISliderWidget import UISliderWidget class MainUI(QtWidgets.QMainWindow): @@ -23,6 +24,13 @@ def __init__(self, parent=None): self.dialog = FormDialog(parent=self, title='Example') self.openFormDialog() + + + + + + self.setstate(0) + self.setstate(1) self.show() def openFormDialog(self): @@ -47,11 +55,87 @@ def openFormDialog(self): # Example of using 'getWidget': self.dialog.getWidget('input2').setCurrentIndex(1) + form=self.dialog + form.addWidget(QtWidgets.QLabel('test label'), 'Label: ', 'label') + form.addWidget(QtWidgets.QCheckBox('test checkbox'), 'CheckBox: ', 'checkBox') + form.addWidget(QtWidgets.QComboBox(), 'ComboBox: ', 'comboBox') + form.addWidget(QtWidgets.QDoubleSpinBox(), 'DoubleSpinBox: ', 'doubleSpinBox') + form.addWidget(QtWidgets.QSpinBox(), 'SpinBox: ', 'spinBox') + form.addWidget(QtWidgets.QSlider(), 'Slider: ', 'slider') + form.addWidget(UISliderWidget(QtWidgets.QLabel()), 'UISliderWidget: ', 'uiSliderWidget') + form.addWidget(QtWidgets.QRadioButton('test'), 'RadioButton: ', 'radioButton') + form.addWidget(QtWidgets.QTextEdit('test'), 'TextEdit: ', 'textEdit') + form.addWidget(QtWidgets.QPlainTextEdit('test'), 'PlainTextEdit: ', 'plainTextEdit') + form.addWidget(QtWidgets.QLineEdit('test'), 'LineEdit: ', 'lineEdit') + form.addWidget(QtWidgets.QPushButton('test'), 'Button: ', 'button') + + + + #redefine the onOk and onCancel functions self.dialog.onOk = self.accepted self.dialog.onCancel = self.rejected + def setstate(self,ii): + + state=[0,0] + state[1] = {'label_value': 'Test label state 1', + 'checkbox_value':True, + 'combobox_value': 1, + 'doubleSpinBox_value': 1.0, + 'spinBox_value': 1, + 'slider_value': 1, + 'uislider_value': 1, + 'radio_value': True, + 'textEdit_value': 'test edit 1', + 'plainTextEdit_value': 'test plain 1', + 'lineEdit_value': 'test line 1', + 'button_value': True + } + + state[0] = {'label_value': 'Test label state 0', + 'checkbox_value':False, + 'combobox_value': 0, + 'doubleSpinBox_value': 10.0, + 'spinBox_value': 10, + 'slider_value': 10, + 'uislider_value': 10, + 'radio_value': False, + 'textEdit_value': 'test edit 0', + 'plainTextEdit_value': 'test plain 0', + 'lineEdit_value': 'test line 0', + 'button_value': False + } + + self.dialog.getWidget('label').setText(state[ii]['label_value']) + self.dialog.getWidget('checkBox').setChecked(state[ii]['checkbox_value']) + + combobox_list = ['test', 'test2'] + self.dialog.getWidget('comboBox').addItems(combobox_list) + self.dialog.getWidget('comboBox').setCurrentIndex(state[ii]['combobox_value']) + + self.dialog.getWidget('doubleSpinBox').setValue(state[ii]['doubleSpinBox_value']) + + self.dialog.getWidget('spinBox').setValue(state[ii]['spinBox_value']) + + self.dialog.getWidget('slider').setValue(state[ii]['slider_value']) + + self.dialog.getWidget('uiSliderWidget').setValue(state[ii]['uislider_value']) + + self.dialog.getWidget('textEdit').setText(state[ii]['textEdit_value']) + + self.dialog.getWidget('plainTextEdit').setPlainText(state[ii]['plainTextEdit_value']) + + self.dialog.getWidget('lineEdit').setText(state[ii]['lineEdit_value']) + + self.dialog.getWidget('button').setCheckable(True) + self.dialog.getWidget('button').setChecked(state[ii]['button_value']) + + self.dialog.getWidget('radioButton').setChecked(state[ii]['radio_value']) + + + #open dialog function when the parent button is clicked def executedialog(self): self.dialog.open() From 9473391045552dffb8e44cd155ad099282fa4f3f Mon Sep 17 00:00:00 2001 From: Danica Sugic Date: Fri, 20 Oct 2023 18:29:02 +0100 Subject: [PATCH 04/96] Add unit test for state changes in form dialog --- not finished --- test/test__formUI_status_test.py | 102 +++++++++++++++++++++++++++++++ 1 file changed, 102 insertions(+) diff --git a/test/test__formUI_status_test.py b/test/test__formUI_status_test.py index c35676b..19f18e4 100644 --- a/test/test__formUI_status_test.py +++ b/test/test__formUI_status_test.py @@ -3,6 +3,8 @@ from unittest import mock from PySide2 import QtWidgets +from PySide2.QtTest import QTest +from PySide2.QtCore import Qt from eqt.ui.FormDialog import FormDialog from eqt.ui.UIFormWidget import FormDockWidget, FormWidget @@ -39,6 +41,64 @@ def add_two_widgets(self): form.addWidget(QtWidgets.QLabel('test label'), 'Label: ', 'label') form.addWidget(QtWidgets.QCheckBox('test checkbox'), 'CheckBox: ', 'checkBox') + def set_state(self,ii): + #define two states for every widget + state=[0,0] + state[1] = {'label_value': 'Test label state 1', + 'checkbox_value':True, + 'combobox_value': 1, + 'doubleSpinBox_value': 1.0, + 'spinBox_value': 1, + 'slider_value': 1, + 'uislider_value': 1, + 'radio_value': True, + 'textEdit_value': 'test edit 1', + 'plainTextEdit_value': 'test plain 1', + 'lineEdit_value': 'test line 1', + 'pushButton_value': True + } + state[0] = {'label_value': 'Test label state 0', + 'checkbox_value':False, + 'combobox_value': 0, + 'doubleSpinBox_value': 10.0, + 'spinBox_value': 10, + 'slider_value': 10, + 'uislider_value': 10, + 'radio_value': False, + 'textEdit_value': 'test edit 0', + 'plainTextEdit_value': 'test plain 0', + 'lineEdit_value': 'test line 0', + 'pushButton_value': False + } + #set the states + #QLabel + self.form.getWidget('label').setText(state[ii]['label_value']) + #QCheckBox + self.form.getWidget('checkBox').setChecked(state[ii]['checkbox_value']) + #QComboBox + combobox_list = ['test', 'test2'] + self.form.getWidget('comboBox').addItems(combobox_list) + self.form.getWidget('comboBox').setCurrentIndex(state[ii]['combobox_value']) + #QDoubleSpinBox + self.form.getWidget('doubleSpinBox').setValue(state[ii]['doubleSpinBox_value']) + #QSpinBox + self.form.getWidget('spinBox').setValue(state[ii]['spinBox_value']) + #QSlider + self.form.getWidget('slider').setValue(state[ii]['slider_value']) + #UISlider + self.form.getWidget('uiSliderWidget').setValue(state[ii]['uislider_value']) + #QRadioButton + self.form.getWidget('radioButton').setChecked(state[ii]['radio_value']) + #QTextEdit + self.form.getWidget('textEdit').setText(state[ii]['textEdit_value']) + #QPlainTextEdit + self.form.getWidget('plainTextEdit').setPlainText(state[ii]['plainTextEdit_value']) + #QLineEdit + self.form.getWidget('lineEdit').setText(state[ii]['lineEdit_value']) + #QPushButton + self.form.getWidget('button').setCheckable(True) + self.form.getWidget('button').setChecked(state[ii]['pushButton_value']) + def test_getWidgetState_returns_visibility(self): """ Check that the visibility of the widget is saved to the state @@ -296,6 +356,48 @@ def setUp(self): self.simple_form = FormDialog() self.add_two_widgets() + def click_Ok(self): + QTest.mouseClick(self.form.Ok, Qt.LeftButton) + + def click_Cancel(self): + QTest.mouseClick(self.form.Cancel, Qt.LeftButton) + + def test_save_states_default(self): + #test both states are working + self.set_state(1) + states1=self.form.getAllWidgetStates() + self.set_state(0) + states0=self.form.getAllWidgetStates() + self.assertEqual(states0,states0) + self.assertEqual(states1,states1) + #self.assertEqual(states0,states1) + # Click the Ok button + self.click_Ok() + #self.form.close() + + #self.form.open() + self.assertEqual(states0,self.form.getAllWidgetStates()) + #self.assertEqual(states0,states1) + #self.assertEqual(states0,states0) + + # Click the Ok button + self.click_Ok() + self.form.close() + + self.form.open() + # #check states are states 1 + self.set_state(0) + self.click_Cancel() + self.form.close() + + self.form.open() + # #check states are states 1 + self.set_state(0) + # #press ok + self.form.close() + self.form.open() + # check states are states 0 + def test_getWidgetState_returns_QLabel_value(self): """Check that the value of the QLabel is saved to the state""" initial_label_value = 'Label: ' From 2e05d9719f8fa96ef24b5d78d57ebc6d5abf02b6 Mon Sep 17 00:00:00 2001 From: Danica Sugic Date: Thu, 26 Oct 2023 12:55:49 +0100 Subject: [PATCH 05/96] Unit tests working --- test/test__formUI_status_test.py | 47 ++++++++++++++++++-------------- 1 file changed, 27 insertions(+), 20 deletions(-) diff --git a/test/test__formUI_status_test.py b/test/test__formUI_status_test.py index 19f18e4..60bc3f8 100644 --- a/test/test__formUI_status_test.py +++ b/test/test__formUI_status_test.py @@ -364,39 +364,46 @@ def click_Cancel(self): def test_save_states_default(self): #test both states are working + self.form.open() + #state1 self.set_state(1) states1=self.form.getAllWidgetStates() + self.assertEqual(states1,self.form.getAllWidgetStates()) + #state0 self.set_state(0) states0=self.form.getAllWidgetStates() + self.assertNotEqual(states1,self.form.getAllWidgetStates()) + self.assertEqual(states0,self.form.getAllWidgetStates()) + #together self.assertEqual(states0,states0) self.assertEqual(states1,states1) - #self.assertEqual(states0,states1) - # Click the Ok button - self.click_Ok() - #self.form.close() - - #self.form.open() + self.assertNotEqual(states0,states1) + #check nothing is saved when Cancel is pressed + self.click_Cancel() + self.assertNotEqual(states0,self.form.getAllWidgetStates()) + self.assertNotEqual(states1,self.form.getAllWidgetStates()) + #save state 0 + self.form.open() + self.set_state(0) self.assertEqual(states0,self.form.getAllWidgetStates()) - #self.assertEqual(states0,states1) - #self.assertEqual(states0,states0) - - # Click the Ok button - self.click_Ok() + self.click_Ok() self.form.close() - self.form.open() - # #check states are states 1 - self.set_state(0) - self.click_Cancel() + self.assertEqual(states0,self.form.getAllWidgetStates()) + #save state 1 + self.form.open() + self.set_state(1) + self.assertEqual(states1,self.form.getAllWidgetStates()) + self.click_Ok() self.form.close() - self.form.open() - # #check states are states 1 + self.assertEqual(states1,self.form.getAllWidgetStates()) + #change to state 0 without saving self.set_state(0) - # #press ok - self.form.close() + self.assertEqual(states0,self.form.getAllWidgetStates()) + self.click_Cancel() self.form.open() - # check states are states 0 + self.assertEqual(states1,self.form.getAllWidgetStates()) def test_getWidgetState_returns_QLabel_value(self): """Check that the value of the QLabel is saved to the state""" From 0538ef5badc75246623df5a79b44ba4b63d9b785 Mon Sep 17 00:00:00 2001 From: Danica Sugic Date: Thu, 26 Oct 2023 13:55:23 +0100 Subject: [PATCH 06/96] Modify and tidy example --- examples/dialog_example_3_save_default.py | 136 ++++------------------ 1 file changed, 22 insertions(+), 114 deletions(-) diff --git a/examples/dialog_example_3_save_default.py b/examples/dialog_example_3_save_default.py index 65a4291..a48ab60 100644 --- a/examples/dialog_example_3_save_default.py +++ b/examples/dialog_example_3_save_default.py @@ -5,16 +5,14 @@ from eqt.ui import FormDialog from eqt.ui.UISliderWidget import UISliderWidget - class MainUI(QtWidgets.QMainWindow): def __init__(self, parent=None): QtWidgets.QMainWindow.__init__(self, parent) pb = QtWidgets.QPushButton(self) pb.setText("Open Dialog with form layout") - pb.clicked.connect(lambda: self.executedialog()) - + layout = QtWidgets.QHBoxLayout() layout.addWidget(pb) widg = QtWidgets.QWidget() @@ -22,133 +20,43 @@ def __init__(self, parent=None): self.setCentralWidget(widg) self.dialog = FormDialog(parent=self, title='Example') - self.openFormDialog() - - - - - self.setstate(0) - self.setstate(1) self.show() def openFormDialog(self): - # add input 1 as QLineEdit - qlabel = QtWidgets.QLabel(self.dialog.groupBox) - qlabel.setText("Input 1: ") - qwidget = QtWidgets.QLineEdit(self.dialog.groupBox) - qwidget.setClearButtonEnabled(True) + # add a spanning widget self.dialog.addSpanningWidget(QtWidgets.QLabel("Input Values: "), 'input_title') - self.dialog.addWidget(qwidget, qlabel, 'input1') - - # add input 2 as QComboBox - qlabel = QtWidgets.QLabel(self.dialog.groupBox) - qlabel.setText("Input 2: ") - qwidget = QtWidgets.QComboBox(self.dialog.groupBox) - qwidget.addItem("option 1") - qwidget.addItem("option 2") - qwidget.setCurrentIndex(0) - qwidget.setEnabled(True) - self.dialog.addWidget(qwidget, qlabel, 'input2') - self.dialog.addWidget(QtWidgets.QLabel("Example Vertical Layout Text"), layout="vertical") - - # Example of using 'getWidget': - self.dialog.getWidget('input2').setCurrentIndex(1) - form=self.dialog - form.addWidget(QtWidgets.QLabel('test label'), 'Label: ', 'label') - form.addWidget(QtWidgets.QCheckBox('test checkbox'), 'CheckBox: ', 'checkBox') - form.addWidget(QtWidgets.QComboBox(), 'ComboBox: ', 'comboBox') - form.addWidget(QtWidgets.QDoubleSpinBox(), 'DoubleSpinBox: ', 'doubleSpinBox') - form.addWidget(QtWidgets.QSpinBox(), 'SpinBox: ', 'spinBox') - form.addWidget(QtWidgets.QSlider(), 'Slider: ', 'slider') - form.addWidget(UISliderWidget(QtWidgets.QLabel()), 'UISliderWidget: ', 'uiSliderWidget') - form.addWidget(QtWidgets.QRadioButton('test'), 'RadioButton: ', 'radioButton') - form.addWidget(QtWidgets.QTextEdit('test'), 'TextEdit: ', 'textEdit') - form.addWidget(QtWidgets.QPlainTextEdit('test'), 'PlainTextEdit: ', 'plainTextEdit') - form.addWidget(QtWidgets.QLineEdit('test'), 'LineEdit: ', 'lineEdit') - form.addWidget(QtWidgets.QPushButton('test'), 'Button: ', 'button') - - - - + # add all widgets + self.dialog.addWidget(QtWidgets.QLabel('Label'), 'Label: ', 'label') + self.dialog.addWidget(QtWidgets.QCheckBox('check me'), 'CheckBox: ', 'checkBox') + combobox_list = ['choice 1', 'choice 2'] + self.dialog.addWidget(QtWidgets.QComboBox(), 'ComboBox: ', 'comboBox') + self.dialog.getWidget('comboBox').addItems(combobox_list) + self.dialog.addWidget(QtWidgets.QDoubleSpinBox(), 'DoubleSpinBox: ', 'doubleSpinBox') + self.dialog.addWidget(QtWidgets.QSpinBox(), 'SpinBox: ', 'spinBox') + self.dialog.addWidget(QtWidgets.QSlider(), 'Slider: ', 'slider') + self.dialog.addWidget(UISliderWidget(QtWidgets.QLabel()), 'UISlider: ', 'uiSliderWidget') + self.dialog.addWidget(QtWidgets.QRadioButton('select me'), 'RadioButton: ', 'radioButton') + self.dialog.addWidget(QtWidgets.QTextEdit('write text here'), 'TextEdit: ', 'textEdit') + self.dialog.addWidget(QtWidgets.QPlainTextEdit('write text here'), 'PlainTextEdit: ', 'plainTextEdit') + self.dialog.addWidget(QtWidgets.QLineEdit('write text here'), 'LineEdit: ', 'lineEdit') + self.dialog.addWidget(QtWidgets.QPushButton('Click me'), 'Button: ', 'button') #redefine the onOk and onCancel functions self.dialog.onOk = self.accepted self.dialog.onCancel = self.rejected - def setstate(self,ii): - - state=[0,0] - state[1] = {'label_value': 'Test label state 1', - 'checkbox_value':True, - 'combobox_value': 1, - 'doubleSpinBox_value': 1.0, - 'spinBox_value': 1, - 'slider_value': 1, - 'uislider_value': 1, - 'radio_value': True, - 'textEdit_value': 'test edit 1', - 'plainTextEdit_value': 'test plain 1', - 'lineEdit_value': 'test line 1', - 'button_value': True - } - - state[0] = {'label_value': 'Test label state 0', - 'checkbox_value':False, - 'combobox_value': 0, - 'doubleSpinBox_value': 10.0, - 'spinBox_value': 10, - 'slider_value': 10, - 'uislider_value': 10, - 'radio_value': False, - 'textEdit_value': 'test edit 0', - 'plainTextEdit_value': 'test plain 0', - 'lineEdit_value': 'test line 0', - 'button_value': False - } - - self.dialog.getWidget('label').setText(state[ii]['label_value']) - self.dialog.getWidget('checkBox').setChecked(state[ii]['checkbox_value']) - - combobox_list = ['test', 'test2'] - self.dialog.getWidget('comboBox').addItems(combobox_list) - self.dialog.getWidget('comboBox').setCurrentIndex(state[ii]['combobox_value']) - - self.dialog.getWidget('doubleSpinBox').setValue(state[ii]['doubleSpinBox_value']) - - self.dialog.getWidget('spinBox').setValue(state[ii]['spinBox_value']) - - self.dialog.getWidget('slider').setValue(state[ii]['slider_value']) - - self.dialog.getWidget('uiSliderWidget').setValue(state[ii]['uislider_value']) - - self.dialog.getWidget('textEdit').setText(state[ii]['textEdit_value']) - - self.dialog.getWidget('plainTextEdit').setPlainText(state[ii]['plainTextEdit_value']) - - self.dialog.getWidget('lineEdit').setText(state[ii]['lineEdit_value']) - - self.dialog.getWidget('button').setCheckable(True) - self.dialog.getWidget('button').setChecked(state[ii]['button_value']) - - self.dialog.getWidget('radioButton').setChecked(state[ii]['radio_value']) - - - - #open dialog function when the parent button is clicked - def executedialog(self): - self.dialog.open() - def accepted(self): - print("accepted") - print(self.dialog.widgets['input1_field'].text()) - print(self.dialog.widgets['input2_field'].currentText()) + print("States saved") self.dialog.close() def rejected(self): - print("rejected") + print("States rejected") + #open dialog function when the parent button is clicked + def executedialog(self): + self.dialog.open() if __name__ == "__main__": app = QtWidgets.QApplication(sys.argv) From 46231b57f645af39a7ea2acde9cbfbf00d8bd1b1 Mon Sep 17 00:00:00 2001 From: Danica Sugic Date: Thu, 26 Oct 2023 14:02:44 +0100 Subject: [PATCH 07/96] Add minor changes --- eqt/ui/FormDialog.py | 4 ++-- test/test__formUI_status_test.py | 26 +++++++++++++------------- 2 files changed, 15 insertions(+), 15 deletions(-) diff --git a/eqt/ui/FormDialog.py b/eqt/ui/FormDialog.py index 5e3f9cc..89a5a89 100644 --- a/eqt/ui/FormDialog.py +++ b/eqt/ui/FormDialog.py @@ -37,12 +37,12 @@ def Cancel(self): return self.buttonBox.button(QtWidgets.QDialogButtonBox.Cancel) def _onOk(self): - '''calls `onOk`''' + '''saves the widget states and calls `onOk`''' self.saveAllWidgetStates() self.onOk() def _onCancel(self): - '''calls onCancel and closes the FormDialog''' + '''calls `onCancel`, restores the previously saved states if existing and closes the FormDialog''' self.onCancel() self.restoreAllSavedWidgetStates() self.close() diff --git a/test/test__formUI_status_test.py b/test/test__formUI_status_test.py index 60bc3f8..415b6f0 100644 --- a/test/test__formUI_status_test.py +++ b/test/test__formUI_status_test.py @@ -44,19 +44,6 @@ def add_two_widgets(self): def set_state(self,ii): #define two states for every widget state=[0,0] - state[1] = {'label_value': 'Test label state 1', - 'checkbox_value':True, - 'combobox_value': 1, - 'doubleSpinBox_value': 1.0, - 'spinBox_value': 1, - 'slider_value': 1, - 'uislider_value': 1, - 'radio_value': True, - 'textEdit_value': 'test edit 1', - 'plainTextEdit_value': 'test plain 1', - 'lineEdit_value': 'test line 1', - 'pushButton_value': True - } state[0] = {'label_value': 'Test label state 0', 'checkbox_value':False, 'combobox_value': 0, @@ -70,6 +57,19 @@ def set_state(self,ii): 'lineEdit_value': 'test line 0', 'pushButton_value': False } + state[1] = {'label_value': 'Test label state 1', + 'checkbox_value':True, + 'combobox_value': 1, + 'doubleSpinBox_value': 1.0, + 'spinBox_value': 1, + 'slider_value': 1, + 'uislider_value': 1, + 'radio_value': True, + 'textEdit_value': 'test edit 1', + 'plainTextEdit_value': 'test plain 1', + 'lineEdit_value': 'test line 1', + 'pushButton_value': True + } #set the states #QLabel self.form.getWidget('label').setText(state[ii]['label_value']) From d2cfb9a9c2d2344a3750a7270c3e7909a2a9e52b Mon Sep 17 00:00:00 2001 From: Danica Sugic Date: Thu, 26 Oct 2023 14:18:34 +0100 Subject: [PATCH 08/96] Add changes from pre-commit --- eqt/ui/FormDialog.py | 7 +- examples/dialog_example_3_save_default.py | 11 +- test/test__formUI_status_test.py | 126 ++++++++++------------ 3 files changed, 67 insertions(+), 77 deletions(-) diff --git a/eqt/ui/FormDialog.py b/eqt/ui/FormDialog.py index 89a5a89..ba9146f 100644 --- a/eqt/ui/FormDialog.py +++ b/eqt/ui/FormDialog.py @@ -25,7 +25,7 @@ def __init__(self, parent=None, title=None): self.formWidget.uiElements['verticalLayout'].addWidget(bb) bb.button(QtWidgets.QDialogButtonBox.Ok).clicked.connect(self._onOk) bb.button(QtWidgets.QDialogButtonBox.Cancel).clicked.connect(self._onCancel) - + @property def Ok(self): '''returns a reference to the Dialog Ok button to connect its signals''' @@ -38,11 +38,12 @@ def Cancel(self): def _onOk(self): '''saves the widget states and calls `onOk`''' - self.saveAllWidgetStates() + self.saveAllWidgetStates() self.onOk() def _onCancel(self): - '''calls `onCancel`, restores the previously saved states if existing and closes the FormDialog''' + '''calls `onCancel`, restores the previously saved states if existing and + closes the FormDialog''' self.onCancel() self.restoreAllSavedWidgetStates() self.close() diff --git a/examples/dialog_example_3_save_default.py b/examples/dialog_example_3_save_default.py index a48ab60..3fef30b 100644 --- a/examples/dialog_example_3_save_default.py +++ b/examples/dialog_example_3_save_default.py @@ -5,6 +5,7 @@ from eqt.ui import FormDialog from eqt.ui.UISliderWidget import UISliderWidget + class MainUI(QtWidgets.QMainWindow): def __init__(self, parent=None): QtWidgets.QMainWindow.__init__(self, parent) @@ -12,7 +13,7 @@ def __init__(self, parent=None): pb = QtWidgets.QPushButton(self) pb.setText("Open Dialog with form layout") pb.clicked.connect(lambda: self.executedialog()) - + layout = QtWidgets.QHBoxLayout() layout.addWidget(pb) widg = QtWidgets.QWidget() @@ -39,11 +40,12 @@ def openFormDialog(self): self.dialog.addWidget(UISliderWidget(QtWidgets.QLabel()), 'UISlider: ', 'uiSliderWidget') self.dialog.addWidget(QtWidgets.QRadioButton('select me'), 'RadioButton: ', 'radioButton') self.dialog.addWidget(QtWidgets.QTextEdit('write text here'), 'TextEdit: ', 'textEdit') - self.dialog.addWidget(QtWidgets.QPlainTextEdit('write text here'), 'PlainTextEdit: ', 'plainTextEdit') + self.dialog.addWidget(QtWidgets.QPlainTextEdit('write text here'), 'PlainTextEdit: ', + 'plainTextEdit') self.dialog.addWidget(QtWidgets.QLineEdit('write text here'), 'LineEdit: ', 'lineEdit') self.dialog.addWidget(QtWidgets.QPushButton('Click me'), 'Button: ', 'button') - #redefine the onOk and onCancel functions + # redefine the onOk and onCancel functions self.dialog.onOk = self.accepted self.dialog.onCancel = self.rejected @@ -54,10 +56,11 @@ def accepted(self): def rejected(self): print("States rejected") - #open dialog function when the parent button is clicked + # open dialog function when the parent button is clicked def executedialog(self): self.dialog.open() + if __name__ == "__main__": app = QtWidgets.QApplication(sys.argv) diff --git a/test/test__formUI_status_test.py b/test/test__formUI_status_test.py index 415b6f0..bafbe5f 100644 --- a/test/test__formUI_status_test.py +++ b/test/test__formUI_status_test.py @@ -3,8 +3,8 @@ from unittest import mock from PySide2 import QtWidgets -from PySide2.QtTest import QTest from PySide2.QtCore import Qt +from PySide2.QtTest import QTest from eqt.ui.FormDialog import FormDialog from eqt.ui.UIFormWidget import FormDockWidget, FormWidget @@ -41,61 +41,47 @@ def add_two_widgets(self): form.addWidget(QtWidgets.QLabel('test label'), 'Label: ', 'label') form.addWidget(QtWidgets.QCheckBox('test checkbox'), 'CheckBox: ', 'checkBox') - def set_state(self,ii): - #define two states for every widget - state=[0,0] - state[0] = {'label_value': 'Test label state 0', - 'checkbox_value':False, - 'combobox_value': 0, - 'doubleSpinBox_value': 10.0, - 'spinBox_value': 10, - 'slider_value': 10, - 'uislider_value': 10, - 'radio_value': False, - 'textEdit_value': 'test edit 0', - 'plainTextEdit_value': 'test plain 0', - 'lineEdit_value': 'test line 0', - 'pushButton_value': False - } - state[1] = {'label_value': 'Test label state 1', - 'checkbox_value':True, - 'combobox_value': 1, - 'doubleSpinBox_value': 1.0, - 'spinBox_value': 1, - 'slider_value': 1, - 'uislider_value': 1, - 'radio_value': True, - 'textEdit_value': 'test edit 1', - 'plainTextEdit_value': 'test plain 1', - 'lineEdit_value': 'test line 1', - 'pushButton_value': True - } - #set the states - #QLabel + def set_state(self, ii): + # define two states for every widget + state = [0, 0] + state[0] = { + 'label_value': 'Test label state 0', 'checkbox_value': False, 'combobox_value': 0, + 'doubleSpinBox_value': 10.0, 'spinBox_value': 10, 'slider_value': 10, + 'uislider_value': 10, 'radio_value': False, 'textEdit_value': 'test edit 0', + 'plainTextEdit_value': 'test plain 0', 'lineEdit_value': 'test line 0', + 'pushButton_value': False} + state[1] = { + 'label_value': 'Test label state 1', 'checkbox_value': True, 'combobox_value': 1, + 'doubleSpinBox_value': 1.0, 'spinBox_value': 1, 'slider_value': 1, 'uislider_value': 1, + 'radio_value': True, 'textEdit_value': 'test edit 1', + 'plainTextEdit_value': 'test plain 1', 'lineEdit_value': 'test line 1', + 'pushButton_value': True} + # set the states + # QLabel self.form.getWidget('label').setText(state[ii]['label_value']) - #QCheckBox + # QCheckBox self.form.getWidget('checkBox').setChecked(state[ii]['checkbox_value']) - #QComboBox + # QComboBox combobox_list = ['test', 'test2'] self.form.getWidget('comboBox').addItems(combobox_list) self.form.getWidget('comboBox').setCurrentIndex(state[ii]['combobox_value']) - #QDoubleSpinBox + # QDoubleSpinBox self.form.getWidget('doubleSpinBox').setValue(state[ii]['doubleSpinBox_value']) - #QSpinBox + # QSpinBox self.form.getWidget('spinBox').setValue(state[ii]['spinBox_value']) - #QSlider + # QSlider self.form.getWidget('slider').setValue(state[ii]['slider_value']) - #UISlider + # UISlider self.form.getWidget('uiSliderWidget').setValue(state[ii]['uislider_value']) - #QRadioButton + # QRadioButton self.form.getWidget('radioButton').setChecked(state[ii]['radio_value']) - #QTextEdit + # QTextEdit self.form.getWidget('textEdit').setText(state[ii]['textEdit_value']) - #QPlainTextEdit + # QPlainTextEdit self.form.getWidget('plainTextEdit').setPlainText(state[ii]['plainTextEdit_value']) - #QLineEdit + # QLineEdit self.form.getWidget('lineEdit').setText(state[ii]['lineEdit_value']) - #QPushButton + # QPushButton self.form.getWidget('button').setCheckable(True) self.form.getWidget('button').setChecked(state[ii]['pushButton_value']) @@ -363,47 +349,47 @@ def click_Cancel(self): QTest.mouseClick(self.form.Cancel, Qt.LeftButton) def test_save_states_default(self): - #test both states are working + # test both states are working self.form.open() - #state1 + # state1 self.set_state(1) - states1=self.form.getAllWidgetStates() - self.assertEqual(states1,self.form.getAllWidgetStates()) - #state0 + states1 = self.form.getAllWidgetStates() + self.assertEqual(states1, self.form.getAllWidgetStates()) + # state0 self.set_state(0) - states0=self.form.getAllWidgetStates() - self.assertNotEqual(states1,self.form.getAllWidgetStates()) - self.assertEqual(states0,self.form.getAllWidgetStates()) - #together - self.assertEqual(states0,states0) - self.assertEqual(states1,states1) - self.assertNotEqual(states0,states1) - #check nothing is saved when Cancel is pressed + states0 = self.form.getAllWidgetStates() + self.assertNotEqual(states1, self.form.getAllWidgetStates()) + self.assertEqual(states0, self.form.getAllWidgetStates()) + # together + self.assertEqual(states0, states0) + self.assertEqual(states1, states1) + self.assertNotEqual(states0, states1) + # check nothing is saved when Cancel is pressed self.click_Cancel() - self.assertNotEqual(states0,self.form.getAllWidgetStates()) - self.assertNotEqual(states1,self.form.getAllWidgetStates()) - #save state 0 + self.assertNotEqual(states0, self.form.getAllWidgetStates()) + self.assertNotEqual(states1, self.form.getAllWidgetStates()) + # save state 0 self.form.open() self.set_state(0) - self.assertEqual(states0,self.form.getAllWidgetStates()) - self.click_Ok() + self.assertEqual(states0, self.form.getAllWidgetStates()) + self.click_Ok() self.form.close() self.form.open() - self.assertEqual(states0,self.form.getAllWidgetStates()) - #save state 1 + self.assertEqual(states0, self.form.getAllWidgetStates()) + # save state 1 self.form.open() self.set_state(1) - self.assertEqual(states1,self.form.getAllWidgetStates()) - self.click_Ok() + self.assertEqual(states1, self.form.getAllWidgetStates()) + self.click_Ok() self.form.close() self.form.open() - self.assertEqual(states1,self.form.getAllWidgetStates()) - #change to state 0 without saving + self.assertEqual(states1, self.form.getAllWidgetStates()) + # change to state 0 without saving self.set_state(0) - self.assertEqual(states0,self.form.getAllWidgetStates()) - self.click_Cancel() + self.assertEqual(states0, self.form.getAllWidgetStates()) + self.click_Cancel() self.form.open() - self.assertEqual(states1,self.form.getAllWidgetStates()) + self.assertEqual(states1, self.form.getAllWidgetStates()) def test_getWidgetState_returns_QLabel_value(self): """Check that the value of the QLabel is saved to the state""" From ffe74e4c4303abcb88fd0a2128f41eb309944442 Mon Sep 17 00:00:00 2001 From: Danica Sugic Date: Mon, 30 Oct 2023 18:00:29 +0000 Subject: [PATCH 09/96] Fix first cancel call bug --- eqt/ui/UIFormWidget.py | 30 ++++++++++++++++++++++++++++-- 1 file changed, 28 insertions(+), 2 deletions(-) diff --git a/eqt/ui/UIFormWidget.py b/eqt/ui/UIFormWidget.py index 926a536..1518cd6 100644 --- a/eqt/ui/UIFormWidget.py +++ b/eqt/ui/UIFormWidget.py @@ -137,6 +137,26 @@ def _addWidget(self, name, qwidget, qlabel=None): formLayout.setWidget(widgetno, field_form_role, qwidget) self.num_widgets += 1 + self.getWidgetValuesFromState() + + def getWidgetValuesFromState(self): + if not hasattr(self, 'widget_default'): + self.widget_default={} + states=self.getAllWidgetStates() + self.widget_default={state_key:states[state_key]['value'] for state_key in states.keys()} + print(self.widget_default) + print("invoking get default") + + def applyWidgetValuesToState(self): + self.saveAllWidgetStates() + for state_key in self.widget_default.keys(): + self.widget_states[state_key]['value']=self.widget_default[state_key] + print("invoking apply default") + + + + + def getAllWidgetStates(self): ''' @@ -292,6 +312,7 @@ def saveAllWidgetStates(self): Saves the state of all widgets in the form. To later restore the states, use `restoreAllSavedWidgetStates()`. ''' + print("saving states") self.widget_states = self.getAllWidgetStates() def restoreAllSavedWidgetStates(self): @@ -299,8 +320,13 @@ def restoreAllSavedWidgetStates(self): Restore all widgets in the form to the state saved by `saveAllWidgetStates()`. If `saveAllWidgetStates()` method was not previously invoked, do nothing. ''' - if hasattr(self, 'widget_states'): - self.applyWidgetStates(self.widget_states) + + if not hasattr(self, 'widget_states'): + self.applyWidgetValuesToState() + print("making the default state") + self.applyWidgetStates(self.widget_states) + print("applying saved states") + class FormWidget(QtWidgets.QWidget, UIFormWidget): From 00dbb7afee700eec54fecc34cd9fb76fd5ea27e1 Mon Sep 17 00:00:00 2001 From: Danica Sugic Date: Mon, 30 Oct 2023 18:52:59 +0000 Subject: [PATCH 10/96] Save default values one by one in `_addWidget` --- eqt/ui/UIFormWidget.py | 24 +++++++++++++----------- 1 file changed, 13 insertions(+), 11 deletions(-) diff --git a/eqt/ui/UIFormWidget.py b/eqt/ui/UIFormWidget.py index 1518cd6..146ca7e 100644 --- a/eqt/ui/UIFormWidget.py +++ b/eqt/ui/UIFormWidget.py @@ -109,6 +109,10 @@ def addSeparator(self, name): def _addWidget(self, name, qwidget, qlabel=None): formLayout = self.uiElements['groupBoxFormLayout'] + # create the default values + if not hasattr(self, 'widget_default'): + self.widget_default={} + # Create the widgets: widgetno = self.num_widgets @@ -117,6 +121,9 @@ def _addWidget(self, name, qwidget, qlabel=None): field = f'{name}_field' self.widgets[field] = qwidget + # add the default value of the qwidget + self.widget_default[field]=self.getWidgetState(qwidget)['value'] + if qlabel is not None: # add the label label = f'{name}_label' @@ -125,30 +132,25 @@ def _addWidget(self, name, qwidget, qlabel=None): qlabel = QtWidgets.QLabel(self.uiElements['groupBox']) qlabel.setText(txt) formLayout.setWidget(widgetno, QtWidgets.QFormLayout.LabelRole, qlabel) - + # save a reference to label widgets in the dictionary self.widgets[label] = qlabel field_form_role = QtWidgets.QFormLayout.FieldRole + # add the default value of the qlabel + self.widget_default[label]=self.getWidgetState(qlabel,label)['value'] + else: # In the case we don't have a qlabel, set a spanning widget: field_form_role = QtWidgets.QFormLayout.SpanningRole formLayout.setWidget(widgetno, field_form_role, qwidget) self.num_widgets += 1 - self.getWidgetValuesFromState() - - def getWidgetValuesFromState(self): - if not hasattr(self, 'widget_default'): - self.widget_default={} - states=self.getAllWidgetStates() - self.widget_default={state_key:states[state_key]['value'] for state_key in states.keys()} - print(self.widget_default) - print("invoking get default") def applyWidgetValuesToState(self): self.saveAllWidgetStates() + print("this time i am inside default apply") for state_key in self.widget_default.keys(): self.widget_states[state_key]['value']=self.widget_default[state_key] print("invoking apply default") @@ -323,7 +325,7 @@ def restoreAllSavedWidgetStates(self): if not hasattr(self, 'widget_states'): self.applyWidgetValuesToState() - print("making the default state") + print("apply the default state") self.applyWidgetStates(self.widget_states) print("applying saved states") From 6be5a9c8e44ab11352b9c1ed9594a2ae44e0581d Mon Sep 17 00:00:00 2001 From: Danica Sugic Date: Tue, 31 Oct 2023 13:35:59 +0000 Subject: [PATCH 11/96] Close dialog when Ok is clicked and add example file for methods --- eqt/ui/FormDialog.py | 1 + examples/dialog_example_3_save_default.py | 28 ++++------------------- examples/utilitiesForExamples.py | 26 +++++++++++++++++++++ 3 files changed, 32 insertions(+), 23 deletions(-) create mode 100644 examples/utilitiesForExamples.py diff --git a/eqt/ui/FormDialog.py b/eqt/ui/FormDialog.py index ba9146f..799400e 100644 --- a/eqt/ui/FormDialog.py +++ b/eqt/ui/FormDialog.py @@ -40,6 +40,7 @@ def _onOk(self): '''saves the widget states and calls `onOk`''' self.saveAllWidgetStates() self.onOk() + self.close() def _onCancel(self): '''calls `onCancel`, restores the previously saved states if existing and diff --git a/examples/dialog_example_3_save_default.py b/examples/dialog_example_3_save_default.py index 3fef30b..8b0f655 100644 --- a/examples/dialog_example_3_save_default.py +++ b/examples/dialog_example_3_save_default.py @@ -3,7 +3,8 @@ from PySide2 import QtWidgets from eqt.ui import FormDialog -from eqt.ui.UISliderWidget import UISliderWidget + +import utilitiesForExamples as utex class MainUI(QtWidgets.QMainWindow): @@ -12,7 +13,7 @@ def __init__(self, parent=None): pb = QtWidgets.QPushButton(self) pb.setText("Open Dialog with form layout") - pb.clicked.connect(lambda: self.executedialog()) + pb.clicked.connect(lambda: self.executeDialog()) layout = QtWidgets.QHBoxLayout() layout.addWidget(pb) @@ -26,38 +27,19 @@ def __init__(self, parent=None): self.show() def openFormDialog(self): - # add a spanning widget - self.dialog.addSpanningWidget(QtWidgets.QLabel("Input Values: "), 'input_title') - # add all widgets - self.dialog.addWidget(QtWidgets.QLabel('Label'), 'Label: ', 'label') - self.dialog.addWidget(QtWidgets.QCheckBox('check me'), 'CheckBox: ', 'checkBox') - combobox_list = ['choice 1', 'choice 2'] - self.dialog.addWidget(QtWidgets.QComboBox(), 'ComboBox: ', 'comboBox') - self.dialog.getWidget('comboBox').addItems(combobox_list) - self.dialog.addWidget(QtWidgets.QDoubleSpinBox(), 'DoubleSpinBox: ', 'doubleSpinBox') - self.dialog.addWidget(QtWidgets.QSpinBox(), 'SpinBox: ', 'spinBox') - self.dialog.addWidget(QtWidgets.QSlider(), 'Slider: ', 'slider') - self.dialog.addWidget(UISliderWidget(QtWidgets.QLabel()), 'UISlider: ', 'uiSliderWidget') - self.dialog.addWidget(QtWidgets.QRadioButton('select me'), 'RadioButton: ', 'radioButton') - self.dialog.addWidget(QtWidgets.QTextEdit('write text here'), 'TextEdit: ', 'textEdit') - self.dialog.addWidget(QtWidgets.QPlainTextEdit('write text here'), 'PlainTextEdit: ', - 'plainTextEdit') - self.dialog.addWidget(QtWidgets.QLineEdit('write text here'), 'LineEdit: ', 'lineEdit') - self.dialog.addWidget(QtWidgets.QPushButton('Click me'), 'Button: ', 'button') - + utex.addWidgetsToExample(self.dialog) # redefine the onOk and onCancel functions self.dialog.onOk = self.accepted self.dialog.onCancel = self.rejected def accepted(self): print("States saved") - self.dialog.close() def rejected(self): print("States rejected") # open dialog function when the parent button is clicked - def executedialog(self): + def executeDialog(self): self.dialog.open() diff --git a/examples/utilitiesForExamples.py b/examples/utilitiesForExamples.py new file mode 100644 index 0000000..1b5a9ec --- /dev/null +++ b/examples/utilitiesForExamples.py @@ -0,0 +1,26 @@ +from PySide2 import QtWidgets +from eqt.ui.UISliderWidget import UISliderWidget + +def addWidgetsToExample(form): + ''' + Adds a spanning widget and every type of widget to a form + ''' + # add a spanning widget + form.addSpanningWidget(QtWidgets.QLabel("Input Values: "), 'input_title') + # add all widgets + form.addWidget(QtWidgets.QLabel('Label'), 'Label: ', 'label') + form.addWidget(QtWidgets.QCheckBox('check me'), 'CheckBox: ', 'checkBox') + combobox_list = ['choice 1', 'choice 2'] + form.addWidget(QtWidgets.QComboBox(), 'ComboBox: ', 'comboBox') + form.getWidget('comboBox').addItems(combobox_list) + form.addWidget(QtWidgets.QDoubleSpinBox(), 'DoubleSpinBox: ', 'doubleSpinBox') + form.addWidget(QtWidgets.QSpinBox(), 'SpinBox: ', 'spinBox') + form.addWidget(QtWidgets.QSlider(), 'Slider: ', 'slider') + form.addWidget(UISliderWidget(QtWidgets.QLabel()), 'UISlider: ', 'uiSliderWidget') + form.addWidget(QtWidgets.QRadioButton('select me'), 'RadioButton: ', 'radioButton') + form.addWidget(QtWidgets.QTextEdit('write text here'), 'TextEdit: ', 'textEdit') + form.addWidget(QtWidgets.QPlainTextEdit('write text here'), 'PlainTextEdit: ', + 'plainTextEdit') + form.addWidget(QtWidgets.QLineEdit('write text here'), 'LineEdit: ', 'lineEdit') + form.addWidget(QtWidgets.QPushButton('Click me'), 'Button: ', 'button') + From 4c5ca41d79b568a24c9909c69d7ed0fa2cb0c532 Mon Sep 17 00:00:00 2001 From: Danica Sugic Date: Tue, 31 Oct 2023 13:38:54 +0000 Subject: [PATCH 12/96] Add example state to tests, add docstring to set_state --- eqt/ui/UIFormWidget.py | 14 +------- test/test__formUI_status_test.py | 56 +++++++++++++++++--------------- 2 files changed, 30 insertions(+), 40 deletions(-) diff --git a/eqt/ui/UIFormWidget.py b/eqt/ui/UIFormWidget.py index 146ca7e..c666b26 100644 --- a/eqt/ui/UIFormWidget.py +++ b/eqt/ui/UIFormWidget.py @@ -150,16 +150,9 @@ def _addWidget(self, name, qwidget, qlabel=None): def applyWidgetValuesToState(self): self.saveAllWidgetStates() - print("this time i am inside default apply") for state_key in self.widget_default.keys(): self.widget_states[state_key]['value']=self.widget_default[state_key] - print("invoking apply default") - - - - - def getAllWidgetStates(self): ''' Returns @@ -314,7 +307,6 @@ def saveAllWidgetStates(self): Saves the state of all widgets in the form. To later restore the states, use `restoreAllSavedWidgetStates()`. ''' - print("saving states") self.widget_states = self.getAllWidgetStates() def restoreAllSavedWidgetStates(self): @@ -322,15 +314,11 @@ def restoreAllSavedWidgetStates(self): Restore all widgets in the form to the state saved by `saveAllWidgetStates()`. If `saveAllWidgetStates()` method was not previously invoked, do nothing. ''' - if not hasattr(self, 'widget_states'): self.applyWidgetValuesToState() - print("apply the default state") self.applyWidgetStates(self.widget_states) - print("applying saved states") - - + class FormWidget(QtWidgets.QWidget, UIFormWidget): def __init__(self, parent=None): # dockWidgetContents = QtWidgets.QWidget() diff --git a/test/test__formUI_status_test.py b/test/test__formUI_status_test.py index bafbe5f..1e228a9 100644 --- a/test/test__formUI_status_test.py +++ b/test/test__formUI_status_test.py @@ -15,9 +15,29 @@ class FormsCommonTests(metaclass=abc.ABCMeta): """Common tests for all Form types""" + @abc.abstractmethod def setUp(self): raise NotImplementedError + + @property + def exampleState(self): + # define two states for every widget + state=[ + { + 'label_value': 'Test label state 0', 'checkbox_value': False, 'combobox_value': 0, + 'doubleSpinBox_value': 10.0, 'spinBox_value': 10, 'slider_value': 10, + 'uislider_value': 10, 'radio_value': False, 'textEdit_value': 'test edit 0', + 'plainTextEdit_value': 'test plain 0', 'lineEdit_value': 'test line 0', + 'pushButton_value': False}, + { + 'label_value': 'Test label state 1', 'checkbox_value': True, 'combobox_value': 1, + 'doubleSpinBox_value': 1.0, 'spinBox_value': 1, 'slider_value': 1, 'uislider_value': 1, + 'radio_value': True, 'textEdit_value': 'test edit 1', + 'plainTextEdit_value': 'test plain 1', 'lineEdit_value': 'test line 1', + 'pushButton_value': True} + ] + return state def add_every_widget(self): """Generate every widget and add it to `self.form`""" @@ -42,20 +62,14 @@ def add_two_widgets(self): form.addWidget(QtWidgets.QCheckBox('test checkbox'), 'CheckBox: ', 'checkBox') def set_state(self, ii): - # define two states for every widget - state = [0, 0] - state[0] = { - 'label_value': 'Test label state 0', 'checkbox_value': False, 'combobox_value': 0, - 'doubleSpinBox_value': 10.0, 'spinBox_value': 10, 'slider_value': 10, - 'uislider_value': 10, 'radio_value': False, 'textEdit_value': 'test edit 0', - 'plainTextEdit_value': 'test plain 0', 'lineEdit_value': 'test line 0', - 'pushButton_value': False} - state[1] = { - 'label_value': 'Test label state 1', 'checkbox_value': True, 'combobox_value': 1, - 'doubleSpinBox_value': 1.0, 'spinBox_value': 1, 'slider_value': 1, 'uislider_value': 1, - 'radio_value': True, 'textEdit_value': 'test edit 1', - 'plainTextEdit_value': 'test plain 1', 'lineEdit_value': 'test line 1', - 'pushButton_value': True} + """ + Applies the values saved in `self.exampleState` at position `ii` to the widgets in the form. + + Parameters + ---------------- + ii: int + """ + state=self.exampleState # set the states # QLabel self.form.getWidget('label').setText(state[ii]['label_value']) @@ -350,7 +364,6 @@ def click_Cancel(self): def test_save_states_default(self): # test both states are working - self.form.open() # state1 self.set_state(1) states1 = self.form.getAllWidgetStates() @@ -360,35 +373,24 @@ def test_save_states_default(self): states0 = self.form.getAllWidgetStates() self.assertNotEqual(states1, self.form.getAllWidgetStates()) self.assertEqual(states0, self.form.getAllWidgetStates()) - # together - self.assertEqual(states0, states0) - self.assertEqual(states1, states1) - self.assertNotEqual(states0, states1) - # check nothing is saved when Cancel is pressed + # check state 0 and 1 are not saved when Cancel is pressed self.click_Cancel() self.assertNotEqual(states0, self.form.getAllWidgetStates()) self.assertNotEqual(states1, self.form.getAllWidgetStates()) # save state 0 - self.form.open() self.set_state(0) self.assertEqual(states0, self.form.getAllWidgetStates()) self.click_Ok() - self.form.close() - self.form.open() self.assertEqual(states0, self.form.getAllWidgetStates()) # save state 1 - self.form.open() self.set_state(1) self.assertEqual(states1, self.form.getAllWidgetStates()) self.click_Ok() - self.form.close() - self.form.open() self.assertEqual(states1, self.form.getAllWidgetStates()) # change to state 0 without saving self.set_state(0) self.assertEqual(states0, self.form.getAllWidgetStates()) self.click_Cancel() - self.form.open() self.assertEqual(states1, self.form.getAllWidgetStates()) def test_getWidgetState_returns_QLabel_value(self): From 540f27eb9db7f017cb5498e851bed7401c4b711d Mon Sep 17 00:00:00 2001 From: Danica Sugic Date: Fri, 17 Nov 2023 13:14:48 +0000 Subject: [PATCH 13/96] ii changed to i in test set_state --- test/test__formUI_status_test.py | 30 +++++++++++++++--------------- 1 file changed, 15 insertions(+), 15 deletions(-) diff --git a/test/test__formUI_status_test.py b/test/test__formUI_status_test.py index 1e228a9..600003c 100644 --- a/test/test__formUI_status_test.py +++ b/test/test__formUI_status_test.py @@ -61,43 +61,43 @@ def add_two_widgets(self): form.addWidget(QtWidgets.QLabel('test label'), 'Label: ', 'label') form.addWidget(QtWidgets.QCheckBox('test checkbox'), 'CheckBox: ', 'checkBox') - def set_state(self, ii): + def set_state(self, i): """ - Applies the values saved in `self.exampleState` at position `ii` to the widgets in the form. + Applies the values saved in `self.exampleState` at position `i` to the widgets in the form. Parameters ---------------- - ii: int + i: int """ state=self.exampleState # set the states # QLabel - self.form.getWidget('label').setText(state[ii]['label_value']) + self.form.getWidget('label').setText(state[i]['label_value']) # QCheckBox - self.form.getWidget('checkBox').setChecked(state[ii]['checkbox_value']) + self.form.getWidget('checkBox').setChecked(state[i]['checkbox_value']) # QComboBox combobox_list = ['test', 'test2'] self.form.getWidget('comboBox').addItems(combobox_list) - self.form.getWidget('comboBox').setCurrentIndex(state[ii]['combobox_value']) + self.form.getWidget('comboBox').setCurrentIndex(state[i]['combobox_value']) # QDoubleSpinBox - self.form.getWidget('doubleSpinBox').setValue(state[ii]['doubleSpinBox_value']) + self.form.getWidget('doubleSpinBox').setValue(state[i]['doubleSpinBox_value']) # QSpinBox - self.form.getWidget('spinBox').setValue(state[ii]['spinBox_value']) + self.form.getWidget('spinBox').setValue(state[i]['spinBox_value']) # QSlider - self.form.getWidget('slider').setValue(state[ii]['slider_value']) + self.form.getWidget('slider').setValue(state[i]['slider_value']) # UISlider - self.form.getWidget('uiSliderWidget').setValue(state[ii]['uislider_value']) + self.form.getWidget('uiSliderWidget').setValue(state[i]['uislider_value']) # QRadioButton - self.form.getWidget('radioButton').setChecked(state[ii]['radio_value']) + self.form.getWidget('radioButton').setChecked(state[i]['radio_value']) # QTextEdit - self.form.getWidget('textEdit').setText(state[ii]['textEdit_value']) + self.form.getWidget('textEdit').setText(state[i]['textEdit_value']) # QPlainTextEdit - self.form.getWidget('plainTextEdit').setPlainText(state[ii]['plainTextEdit_value']) + self.form.getWidget('plainTextEdit').setPlainText(state[i]['plainTextEdit_value']) # QLineEdit - self.form.getWidget('lineEdit').setText(state[ii]['lineEdit_value']) + self.form.getWidget('lineEdit').setText(state[i]['lineEdit_value']) # QPushButton self.form.getWidget('button').setCheckable(True) - self.form.getWidget('button').setChecked(state[ii]['pushButton_value']) + self.form.getWidget('button').setChecked(state[i]['pushButton_value']) def test_getWidgetState_returns_visibility(self): """ From 006e4a947410d7a2b5be78a4539d3b1579fe3d75 Mon Sep 17 00:00:00 2001 From: Danica Sugic Date: Fri, 17 Nov 2023 14:00:35 +0000 Subject: [PATCH 14/96] Improve applyDefaultWidgetValuesToState with docstring and new name --- eqt/ui/UIFormWidget.py | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/eqt/ui/UIFormWidget.py b/eqt/ui/UIFormWidget.py index c666b26..73ae99e 100644 --- a/eqt/ui/UIFormWidget.py +++ b/eqt/ui/UIFormWidget.py @@ -148,7 +148,12 @@ def _addWidget(self, name, qwidget, qlabel=None): formLayout.setWidget(widgetno, field_form_role, qwidget) self.num_widgets += 1 - def applyWidgetValuesToState(self): + def applyDefaultWidgetValuesToState(self): + ''' + Saves all states in a form widget - typically invoked when a form is firstly opened and no states are saved yet. + Retrieves the default values from the widgets and applies them to the saved states - this preserves visible and + enabled in the widgets. + ''' self.saveAllWidgetStates() for state_key in self.widget_default.keys(): self.widget_states[state_key]['value']=self.widget_default[state_key] @@ -315,7 +320,7 @@ def restoreAllSavedWidgetStates(self): If `saveAllWidgetStates()` method was not previously invoked, do nothing. ''' if not hasattr(self, 'widget_states'): - self.applyWidgetValuesToState() + self.applyDefaultWidgetValuesToState() self.applyWidgetStates(self.widget_states) From 54235ecfbc8bdda8f4cd9563c724d46f5fef8202 Mon Sep 17 00:00:00 2001 From: Danica Sugic Date: Fri, 17 Nov 2023 14:14:50 +0000 Subject: [PATCH 15/96] Change docstring to restoreAllSavedWidgetStates --- eqt/ui/UIFormWidget.py | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/eqt/ui/UIFormWidget.py b/eqt/ui/UIFormWidget.py index 73ae99e..0d22954 100644 --- a/eqt/ui/UIFormWidget.py +++ b/eqt/ui/UIFormWidget.py @@ -316,8 +316,10 @@ def saveAllWidgetStates(self): def restoreAllSavedWidgetStates(self): ''' - Restore all widgets in the form to the state saved by `saveAllWidgetStates()`. - If `saveAllWidgetStates()` method was not previously invoked, do nothing. + There are saved states only if `saveAllWidgetStates` was previously invoked. + If there are no previously saved states, `applyDefaultWidgetValuesToState` + saves the states and applies default values to them. Once the existence of the + `widget_states` is checked, all widgets in the form are restored to the saved states. ''' if not hasattr(self, 'widget_states'): self.applyDefaultWidgetValuesToState() From 424d6b498c33a3b95257ea4112231929e38e4738 Mon Sep 17 00:00:00 2001 From: Danica Sugic Date: Fri, 17 Nov 2023 14:31:00 +0000 Subject: [PATCH 16/96] Pre-commit run --- eqt/ui/UIFormWidget.py | 24 ++++++++++----------- examples/dialog_example_3_save_default.py | 3 +-- examples/utilitiesForExamples.py | 6 +++--- test/test__formUI_status_test.py | 26 ++++++++++------------- 4 files changed, 27 insertions(+), 32 deletions(-) diff --git a/eqt/ui/UIFormWidget.py b/eqt/ui/UIFormWidget.py index 0d22954..5c5fd32 100644 --- a/eqt/ui/UIFormWidget.py +++ b/eqt/ui/UIFormWidget.py @@ -111,7 +111,7 @@ def _addWidget(self, name, qwidget, qlabel=None): # create the default values if not hasattr(self, 'widget_default'): - self.widget_default={} + self.widget_default = {} # Create the widgets: @@ -122,7 +122,7 @@ def _addWidget(self, name, qwidget, qlabel=None): self.widgets[field] = qwidget # add the default value of the qwidget - self.widget_default[field]=self.getWidgetState(qwidget)['value'] + self.widget_default[field] = self.getWidgetState(qwidget)['value'] if qlabel is not None: # add the label @@ -132,14 +132,14 @@ def _addWidget(self, name, qwidget, qlabel=None): qlabel = QtWidgets.QLabel(self.uiElements['groupBox']) qlabel.setText(txt) formLayout.setWidget(widgetno, QtWidgets.QFormLayout.LabelRole, qlabel) - + # save a reference to label widgets in the dictionary self.widgets[label] = qlabel field_form_role = QtWidgets.QFormLayout.FieldRole # add the default value of the qlabel - self.widget_default[label]=self.getWidgetState(qlabel,label)['value'] + self.widget_default[label] = self.getWidgetState(qlabel, label)['value'] else: # In the case we don't have a qlabel, set a spanning widget: @@ -150,14 +150,14 @@ def _addWidget(self, name, qwidget, qlabel=None): def applyDefaultWidgetValuesToState(self): ''' - Saves all states in a form widget - typically invoked when a form is firstly opened and no states are saved yet. - Retrieves the default values from the widgets and applies them to the saved states - this preserves visible and - enabled in the widgets. + Saves all states in a form widget - typically invoked when a form is firstly opened + and no states are saved yet. Retrieves the default values from the widgets and applies + them to the saved states - this preserves visible and enabled in the widgets. ''' self.saveAllWidgetStates() for state_key in self.widget_default.keys(): - self.widget_states[state_key]['value']=self.widget_default[state_key] - + self.widget_states[state_key]['value'] = self.widget_default[state_key] + def getAllWidgetStates(self): ''' Returns @@ -317,15 +317,15 @@ def saveAllWidgetStates(self): def restoreAllSavedWidgetStates(self): ''' There are saved states only if `saveAllWidgetStates` was previously invoked. - If there are no previously saved states, `applyDefaultWidgetValuesToState` - saves the states and applies default values to them. Once the existence of the + If there are no previously saved states, `applyDefaultWidgetValuesToState` + saves the states and applies default values to them. Once the existence of the `widget_states` is checked, all widgets in the form are restored to the saved states. ''' if not hasattr(self, 'widget_states'): self.applyDefaultWidgetValuesToState() self.applyWidgetStates(self.widget_states) - + class FormWidget(QtWidgets.QWidget, UIFormWidget): def __init__(self, parent=None): # dockWidgetContents = QtWidgets.QWidget() diff --git a/examples/dialog_example_3_save_default.py b/examples/dialog_example_3_save_default.py index 8b0f655..27c8cc5 100644 --- a/examples/dialog_example_3_save_default.py +++ b/examples/dialog_example_3_save_default.py @@ -1,11 +1,10 @@ import sys +import utilitiesForExamples as utex from PySide2 import QtWidgets from eqt.ui import FormDialog -import utilitiesForExamples as utex - class MainUI(QtWidgets.QMainWindow): def __init__(self, parent=None): diff --git a/examples/utilitiesForExamples.py b/examples/utilitiesForExamples.py index 1b5a9ec..19eda57 100644 --- a/examples/utilitiesForExamples.py +++ b/examples/utilitiesForExamples.py @@ -1,6 +1,8 @@ from PySide2 import QtWidgets + from eqt.ui.UISliderWidget import UISliderWidget + def addWidgetsToExample(form): ''' Adds a spanning widget and every type of widget to a form @@ -19,8 +21,6 @@ def addWidgetsToExample(form): form.addWidget(UISliderWidget(QtWidgets.QLabel()), 'UISlider: ', 'uiSliderWidget') form.addWidget(QtWidgets.QRadioButton('select me'), 'RadioButton: ', 'radioButton') form.addWidget(QtWidgets.QTextEdit('write text here'), 'TextEdit: ', 'textEdit') - form.addWidget(QtWidgets.QPlainTextEdit('write text here'), 'PlainTextEdit: ', - 'plainTextEdit') + form.addWidget(QtWidgets.QPlainTextEdit('write text here'), 'PlainTextEdit: ', 'plainTextEdit') form.addWidget(QtWidgets.QLineEdit('write text here'), 'LineEdit: ', 'lineEdit') form.addWidget(QtWidgets.QPushButton('Click me'), 'Button: ', 'button') - diff --git a/test/test__formUI_status_test.py b/test/test__formUI_status_test.py index 600003c..5db1eba 100644 --- a/test/test__formUI_status_test.py +++ b/test/test__formUI_status_test.py @@ -15,28 +15,24 @@ class FormsCommonTests(metaclass=abc.ABCMeta): """Common tests for all Form types""" - @abc.abstractmethod def setUp(self): raise NotImplementedError - - @property - def exampleState(self): + + @property + def exampleState(self): # define two states for every widget - state=[ - { + state = [{ 'label_value': 'Test label state 0', 'checkbox_value': False, 'combobox_value': 0, 'doubleSpinBox_value': 10.0, 'spinBox_value': 10, 'slider_value': 10, 'uislider_value': 10, 'radio_value': False, 'textEdit_value': 'test edit 0', 'plainTextEdit_value': 'test plain 0', 'lineEdit_value': 'test line 0', - 'pushButton_value': False}, - { - 'label_value': 'Test label state 1', 'checkbox_value': True, 'combobox_value': 1, - 'doubleSpinBox_value': 1.0, 'spinBox_value': 1, 'slider_value': 1, 'uislider_value': 1, - 'radio_value': True, 'textEdit_value': 'test edit 1', - 'plainTextEdit_value': 'test plain 1', 'lineEdit_value': 'test line 1', - 'pushButton_value': True} - ] + 'pushButton_value': False}, { + 'label_value': 'Test label state 1', 'checkbox_value': True, 'combobox_value': 1, + 'doubleSpinBox_value': 1.0, 'spinBox_value': 1, 'slider_value': 1, + 'uislider_value': 1, 'radio_value': True, 'textEdit_value': 'test edit 1', + 'plainTextEdit_value': 'test plain 1', 'lineEdit_value': 'test line 1', + 'pushButton_value': True}] return state def add_every_widget(self): @@ -69,7 +65,7 @@ def set_state(self, i): ---------------- i: int """ - state=self.exampleState + state = self.exampleState # set the states # QLabel self.form.getWidget('label').setText(state[i]['label_value']) From 78ec108ef6924f74560c1233d8988746e6375890 Mon Sep 17 00:00:00 2001 From: Danica Sugic Date: Mon, 20 Nov 2023 20:53:08 +0000 Subject: [PATCH 17/96] add insert widget working with add row and extra example --- eqt/ui/FormDialog.py | 14 ++- eqt/ui/UIFormWidget.py | 14 +++ examples/insert_widgets_example.py | 148 +++++++++++++++++++++++++++++ 3 files changed, 172 insertions(+), 4 deletions(-) create mode 100644 examples/insert_widgets_example.py diff --git a/eqt/ui/FormDialog.py b/eqt/ui/FormDialog.py index 53ef76f..ff0a940 100644 --- a/eqt/ui/FormDialog.py +++ b/eqt/ui/FormDialog.py @@ -74,6 +74,16 @@ def addWidget(self, qwidget, qlabel=None, name=None, layout='form'): else: raise ValueError(f"layout '{layout}' unrecognised: expected 'form' or 'vertical'") + def insertWidget3(self, index, qwidget, qlabel, name): + '''Invokes `insertWidget` from `UIFormWidget`.''' + self.formWidget.insertWidget3(index, qwidget, qlabel, name) + + def insertWidgetVerticalLayout(self, index, qwidget): + ''' + Inserts a widget to the vertical layout at the specific index. + ''' + self.formWidget.uiElements['verticalLayout'].insertWidget(index, qwidget) + def removeWidget(self, name): ''' Removes a widget (and its label if present) from the layout. @@ -107,10 +117,6 @@ def getNumWidgets(self): ''' return self.formWidget.getNumWidgets() - def insertWidget(self, index, qwidget): - '''inserts a widget to the vertical layout at the specific index''' - self.formWidget.uiElements['verticalLayout'].insertWidget(index, qwidget) - def getWidget(self, name, role='field'): '''returns the Widget by the name with which it has been added diff --git a/eqt/ui/UIFormWidget.py b/eqt/ui/UIFormWidget.py index def2939..36097ce 100644 --- a/eqt/ui/UIFormWidget.py +++ b/eqt/ui/UIFormWidget.py @@ -57,6 +57,16 @@ def addSpanningWidget(self, qwidget, name): def addWidget(self, qwidget, qlabel, name): self._addWidget(name, qwidget, qlabel) + def insertWidget3(self, index, qwidget, qlabel, name): + ''' + Inserts a widget to the form layout at the specific index. + ''' + #temp_tot_widgets = self.num_widgets + #self.num_widgets = index + self.uiElements['groupBoxFormLayout'].insertRow(index, qlabel, qwidget) + #self.addWidget(qwidget, qlabel, name) + self.num_widgets += 1 + def removeWidget(self, name): ''' Removes a widget (and its label if present) from the layout. @@ -349,6 +359,10 @@ def addWidget(self, qwidget, qlabel, name): def addSpanningWidget(self, qwidget, name): self.widget().addSpanningWidget(qwidget, name) + def insertWidget(self, index, qwidget): + '''Invokes `insertWidget` from `UIFormWidget`.''' + self.widget().insertWidget(index, qwidget) + def removeWidget(self, name): ''' Removes a widget (and its label if present) from the layout. diff --git a/examples/insert_widgets_example.py b/examples/insert_widgets_example.py new file mode 100644 index 0000000..1db8c49 --- /dev/null +++ b/examples/insert_widgets_example.py @@ -0,0 +1,148 @@ +import sys + +from PySide2 import QtWidgets + +from eqt.ui import FormDialog, UIFormWidget + + +class MainUI(QtWidgets.QMainWindow): + def __init__(self, parent=None): + QtWidgets.QMainWindow.__init__(self, parent) + + # create a FormDockWidget + dock = UIFormWidget.FormDockWidget(parent=self) + dock.setWindowTitle('Example remove widget') + self.addWidgetsToExampleForm(dock) + + # create button for Form Dialog + pb = QtWidgets.QPushButton(self) + pb.setText("Open Form Dialog") + pb.clicked.connect(lambda: self.openFormDialog()) + + # create window layout + layout = QtWidgets.QHBoxLayout() + layout.addWidget(pb) + layout.addWidget(dock) + widg = QtWidgets.QWidget() + widg.setLayout(layout) + self.setCentralWidget(widg) + + # print dictionary of all widgets in dock + print("\nDictionary of widgets in the Form Dock Widget:\n" + str(dock.getWidgets())) + + self.show() + + def openFormDialog(self): + dialog = FormDialog(parent=self, title='Example remove widget') + buttonuser = QtWidgets.QPushButton(self) + buttonuser.setText("inserted widget") + print(dialog.formWidget.uiElements['verticalLayout'].count(),dialog.formWidget.uiElements['groupBoxFormLayout'].count(),dialog.formWidget.num_widgets) + #dialog.Ok.clicked.connect(lambda: self.insert(dialog, buttonuser)) + + + dialog.insertWidgetVerticalLayout(3, buttonuser) + dialog.Ok.clicked.connect(lambda: self.insert2(dialog,0, 'Widget 2',qwidget,qlabel)) + + # add input as QComboBox + dialog.addSpanningWidget(QtWidgets.QLabel("Pick the widget you want to remove:"), + 'input_title') + qlabel = QtWidgets.QLabel(dialog) + qlabel.setText("User input: ") + qwidget = QtWidgets.QComboBox(dialog) + qwidget.addItem("Widget 2") + qwidget.addItem("Widget 3") + qwidget.setCurrentIndex(0) + qwidget.setEnabled(True) + dialog.addWidget(qwidget, qlabel, 'userinput') + print(dialog.formWidget.uiElements['verticalLayout'].count(),dialog.formWidget.uiElements['groupBoxFormLayout'].count(),dialog.formWidget.num_widgets) + + # add widget 1 as QLineEdit + qlabel = QtWidgets.QLabel(dialog) + qlabel.setText("Widget 2: ") + qwidget = QtWidgets.QLineEdit(dialog) + #dialog.addWidget(qwidget,qlabel,'hello') + dialog.insertWidget3(3, qwidget,qlabel,'hello') + #self.addWidgetsToExampleForm(dialog) + # dialog.addSpanningWidget( + # QtWidgets.QLabel( + # "Press `Ok` to remove the user selected widget and `Cancel` to close the dialog:"), + # 'ok_cancel_instructions') + + # store a reference + self.dialog = dialog + self.dialog.onCancel = self.rejected + + # print dictionary of all widgets in dialog + print("Dictionary of widgets in Form Dialog:\n" + str(self.dialog.getWidgets())) + + dialog.open() + + def addWidgetsToExampleForm(self, form): + + # add widget 1 as QLineEdit + qlabel = QtWidgets.QLabel(form) + qlabel.setText("Widget 1: ") + qwidget = QtWidgets.QLineEdit(form) + qwidget.setClearButtonEnabled(True) + form.addWidget(qwidget, qlabel, 'Widget 1') + + # add widget 2 as QLineEdit + qlabel = QtWidgets.QLabel(form) + qlabel.setText("Widget 2: ") + qwidget = QtWidgets.QLineEdit(form) + qwidget.setClearButtonEnabled(True) + form.addWidget(qwidget, qlabel, 'Widget 2') + + # add widget 3 as QLineEdit + qlabel = QtWidgets.QLabel(form) + qlabel.setText("Widget 3: ") + qwidget = QtWidgets.QLineEdit(form) + qwidget.setClearButtonEnabled(True) + form.addWidget(qwidget, qlabel, 'Widget 3') + + # add input as QComboBox + form.addSpanningWidget(QtWidgets.QLabel("Pick the widget you want to remove:"), + 'input_title') + qlabel = QtWidgets.QLabel(form) + qlabel.setText("User input: ") + qwidget = QtWidgets.QComboBox(form) + qwidget.addItem("Widget 2") + qwidget.addItem("Widget 3") + qwidget.setCurrentIndex(0) + qwidget.setEnabled(True) + form.addWidget(qwidget, qlabel, 'userinput') + + # add a button to remove widget 1 + button1 = QtWidgets.QPushButton(form) + button1.setText("Remove widget 1") + form.addSpanningWidget(button1, 'Button Remove w1') + button1.clicked.connect(lambda: self.remove(form, button1, 'Widget 1')) + + # add a button to remove spanning widget + buttonspanning = QtWidgets.QPushButton(form) + buttonspanning.setText("Remove spanning widget") + form.addSpanningWidget(buttonspanning, 'Button Remove Spanning') + buttonspanning.clicked.connect(lambda: self.remove(form, buttonspanning, 'input_title')) + + def rejected(self): + print("\nDialog closed.") + + def insert(self, form,qwidget): + form.insertWidgetVerticalLayout(1,qwidget) + print("\nDictionary of widgets after insertion" + ":\n" + + str(form.getWidgets())) + print("insert count"+str(form.formWidget.uiElements['verticalLayout'].count()),form.formWidget.num_widgets) + + def insert2(self, form,index, name,qwidget,qlabel): + #form.insertWidget(index, qwidget,qlabel,name) + print("\nDictionary of widgets after insertion" + ":\n" + + str(form.getWidgets())) + print("insert count"+str(form.formWidget.uiElements['verticalLayout'].count()),form.formWidget.num_widgets) + + +if __name__ == "__main__": + app = QtWidgets.QApplication(sys.argv) + + window = MainUI() + + sys.exit(app.exec_()) From 92d1332a4a38c716124f8a564758c4b8c48771b4 Mon Sep 17 00:00:00 2001 From: lauramurgatroyd Date: Tue, 21 Nov 2023 09:08:55 +0000 Subject: [PATCH 18/96] Fix issues with unit tests --- eqt/ui/SessionDialogs.py | 2 +- test/test_MainWindowWithSessionManagement.py | 46 +------------ ..._MainWindowWithSessionManagementDialogs.py | 68 +++++++++++++++++++ test/test_SessionDialogs.py | 4 ++ 4 files changed, 74 insertions(+), 46 deletions(-) create mode 100644 test/test_MainWindowWithSessionManagementDialogs.py diff --git a/eqt/ui/SessionDialogs.py b/eqt/ui/SessionDialogs.py index 71c44e9..dfb77cf 100644 --- a/eqt/ui/SessionDialogs.py +++ b/eqt/ui/SessionDialogs.py @@ -70,7 +70,7 @@ def __init__(self, parent=None, app_name=None): self.app_name = app_name label_text = ("Select a session directory to save and retrieve all" - f" {app_name or ''} Sessions:") + f"{app_name or ''} Sessions:") self.addSpanningWidget(QLabel(label_text), 'select_session_directory') diff --git a/test/test_MainWindowWithSessionManagement.py b/test/test_MainWindowWithSessionManagement.py index c5f0365..777014c 100644 --- a/test/test_MainWindowWithSessionManagement.py +++ b/test/test_MainWindowWithSessionManagement.py @@ -228,57 +228,13 @@ def tearDown(self): shutil.rmtree("Test Folder") -@skip_ci -class TestMainWindowWithSessionManagementCreateLoadSessionDialog(unittest.TestCase): - ''' - Tests the createLoadSessionDialog method of the MainWindowWithSessionManagement class - - This method is responsible for creating the load session dialog - and populating it with the available sessions - ''' - def setUp(self): - self.title = "title" - self.app_name = "app_name" - self.smw = MainWindowWithSessionManagement(self.title, self.app_name) - self.smw.sessions_directory = mock.MagicMock() - self.zip_folders = ["zip_folder_1", "zip_folder_2"] - - def test_createLoadSessionDialog_populates_session_dropdown(self): - dialog = self.smw.createLoadSessionDialog(self.zip_folders) - assert dialog is not None - assert isinstance(dialog, eqt.ui.SessionDialogs.LoadSessionDialog) - select_session_combo = dialog.getWidget('select_session') - assert select_session_combo is not None - items_in_combo = [ - select_session_combo.itemText(i) for i in range(select_session_combo.count())] - assert items_in_combo == self.zip_folders - - def test_createLoadSessionDialog_connections(self): - dialog = self.smw.createLoadSessionDialog(self.zip_folders) - - self.smw.loadSessionLoad = mock.MagicMock() - self.smw.selectLoadSessionsDirectorySelectedInSessionSelector = mock.MagicMock() - self.smw.loadSessionNew = mock.MagicMock() - - dialog = self.smw.createLoadSessionDialog(self.zip_folders) - - dialog.Ok.click() - self.smw.loadSessionLoad.assert_called_once() - - dialog.Select.click() - self.smw.selectLoadSessionsDirectorySelectedInSessionSelector.assert_called_with(dialog) - - dialog.Cancel.click() - self.smw.loadSessionNew.assert_called_once() - - @skip_ci class TestSelectLoadSessionsDirectorySelectedInSessionSelector(unittest.TestCase): ''' Tests the `selectLoadSessionsDirectorySelectedInSessionSelector` method of the `MainWindowWithSessionManagement` class - This method sould close the passed dialog, and call + This method should close the passed dialog, and call `createSessionsDirectorySelectionDialog(new_session=True)` ''' def setUp(self): diff --git a/test/test_MainWindowWithSessionManagementDialogs.py b/test/test_MainWindowWithSessionManagementDialogs.py new file mode 100644 index 0000000..81a611f --- /dev/null +++ b/test/test_MainWindowWithSessionManagementDialogs.py @@ -0,0 +1,68 @@ + +import json +import os +import shutil +import unittest +from datetime import datetime +from unittest import mock +from unittest.mock import patch + +from PySide2.QtCore import QSettings, QThreadPool +from PySide2.QtWidgets import QMenu, QMenuBar + +import eqt +from eqt.io import zip_directory +from eqt.ui.MainWindowWithSessionManagement import MainWindowWithSessionManagement + +from eqt.ui.SessionDialogs import (LoadSessionDialog) + +from . import skip_ci + +''' Unit tests for the MainWindowWithSessionManagement class +methods which create dialogs''' + +@skip_ci +class TestMainWindowWithSessionManagementCreateLoadSessionDialog(unittest.TestCase): + ''' + Tests the createLoadSessionDialog method of the MainWindowWithSessionManagement class + + This method is responsible for creating the load session dialog + and populating it with the available sessions + ''' + def setUp(self): + self.title = "title" + self.app_name = "app_name" + self.smw = MainWindowWithSessionManagement(self.title, self.app_name) + self.smw.sessions_directory = mock.MagicMock() + self.zip_folders = ["zip_folder_1", "zip_folder_2"] + + def test_createLoadSessionDialog_populates_session_dropdown(self): + dialog = self.smw.createLoadSessionDialog(self.zip_folders) + assert dialog is not None + print(LoadSessionDialog) + print(type(LoadSessionDialog)) + print(type(dialog)) + assert isinstance(dialog, LoadSessionDialog) + select_session_combo = dialog.getWidget('select_session') + assert select_session_combo is not None + items_in_combo = [ + select_session_combo.itemText(i) for i in range(select_session_combo.count())] + assert items_in_combo == self.zip_folders + + def test_createLoadSessionDialog_connections(self): + dialog = self.smw.createLoadSessionDialog(self.zip_folders) + + self.smw.loadSessionLoad = mock.MagicMock() + self.smw.selectLoadSessionsDirectorySelectedInSessionSelector = mock.MagicMock() + self.smw.loadSessionNew = mock.MagicMock() + + dialog = self.smw.createLoadSessionDialog(self.zip_folders) + + dialog.Ok.click() + self.smw.loadSessionLoad.assert_called_once() + + dialog.Select.click() + self.smw.selectLoadSessionsDirectorySelectedInSessionSelector.assert_called_with(dialog) + + dialog.Cancel.click() + self.smw.loadSessionNew.assert_called_once() diff --git a/test/test_SessionDialogs.py b/test/test_SessionDialogs.py index 5a3c352..4761c13 100644 --- a/test/test_SessionDialogs.py +++ b/test/test_SessionDialogs.py @@ -1,6 +1,7 @@ import os import unittest from pathlib import Path +from unittest import mock from unittest.mock import patch from PySide2.QtWidgets import QFileDialog @@ -14,6 +15,8 @@ WarningDialog, ) +from eqt.ui.MainWindowWithSessionManagement import MainWindowWithSessionManagement + from . import skip_ci @@ -139,3 +142,4 @@ class TestAppSettingsDialog(unittest.TestCase): def test_init(self): asd = AppSettingsDialog() assert asd is not None + From 94f172e0cb34570b40781f38fe534d7efbc66710 Mon Sep 17 00:00:00 2001 From: lauramurgatroyd Date: Tue, 21 Nov 2023 09:14:35 +0000 Subject: [PATCH 19/96] Fix issues with session label --- eqt/ui/SessionDialogs.py | 7 ++++++- test/dialog_example_2_test.py | 2 +- test/test_MainWindowWithSessionManagementDialogs.py | 11 +---------- 3 files changed, 8 insertions(+), 12 deletions(-) diff --git a/eqt/ui/SessionDialogs.py b/eqt/ui/SessionDialogs.py index dfb77cf..cf5a35d 100644 --- a/eqt/ui/SessionDialogs.py +++ b/eqt/ui/SessionDialogs.py @@ -69,8 +69,13 @@ def __init__(self, parent=None, app_name=None): self.app_name = app_name + if app_name is not None: + app_name_label = ' ' + app_name + else: + app_name_label = '' + label_text = ("Select a session directory to save and retrieve all" - f"{app_name or ''} Sessions:") + f"{app_name_label} Sessions:") self.addSpanningWidget(QLabel(label_text), 'select_session_directory') diff --git a/test/dialog_example_2_test.py b/test/dialog_example_2_test.py index 1bacc34..d15e7f1 100644 --- a/test/dialog_example_2_test.py +++ b/test/dialog_example_2_test.py @@ -56,7 +56,7 @@ def openFormDialog(self): # store a reference self.dialog = dialog - dialog.exec() + dialog.open() def accepted(self): print("accepted") diff --git a/test/test_MainWindowWithSessionManagementDialogs.py b/test/test_MainWindowWithSessionManagementDialogs.py index 81a611f..f611b88 100644 --- a/test/test_MainWindowWithSessionManagementDialogs.py +++ b/test/test_MainWindowWithSessionManagementDialogs.py @@ -1,20 +1,11 @@ -import json -import os -import shutil import unittest -from datetime import datetime from unittest import mock -from unittest.mock import patch -from PySide2.QtCore import QSettings, QThreadPool -from PySide2.QtWidgets import QMenu, QMenuBar - -import eqt from eqt.io import zip_directory from eqt.ui.MainWindowWithSessionManagement import MainWindowWithSessionManagement -from eqt.ui.SessionDialogs import (LoadSessionDialog) +from eqt.ui.SessionDialogs import LoadSessionDialog from . import skip_ci From d6d2cc6eadf2acd8e58d926c86dbaf72be94f4f3 Mon Sep 17 00:00:00 2001 From: "pre-commit-ci[bot]" <66853113+pre-commit-ci[bot]@users.noreply.github.com> Date: Tue, 21 Nov 2023 09:15:52 +0000 Subject: [PATCH 20/96] [pre-commit.ci] auto fixes from pre-commit.com hooks for more information, see https://pre-commit.ci --- test/test_MainWindowWithSessionManagementDialogs.py | 3 +-- test/test_SessionDialogs.py | 4 +--- 2 files changed, 2 insertions(+), 5 deletions(-) diff --git a/test/test_MainWindowWithSessionManagementDialogs.py b/test/test_MainWindowWithSessionManagementDialogs.py index f611b88..6a38afb 100644 --- a/test/test_MainWindowWithSessionManagementDialogs.py +++ b/test/test_MainWindowWithSessionManagementDialogs.py @@ -1,10 +1,8 @@ - import unittest from unittest import mock from eqt.io import zip_directory from eqt.ui.MainWindowWithSessionManagement import MainWindowWithSessionManagement - from eqt.ui.SessionDialogs import LoadSessionDialog from . import skip_ci @@ -12,6 +10,7 @@ ''' Unit tests for the MainWindowWithSessionManagement class methods which create dialogs''' + @skip_ci class TestMainWindowWithSessionManagementCreateLoadSessionDialog(unittest.TestCase): ''' diff --git a/test/test_SessionDialogs.py b/test/test_SessionDialogs.py index 4761c13..31b2d7b 100644 --- a/test/test_SessionDialogs.py +++ b/test/test_SessionDialogs.py @@ -6,6 +6,7 @@ from PySide2.QtWidgets import QFileDialog +from eqt.ui.MainWindowWithSessionManagement import MainWindowWithSessionManagement from eqt.ui.SessionDialogs import ( AppSettingsDialog, ErrorDialog, @@ -15,8 +16,6 @@ WarningDialog, ) -from eqt.ui.MainWindowWithSessionManagement import MainWindowWithSessionManagement - from . import skip_ci @@ -142,4 +141,3 @@ class TestAppSettingsDialog(unittest.TestCase): def test_init(self): asd = AppSettingsDialog() assert asd is not None - From 73f419c09a32b2e7432d60ac1345d8bbf6fb19c1 Mon Sep 17 00:00:00 2001 From: lauramurgatroyd Date: Tue, 21 Nov 2023 09:21:12 +0000 Subject: [PATCH 21/96] Fix formatting --- test/test_MainWindowWithSessionManagementDialogs.py | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/test/test_MainWindowWithSessionManagementDialogs.py b/test/test_MainWindowWithSessionManagementDialogs.py index 6a38afb..2f00f0c 100644 --- a/test/test_MainWindowWithSessionManagementDialogs.py +++ b/test/test_MainWindowWithSessionManagementDialogs.py @@ -1,14 +1,13 @@ import unittest from unittest import mock -from eqt.io import zip_directory from eqt.ui.MainWindowWithSessionManagement import MainWindowWithSessionManagement from eqt.ui.SessionDialogs import LoadSessionDialog from . import skip_ci -''' Unit tests for the MainWindowWithSessionManagement class -methods which create dialogs''' +# Unit tests for the MainWindowWithSessionManagement class +# methods which create dialogs @skip_ci From ccdf0fa39e07a6827c8c35492273108ed5fa1438 Mon Sep 17 00:00:00 2001 From: lauramurgatroyd Date: Tue, 21 Nov 2023 09:27:18 +0000 Subject: [PATCH 22/96] Remove unused imports --- test/test_SessionDialogs.py | 2 -- 1 file changed, 2 deletions(-) diff --git a/test/test_SessionDialogs.py b/test/test_SessionDialogs.py index 31b2d7b..5a3c352 100644 --- a/test/test_SessionDialogs.py +++ b/test/test_SessionDialogs.py @@ -1,12 +1,10 @@ import os import unittest from pathlib import Path -from unittest import mock from unittest.mock import patch from PySide2.QtWidgets import QFileDialog -from eqt.ui.MainWindowWithSessionManagement import MainWindowWithSessionManagement from eqt.ui.SessionDialogs import ( AppSettingsDialog, ErrorDialog, From 05ff03703b744ba53b57e0080d250c26c5cc12bc Mon Sep 17 00:00:00 2001 From: lauramurgatroyd Date: Tue, 21 Nov 2023 09:29:23 +0000 Subject: [PATCH 23/96] remove prints --- test/test_MainWindowWithSessionManagementDialogs.py | 3 --- 1 file changed, 3 deletions(-) diff --git a/test/test_MainWindowWithSessionManagementDialogs.py b/test/test_MainWindowWithSessionManagementDialogs.py index 2f00f0c..1c8bb79 100644 --- a/test/test_MainWindowWithSessionManagementDialogs.py +++ b/test/test_MainWindowWithSessionManagementDialogs.py @@ -28,9 +28,6 @@ def setUp(self): def test_createLoadSessionDialog_populates_session_dropdown(self): dialog = self.smw.createLoadSessionDialog(self.zip_folders) assert dialog is not None - print(LoadSessionDialog) - print(type(LoadSessionDialog)) - print(type(dialog)) assert isinstance(dialog, LoadSessionDialog) select_session_combo = dialog.getWidget('select_session') assert select_session_combo is not None From ff08cf422217510a340a1c9dfd6196113b9c0304 Mon Sep 17 00:00:00 2001 From: Danica Sugic Date: Tue, 21 Nov 2023 16:57:15 +0000 Subject: [PATCH 24/96] Working example and improved insert methods --- eqt/ui/FormDialog.py | 10 +-- eqt/ui/UIFormWidget.py | 25 ++++--- examples/insert_widgets_example.py | 111 +++++++++++------------------ 3 files changed, 62 insertions(+), 84 deletions(-) diff --git a/eqt/ui/FormDialog.py b/eqt/ui/FormDialog.py index ff0a940..8d56c64 100644 --- a/eqt/ui/FormDialog.py +++ b/eqt/ui/FormDialog.py @@ -74,15 +74,15 @@ def addWidget(self, qwidget, qlabel=None, name=None, layout='form'): else: raise ValueError(f"layout '{layout}' unrecognised: expected 'form' or 'vertical'") - def insertWidget3(self, index, qwidget, qlabel, name): + def insertWidgetToFormLayout(self, row, name, qwidget, qlabel=None): '''Invokes `insertWidget` from `UIFormWidget`.''' - self.formWidget.insertWidget3(index, qwidget, qlabel, name) + self.formWidget.insertWidgetToFormLayout(row, name, qwidget, qlabel) - def insertWidgetVerticalLayout(self, index, qwidget): + def insertWidgetToVerticalLayout(self, row, qwidget): ''' - Inserts a widget to the vertical layout at the specific index. + Inserts a widget to the vertical layout at position specified by row. ''' - self.formWidget.uiElements['verticalLayout'].insertWidget(index, qwidget) + self.formWidget.uiElements['verticalLayout'].insertWidget(row, qwidget) def removeWidget(self, name): ''' diff --git a/eqt/ui/UIFormWidget.py b/eqt/ui/UIFormWidget.py index 36097ce..f07b1b6 100644 --- a/eqt/ui/UIFormWidget.py +++ b/eqt/ui/UIFormWidget.py @@ -57,14 +57,21 @@ def addSpanningWidget(self, qwidget, name): def addWidget(self, qwidget, qlabel, name): self._addWidget(name, qwidget, qlabel) - def insertWidget3(self, index, qwidget, qlabel, name): + def insertWidgetToFormLayout(self, row, name, qwidget, qlabel=None): ''' - Inserts a widget to the form layout at the specific index. + Inserts a widget and a label widget or a spanning widget to the form layout in the position specified by row. + If row is out of bounds, the widget is added at the end. + It adds the field (and label if present) in the widget dictionary. + It increases "num_widgets" by 1 unit. ''' - #temp_tot_widgets = self.num_widgets - #self.num_widgets = index - self.uiElements['groupBoxFormLayout'].insertRow(index, qlabel, qwidget) - #self.addWidget(qwidget, qlabel, name) + field = f'{name}_field' + self.widgets[field] = qwidget + if qlabel is not None: + self.uiElements['groupBoxFormLayout'].insertRow(row, qlabel, qwidget) + label = f'{name}_label' + self.widgets[label] = qlabel + else: + self.uiElements['groupBoxFormLayout'].insertRow(row, qwidget) self.num_widgets += 1 def removeWidget(self, name): @@ -359,9 +366,9 @@ def addWidget(self, qwidget, qlabel, name): def addSpanningWidget(self, qwidget, name): self.widget().addSpanningWidget(qwidget, name) - def insertWidget(self, index, qwidget): - '''Invokes `insertWidget` from `UIFormWidget`.''' - self.widget().insertWidget(index, qwidget) + def insertWidgetToFormLayout(self, row, name, qwidget, qlabel=None): + '''Invokes `insertWidgetToFormLayout(` from `UIFormWidget`.''' + self.widget().insertWidgetToFormLayout(row, name, qwidget, qlabel) def removeWidget(self, name): ''' diff --git a/examples/insert_widgets_example.py b/examples/insert_widgets_example.py index 1db8c49..1462092 100644 --- a/examples/insert_widgets_example.py +++ b/examples/insert_widgets_example.py @@ -11,9 +11,13 @@ def __init__(self, parent=None): # create a FormDockWidget dock = UIFormWidget.FormDockWidget(parent=self) - dock.setWindowTitle('Example remove widget') + dock.setWindowTitle('Example insert widget') self.addWidgetsToExampleForm(dock) - + buttoninsert = QtWidgets.QPushButton(dock) + buttoninsert.setText("Insert widgets") + dock.addSpanningWidget(buttoninsert, 'Button insert widgets') + buttoninsert.clicked.connect(lambda: self.insert_form(dock,buttoninsert)) + # create button for Form Dialog pb = QtWidgets.QPushButton(self) pb.setText("Open Form Dialog") @@ -33,35 +37,16 @@ def __init__(self, parent=None): self.show() def openFormDialog(self): - dialog = FormDialog(parent=self, title='Example remove widget') - buttonuser = QtWidgets.QPushButton(self) - buttonuser.setText("inserted widget") - print(dialog.formWidget.uiElements['verticalLayout'].count(),dialog.formWidget.uiElements['groupBoxFormLayout'].count(),dialog.formWidget.num_widgets) - #dialog.Ok.clicked.connect(lambda: self.insert(dialog, buttonuser)) + dialog = FormDialog(parent=self, title='Example insert widget') + self.addWidgetsToExampleForm(dialog) - - dialog.insertWidgetVerticalLayout(3, buttonuser) - dialog.Ok.clicked.connect(lambda: self.insert2(dialog,0, 'Widget 2',qwidget,qlabel)) - - # add input as QComboBox - dialog.addSpanningWidget(QtWidgets.QLabel("Pick the widget you want to remove:"), - 'input_title') - qlabel = QtWidgets.QLabel(dialog) - qlabel.setText("User input: ") - qwidget = QtWidgets.QComboBox(dialog) - qwidget.addItem("Widget 2") - qwidget.addItem("Widget 3") - qwidget.setCurrentIndex(0) - qwidget.setEnabled(True) - dialog.addWidget(qwidget, qlabel, 'userinput') + print(dialog.formWidget.uiElements['verticalLayout'].count(),dialog.formWidget.uiElements['groupBoxFormLayout'].count(),dialog.formWidget.num_widgets) + dialog.Ok.clicked.connect(lambda: self.insert_vertical(dialog)) + dialog.Ok.clicked.connect(lambda: self.insert_form(dialog, dialog.Ok)) print(dialog.formWidget.uiElements['verticalLayout'].count(),dialog.formWidget.uiElements['groupBoxFormLayout'].count(),dialog.formWidget.num_widgets) - # add widget 1 as QLineEdit - qlabel = QtWidgets.QLabel(dialog) - qlabel.setText("Widget 2: ") - qwidget = QtWidgets.QLineEdit(dialog) - #dialog.addWidget(qwidget,qlabel,'hello') - dialog.insertWidget3(3, qwidget,qlabel,'hello') + + #self.addWidgetsToExampleForm(dialog) # dialog.addSpanningWidget( # QtWidgets.QLabel( @@ -81,64 +66,50 @@ def addWidgetsToExampleForm(self, form): # add widget 1 as QLineEdit qlabel = QtWidgets.QLabel(form) - qlabel.setText("Widget 1: ") - qwidget = QtWidgets.QLineEdit(form) - qwidget.setClearButtonEnabled(True) - form.addWidget(qwidget, qlabel, 'Widget 1') - - # add widget 2 as QLineEdit - qlabel = QtWidgets.QLabel(form) - qlabel.setText("Widget 2: ") + qlabel.setText("Initial widget raw 0: ") qwidget = QtWidgets.QLineEdit(form) qwidget.setClearButtonEnabled(True) - form.addWidget(qwidget, qlabel, 'Widget 2') - - # add widget 3 as QLineEdit - qlabel = QtWidgets.QLabel(form) - qlabel.setText("Widget 3: ") - qwidget = QtWidgets.QLineEdit(form) - qwidget.setClearButtonEnabled(True) - form.addWidget(qwidget, qlabel, 'Widget 3') + form.addWidget(qwidget, qlabel, 'Initial widget raw 0') + #add spanning widget + form.addSpanningWidget(QtWidgets.QLabel("Initial widget row 1"), + 'Initial widget row 1') # add input as QComboBox - form.addSpanningWidget(QtWidgets.QLabel("Pick the widget you want to remove:"), - 'input_title') qlabel = QtWidgets.QLabel(form) - qlabel.setText("User input: ") + qlabel.setText("Initial widget row 2") qwidget = QtWidgets.QComboBox(form) - qwidget.addItem("Widget 2") - qwidget.addItem("Widget 3") + qwidget.addItem("0") + qwidget.addItem("1") qwidget.setCurrentIndex(0) qwidget.setEnabled(True) - form.addWidget(qwidget, qlabel, 'userinput') - - # add a button to remove widget 1 - button1 = QtWidgets.QPushButton(form) - button1.setText("Remove widget 1") - form.addSpanningWidget(button1, 'Button Remove w1') - button1.clicked.connect(lambda: self.remove(form, button1, 'Widget 1')) - - # add a button to remove spanning widget - buttonspanning = QtWidgets.QPushButton(form) - buttonspanning.setText("Remove spanning widget") - form.addSpanningWidget(buttonspanning, 'Button Remove Spanning') - buttonspanning.clicked.connect(lambda: self.remove(form, buttonspanning, 'input_title')) + form.addWidget(qwidget, qlabel, 'Initial widget row 2') def rejected(self): print("\nDialog closed.") - def insert(self, form,qwidget): - form.insertWidgetVerticalLayout(1,qwidget) - print("\nDictionary of widgets after insertion" + ":\n" + + def insert_vertical(self, form): + buttonuser = QtWidgets.QPushButton(self) + buttonuser.setText("Insert widget") + form.insertWidgetToVerticalLayout(1,buttonuser) + print("\nDictionary of widgets after insertion in the vertical lyout" + ":\n" + str(form.getWidgets())) print("insert count"+str(form.formWidget.uiElements['verticalLayout'].count()),form.formWidget.num_widgets) - def insert2(self, form,index, name,qwidget,qlabel): - #form.insertWidget(index, qwidget,qlabel,name) - print("\nDictionary of widgets after insertion" + ":\n" + - str(form.getWidgets())) - print("insert count"+str(form.formWidget.uiElements['verticalLayout'].count()),form.formWidget.num_widgets) + def insert_form(self, form, button): + # insert widget + qlabel = QtWidgets.QLabel(form) + qlabel.setText("Widget inserted in row 0: ") + qwidget = QtWidgets.QLineEdit(form) + form.insertWidgetToFormLayout(0, 'inserted widget', qwidget, qlabel) + + buttonuser = QtWidgets.QPushButton(self) + buttonuser.setText("Inserted widget in row 2") + form.insertWidgetToFormLayout(2, 'inserted spanning widget', buttonuser) + + print("\nDictionary of widgets after insertion in the form layout" + ":\n" + + str(form.getWidgets())) + button.setEnabled(False) if __name__ == "__main__": app = QtWidgets.QApplication(sys.argv) From a3b5c4062ec5c841b904e59536844a0a97cea347 Mon Sep 17 00:00:00 2001 From: Danica Sugic Date: Tue, 21 Nov 2023 18:25:55 +0000 Subject: [PATCH 25/96] Add unit test --- examples/insert_widgets_testbuiltTEMP.py | 185 +++++++++++++++++++++++ test/test__formUI_status_test.py | 24 +++ 2 files changed, 209 insertions(+) create mode 100644 examples/insert_widgets_testbuiltTEMP.py diff --git a/examples/insert_widgets_testbuiltTEMP.py b/examples/insert_widgets_testbuiltTEMP.py new file mode 100644 index 0000000..2ed47c1 --- /dev/null +++ b/examples/insert_widgets_testbuiltTEMP.py @@ -0,0 +1,185 @@ +import sys + +from PySide2 import QtWidgets + +from eqt.ui import FormDialog, UIFormWidget + +from eqt.ui.UISliderWidget import UISliderWidget + + +class MainUI(QtWidgets.QMainWindow): + def __init__(self, parent=None): + QtWidgets.QMainWindow.__init__(self, parent) + + # create a FormDockWidget + dock = UIFormWidget.FormDockWidget(parent=self) + dock.setWindowTitle('Example insert widget') + self.addWidgetsToExampleForm(dock) + buttoninsert = QtWidgets.QPushButton(dock) + buttoninsert.setText("Insert widgets") + dock.addSpanningWidget(buttoninsert, 'Button insert widgets') + buttoninsert.clicked.connect(lambda: self.insert_form(dock,buttoninsert)) + + form = dock + form.layout=form.widget().uiElements['groupBoxFormLayout'] + form.addWidget(QtWidgets.QLabel('test label'), 'Label: ', 'label') + form.addWidget(QtWidgets.QCheckBox('test checkbox'), 'CheckBox: ', 'checkBox') + form.addWidget(QtWidgets.QComboBox(), 'ComboBox: ', 'comboBox') + form.addWidget(QtWidgets.QDoubleSpinBox(), 'DoubleSpinBox: ', 'doubleSpinBox') + form.addWidget(QtWidgets.QSpinBox(), 'SpinBox: ', 'spinBox') + form.addWidget(QtWidgets.QSlider(), 'Slider: ', 'slider') + form.addWidget(UISliderWidget(QtWidgets.QLabel()), 'UISliderWidget: ', 'uiSliderWidget') + form.addWidget(QtWidgets.QRadioButton('test'), 'RadioButton: ', 'radioButton') + form.addWidget(QtWidgets.QTextEdit('test'), 'TextEdit: ', 'textEdit') + form.addWidget(QtWidgets.QPlainTextEdit('test'), 'PlainTextEdit: ', 'plainTextEdit') + form.addWidget(QtWidgets.QLineEdit('test'), 'LineEdit: ', 'lineEdit') + form.addWidget(QtWidgets.QPushButton('test'), 'Button: ', 'button') + form.addSpanningWidget(QtWidgets.QPushButton('spanning widget'), 'spanning widget') + + self.test_insert_every_widget(form) + + # create button for Form Dialog + pb = QtWidgets.QPushButton(self) + pb.setText("Open Form Dialog") + pb.clicked.connect(lambda: self.openFormDialog()) + + # create window layout + layout = QtWidgets.QHBoxLayout() + layout.addWidget(pb) + layout.addWidget(dock) + widg = QtWidgets.QWidget() + widg.setLayout(layout) + self.setCentralWidget(widg) + + # print dictionary of all widgets in dock + #print("\nDictionary of widgets in the Form Dock Widget:\n" + str(dock.getWidgets())) + + + self.show() + + def openFormDialog(self): + dialog = FormDialog(parent=self, title='Example insert widget') + dialog.layout=dialog.formWidget.uiElements['groupBoxFormLayout'] + self.addWidgetsToExampleForm(dialog) + + form = dialog + form.addWidget(QtWidgets.QLabel('test label'), 'Label: ', 'label') + form.addWidget(QtWidgets.QCheckBox('test checkbox'), 'CheckBox: ', 'checkBox') + form.addWidget(QtWidgets.QComboBox(), 'ComboBox: ', 'comboBox') + form.addWidget(QtWidgets.QDoubleSpinBox(), 'DoubleSpinBox: ', 'doubleSpinBox') + form.addWidget(QtWidgets.QSpinBox(), 'SpinBox: ', 'spinBox') + form.addWidget(QtWidgets.QSlider(), 'Slider: ', 'slider') + form.addWidget(UISliderWidget(QtWidgets.QLabel()), 'UISliderWidget: ', 'uiSliderWidget') + form.addWidget(QtWidgets.QRadioButton('test'), 'RadioButton: ', 'radioButton') + form.addWidget(QtWidgets.QTextEdit('test'), 'TextEdit: ', 'textEdit') + form.addWidget(QtWidgets.QPlainTextEdit('test'), 'PlainTextEdit: ', 'plainTextEdit') + form.addWidget(QtWidgets.QLineEdit('test'), 'LineEdit: ', 'lineEdit') + form.addWidget(QtWidgets.QPushButton('test'), 'Button: ', 'button') + form.addSpanningWidget(QtWidgets.QPushButton('spanning widget'), 'spanning widget') + + self.test_insert_every_widget(form) + + + #print(dialog.formWidget.uiElements['verticalLayout'].count(),dialog.formWidget.uiElements['groupBoxFormLayout'].count(),dialog.formWidget.num_widgets) + dialog.Ok.clicked.connect(lambda: self.insert_vertical(dialog)) + dialog.Ok.clicked.connect(lambda: self.insert_form(dialog, dialog.Ok)) + #print(dialog.formWidget.uiElements['verticalLayout'].count(),dialog.formWidget.uiElements['groupBoxFormLayout'].count(),dialog.formWidget.num_widgets) + + + + #self.addWidgetsToExampleForm(dialog) + # dialog.addSpanningWidget( + # QtWidgets.QLabel( + # "Press `Ok` to remove the user selected widget and `Cancel` to close the dialog:"), + # 'ok_cancel_instructions') + + # store a reference + self.dialog = dialog + self.dialog.onCancel = self.rejected + + # print dictionary of all widgets in dialog + #print("Dictionary of widgets in Form Dialog:\n" + str(self.dialog.getWidgets())) + + dialog.open() + + def addWidgetsToExampleForm(self, form): + + # add widget 1 as QLineEdit + qlabel = QtWidgets.QLabel(form) + qlabel.setText("Initial widget raw 0: ") + qwidget = QtWidgets.QLineEdit(form) + qwidget.setClearButtonEnabled(True) + form.addWidget(qwidget, qlabel, 'Initial widget raw 0') + + #add spanning widget + form.addSpanningWidget(QtWidgets.QLabel("Initial widget row 1"), + 'Initial widget row 1') + # add input as QComboBox + qlabel = QtWidgets.QLabel(form) + qlabel.setText("Initial widget row 2") + qwidget = QtWidgets.QComboBox(form) + qwidget.addItem("0") + qwidget.addItem("1") + qwidget.setCurrentIndex(0) + qwidget.setEnabled(True) + form.addWidget(qwidget, qlabel, 'Initial widget row 2') + + def rejected(self): + print("\nDialog closed.") + + def insert_vertical(self, form): + buttonuser = QtWidgets.QPushButton(self) + buttonuser.setText("Insert widget") + form.insertWidgetToVerticalLayout(1,buttonuser) + #print("\nDictionary of widgets after insertion in the vertical lyout" + ":\n" + + #str(form.getWidgets())) + #print("insert count"+str(form.formWidget.uiElements['verticalLayout'].count()),form.formWidget.num_widgets) + + + def insert_form(self, form, button): + # insert widget + qlabel = QtWidgets.QLabel(form) + qlabel.setText("Widget inserted in row 0: ") + qwidget = QtWidgets.QLineEdit(form) + form.insertWidgetToFormLayout(0, 'inserted widget', qwidget, qlabel) + + buttonuser = QtWidgets.QPushButton(self) + buttonuser.setText("Inserted widget in row 2") + form.insertWidgetToFormLayout(2, 'inserted spanning widget', buttonuser) + + #print("\nDictionary of widgets after insertion in the form layout" + ":\n" + + # str(form.getWidgets())) + button.setEnabled(False) + + def _test_insert_one_widget(self, row,name,form): + qwid = form.getWidget(name, role='field') + if f'{name}_label' in form.getWidgets(): + qlab = form.getWidget(name, role='label') + else: + qlab=None + form.insertWidgetToFormLayout(row,name,qwid, qlab) + position=form.layout.getWidgetPosition(form.getWidget(name,'field')) + print(position[0]) + if f'{name}_label' in form.getWidgets(): + position=form.layout.getWidgetPosition(form.getWidget(name,'label')) + print(position) + + def test_insert_every_widget(self,form): + """Insert every widget from `self.form`""" + list_widgets = [ + 'label', 'checkBox', 'comboBox', 'doubleSpinBox', 'spinBox', 'slider', + 'uiSliderWidget', 'radioButton', 'textEdit', 'plainTextEdit', 'lineEdit', 'button'] + for name in list_widgets: + self._test_insert_one_widget(0,name,form) + + self._test_insert_one_widget(0,'spanning widget',form) + + + + +if __name__ == "__main__": + app = QtWidgets.QApplication(sys.argv) + + window = MainUI() + + sys.exit(app.exec_()) diff --git a/test/test__formUI_status_test.py b/test/test__formUI_status_test.py index c5539c7..46ee0ec 100644 --- a/test/test__formUI_status_test.py +++ b/test/test__formUI_status_test.py @@ -39,6 +39,30 @@ def add_two_widgets(self): form.addWidget(QtWidgets.QLabel('test label'), 'Label: ', 'label') form.addWidget(QtWidgets.QCheckBox('test checkbox'), 'CheckBox: ', 'checkBox') + def _test_insert_one_widget(self, row,name): + """ + Inserts the widget `name` from the widgets dictionary at position row in the layout. + Checks the position of the widget in the form is `row`. + + name: name in the dictionary of the widgets already present in the layout. + """ + qwidget = self.form.getWidget(name, role='field') + if f'{name}_label' in self.form.getWidgets(): + qlabel = self.form.getWidget(name, role='label') + else: + qlabel=None + self.form.insertWidgetToFormLayout(row,name,qwidget, qlabel) + position=self.layout.getWidgetPosition(self.form.getWidget(name,'field'))[0] + self.assertEqual(position, row) + + def test_insert_every_widget(self): + """Inserts every widget from `self.form` in position 0""" + list_widgets = [ + 'label', 'checkBox', 'comboBox', 'doubleSpinBox', 'spinBox', 'slider', + 'uiSliderWidget', 'radioButton', 'textEdit', 'plainTextEdit', 'lineEdit', 'button'] + for name in list_widgets: + self._test_insert_one_widget(0,name) + def _test_remove_one_widget(self, name): """ Remove one widget. From 40d43503a6cbdcfcf0e5f71a068bb4f9fecc98bb Mon Sep 17 00:00:00 2001 From: Danica Sugic Date: Wed, 22 Nov 2023 13:38:41 +0000 Subject: [PATCH 26/96] Improve unit test --- eqt/ui/UIFormWidget.py | 9 ++ examples/insert_widgets_testbuiltTEMP.py | 130 ++++++++++++++--------- test/test__formUI_status_test.py | 72 +++++++++---- 3 files changed, 142 insertions(+), 69 deletions(-) diff --git a/eqt/ui/UIFormWidget.py b/eqt/ui/UIFormWidget.py index f07b1b6..83287ea 100644 --- a/eqt/ui/UIFormWidget.py +++ b/eqt/ui/UIFormWidget.py @@ -63,10 +63,18 @@ def insertWidgetToFormLayout(self, row, name, qwidget, qlabel=None): If row is out of bounds, the widget is added at the end. It adds the field (and label if present) in the widget dictionary. It increases "num_widgets" by 1 unit. + It should not be used to move widgets in a form. + ---------- + qlabel: str or qlabel widget ''' field = f'{name}_field' self.widgets[field] = qwidget if qlabel is not None: + if isinstance(qlabel, str): + txt = qlabel + qlabel = QtWidgets.QLabel(self) + qlabel.setText(txt) + print("hello") self.uiElements['groupBoxFormLayout'].insertRow(row, qlabel, qwidget) label = f'{name}_label' self.widgets[label] = qlabel @@ -148,6 +156,7 @@ def addSeparator(self, name): self._addWidget(name, frame) def _addWidget(self, name, qwidget, qlabel=None): + """qlabel string or widget""" formLayout = self.uiElements['groupBoxFormLayout'] # Create the widgets: diff --git a/examples/insert_widgets_testbuiltTEMP.py b/examples/insert_widgets_testbuiltTEMP.py index 2ed47c1..4fc79b3 100644 --- a/examples/insert_widgets_testbuiltTEMP.py +++ b/examples/insert_widgets_testbuiltTEMP.py @@ -14,7 +14,7 @@ def __init__(self, parent=None): # create a FormDockWidget dock = UIFormWidget.FormDockWidget(parent=self) dock.setWindowTitle('Example insert widget') - self.addWidgetsToExampleForm(dock) + #self.addWidgetsToExampleForm(dock) buttoninsert = QtWidgets.QPushButton(dock) buttoninsert.setText("Insert widgets") dock.addSpanningWidget(buttoninsert, 'Button insert widgets') @@ -22,19 +22,19 @@ def __init__(self, parent=None): form = dock form.layout=form.widget().uiElements['groupBoxFormLayout'] - form.addWidget(QtWidgets.QLabel('test label'), 'Label: ', 'label') - form.addWidget(QtWidgets.QCheckBox('test checkbox'), 'CheckBox: ', 'checkBox') - form.addWidget(QtWidgets.QComboBox(), 'ComboBox: ', 'comboBox') - form.addWidget(QtWidgets.QDoubleSpinBox(), 'DoubleSpinBox: ', 'doubleSpinBox') - form.addWidget(QtWidgets.QSpinBox(), 'SpinBox: ', 'spinBox') - form.addWidget(QtWidgets.QSlider(), 'Slider: ', 'slider') - form.addWidget(UISliderWidget(QtWidgets.QLabel()), 'UISliderWidget: ', 'uiSliderWidget') - form.addWidget(QtWidgets.QRadioButton('test'), 'RadioButton: ', 'radioButton') - form.addWidget(QtWidgets.QTextEdit('test'), 'TextEdit: ', 'textEdit') - form.addWidget(QtWidgets.QPlainTextEdit('test'), 'PlainTextEdit: ', 'plainTextEdit') - form.addWidget(QtWidgets.QLineEdit('test'), 'LineEdit: ', 'lineEdit') - form.addWidget(QtWidgets.QPushButton('test'), 'Button: ', 'button') - form.addSpanningWidget(QtWidgets.QPushButton('spanning widget'), 'spanning widget') + # form.addWidget(QtWidgets.QLabel('test label'), 'Label: ', 'label') + # form.addWidget(QtWidgets.QCheckBox('test checkbox'), 'CheckBox: ', 'checkBox') + # form.addWidget(QtWidgets.QComboBox(), 'ComboBox: ', 'comboBox') + # form.addWidget(QtWidgets.QDoubleSpinBox(), 'DoubleSpinBox: ', 'doubleSpinBox') + # form.addWidget(QtWidgets.QSpinBox(), 'SpinBox: ', 'spinBox') + # form.addWidget(QtWidgets.QSlider(), 'Slider: ', 'slider') + # form.addWidget(UISliderWidget(QtWidgets.QLabel()), 'UISliderWidget: ', 'uiSliderWidget') + # form.addWidget(QtWidgets.QRadioButton('test'), 'RadioButton: ', 'radioButton') + # form.addWidget(QtWidgets.QTextEdit('test'), 'TextEdit: ', 'textEdit') + # form.addWidget(QtWidgets.QPlainTextEdit('test'), 'PlainTextEdit: ', 'plainTextEdit') + # form.addWidget(QtWidgets.QLineEdit('test'), 'LineEdit: ', 'lineEdit') + # form.addWidget(QtWidgets.QPushButton('test'), 'Button: ', 'button') + # form.addSpanningWidget(QtWidgets.QPushButton('spanning widget'), 'spanning widget') self.test_insert_every_widget(form) @@ -60,22 +60,37 @@ def __init__(self, parent=None): def openFormDialog(self): dialog = FormDialog(parent=self, title='Example insert widget') dialog.layout=dialog.formWidget.uiElements['groupBoxFormLayout'] - self.addWidgetsToExampleForm(dialog) + #self.addWidgetsToExampleForm(dialog) form = dialog - form.addWidget(QtWidgets.QLabel('test label'), 'Label: ', 'label') - form.addWidget(QtWidgets.QCheckBox('test checkbox'), 'CheckBox: ', 'checkBox') - form.addWidget(QtWidgets.QComboBox(), 'ComboBox: ', 'comboBox') - form.addWidget(QtWidgets.QDoubleSpinBox(), 'DoubleSpinBox: ', 'doubleSpinBox') - form.addWidget(QtWidgets.QSpinBox(), 'SpinBox: ', 'spinBox') - form.addWidget(QtWidgets.QSlider(), 'Slider: ', 'slider') - form.addWidget(UISliderWidget(QtWidgets.QLabel()), 'UISliderWidget: ', 'uiSliderWidget') - form.addWidget(QtWidgets.QRadioButton('test'), 'RadioButton: ', 'radioButton') - form.addWidget(QtWidgets.QTextEdit('test'), 'TextEdit: ', 'textEdit') - form.addWidget(QtWidgets.QPlainTextEdit('test'), 'PlainTextEdit: ', 'plainTextEdit') - form.addWidget(QtWidgets.QLineEdit('test'), 'LineEdit: ', 'lineEdit') - form.addWidget(QtWidgets.QPushButton('test'), 'Button: ', 'button') - form.addSpanningWidget(QtWidgets.QPushButton('spanning widget'), 'spanning widget') + # form.addWidget(QtWidgets.QLabel('test label'), 'Label: ', 'label') + # form.addWidget(QtWidgets.QCheckBox('test checkbox'), 'CheckBox: ', 'checkBox') + # form.addWidget(QtWidgets.QComboBox(), 'ComboBox: ', 'comboBox') + # form.addWidget(QtWidgets.QDoubleSpinBox(), 'DoubleSpinBox: ', 'doubleSpinBox') + # form.addWidget(QtWidgets.QSpinBox(), 'SpinBox: ', 'spinBox') + # form.addWidget(QtWidgets.QSlider(), 'Slider: ', 'slider') + # form.addWidget(UISliderWidget(QtWidgets.QLabel()), 'UISliderWidget: ', 'uiSliderWidget') + # form.addWidget(QtWidgets.QRadioButton('test'), 'RadioButton: ', 'radioButton') + # form.addWidget(QtWidgets.QTextEdit('test'), 'TextEdit: ', 'textEdit') + # form.addWidget(QtWidgets.QPlainTextEdit('test'), 'PlainTextEdit: ', 'plainTextEdit') + # form.addWidget(QtWidgets.QLineEdit('test'), 'LineEdit: ', 'lineEdit') + # form.addWidget(QtWidgets.QPushButton('test'), 'Button: ', 'button') + # form.addSpanningWidget(QtWidgets.QPushButton('spanning widget'), 'spanning widget') + + """Generate every spanning widget and add it to `self.form`""" + + # form.addSpanningWidget(QtWidgets.QLabel('test label'), 'Label: s') + # form.addSpanningWidget(QtWidgets.QCheckBox('test checkbox'), 'CheckBox: s') + # form.addSpanningWidget(QtWidgets.QComboBox(), 'ComboBox: s') + # form.addSpanningWidget(QtWidgets.QDoubleSpinBox(), 'DoubleSpinBox:s ') + # form.addSpanningWidget(QtWidgets.QSpinBox(), 'SpinBox:s ') + # form.addSpanningWidget(QtWidgets.QSlider(), 'Sliders: ') + # form.addSpanningWidget(UISliderWidget(QtWidgets.QLabel()), 'UISliderWidget:s ') + # form.addSpanningWidget(QtWidgets.QRadioButton('test'), 'RadioButton:s ') + # form.addSpanningWidget(QtWidgets.QTextEdit('test'), 'TextEdit:s ') + # form.addSpanningWidget(QtWidgets.QPlainTextEdit('test'), 'PlainTextEdit: s') + # form.addSpanningWidget(QtWidgets.QLineEdit('test'), 'LineEdit:s ') + # form.addSpanningWidget(QtWidgets.QPushButton('test'), 'Button: s') self.test_insert_every_widget(form) @@ -129,12 +144,26 @@ def rejected(self): def insert_vertical(self, form): buttonuser = QtWidgets.QPushButton(self) - buttonuser.setText("Insert widget") + buttonuser.setText("Insert widget button bbbb") form.insertWidgetToVerticalLayout(1,buttonuser) #print("\nDictionary of widgets after insertion in the vertical lyout" + ":\n" + #str(form.getWidgets())) #print("insert count"+str(form.formWidget.uiElements['verticalLayout'].count()),form.formWidget.num_widgets) + @property + def list_all_widgets(self): + list_all_widgets = [QtWidgets.QLabel('test label'), QtWidgets.QCheckBox('test checkbox'), + QtWidgets.QComboBox(), + QtWidgets.QDoubleSpinBox(), + QtWidgets.QSpinBox(), + QtWidgets.QSlider(), + UISliderWidget(QtWidgets.QLabel()), + QtWidgets.QRadioButton('test r adio button'), + QtWidgets.QTextEdit('test text edit'), + QtWidgets.QPlainTextEdit('test plain text edit'), + QtWidgets.QLineEdit('test line edit'), + QtWidgets.QPushButton('test push button')] + return list_all_widgets def insert_form(self, form, button): # insert widget @@ -151,29 +180,32 @@ def insert_form(self, form, button): # str(form.getWidgets())) button.setEnabled(False) - def _test_insert_one_widget(self, row,name,form): - qwid = form.getWidget(name, role='field') - if f'{name}_label' in form.getWidgets(): - qlab = form.getWidget(name, role='label') - else: - qlab=None - form.insertWidgetToFormLayout(row,name,qwid, qlab) - position=form.layout.getWidgetPosition(form.getWidget(name,'field')) - print(position[0]) - if f'{name}_label' in form.getWidgets(): - position=form.layout.getWidgetPosition(form.getWidget(name,'label')) - print(position) + def _test_insert_one_widget(self, form, row,name, qwidget, qlabel=None): + form.insertWidgetToFormLayout(row,f'{name}',qwidget,qlabel) + #position=self.layout.getWidgetPosition(self.form.getWidget(name,'field'))[0] + #self.assertEqual(position, row) + #form.insertWidgetToFormLayout(row,f'{name}_spanning',qwidget) + #position=self.layout.getWidgetPosition(self.form.getWidget(name,'field'))[0] + #self.assertEqual(position, row) + + + + def test_insert_every_widget(self,form): """Insert every widget from `self.form`""" - list_widgets = [ - 'label', 'checkBox', 'comboBox', 'doubleSpinBox', 'spinBox', 'slider', - 'uiSliderWidget', 'radioButton', 'textEdit', 'plainTextEdit', 'lineEdit', 'button'] - for name in list_widgets: - self._test_insert_one_widget(0,name,form) - - self._test_insert_one_widget(0,'spanning widget',form) - + list_widgets_names = [ + 'label insert', 'checkBox insert', 'comboBox insert', 'doubleSpinBox insert', 'spinBox insert', 'slider insert', + 'uiSliderWidget insert', 'radioButton insert', 'textEdit insert', 'plainTextEdit insert', 'lineEdit insert', 'button insert'] + for i in range(0,len(self.list_all_widgets)): + #print(self.list_all_widgets[i]) + qwidget = self.list_all_widgets[i] + #qlabel = QtWidgets.QLabel(form) + name = list_widgets_names[i] + self._test_insert_one_widget(form,0,name,qwidget,name) + qwidget = self.list_all_widgets[i] + self._test_insert_one_widget(form,0,name+' spanning',qwidget) + print(name+' spanning') diff --git a/test/test__formUI_status_test.py b/test/test__formUI_status_test.py index 46ee0ec..852eeeb 100644 --- a/test/test__formUI_status_test.py +++ b/test/test__formUI_status_test.py @@ -17,6 +17,21 @@ class FormsCommonTests(metaclass=abc.ABCMeta): def setUp(self): raise NotImplementedError + @property + def list_all_widgets(self): + list_all_widgets = [QtWidgets.QLabel('test label'), QtWidgets.QCheckBox('test checkbox'), + QtWidgets.QComboBox(), + QtWidgets.QDoubleSpinBox(), + QtWidgets.QSpinBox(), + QtWidgets.QSlider(), + UISliderWidget(QtWidgets.QLabel()), + QtWidgets.QRadioButton('test r adio button'), + QtWidgets.QTextEdit('test text edit'), + QtWidgets.QPlainTextEdit('test plain text edit'), + QtWidgets.QLineEdit('test line edit'), + QtWidgets.QPushButton('test push button')] + return list_all_widgets + def add_every_widget(self): """Generate every widget and add it to `self.form`""" form = self.form @@ -33,44 +48,61 @@ def add_every_widget(self): form.addWidget(QtWidgets.QLineEdit('test'), 'LineEdit: ', 'lineEdit') form.addWidget(QtWidgets.QPushButton('test'), 'Button: ', 'button') + def add_every_spanning_widget(self): + """Generate every spanning widget and add it to `self.form`""" + form = self.form + form.addSpanningWidget(QtWidgets.QLabel('test label'), 'spanning label') + form.addSpanningWidget(QtWidgets.QCheckBox('test checkbox'), 'spanning checkBox') + form.addSpanningWidget(QtWidgets.QComboBox(), 'spanning comboBox') + form.addSpanningWidget(QtWidgets.QDoubleSpinBox(), 'spanning doubleSpinBox') + form.addSpanningWidget(QtWidgets.QSpinBox(), 'spanning spinBox') + form.addSpanningWidget(QtWidgets.QSlider(), 'spanning slider') + form.addSpanningWidget(UISliderWidget(QtWidgets.QLabel()), 'spanning uiSliderWidget') + form.addSpanningWidget(QtWidgets.QRadioButton('test'), 'spanning radioButton') + form.addSpanningWidget(QtWidgets.QTextEdit('test'), 'spanning textEdit') + form.addSpanningWidget(QtWidgets.QPlainTextEdit('test'), 'spanning plainTextEdit') + form.addSpanningWidget(QtWidgets.QLineEdit('test'), 'spanning lineEdit') + form.addSpanningWidget(QtWidgets.QPushButton('test'), 'spanning button') + def add_two_widgets(self): """Generate two widgets and add them to `self.simple_form`""" form = self.simple_form form.addWidget(QtWidgets.QLabel('test label'), 'Label: ', 'label') form.addWidget(QtWidgets.QCheckBox('test checkbox'), 'CheckBox: ', 'checkBox') - def _test_insert_one_widget(self, row,name): + def _test_insert_one_widget(self, row,name, qwidget, qlabel=None): """ Inserts the widget `name` from the widgets dictionary at position row in the layout. Checks the position of the widget in the form is `row`. - + ---------------- name: name in the dictionary of the widgets already present in the layout. """ - qwidget = self.form.getWidget(name, role='field') - if f'{name}_label' in self.form.getWidgets(): - qlabel = self.form.getWidget(name, role='label') - else: - qlabel=None - self.form.insertWidgetToFormLayout(row,name,qwidget, qlabel) + self.form.insertWidgetToFormLayout(row,f'{name}',qwidget,qlabel) position=self.layout.getWidgetPosition(self.form.getWidget(name,'field'))[0] self.assertEqual(position, row) + def test_insert_every_widget(self): - """Inserts every widget from `self.form` in position 0""" - list_widgets = [ - 'label', 'checkBox', 'comboBox', 'doubleSpinBox', 'spinBox', 'slider', - 'uiSliderWidget', 'radioButton', 'textEdit', 'plainTextEdit', 'lineEdit', 'button'] - for name in list_widgets: - self._test_insert_one_widget(0,name) + """Inserts every widget from `self.form` in position 0.""" + list_widgets_names = [ + 'label insert', 'checkBox insert', 'comboBox insert', 'doubleSpinBox insert', 'spinBox insert', 'slider insert', + 'uiSliderWidget insert', 'radioButton insert', 'textEdit insert', 'plainTextEdit insert', 'lineEdit insert', 'button insert'] + for i in range(0,len(self.list_all_widgets)): + qwidget = self.list_all_widgets[i] + name = list_widgets_names[i] + self._test_insert_one_widget(0,name,qwidget,name) + qwidget = self.list_all_widgets[i] + self._test_insert_one_widget(0,name+' spanning',qwidget) + print(name+' spanning') def _test_remove_one_widget(self, name): """ - Remove one widget. - Checks the number of widgets in the form before and after deletion are consistent. - Checks the number of rows in the layout and number of widgets in the form are - consistent. - - name: name in the dictionary of the widget to be removed + Remove one widget. + Checks the number of widgets in the form before and after deletion are consistent. + Checks the number of rows in the layout and number of widgets in the form are + consistent. + ---------------- + name: name in the dictionary of the widget to be removed """ qwidget = self.form.getWidget(name, role='field') rowpre, role = self.layout.getWidgetPosition(qwidget) # checks the widget exists From ca5d09bb753e9d7c352dd2203798f2c09cda8937 Mon Sep 17 00:00:00 2001 From: Danica Sugic Date: Wed, 22 Nov 2023 13:43:16 +0000 Subject: [PATCH 27/96] Improve docstring etc --- eqt/ui/FormDialog.py | 38 +++++++++++----------- eqt/ui/UIFormWidget.py | 24 +++++++++++--- examples/insert_widgets_example.py | 52 +++++++----------------------- test/test__formUI_status_test.py | 18 ++++------- 4 files changed, 56 insertions(+), 76 deletions(-) diff --git a/eqt/ui/FormDialog.py b/eqt/ui/FormDialog.py index 8d56c64..97e94f3 100644 --- a/eqt/ui/FormDialog.py +++ b/eqt/ui/FormDialog.py @@ -60,7 +60,6 @@ def addWidget(self, qwidget, qlabel=None, name=None, layout='form'): layout = 'vertical' - adds to the Vertical layout below the form. To add to the form layout, qlabel and name must be passed. ''' - if layout == 'vertical': if name is not None or qlabel is not None: raise ValueError('`qlabel` and `name` are unsupported when `layout=vertical`') @@ -74,24 +73,6 @@ def addWidget(self, qwidget, qlabel=None, name=None, layout='form'): else: raise ValueError(f"layout '{layout}' unrecognised: expected 'form' or 'vertical'") - def insertWidgetToFormLayout(self, row, name, qwidget, qlabel=None): - '''Invokes `insertWidget` from `UIFormWidget`.''' - self.formWidget.insertWidgetToFormLayout(row, name, qwidget, qlabel) - - def insertWidgetToVerticalLayout(self, row, qwidget): - ''' - Inserts a widget to the vertical layout at position specified by row. - ''' - self.formWidget.uiElements['verticalLayout'].insertWidget(row, qwidget) - - def removeWidget(self, name): - ''' - Removes a widget (and its label if present) from the layout. - Decreases the counter for the number of widgets in the layout. - Deletes the field (and label) from the dictionary. - ''' - self.formWidget.removeWidget(name) - def addSpanningWidget(self, qwidget, name=None, layout='form'): ''' Adds a spanning widget to the layout. @@ -111,6 +92,25 @@ def addSpanningWidget(self, qwidget, name=None, layout='form'): raise ValueError( f"layout {layout} is not recognised, must be set to 'form' or 'vertical'") + + def insertWidgetToFormLayout(self, row, name, qwidget, qlabel=None): + '''Invokes `insertWidgetToFormLayout` in `UIFormWidget`.''' + self.formWidget.insertWidgetToFormLayout(row, name, qwidget, qlabel) + + def insertWidgetToVerticalLayout(self, row, qwidget): + ''' + Inserts a widget to the vertical layout at position specified by row. + ''' + self.formWidget.uiElements['verticalLayout'].insertWidget(row, qwidget) + + def removeWidget(self, name): + ''' + Removes a widget (and its label if present) from the layout. + Decreases the counter for the number of widgets in the layout. + Deletes the field (and label) from the dictionary. + ''' + self.formWidget.removeWidget(name) + def getNumWidgets(self): ''' Returns the number of widgets in the form. diff --git a/eqt/ui/UIFormWidget.py b/eqt/ui/UIFormWidget.py index 83287ea..7fae65a 100644 --- a/eqt/ui/UIFormWidget.py +++ b/eqt/ui/UIFormWidget.py @@ -59,13 +59,18 @@ def addWidget(self, qwidget, qlabel, name): def insertWidgetToFormLayout(self, row, name, qwidget, qlabel=None): ''' - Inserts a widget and a label widget or a spanning widget to the form layout in the position specified by row. + Inserts a widget, and a label widget, or a spanning widget to the form layout in the position specified by row. If row is out of bounds, the widget is added at the end. It adds the field (and label if present) in the widget dictionary. It increases "num_widgets" by 1 unit. It should not be used to move widgets in a form. + + Parameters: ---------- - qlabel: str or qlabel widget + row: int + name: str + qwidget: qwidget + qlabel: qlabel widget or str ''' field = f'{name}_field' self.widgets[field] = qwidget @@ -74,7 +79,6 @@ def insertWidgetToFormLayout(self, row, name, qwidget, qlabel=None): txt = qlabel qlabel = QtWidgets.QLabel(self) qlabel.setText(txt) - print("hello") self.uiElements['groupBoxFormLayout'].insertRow(row, qlabel, qwidget) label = f'{name}_label' self.widgets[label] = qlabel @@ -156,7 +160,17 @@ def addSeparator(self, name): self._addWidget(name, frame) def _addWidget(self, name, qwidget, qlabel=None): - """qlabel string or widget""" + ''' + Adds a widget, and a label widget, or a spanning widget to the the end of the `groupBoxFormLayout`. + It adds the field (and label if present) in the widget dictionary, `self.widgets`. + It creates the counter `self.num_widgets` and it increases it by 1 unit. + + Parameters: + ---------- + name: str + qwidget: widget + qlabel: qlabel widget or str + ''' formLayout = self.uiElements['groupBoxFormLayout'] # Create the widgets: @@ -376,7 +390,7 @@ def addSpanningWidget(self, qwidget, name): self.widget().addSpanningWidget(qwidget, name) def insertWidgetToFormLayout(self, row, name, qwidget, qlabel=None): - '''Invokes `insertWidgetToFormLayout(` from `UIFormWidget`.''' + '''Invokes `insertWidgetToFormLayout` in `UIFormWidget`.''' self.widget().insertWidgetToFormLayout(row, name, qwidget, qlabel) def removeWidget(self, name): diff --git a/examples/insert_widgets_example.py b/examples/insert_widgets_example.py index 1462092..b5dcc06 100644 --- a/examples/insert_widgets_example.py +++ b/examples/insert_widgets_example.py @@ -39,75 +39,45 @@ def __init__(self, parent=None): def openFormDialog(self): dialog = FormDialog(parent=self, title='Example insert widget') self.addWidgetsToExampleForm(dialog) - - print(dialog.formWidget.uiElements['verticalLayout'].count(),dialog.formWidget.uiElements['groupBoxFormLayout'].count(),dialog.formWidget.num_widgets) dialog.Ok.clicked.connect(lambda: self.insert_vertical(dialog)) dialog.Ok.clicked.connect(lambda: self.insert_form(dialog, dialog.Ok)) - print(dialog.formWidget.uiElements['verticalLayout'].count(),dialog.formWidget.uiElements['groupBoxFormLayout'].count(),dialog.formWidget.num_widgets) - - - - #self.addWidgetsToExampleForm(dialog) - # dialog.addSpanningWidget( - # QtWidgets.QLabel( - # "Press `Ok` to remove the user selected widget and `Cancel` to close the dialog:"), - # 'ok_cancel_instructions') # store a reference self.dialog = dialog self.dialog.onCancel = self.rejected # print dictionary of all widgets in dialog - print("Dictionary of widgets in Form Dialog:\n" + str(self.dialog.getWidgets())) + print("\nDictionary of widgets in Form Dialog:\n" + str(self.dialog.getWidgets())) dialog.open() def addWidgetsToExampleForm(self, form): - - # add widget 1 as QLineEdit - qlabel = QtWidgets.QLabel(form) - qlabel.setText("Initial widget raw 0: ") - qwidget = QtWidgets.QLineEdit(form) - qwidget.setClearButtonEnabled(True) - form.addWidget(qwidget, qlabel, 'Initial widget raw 0') - - #add spanning widget - form.addSpanningWidget(QtWidgets.QLabel("Initial widget row 1"), - 'Initial widget row 1') - # add input as QComboBox - qlabel = QtWidgets.QLabel(form) - qlabel.setText("Initial widget row 2") + form.addWidget(QtWidgets.QLineEdit(), "Initial widget raw 0: ", 'Initial widget raw 0') + form.addSpanningWidget(QtWidgets.QLabel("Initial widget row 1"), 'Initial widget row 1') + # add QComboBox qwidget = QtWidgets.QComboBox(form) qwidget.addItem("0") qwidget.addItem("1") - qwidget.setCurrentIndex(0) - qwidget.setEnabled(True) - form.addWidget(qwidget, qlabel, 'Initial widget row 2') + form.addWidget(qwidget, "Initial widget row 2", 'Initial widget row 2') def rejected(self): print("\nDialog closed.") def insert_vertical(self, form): - buttonuser = QtWidgets.QPushButton(self) - buttonuser.setText("Insert widget") - form.insertWidgetToVerticalLayout(1,buttonuser) - print("\nDictionary of widgets after insertion in the vertical lyout" + ":\n" + - str(form.getWidgets())) - print("insert count"+str(form.formWidget.uiElements['verticalLayout'].count()),form.formWidget.num_widgets) - + form.insertWidgetToVerticalLayout(1,QtWidgets.QPushButton("Inserted widget in vertical layout")) + print("\nThe dictionary of widgets does not change after insertion in the vertical layout.") def insert_form(self, form, button): - # insert widget qlabel = QtWidgets.QLabel(form) qlabel.setText("Widget inserted in row 0: ") qwidget = QtWidgets.QLineEdit(form) form.insertWidgetToFormLayout(0, 'inserted widget', qwidget, qlabel) - buttonuser = QtWidgets.QPushButton(self) - buttonuser.setText("Inserted widget in row 2") - form.insertWidgetToFormLayout(2, 'inserted spanning widget', buttonuser) + buttonspanning = QtWidgets.QPushButton(self) + buttonspanning.setText("Spanning widget inserted in row 2") + form.insertWidgetToFormLayout(2, 'inserted spanning widget', buttonspanning) - print("\nDictionary of widgets after insertion in the form layout" + ":\n" + + print(f'\nDictionary of widgets after insertion in the form layout:\n' + str(form.getWidgets())) button.setEnabled(False) diff --git a/test/test__formUI_status_test.py b/test/test__formUI_status_test.py index 852eeeb..9254f36 100644 --- a/test/test__formUI_status_test.py +++ b/test/test__formUI_status_test.py @@ -25,7 +25,7 @@ def list_all_widgets(self): QtWidgets.QSpinBox(), QtWidgets.QSlider(), UISliderWidget(QtWidgets.QLabel()), - QtWidgets.QRadioButton('test r adio button'), + QtWidgets.QRadioButton('test radio button'), QtWidgets.QTextEdit('test text edit'), QtWidgets.QPlainTextEdit('test plain text edit'), QtWidgets.QLineEdit('test line edit'), @@ -72,28 +72,24 @@ def add_two_widgets(self): def _test_insert_one_widget(self, row,name, qwidget, qlabel=None): """ - Inserts the widget `name` from the widgets dictionary at position row in the layout. - Checks the position of the widget in the form is `row`. - ---------------- - name: name in the dictionary of the widgets already present in the layout. + Invokes `insertWidgetToFormLayout`, therefore inserts the qwidget (and the qlabel) + at position row in the layout. Checks the position of the widget in the form is `row`. """ self.form.insertWidgetToFormLayout(row,f'{name}',qwidget,qlabel) position=self.layout.getWidgetPosition(self.form.getWidget(name,'field'))[0] self.assertEqual(position, row) - def test_insert_every_widget(self): - """Inserts every widget from `self.form` in position 0.""" - list_widgets_names = [ + """Inserts each widget, and then each spanning widget, in position 0 of the form layout.""" + list_widget_names = [ 'label insert', 'checkBox insert', 'comboBox insert', 'doubleSpinBox insert', 'spinBox insert', 'slider insert', 'uiSliderWidget insert', 'radioButton insert', 'textEdit insert', 'plainTextEdit insert', 'lineEdit insert', 'button insert'] for i in range(0,len(self.list_all_widgets)): qwidget = self.list_all_widgets[i] - name = list_widgets_names[i] + name = list_widget_names[i] self._test_insert_one_widget(0,name,qwidget,name) qwidget = self.list_all_widgets[i] self._test_insert_one_widget(0,name+' spanning',qwidget) - print(name+' spanning') def _test_remove_one_widget(self, name): """ @@ -103,7 +99,7 @@ def _test_remove_one_widget(self, name): consistent. ---------------- name: name in the dictionary of the widget to be removed - """ + """ qwidget = self.form.getWidget(name, role='field') rowpre, role = self.layout.getWidgetPosition(qwidget) # checks the widget exists prerowcount = self.layout.rowCount() From d7de5dd6dcec35227534e270f9132c9b1aaa96e7 Mon Sep 17 00:00:00 2001 From: Danica Sugic Date: Wed, 22 Nov 2023 15:04:22 +0000 Subject: [PATCH 28/96] run pre-commit --- eqt/ui/FormDialog.py | 1 - examples/insert_widgets_example.py | 17 +++++++------ test/test__formUI_status_test.py | 39 ++++++++++++++++-------------- 3 files changed, 31 insertions(+), 26 deletions(-) diff --git a/eqt/ui/FormDialog.py b/eqt/ui/FormDialog.py index 97e94f3..face340 100644 --- a/eqt/ui/FormDialog.py +++ b/eqt/ui/FormDialog.py @@ -92,7 +92,6 @@ def addSpanningWidget(self, qwidget, name=None, layout='form'): raise ValueError( f"layout {layout} is not recognised, must be set to 'form' or 'vertical'") - def insertWidgetToFormLayout(self, row, name, qwidget, qlabel=None): '''Invokes `insertWidgetToFormLayout` in `UIFormWidget`.''' self.formWidget.insertWidgetToFormLayout(row, name, qwidget, qlabel) diff --git a/examples/insert_widgets_example.py b/examples/insert_widgets_example.py index b5dcc06..9179a74 100644 --- a/examples/insert_widgets_example.py +++ b/examples/insert_widgets_example.py @@ -16,8 +16,8 @@ def __init__(self, parent=None): buttoninsert = QtWidgets.QPushButton(dock) buttoninsert.setText("Insert widgets") dock.addSpanningWidget(buttoninsert, 'Button insert widgets') - buttoninsert.clicked.connect(lambda: self.insert_form(dock,buttoninsert)) - + buttoninsert.clicked.connect(lambda: self.insert_form(dock, buttoninsert)) + # create button for Form Dialog pb = QtWidgets.QPushButton(self) pb.setText("Open Form Dialog") @@ -64,23 +64,26 @@ def rejected(self): print("\nDialog closed.") def insert_vertical(self, form): - form.insertWidgetToVerticalLayout(1,QtWidgets.QPushButton("Inserted widget in vertical layout")) - print("\nThe dictionary of widgets does not change after insertion in the vertical layout.") + form.insertWidgetToVerticalLayout( + 1, QtWidgets.QPushButton("Inserted widget in vertical layout")) + print( + "\nThe dictionary of widgets does not change after insertion in the vertical layout.") def insert_form(self, form, button): qlabel = QtWidgets.QLabel(form) qlabel.setText("Widget inserted in row 0: ") qwidget = QtWidgets.QLineEdit(form) form.insertWidgetToFormLayout(0, 'inserted widget', qwidget, qlabel) - + buttonspanning = QtWidgets.QPushButton(self) buttonspanning.setText("Spanning widget inserted in row 2") form.insertWidgetToFormLayout(2, 'inserted spanning widget', buttonspanning) - - print(f'\nDictionary of widgets after insertion in the form layout:\n' + + + print('\nDictionary of widgets after insertion in the form layout:\n' + str(form.getWidgets())) button.setEnabled(False) + if __name__ == "__main__": app = QtWidgets.QApplication(sys.argv) diff --git a/test/test__formUI_status_test.py b/test/test__formUI_status_test.py index 9254f36..a70b5aa 100644 --- a/test/test__formUI_status_test.py +++ b/test/test__formUI_status_test.py @@ -19,16 +19,18 @@ def setUp(self): @property def list_all_widgets(self): - list_all_widgets = [QtWidgets.QLabel('test label'), QtWidgets.QCheckBox('test checkbox'), + list_all_widgets = [ + QtWidgets.QLabel('test label'), + QtWidgets.QCheckBox('test checkbox'), QtWidgets.QComboBox(), - QtWidgets.QDoubleSpinBox(), - QtWidgets.QSpinBox(), - QtWidgets.QSlider(), - UISliderWidget(QtWidgets.QLabel()), - QtWidgets.QRadioButton('test radio button'), - QtWidgets.QTextEdit('test text edit'), - QtWidgets.QPlainTextEdit('test plain text edit'), - QtWidgets.QLineEdit('test line edit'), + QtWidgets.QDoubleSpinBox(), + QtWidgets.QSpinBox(), + QtWidgets.QSlider(), + UISliderWidget(QtWidgets.QLabel()), + QtWidgets.QRadioButton('test radio button'), + QtWidgets.QTextEdit('test text edit'), + QtWidgets.QPlainTextEdit('test plain text edit'), + QtWidgets.QLineEdit('test line edit'), QtWidgets.QPushButton('test push button')] return list_all_widgets @@ -70,26 +72,27 @@ def add_two_widgets(self): form.addWidget(QtWidgets.QLabel('test label'), 'Label: ', 'label') form.addWidget(QtWidgets.QCheckBox('test checkbox'), 'CheckBox: ', 'checkBox') - def _test_insert_one_widget(self, row,name, qwidget, qlabel=None): + def _test_insert_one_widget(self, row, name, qwidget, qlabel=None): """ - Invokes `insertWidgetToFormLayout`, therefore inserts the qwidget (and the qlabel) + Invokes `insertWidgetToFormLayout`, therefore inserts the qwidget (and the qlabel) at position row in the layout. Checks the position of the widget in the form is `row`. """ - self.form.insertWidgetToFormLayout(row,f'{name}',qwidget,qlabel) - position=self.layout.getWidgetPosition(self.form.getWidget(name,'field'))[0] + self.form.insertWidgetToFormLayout(row, f'{name}', qwidget, qlabel) + position = self.layout.getWidgetPosition(self.form.getWidget(name, 'field'))[0] self.assertEqual(position, row) def test_insert_every_widget(self): """Inserts each widget, and then each spanning widget, in position 0 of the form layout.""" list_widget_names = [ - 'label insert', 'checkBox insert', 'comboBox insert', 'doubleSpinBox insert', 'spinBox insert', 'slider insert', - 'uiSliderWidget insert', 'radioButton insert', 'textEdit insert', 'plainTextEdit insert', 'lineEdit insert', 'button insert'] - for i in range(0,len(self.list_all_widgets)): + 'label insert', 'checkBox insert', 'comboBox insert', 'doubleSpinBox insert', + 'spinBox insert', 'slider insert', 'uiSliderWidget insert', 'radioButton insert', + 'textEdit insert', 'plainTextEdit insert', 'lineEdit insert', 'button insert'] + for i in range(0, len(self.list_all_widgets)): qwidget = self.list_all_widgets[i] name = list_widget_names[i] - self._test_insert_one_widget(0,name,qwidget,name) + self._test_insert_one_widget(0, name, qwidget, name) qwidget = self.list_all_widgets[i] - self._test_insert_one_widget(0,name+' spanning',qwidget) + self._test_insert_one_widget(0, name + ' spanning', qwidget) def _test_remove_one_widget(self, name): """ From 847a7aa62abca647dd26d6f28fa7c6825efbdd1b Mon Sep 17 00:00:00 2001 From: Danica Sugic Date: Wed, 22 Nov 2023 15:05:19 +0000 Subject: [PATCH 29/96] delete temporary example for testing --- examples/insert_widgets_testbuiltTEMP.py | 217 ----------------------- 1 file changed, 217 deletions(-) delete mode 100644 examples/insert_widgets_testbuiltTEMP.py diff --git a/examples/insert_widgets_testbuiltTEMP.py b/examples/insert_widgets_testbuiltTEMP.py deleted file mode 100644 index 4fc79b3..0000000 --- a/examples/insert_widgets_testbuiltTEMP.py +++ /dev/null @@ -1,217 +0,0 @@ -import sys - -from PySide2 import QtWidgets - -from eqt.ui import FormDialog, UIFormWidget - -from eqt.ui.UISliderWidget import UISliderWidget - - -class MainUI(QtWidgets.QMainWindow): - def __init__(self, parent=None): - QtWidgets.QMainWindow.__init__(self, parent) - - # create a FormDockWidget - dock = UIFormWidget.FormDockWidget(parent=self) - dock.setWindowTitle('Example insert widget') - #self.addWidgetsToExampleForm(dock) - buttoninsert = QtWidgets.QPushButton(dock) - buttoninsert.setText("Insert widgets") - dock.addSpanningWidget(buttoninsert, 'Button insert widgets') - buttoninsert.clicked.connect(lambda: self.insert_form(dock,buttoninsert)) - - form = dock - form.layout=form.widget().uiElements['groupBoxFormLayout'] - # form.addWidget(QtWidgets.QLabel('test label'), 'Label: ', 'label') - # form.addWidget(QtWidgets.QCheckBox('test checkbox'), 'CheckBox: ', 'checkBox') - # form.addWidget(QtWidgets.QComboBox(), 'ComboBox: ', 'comboBox') - # form.addWidget(QtWidgets.QDoubleSpinBox(), 'DoubleSpinBox: ', 'doubleSpinBox') - # form.addWidget(QtWidgets.QSpinBox(), 'SpinBox: ', 'spinBox') - # form.addWidget(QtWidgets.QSlider(), 'Slider: ', 'slider') - # form.addWidget(UISliderWidget(QtWidgets.QLabel()), 'UISliderWidget: ', 'uiSliderWidget') - # form.addWidget(QtWidgets.QRadioButton('test'), 'RadioButton: ', 'radioButton') - # form.addWidget(QtWidgets.QTextEdit('test'), 'TextEdit: ', 'textEdit') - # form.addWidget(QtWidgets.QPlainTextEdit('test'), 'PlainTextEdit: ', 'plainTextEdit') - # form.addWidget(QtWidgets.QLineEdit('test'), 'LineEdit: ', 'lineEdit') - # form.addWidget(QtWidgets.QPushButton('test'), 'Button: ', 'button') - # form.addSpanningWidget(QtWidgets.QPushButton('spanning widget'), 'spanning widget') - - self.test_insert_every_widget(form) - - # create button for Form Dialog - pb = QtWidgets.QPushButton(self) - pb.setText("Open Form Dialog") - pb.clicked.connect(lambda: self.openFormDialog()) - - # create window layout - layout = QtWidgets.QHBoxLayout() - layout.addWidget(pb) - layout.addWidget(dock) - widg = QtWidgets.QWidget() - widg.setLayout(layout) - self.setCentralWidget(widg) - - # print dictionary of all widgets in dock - #print("\nDictionary of widgets in the Form Dock Widget:\n" + str(dock.getWidgets())) - - - self.show() - - def openFormDialog(self): - dialog = FormDialog(parent=self, title='Example insert widget') - dialog.layout=dialog.formWidget.uiElements['groupBoxFormLayout'] - #self.addWidgetsToExampleForm(dialog) - - form = dialog - # form.addWidget(QtWidgets.QLabel('test label'), 'Label: ', 'label') - # form.addWidget(QtWidgets.QCheckBox('test checkbox'), 'CheckBox: ', 'checkBox') - # form.addWidget(QtWidgets.QComboBox(), 'ComboBox: ', 'comboBox') - # form.addWidget(QtWidgets.QDoubleSpinBox(), 'DoubleSpinBox: ', 'doubleSpinBox') - # form.addWidget(QtWidgets.QSpinBox(), 'SpinBox: ', 'spinBox') - # form.addWidget(QtWidgets.QSlider(), 'Slider: ', 'slider') - # form.addWidget(UISliderWidget(QtWidgets.QLabel()), 'UISliderWidget: ', 'uiSliderWidget') - # form.addWidget(QtWidgets.QRadioButton('test'), 'RadioButton: ', 'radioButton') - # form.addWidget(QtWidgets.QTextEdit('test'), 'TextEdit: ', 'textEdit') - # form.addWidget(QtWidgets.QPlainTextEdit('test'), 'PlainTextEdit: ', 'plainTextEdit') - # form.addWidget(QtWidgets.QLineEdit('test'), 'LineEdit: ', 'lineEdit') - # form.addWidget(QtWidgets.QPushButton('test'), 'Button: ', 'button') - # form.addSpanningWidget(QtWidgets.QPushButton('spanning widget'), 'spanning widget') - - """Generate every spanning widget and add it to `self.form`""" - - # form.addSpanningWidget(QtWidgets.QLabel('test label'), 'Label: s') - # form.addSpanningWidget(QtWidgets.QCheckBox('test checkbox'), 'CheckBox: s') - # form.addSpanningWidget(QtWidgets.QComboBox(), 'ComboBox: s') - # form.addSpanningWidget(QtWidgets.QDoubleSpinBox(), 'DoubleSpinBox:s ') - # form.addSpanningWidget(QtWidgets.QSpinBox(), 'SpinBox:s ') - # form.addSpanningWidget(QtWidgets.QSlider(), 'Sliders: ') - # form.addSpanningWidget(UISliderWidget(QtWidgets.QLabel()), 'UISliderWidget:s ') - # form.addSpanningWidget(QtWidgets.QRadioButton('test'), 'RadioButton:s ') - # form.addSpanningWidget(QtWidgets.QTextEdit('test'), 'TextEdit:s ') - # form.addSpanningWidget(QtWidgets.QPlainTextEdit('test'), 'PlainTextEdit: s') - # form.addSpanningWidget(QtWidgets.QLineEdit('test'), 'LineEdit:s ') - # form.addSpanningWidget(QtWidgets.QPushButton('test'), 'Button: s') - - self.test_insert_every_widget(form) - - - #print(dialog.formWidget.uiElements['verticalLayout'].count(),dialog.formWidget.uiElements['groupBoxFormLayout'].count(),dialog.formWidget.num_widgets) - dialog.Ok.clicked.connect(lambda: self.insert_vertical(dialog)) - dialog.Ok.clicked.connect(lambda: self.insert_form(dialog, dialog.Ok)) - #print(dialog.formWidget.uiElements['verticalLayout'].count(),dialog.formWidget.uiElements['groupBoxFormLayout'].count(),dialog.formWidget.num_widgets) - - - - #self.addWidgetsToExampleForm(dialog) - # dialog.addSpanningWidget( - # QtWidgets.QLabel( - # "Press `Ok` to remove the user selected widget and `Cancel` to close the dialog:"), - # 'ok_cancel_instructions') - - # store a reference - self.dialog = dialog - self.dialog.onCancel = self.rejected - - # print dictionary of all widgets in dialog - #print("Dictionary of widgets in Form Dialog:\n" + str(self.dialog.getWidgets())) - - dialog.open() - - def addWidgetsToExampleForm(self, form): - - # add widget 1 as QLineEdit - qlabel = QtWidgets.QLabel(form) - qlabel.setText("Initial widget raw 0: ") - qwidget = QtWidgets.QLineEdit(form) - qwidget.setClearButtonEnabled(True) - form.addWidget(qwidget, qlabel, 'Initial widget raw 0') - - #add spanning widget - form.addSpanningWidget(QtWidgets.QLabel("Initial widget row 1"), - 'Initial widget row 1') - # add input as QComboBox - qlabel = QtWidgets.QLabel(form) - qlabel.setText("Initial widget row 2") - qwidget = QtWidgets.QComboBox(form) - qwidget.addItem("0") - qwidget.addItem("1") - qwidget.setCurrentIndex(0) - qwidget.setEnabled(True) - form.addWidget(qwidget, qlabel, 'Initial widget row 2') - - def rejected(self): - print("\nDialog closed.") - - def insert_vertical(self, form): - buttonuser = QtWidgets.QPushButton(self) - buttonuser.setText("Insert widget button bbbb") - form.insertWidgetToVerticalLayout(1,buttonuser) - #print("\nDictionary of widgets after insertion in the vertical lyout" + ":\n" + - #str(form.getWidgets())) - #print("insert count"+str(form.formWidget.uiElements['verticalLayout'].count()),form.formWidget.num_widgets) - - @property - def list_all_widgets(self): - list_all_widgets = [QtWidgets.QLabel('test label'), QtWidgets.QCheckBox('test checkbox'), - QtWidgets.QComboBox(), - QtWidgets.QDoubleSpinBox(), - QtWidgets.QSpinBox(), - QtWidgets.QSlider(), - UISliderWidget(QtWidgets.QLabel()), - QtWidgets.QRadioButton('test r adio button'), - QtWidgets.QTextEdit('test text edit'), - QtWidgets.QPlainTextEdit('test plain text edit'), - QtWidgets.QLineEdit('test line edit'), - QtWidgets.QPushButton('test push button')] - return list_all_widgets - - def insert_form(self, form, button): - # insert widget - qlabel = QtWidgets.QLabel(form) - qlabel.setText("Widget inserted in row 0: ") - qwidget = QtWidgets.QLineEdit(form) - form.insertWidgetToFormLayout(0, 'inserted widget', qwidget, qlabel) - - buttonuser = QtWidgets.QPushButton(self) - buttonuser.setText("Inserted widget in row 2") - form.insertWidgetToFormLayout(2, 'inserted spanning widget', buttonuser) - - #print("\nDictionary of widgets after insertion in the form layout" + ":\n" + - # str(form.getWidgets())) - button.setEnabled(False) - - def _test_insert_one_widget(self, form, row,name, qwidget, qlabel=None): - form.insertWidgetToFormLayout(row,f'{name}',qwidget,qlabel) - #position=self.layout.getWidgetPosition(self.form.getWidget(name,'field'))[0] - #self.assertEqual(position, row) - #form.insertWidgetToFormLayout(row,f'{name}_spanning',qwidget) - #position=self.layout.getWidgetPosition(self.form.getWidget(name,'field'))[0] - #self.assertEqual(position, row) - - - - - - def test_insert_every_widget(self,form): - """Insert every widget from `self.form`""" - list_widgets_names = [ - 'label insert', 'checkBox insert', 'comboBox insert', 'doubleSpinBox insert', 'spinBox insert', 'slider insert', - 'uiSliderWidget insert', 'radioButton insert', 'textEdit insert', 'plainTextEdit insert', 'lineEdit insert', 'button insert'] - for i in range(0,len(self.list_all_widgets)): - #print(self.list_all_widgets[i]) - qwidget = self.list_all_widgets[i] - #qlabel = QtWidgets.QLabel(form) - name = list_widgets_names[i] - self._test_insert_one_widget(form,0,name,qwidget,name) - qwidget = self.list_all_widgets[i] - self._test_insert_one_widget(form,0,name+' spanning',qwidget) - print(name+' spanning') - - - -if __name__ == "__main__": - app = QtWidgets.QApplication(sys.argv) - - window = MainUI() - - sys.exit(app.exec_()) From 431a29a1440e4101f509f38b951b00386b01ebc6 Mon Sep 17 00:00:00 2001 From: "pre-commit-ci[bot]" <66853113+pre-commit-ci[bot]@users.noreply.github.com> Date: Wed, 22 Nov 2023 16:04:17 +0000 Subject: [PATCH 30/96] [pre-commit.ci] auto fixes from pre-commit.com hooks for more information, see https://pre-commit.ci --- eqt/ui/UIFormWidget.py | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/eqt/ui/UIFormWidget.py b/eqt/ui/UIFormWidget.py index 7fae65a..0749093 100644 --- a/eqt/ui/UIFormWidget.py +++ b/eqt/ui/UIFormWidget.py @@ -64,7 +64,7 @@ def insertWidgetToFormLayout(self, row, name, qwidget, qlabel=None): It adds the field (and label if present) in the widget dictionary. It increases "num_widgets" by 1 unit. It should not be used to move widgets in a form. - + Parameters: ---------- row: int @@ -84,7 +84,7 @@ def insertWidgetToFormLayout(self, row, name, qwidget, qlabel=None): self.widgets[label] = qlabel else: self.uiElements['groupBoxFormLayout'].insertRow(row, qwidget) - self.num_widgets += 1 + self.num_widgets += 1 def removeWidget(self, name): ''' @@ -164,7 +164,7 @@ def _addWidget(self, name, qwidget, qlabel=None): Adds a widget, and a label widget, or a spanning widget to the the end of the `groupBoxFormLayout`. It adds the field (and label if present) in the widget dictionary, `self.widgets`. It creates the counter `self.num_widgets` and it increases it by 1 unit. - + Parameters: ---------- name: str From 96abaeeec6ed504fa97595d324c9991bb869e169 Mon Sep 17 00:00:00 2001 From: Danica Sugic Date: Wed, 22 Nov 2023 16:17:47 +0000 Subject: [PATCH 31/96] Changed pre-commit suggestions --- eqt/ui/UIFormWidget.py | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/eqt/ui/UIFormWidget.py b/eqt/ui/UIFormWidget.py index 0749093..6b95e55 100644 --- a/eqt/ui/UIFormWidget.py +++ b/eqt/ui/UIFormWidget.py @@ -59,8 +59,8 @@ def addWidget(self, qwidget, qlabel, name): def insertWidgetToFormLayout(self, row, name, qwidget, qlabel=None): ''' - Inserts a widget, and a label widget, or a spanning widget to the form layout in the position specified by row. - If row is out of bounds, the widget is added at the end. + Inserts a widget, and a label widget, or a spanning widget to the form layout + in the position specified by row. If row is out of bounds, the widget is added at the end. It adds the field (and label if present) in the widget dictionary. It increases "num_widgets" by 1 unit. It should not be used to move widgets in a form. @@ -161,9 +161,10 @@ def addSeparator(self, name): def _addWidget(self, name, qwidget, qlabel=None): ''' - Adds a widget, and a label widget, or a spanning widget to the the end of the `groupBoxFormLayout`. - It adds the field (and label if present) in the widget dictionary, `self.widgets`. - It creates the counter `self.num_widgets` and it increases it by 1 unit. + Adds a widget, and a label widget, or a spanning widget to the the end of + the `groupBoxFormLayout`. It adds the field (and label if present) in the + widget dictionary, `self.widgets`. It creates the counter `self.num_widgets` + and it increases it by 1 unit. Parameters: ---------- From d3bf1716f249f863485eb7a72af7dd491915598b Mon Sep 17 00:00:00 2001 From: Danica Sugic Date: Thu, 23 Nov 2023 12:58:00 +0000 Subject: [PATCH 32/96] Add default widget state as a larger dictionary --- eqt/ui/FormDialog.py | 2 +- eqt/ui/UIFormWidget.py | 50 +++++++++++++++++++++++------------------- 2 files changed, 29 insertions(+), 23 deletions(-) diff --git a/eqt/ui/FormDialog.py b/eqt/ui/FormDialog.py index 799400e..964e655 100644 --- a/eqt/ui/FormDialog.py +++ b/eqt/ui/FormDialog.py @@ -46,8 +46,8 @@ def _onCancel(self): '''calls `onCancel`, restores the previously saved states if existing and closes the FormDialog''' self.onCancel() - self.restoreAllSavedWidgetStates() self.close() + self.restoreAllSavedWidgetStates() def onOk(self): '''Called when the dialog's "Ok" button is clicked. diff --git a/eqt/ui/UIFormWidget.py b/eqt/ui/UIFormWidget.py index 5c5fd32..6d5c6d4 100644 --- a/eqt/ui/UIFormWidget.py +++ b/eqt/ui/UIFormWidget.py @@ -109,10 +109,6 @@ def addSeparator(self, name): def _addWidget(self, name, qwidget, qlabel=None): formLayout = self.uiElements['groupBoxFormLayout'] - # create the default values - if not hasattr(self, 'widget_default'): - self.widget_default = {} - # Create the widgets: widgetno = self.num_widgets @@ -121,9 +117,7 @@ def _addWidget(self, name, qwidget, qlabel=None): field = f'{name}_field' self.widgets[field] = qwidget - # add the default value of the qwidget - self.widget_default[field] = self.getWidgetState(qwidget)['value'] - + if qlabel is not None: # add the label label = f'{name}_label' @@ -138,8 +132,7 @@ def _addWidget(self, name, qwidget, qlabel=None): field_form_role = QtWidgets.QFormLayout.FieldRole - # add the default value of the qlabel - self.widget_default[label] = self.getWidgetState(qlabel, label)['value'] + else: # In the case we don't have a qlabel, set a spanning widget: @@ -147,16 +140,28 @@ def _addWidget(self, name, qwidget, qlabel=None): formLayout.setWidget(widgetno, field_form_role, qwidget) self.num_widgets += 1 + self.populate_default_widget_states_dictionary(name,qlabel) - def applyDefaultWidgetValuesToState(self): + def populate_default_widget_states_dictionary(self,name,qlabel): + ''' + Creates an attribute dictionary of default widget states. The entries are in the + format: {'value': str | bool | int, 'enabled': bool, 'visible': bool}. + This can be used to restore the default states of the widgets invoking `applyWidgetStates`. ''' - Saves all states in a form widget - typically invoked when a form is firstly opened - and no states are saved yet. Retrieves the default values from the widgets and applies - them to the saved states - this preserves visible and enabled in the widgets. + if not hasattr(self, 'default_widget_states'): + self.default_widget_states = {} + # add the default state of the qwidget + self.default_widget_states[f'{name}_field'] = self.getWidgetState(name,'field') + # add the default state of the qlabel + if qlabel is not None: + self.default_widget_states[f'{name}_label'] = self.getWidgetState(name, 'label') + + def make_default_widget_states_visible(self): + ''' + Sets all of the entries 'visible' in the `default_widget_states` dictionary to be `True`. ''' - self.saveAllWidgetStates() - for state_key in self.widget_default.keys(): - self.widget_states[state_key]['value'] = self.widget_default[state_key] + for key in self.default_widget_states.keys(): + self.default_widget_states[key]['visible'] = True def getAllWidgetStates(self): ''' @@ -316,14 +321,15 @@ def saveAllWidgetStates(self): def restoreAllSavedWidgetStates(self): ''' - There are saved states only if `saveAllWidgetStates` was previously invoked. - If there are no previously saved states, `applyDefaultWidgetValuesToState` - saves the states and applies default values to them. Once the existence of the - `widget_states` is checked, all widgets in the form are restored to the saved states. + All widgets in the form are restored to the saved states. There are saved states only if + `saveAllWidgetStates` was previously invoked. If there are no previously saved states, + `default_widget_states` are used instead, after being made visible. ''' if not hasattr(self, 'widget_states'): - self.applyDefaultWidgetValuesToState() - self.applyWidgetStates(self.widget_states) + self.make_default_widget_states_visible() + self.applyWidgetStates(self.default_widget_states) + else: + self.applyWidgetStates(self.widget_states) class FormWidget(QtWidgets.QWidget, UIFormWidget): From 90ea8e8839dad1fefecfc86d8ffe827bf5910b9f Mon Sep 17 00:00:00 2001 From: Danica Sugic Date: Thu, 23 Nov 2023 13:19:48 +0000 Subject: [PATCH 33/96] Polish test_dialog_buttons_default_behaviour --- test/test__formUI_status_test.py | 9 ++------- 1 file changed, 2 insertions(+), 7 deletions(-) diff --git a/test/test__formUI_status_test.py b/test/test__formUI_status_test.py index 5db1eba..3417acd 100644 --- a/test/test__formUI_status_test.py +++ b/test/test__formUI_status_test.py @@ -358,17 +358,12 @@ def click_Ok(self): def click_Cancel(self): QTest.mouseClick(self.form.Cancel, Qt.LeftButton) - def test_save_states_default(self): - # test both states are working - # state1 + def test_dialog_buttons_default_behaviour(self): + # create the states dictionary self.set_state(1) states1 = self.form.getAllWidgetStates() - self.assertEqual(states1, self.form.getAllWidgetStates()) - # state0 self.set_state(0) states0 = self.form.getAllWidgetStates() - self.assertNotEqual(states1, self.form.getAllWidgetStates()) - self.assertEqual(states0, self.form.getAllWidgetStates()) # check state 0 and 1 are not saved when Cancel is pressed self.click_Cancel() self.assertNotEqual(states0, self.form.getAllWidgetStates()) From 1ecc16a3e4b81f387622e2d9dcd51323d2eac42a Mon Sep 17 00:00:00 2001 From: Danica Sugic Date: Thu, 23 Nov 2023 13:27:00 +0000 Subject: [PATCH 34/96] pre-commit run --- eqt/ui/UIFormWidget.py | 19 ++++++++----------- 1 file changed, 8 insertions(+), 11 deletions(-) diff --git a/eqt/ui/UIFormWidget.py b/eqt/ui/UIFormWidget.py index 6d5c6d4..8dd1986 100644 --- a/eqt/ui/UIFormWidget.py +++ b/eqt/ui/UIFormWidget.py @@ -117,7 +117,6 @@ def _addWidget(self, name, qwidget, qlabel=None): field = f'{name}_field' self.widgets[field] = qwidget - if qlabel is not None: # add the label label = f'{name}_label' @@ -132,30 +131,28 @@ def _addWidget(self, name, qwidget, qlabel=None): field_form_role = QtWidgets.QFormLayout.FieldRole - - else: # In the case we don't have a qlabel, set a spanning widget: field_form_role = QtWidgets.QFormLayout.SpanningRole formLayout.setWidget(widgetno, field_form_role, qwidget) self.num_widgets += 1 - self.populate_default_widget_states_dictionary(name,qlabel) + self.populate_default_widget_states_dictionary(name, qlabel) - def populate_default_widget_states_dictionary(self,name,qlabel): + def populate_default_widget_states_dictionary(self, name, qlabel): ''' - Creates an attribute dictionary of default widget states. The entries are in the + Creates an attribute dictionary of default widget states. The entries are in the format: {'value': str | bool | int, 'enabled': bool, 'visible': bool}. This can be used to restore the default states of the widgets invoking `applyWidgetStates`. ''' if not hasattr(self, 'default_widget_states'): self.default_widget_states = {} # add the default state of the qwidget - self.default_widget_states[f'{name}_field'] = self.getWidgetState(name,'field') + self.default_widget_states[f'{name}_field'] = self.getWidgetState(name, 'field') # add the default state of the qlabel if qlabel is not None: self.default_widget_states[f'{name}_label'] = self.getWidgetState(name, 'label') - + def make_default_widget_states_visible(self): ''' Sets all of the entries 'visible' in the `default_widget_states` dictionary to be `True`. @@ -321,9 +318,9 @@ def saveAllWidgetStates(self): def restoreAllSavedWidgetStates(self): ''' - All widgets in the form are restored to the saved states. There are saved states only if - `saveAllWidgetStates` was previously invoked. If there are no previously saved states, - `default_widget_states` are used instead, after being made visible. + All widgets in the form are restored to the saved states. There are saved states only if + `saveAllWidgetStates` was previously invoked. If there are no previously saved states, + `default_widget_states` are used instead, after being made visible. ''' if not hasattr(self, 'widget_states'): self.make_default_widget_states_visible() From 69701cde29daa68d4580e05ba58d23de61929e63 Mon Sep 17 00:00:00 2001 From: Danica Sugic Date: Thu, 23 Nov 2023 13:29:45 +0000 Subject: [PATCH 35/96] improve docstring and other minor things --- eqt/ui/FormDialog.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/eqt/ui/FormDialog.py b/eqt/ui/FormDialog.py index 964e655..8ed7738 100644 --- a/eqt/ui/FormDialog.py +++ b/eqt/ui/FormDialog.py @@ -43,8 +43,8 @@ def _onOk(self): self.close() def _onCancel(self): - '''calls `onCancel`, restores the previously saved states if existing and - closes the FormDialog''' + '''calls `onCancel`, closes the FormDialog and restores the previously saved states + or the default states.''' self.onCancel() self.close() self.restoreAllSavedWidgetStates() From 664316745ecbde48d7a415a87adcaf1cf025623a Mon Sep 17 00:00:00 2001 From: Danica Sugic Date: Fri, 24 Nov 2023 11:08:04 +0000 Subject: [PATCH 36/96] Attempt to make remove widget and save default states compatible, not working yet --- eqt/ui/UIFormWidget.py | 13 +++++++++++++ examples/remove_widgets_example.py | 9 ++++++++- 2 files changed, 21 insertions(+), 1 deletion(-) diff --git a/eqt/ui/UIFormWidget.py b/eqt/ui/UIFormWidget.py index 073984b..fede5dd 100644 --- a/eqt/ui/UIFormWidget.py +++ b/eqt/ui/UIFormWidget.py @@ -46,6 +46,7 @@ def createForm(self): 'verticalLayout': verticalLayout, 'groupBox': groupBox, 'groupBoxFormLayout': groupBoxFormLayout} self.widgets = {} + self.default_widgets = {} @property def groupBox(self): @@ -140,6 +141,7 @@ def _addWidget(self, name, qwidget, qlabel=None): # add the field field = f'{name}_field' self.widgets[field] = qwidget + self.default_widgets[field] = qwidget if qlabel is not None: # add the label @@ -152,6 +154,7 @@ def _addWidget(self, name, qwidget, qlabel=None): # save a reference to label widgets in the dictionary self.widgets[label] = qlabel + self.default_widgets[label] = qlabel field_form_role = QtWidgets.QFormLayout.FieldRole @@ -161,6 +164,7 @@ def _addWidget(self, name, qwidget, qlabel=None): formLayout.setWidget(widgetno, field_form_role, qwidget) self.num_widgets += 1 + #self.default_widgets = self.widgets.copy() self.populate_default_widget_states_dictionary(name, qlabel) def populate_default_widget_states_dictionary(self, name, qlabel): @@ -347,9 +351,18 @@ def restoreAllSavedWidgetStates(self): `default_widget_states` are used instead, after being made visible. ''' if not hasattr(self, 'widget_states'): + print(self.widgets) + print(self.default_widgets) + #self.widgets=self.default_widgets + print(self.widgets) self.make_default_widget_states_visible() + #for key in self.default_widget_states.keys(): + ## if key not in self.widgets: + # self.addWidget + #self.widgets[name + '_field'] self.applyWidgetStates(self.default_widget_states) else: + print(self.default_widgets) self.applyWidgetStates(self.widget_states) diff --git a/examples/remove_widgets_example.py b/examples/remove_widgets_example.py index aebfdf4..ff10a40 100644 --- a/examples/remove_widgets_example.py +++ b/examples/remove_widgets_example.py @@ -50,12 +50,19 @@ def openFormDialog(self): # store a reference self.dialog = dialog self.dialog.onCancel = self.rejected + #redefine `onOk`` so it does not close the dialog. + self.dialog._onOk= self._onOkRedefined # print dictionary of all widgets in dialog - print("Dictionary of widgets in Form Dialog:\n" + str(self.dialog.getWidgets())) + print("\nDictionary of widgets in Form Dialog:\n" + str(self.dialog.getWidgets())) dialog.open() + def _onOkRedefined(self): + '''saves the widget states''' + self.dialog.saveAllWidgetStates() + #pass + def addWidgetsToExampleForm(self, form): # add widget 1 as QLineEdit From 970be18bb345b22210d8639d8eb9a77826de62ee Mon Sep 17 00:00:00 2001 From: Danica Sugic Date: Mon, 4 Dec 2023 12:04:34 +0000 Subject: [PATCH 37/96] Polish code and run pre-commit --- eqt/ui/UIFormWidget.py | 10 ---------- examples/remove_widgets_example.py | 7 +++---- 2 files changed, 3 insertions(+), 14 deletions(-) diff --git a/eqt/ui/UIFormWidget.py b/eqt/ui/UIFormWidget.py index fede5dd..4b3606f 100644 --- a/eqt/ui/UIFormWidget.py +++ b/eqt/ui/UIFormWidget.py @@ -164,7 +164,6 @@ def _addWidget(self, name, qwidget, qlabel=None): formLayout.setWidget(widgetno, field_form_role, qwidget) self.num_widgets += 1 - #self.default_widgets = self.widgets.copy() self.populate_default_widget_states_dictionary(name, qlabel) def populate_default_widget_states_dictionary(self, name, qlabel): @@ -351,18 +350,9 @@ def restoreAllSavedWidgetStates(self): `default_widget_states` are used instead, after being made visible. ''' if not hasattr(self, 'widget_states'): - print(self.widgets) - print(self.default_widgets) - #self.widgets=self.default_widgets - print(self.widgets) self.make_default_widget_states_visible() - #for key in self.default_widget_states.keys(): - ## if key not in self.widgets: - # self.addWidget - #self.widgets[name + '_field'] self.applyWidgetStates(self.default_widget_states) else: - print(self.default_widgets) self.applyWidgetStates(self.widget_states) diff --git a/examples/remove_widgets_example.py b/examples/remove_widgets_example.py index ff10a40..0884c8a 100644 --- a/examples/remove_widgets_example.py +++ b/examples/remove_widgets_example.py @@ -50,8 +50,8 @@ def openFormDialog(self): # store a reference self.dialog = dialog self.dialog.onCancel = self.rejected - #redefine `onOk`` so it does not close the dialog. - self.dialog._onOk= self._onOkRedefined + # redefine `onOk`` so it does not close the dialog. + self.dialog._onOk = self._onOkRedefined # print dictionary of all widgets in dialog print("\nDictionary of widgets in Form Dialog:\n" + str(self.dialog.getWidgets())) @@ -59,9 +59,8 @@ def openFormDialog(self): dialog.open() def _onOkRedefined(self): - '''saves the widget states''' + '''Saves the widget states.''' self.dialog.saveAllWidgetStates() - #pass def addWidgetsToExampleForm(self, form): From f9a342bfd8f1dace5bc0d81b948b4d9111af4141 Mon Sep 17 00:00:00 2001 From: Danica Sugic Date: Mon, 4 Dec 2023 18:20:19 +0000 Subject: [PATCH 38/96] Change method name and remove qlabel from default state dictionary --- eqt/ui/UIFormWidget.py | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/eqt/ui/UIFormWidget.py b/eqt/ui/UIFormWidget.py index a4ff0fc..48947f1 100644 --- a/eqt/ui/UIFormWidget.py +++ b/eqt/ui/UIFormWidget.py @@ -164,9 +164,9 @@ def _addWidget(self, name, qwidget, qlabel=None): formLayout.setWidget(widgetno, field_form_role, qwidget) self.num_widgets += 1 - self.populate_default_widget_states_dictionary(name, qlabel) + self.populate_default_widget_states_dictionary(name) - def populate_default_widget_states_dictionary(self, name, qlabel): + def populate_default_widget_states_dictionary(self, name): ''' Creates an attribute dictionary of default widget states. The entries are in the format: {'value': str | bool | int, 'enabled': bool, 'visible': bool}. @@ -177,10 +177,10 @@ def populate_default_widget_states_dictionary(self, name, qlabel): # add the default state of the qwidget self.default_widget_states[f'{name}_field'] = self.getWidgetState(name, 'field') # add the default state of the qlabel - if qlabel is not None: + if f'{name}_label' in self.widgets.keys(): self.default_widget_states[f'{name}_label'] = self.getWidgetState(name, 'label') - def make_default_widget_states_visible(self): + def set_default_widget_states_visible_true(self): ''' Sets all of the entries 'visible' in the `default_widget_states` dictionary to be `True`. ''' @@ -350,7 +350,7 @@ def restoreAllSavedWidgetStates(self): `default_widget_states` are used instead, after being made visible. ''' if not hasattr(self, 'widget_states'): - self.make_default_widget_states_visible() + self.set_default_widget_states_visible_true() self.applyWidgetStates(self.default_widget_states) else: self.applyWidgetStates(self.widget_states) From e9c664952ed6c76e71ae59ce63432b6f4ac507e4 Mon Sep 17 00:00:00 2001 From: Danica Sugic Date: Tue, 5 Dec 2023 11:31:56 +0000 Subject: [PATCH 39/96] Add unit test for insertWidgetToVerticalLayout --- test/test__formUI_status_test.py | 22 ++++++++++++++++++++-- 1 file changed, 20 insertions(+), 2 deletions(-) diff --git a/test/test__formUI_status_test.py b/test/test__formUI_status_test.py index c7762b6..359852f 100644 --- a/test/test__formUI_status_test.py +++ b/test/test__formUI_status_test.py @@ -138,7 +138,10 @@ def _test_insert_one_widget(self, row, name, qwidget, qlabel=None): self.assertEqual(position, row) def test_insert_every_widget(self): - """Inserts each widget, and then each spanning widget, in position 0 of the form layout.""" + """ + Inserts each widget, and then each spanning widget, in position 0 of the form layout. + Tests the position of the widgets in the layout is 0. + """ list_widget_names = [ 'label insert', 'checkBox insert', 'comboBox insert', 'doubleSpinBox insert', 'spinBox insert', 'slider insert', 'uiSliderWidget insert', 'radioButton insert', @@ -438,7 +441,7 @@ def setUp(self): self.simple_form = FormDialog() self.add_two_widgets() self.layout = self.form.formWidget.uiElements['groupBoxFormLayout'] - + self.vertical_layout = self.form.formWidget.uiElements['verticalLayout'] def click_Ok(self): QTest.mouseClick(self.form.Ok, Qt.LeftButton) @@ -477,6 +480,21 @@ def test_form_init_title(self): FormDialog(title=None) FormDialog(title='title') + def _test_insert_one_widget_to_vertical_layout(self, row, qwidget): + """ + Invokes `insertWidgetToVerticalLayout`, therefore inserts the qwidget at position + row in the layout. Checks the position of the widget in the form is `row`. + """ + self.form.insertWidgetToVerticalLayout(row, qwidget) + position = self.vertical_layout.indexOf(qwidget) + self.assertEqual(position, row) + + def test_insert_every_widget_to_vertical_layout(self): + """Inserts each widget in position 0 of the vertical layout and tests its position in the layout is 0.""" + for i in range(0, len(self.list_all_widgets)): + qwidget = self.list_all_widgets[i] + self._test_insert_one_widget_to_vertical_layout(0, qwidget) + def test_getWidgetState_returns_QLabel_value(self): """Check that the value of the QLabel is saved to the state""" initial_label_value = 'Label: ' From 9660836800007cf05a2295d226182e34f4259dc3 Mon Sep 17 00:00:00 2001 From: Danica Sugic Date: Tue, 5 Dec 2023 14:17:47 +0000 Subject: [PATCH 40/96] Change dictionaries --- eqt/ui/UIFormWidget.py | 136 ++++++++++++++++++++--------------------- 1 file changed, 65 insertions(+), 71 deletions(-) diff --git a/eqt/ui/UIFormWidget.py b/eqt/ui/UIFormWidget.py index 484ef01..34a4420 100644 --- a/eqt/ui/UIFormWidget.py +++ b/eqt/ui/UIFormWidget.py @@ -52,17 +52,12 @@ def createForm(self): def groupBox(self): return self.uiElements['groupBox'] - def addSpanningWidget(self, qwidget, name): - self._addWidget(name, qwidget) - - def addWidget(self, qwidget, qlabel, name): - self._addWidget(name, qwidget, qlabel) - def insertWidgetToFormLayout(self, row, name, qwidget, qlabel=None): ''' - Inserts a widget, and a label widget, or a spanning widget to the form layout + Inserts a widget, and a label widget, or a spanning widget to the form layout, `groupBoxFormLayout`, in the position specified by row. If row is out of bounds, the widget is added at the end. - It adds the field (and label if present) in the widget dictionary. + It invokes `populate_widget_dictionaries` to populate the widget dictionary and the default states + dictionary. It increases "num_widgets" by 1 unit. It should not be used to move widgets in a form. @@ -73,20 +68,67 @@ def insertWidgetToFormLayout(self, row, name, qwidget, qlabel=None): qwidget: qwidget qlabel: qlabel widget or str ''' - field = f'{name}_field' - self.widgets[field] = qwidget + formLayout = self.uiElements['groupBoxFormLayout'] + if qlabel is not None: if isinstance(qlabel, str): txt = qlabel qlabel = QtWidgets.QLabel(self) qlabel.setText(txt) self.uiElements['groupBoxFormLayout'].insertRow(row, qlabel, qwidget) - label = f'{name}_label' - self.widgets[label] = qlabel else: self.uiElements['groupBoxFormLayout'].insertRow(row, qwidget) + self.increaseNumWidgets() + self.populate_widget_dictionary(self.widgets, name, qwidget, qlabel) + self.populate_widget_dictionary(self.default_widgets, name, qwidget, qlabel) + self.populate_default_widget_states_dictionary(name) + + def _addWidget(self, name, qwidget, qlabel=None): + ''' + Adds a widget, and a label widget, or a spanning widget at the the end of + the `groupBoxFormLayout` by invoking `insertWidgetToFormLayout`, where row is out of bounds. + + Parameters: + ---------- + name: str + qwidget: widget + qlabel: qlabel widget or str + ''' + self.insertWidgetToFormLayout(-1, name, qwidget, qlabel) + + def populate_widget_dictionary(self, dictionary, name, qwidget, qlabel = None): + """Adds the field (and label if present) in the widget dictionary.""" + field = f'{name}_field' + dictionary[field] = qwidget + if qlabel is not None: + label = f'{name}_label' + dictionary[label] = qlabel + + def remove_widget_from_dictionary(self, dictionary, name): + dictionary.pop(f'{name}_field') # removes field from the dictionary + if f'{name}_label' in dictionary.keys(): + dictionary.pop(f'{name}_label') + + def addWidget(self, qwidget, qlabel, name): + self._addWidget(name, qwidget, qlabel) + + def addSpanningWidget(self, qwidget, name): + self._addWidget(name, qwidget) + + def getNumWidgets(self): + ''' + Returns the number of widgets in the form. + ''' + return self.num_widgets + + def increaseNumWidgets(self): + """Increases `num_widget` by 1 unit.""" self.num_widgets += 1 + def decreaseNumWidgets(self): + """Decreases `num_widget` by 1 unit.""" + self.num_widgets -= 1 + def removeWidget(self, name): ''' Removes a widget (and its label if present) from the layout. @@ -94,20 +136,19 @@ def removeWidget(self, name): Deletes the field (and label) from the dictionary. ''' formLayout = self.uiElements['groupBoxFormLayout'] + if not hasattr(self, 'removed_widget_dictionary'): + self.removed_widget_dictionary = {} qwidget = self.getWidget(name, role='field') # retrieves the widget from its name + if f'{name}_label' in self.getWidgets().keys(): + qlabel = self.getWidget(name, role='label') + self.populate_widget_dictionary(self.removed_widget_dictionary, name, qwidget, qlabel) + else: + self.populate_widget_dictionary(self.removed_widget_dictionary, name, qwidget) formLayout.removeRow(qwidget) # removes the whole row from the layout - self.num_widgets -= 1 # updates total number of widgets - self.getWidgets().pop(name + '_field') # removes field from the dictionary - try: - self.getWidgets().pop(name + '_label') - except KeyError: - logging.info('Widget ' + name + ' does not have a label.') + self.decreaseNumWidgets() # updates total number of widgets + self.remove_widget_from_dictionary(self.getWidgets(), name) + - def getNumWidgets(self): - ''' - Returns the number of widgets in the form. - ''' - return self.num_widgets def getWidget(self, name, role='field'): '''returns the Widget by the name with which it has been added @@ -160,53 +201,6 @@ def addSeparator(self, name): frame.setFrameShadow(QtWidgets.QFrame.Raised) self._addWidget(name, frame) - def _addWidget(self, name, qwidget, qlabel=None): - ''' - Adds a widget, and a label widget, or a spanning widget to the the end of - the `groupBoxFormLayout`. It adds the field (and label if present) in the - widget dictionary, `self.widgets`. It creates the counter `self.num_widgets` - and it increases it by 1 unit. - - Parameters: - ---------- - name: str - qwidget: widget - qlabel: qlabel widget or str - ''' - formLayout = self.uiElements['groupBoxFormLayout'] - - # Create the widgets: - - widgetno = self.num_widgets - - # add the field - field = f'{name}_field' - self.widgets[field] = qwidget - self.default_widgets[field] = qwidget - - if qlabel is not None: - # add the label - label = f'{name}_label' - if isinstance(qlabel, str): - txt = qlabel - qlabel = QtWidgets.QLabel(self.uiElements['groupBox']) - qlabel.setText(txt) - formLayout.setWidget(widgetno, QtWidgets.QFormLayout.LabelRole, qlabel) - - # save a reference to label widgets in the dictionary - self.widgets[label] = qlabel - self.default_widgets[label] = qlabel - - field_form_role = QtWidgets.QFormLayout.FieldRole - - else: - # In the case we don't have a qlabel, set a spanning widget: - field_form_role = QtWidgets.QFormLayout.SpanningRole - - formLayout.setWidget(widgetno, field_form_role, qwidget) - self.num_widgets += 1 - self.populate_default_widget_states_dictionary(name) - def populate_default_widget_states_dictionary(self, name): ''' Creates an attribute dictionary of default widget states. The entries are in the @@ -220,7 +214,7 @@ def populate_default_widget_states_dictionary(self, name): # add the default state of the qlabel if f'{name}_label' in self.widgets.keys(): self.default_widget_states[f'{name}_label'] = self.getWidgetState(name, 'label') - + def set_default_widget_states_visible_true(self): ''' Sets all of the entries 'visible' in the `default_widget_states` dictionary to be `True`. From ed5904aeffe73295352649e2c039ae066e63a98c Mon Sep 17 00:00:00 2001 From: Danica Sugic Date: Tue, 5 Dec 2023 20:08:14 +0000 Subject: [PATCH 41/96] Add dictionary for widget number --- eqt/ui/UIFormWidget.py | 39 +++++++++++++++++++++++++++++++++------ 1 file changed, 33 insertions(+), 6 deletions(-) diff --git a/eqt/ui/UIFormWidget.py b/eqt/ui/UIFormWidget.py index 34a4420..1cd0b3a 100644 --- a/eqt/ui/UIFormWidget.py +++ b/eqt/ui/UIFormWidget.py @@ -41,7 +41,11 @@ def createForm(self): # Add elements to layout verticalLayout.addWidget(groupBox) + # number of widgets currently present in the groupBoxFormLayout self.num_widgets = 0 + # number of widgets removed from the groupBoxFormLayout + self.num_removed_widgets = 0 + self.widget_number_dictionary = {} self.uiElements = { 'verticalLayout': verticalLayout, 'groupBox': groupBox, 'groupBoxFormLayout': groupBoxFormLayout} @@ -80,6 +84,7 @@ def insertWidgetToFormLayout(self, row, name, qwidget, qlabel=None): self.uiElements['groupBoxFormLayout'].insertRow(row, qwidget) self.increaseNumWidgets() self.populate_widget_dictionary(self.widgets, name, qwidget, qlabel) + self.populate_widget_number_dictionary(name, row) self.populate_widget_dictionary(self.default_widgets, name, qwidget, qlabel) self.populate_default_widget_states_dictionary(name) @@ -97,17 +102,33 @@ def _addWidget(self, name, qwidget, qlabel=None): self.insertWidgetToFormLayout(-1, name, qwidget, qlabel) def populate_widget_dictionary(self, dictionary, name, qwidget, qlabel = None): - """Adds the field (and label if present) in the widget dictionary.""" - field = f'{name}_field' - dictionary[field] = qwidget + """Adds the field (and label if present) in the widget dictionary.""" + dictionary[f'{name}_field'] = qwidget if qlabel is not None: - label = f'{name}_label' - dictionary[label] = qlabel + dictionary[f'{name}_label'] = qlabel + + + def populate_widget_number_dictionary(self, name, widget_number): + if widget_number == -1: + self.widget_number_dictionary[name] = self.num_widgets + self.num_removed_widgets + #else: + d = {} + digits = {} + d = [key for key, value in d.items() if str(value).isdigit() and value >= widget_number] + print(d) + print("Hello") + #dictionary[f'{name}_number'] = widget_number + + + def remove_widget_from_dictionary(self, dictionary, name): - dictionary.pop(f'{name}_field') # removes field from the dictionary + if f'{name}_field' in dictionary.keys(): + dictionary.pop(f'{name}_field') # removes field from the dictionary if f'{name}_label' in dictionary.keys(): dictionary.pop(f'{name}_label') + if name in dictionary.keys(): + dictionary.pop(name) def addWidget(self, qwidget, qlabel, name): self._addWidget(name, qwidget, qlabel) @@ -138,6 +159,7 @@ def removeWidget(self, name): formLayout = self.uiElements['groupBoxFormLayout'] if not hasattr(self, 'removed_widget_dictionary'): self.removed_widget_dictionary = {} + widget_number = self.getWidgetNumber(name) qwidget = self.getWidget(name, role='field') # retrieves the widget from its name if f'{name}_label' in self.getWidgets().keys(): qlabel = self.getWidget(name, role='label') @@ -147,6 +169,7 @@ def removeWidget(self, name): formLayout.removeRow(qwidget) # removes the whole row from the layout self.decreaseNumWidgets() # updates total number of widgets self.remove_widget_from_dictionary(self.getWidgets(), name) + self.num_removed_widgets += 1 @@ -163,6 +186,10 @@ def getWidget(self, name, role='field'): return self.widgets[f'{name}_{role}'] raise ValueError(f'Unexpected role: expected any of {allowed_roles}, got {role}') + def getWidgetNumber(self, name): + '''Returns the Widget number by the name with which it has been added.''' + return self.widget_number_dictionary[name] + def setWidgetVisible(self, name, visible): ''' Sets the visibility of the widget and associated label with the given name. From bdcab4c7dc1a0aaa1915dbbb4a4b1bc676217917 Mon Sep 17 00:00:00 2001 From: Danica Sugic Date: Tue, 5 Dec 2023 21:08:18 +0000 Subject: [PATCH 42/96] Widget number dictionary works well --- eqt/ui/UIFormWidget.py | 35 ++++++++++++++++++++--------------- 1 file changed, 20 insertions(+), 15 deletions(-) diff --git a/eqt/ui/UIFormWidget.py b/eqt/ui/UIFormWidget.py index 1cd0b3a..846f03f 100644 --- a/eqt/ui/UIFormWidget.py +++ b/eqt/ui/UIFormWidget.py @@ -108,27 +108,31 @@ def populate_widget_dictionary(self, dictionary, name, qwidget, qlabel = None): dictionary[f'{name}_label'] = qlabel - def populate_widget_number_dictionary(self, name, widget_number): + def populate_widget_number_dictionary(self, name, row): + widget_number = row if widget_number == -1: - self.widget_number_dictionary[name] = self.num_widgets + self.num_removed_widgets - #else: - d = {} - digits = {} - d = [key for key, value in d.items() if str(value).isdigit() and value >= widget_number] - print(d) - print("Hello") - #dictionary[f'{name}_number'] = widget_number - - - + self.widget_number_dictionary[name] = self.num_widgets + self.num_removed_widgets - 1 + print(self.widget_number_dictionary) + else: + for key, value in self.widget_number_dictionary.items(): + if value >= widget_number: + self.widget_number_dictionary[key] = value + 1 + self.widget_number_dictionary[name] = widget_number + print(self.widget_number_dictionary) + + def pop_widget_number_dictionary(self, name, row): + widget_number = row + for key, value in self.widget_number_dictionary.items(): + if value > widget_number: + self.widget_number_dictionary[key] = value - 1 + self.widget_number_dictionary.pop(name) + print(self.widget_number_dictionary) def remove_widget_from_dictionary(self, dictionary, name): if f'{name}_field' in dictionary.keys(): dictionary.pop(f'{name}_field') # removes field from the dictionary if f'{name}_label' in dictionary.keys(): - dictionary.pop(f'{name}_label') - if name in dictionary.keys(): - dictionary.pop(name) + dictionary.pop(f'{name}_label') def addWidget(self, qwidget, qlabel, name): self._addWidget(name, qwidget, qlabel) @@ -170,6 +174,7 @@ def removeWidget(self, name): self.decreaseNumWidgets() # updates total number of widgets self.remove_widget_from_dictionary(self.getWidgets(), name) self.num_removed_widgets += 1 + self.pop_widget_number_dictionary(name, widget_number) From ce92bf76a225ef761f4a033538b0954bd970b322 Mon Sep 17 00:00:00 2001 From: Danica Sugic Date: Wed, 6 Dec 2023 15:55:51 +0000 Subject: [PATCH 43/96] Modify various methods so remove widgets works --- eqt/ui/FormDialog.py | 6 +- eqt/ui/UIFormWidget.py | 195 ++++++++++++++++++++++++++++------------- 2 files changed, 139 insertions(+), 62 deletions(-) diff --git a/eqt/ui/FormDialog.py b/eqt/ui/FormDialog.py index 24cbc8e..07a1f3b 100644 --- a/eqt/ui/FormDialog.py +++ b/eqt/ui/FormDialog.py @@ -141,9 +141,13 @@ def getWidget(self, name, role='field'): return self.formWidget.getWidget(name, role) def getWidgets(self): - '''returns a dictionary of all the widgets in the form''' + '''Invokes `getWidgets` from `UIFormWidget`.''' return self.formWidget.getWidgets() + def getRemovedWidgets(self): + '''Invokes `getRemovedWidgets` from `UIFormWidget`.''' + return self.formWidget.getRemovedWidgets() + def setWidgetVisible(self, name, visible): ''' Sets the visibility of the widget and associated label with the given name. diff --git a/eqt/ui/UIFormWidget.py b/eqt/ui/UIFormWidget.py index 846f03f..67d3126 100644 --- a/eqt/ui/UIFormWidget.py +++ b/eqt/ui/UIFormWidget.py @@ -108,25 +108,46 @@ def populate_widget_dictionary(self, dictionary, name, qwidget, qlabel = None): dictionary[f'{name}_label'] = qlabel - def populate_widget_number_dictionary(self, name, row): - widget_number = row + def populate_widget_number_dictionary(self, name, widget_number): + """ + Adds one item in the widget-number dictionary whose key is name and value is + the current widget number (i.e. row) in the form layout. + As one widget is inserted, the widget number associated to the other widgets + in the layout are updated. + + Parameters: + --------------- + name: string + name of the widget + widget_number : int + position of the widget in the form layout, i.e. row, in the current state + """ if widget_number == -1: - self.widget_number_dictionary[name] = self.num_widgets + self.num_removed_widgets - 1 - print(self.widget_number_dictionary) + self.widget_number_dictionary[name] = self.num_widgets - 1 else: for key, value in self.widget_number_dictionary.items(): if value >= widget_number: self.widget_number_dictionary[key] = value + 1 self.widget_number_dictionary[name] = widget_number - print(self.widget_number_dictionary) - def pop_widget_number_dictionary(self, name, row): - widget_number = row + def pop_widget_number_dictionary(self, name, widget_number): + """ + Removes one item in the widget-number dictionary whose key is name and value is + the widget number (i.e. row) in the form layout. + As one widget is removed, the widget number associated to the other widgets + in the layout are updated. + + Parameters: + --------------- + name: string + name of the widget + widget_number : int + position of the widget in the form layout, i.e. row, in the current state + """ for key, value in self.widget_number_dictionary.items(): if value > widget_number: self.widget_number_dictionary[key] = value - 1 self.widget_number_dictionary.pop(name) - print(self.widget_number_dictionary) def remove_widget_from_dictionary(self, dictionary, name): if f'{name}_field' in dictionary.keys(): @@ -161,16 +182,21 @@ def removeWidget(self, name): Deletes the field (and label) from the dictionary. ''' formLayout = self.uiElements['groupBoxFormLayout'] - if not hasattr(self, 'removed_widget_dictionary'): - self.removed_widget_dictionary = {} + if not hasattr(self, 'removed_widgets_dictionary'): + self.removed_widgets_dictionary = {} widget_number = self.getWidgetNumber(name) qwidget = self.getWidget(name, role='field') # retrieves the widget from its name if f'{name}_label' in self.getWidgets().keys(): qlabel = self.getWidget(name, role='label') - self.populate_widget_dictionary(self.removed_widget_dictionary, name, qwidget, qlabel) + self.populate_widget_dictionary(self.removed_widgets_dictionary, name, qwidget, qlabel) + print(formLayout.rowCount()) + self.getWidget(name, 'label').setParent(None) + print(formLayout.rowCount()) else: - self.populate_widget_dictionary(self.removed_widget_dictionary, name, qwidget) - formLayout.removeRow(qwidget) # removes the whole row from the layout + self.populate_widget_dictionary(self.removed_widgets_dictionary, name, qwidget) + print(formLayout.rowCount()) + self.getWidget(name, 'field').setParent(None) # removes the whole row from the layout + print(formLayout.rowCount()) self.decreaseNumWidgets() # updates total number of widgets self.remove_widget_from_dictionary(self.getWidgets(), name) self.num_removed_widgets += 1 @@ -215,8 +241,12 @@ def setWidgetVisible(self, name, visible): pass def getWidgets(self): - '''returns a dictionary of all the widgets in the form''' + '''Returns a dictionary of the widgets currently present in the form.''' return self.widgets + + def getRemovedWidgets(self): + '''Returns the dictionary of the removed widgets previously present in the form.''' + return self.removed_widgets_dictionary def addTitle(self, qlabel, name): if isinstance(qlabel, str): @@ -236,7 +266,7 @@ def addSeparator(self, name): def populate_default_widget_states_dictionary(self, name): ''' Creates an attribute dictionary of default widget states. The entries are in the - format: {'value': str | bool | int, 'enabled': bool, 'visible': bool}. + format: {'value': str | bool | int, 'enabled': bool, 'visible': bool, 'widget_number': int}. This can be used to restore the default states of the widgets invoking `applyWidgetStates`. ''' if not hasattr(self, 'default_widget_states'): @@ -246,6 +276,7 @@ def populate_default_widget_states_dictionary(self, name): # add the default state of the qlabel if f'{name}_label' in self.widgets.keys(): self.default_widget_states[f'{name}_label'] = self.getWidgetState(name, 'label') + print(self.default_widget_states) def set_default_widget_states_visible_true(self): ''' @@ -265,9 +296,8 @@ def getAllWidgetStates(self): 'widget2': {'value': 2, 'enabled': False, 'visible': False}}. ''' all_widget_states = {} - for name, widget in self.widgets.items(): - widget_state = self.getWidgetState(widget) - all_widget_states[name] = widget_state + for key, widget in self.widgets.items(): + all_widget_states[key] = self.getWidgetState(widget) return all_widget_states def getWidgetState(self, widget, role=None): @@ -275,15 +305,15 @@ def getWidgetState(self, widget, role=None): Parameters ---------- widget: QWidget or str - The (name of) widget to get the state of. + The widget or its name to get the state of. role: str, optional, default None, values: 'label', 'field', None. - The role of the widget to apply the state to (only if `widget` is a `str`). - If unspecified, the widget is chosen based on `name=widget`. + The role of the widget to apply the state to (only if `widget` is the widget name string.). Returns ------- state: dict - Format: {'value': str | bool | int, 'enabled': bool, 'visible': bool}, + Format: {'value': str | bool | int, 'enabled': bool, 'visible': bool, 'widget_number' : int}, + or {'value': str | bool | int, 'enabled': bool, 'visible': bool}, e.g. {'value': 1, 'enabled': True, 'visible': True}. This can be used to restore the state of the widget using `setWidgetState()`. ''' @@ -291,28 +321,21 @@ def getWidgetState(self, widget, role=None): raise ValueError('The widget (or name of widget) must be given') if isinstance(widget, str): - if role is not None: - if role not in ['label', 'field']: - raise ValueError('role must be either "label", "field" or None') - name = widget + '_' + role + if role is None or role not in ['label', 'field']: + raise ValueError('Role must be either "label" or "field" when the name string is inputted.') else: + name_role = widget + '_' + role name = widget - - try: - widget = self.widgets[name] - except KeyError: - if role is None: - try: - widget = self.widgets[name + '_field'] - except KeyError: - raise KeyError('No widget with name: ' + name + ' or ' + name + '_field') - else: - raise KeyError('No widget with name: ' + name) - + try: + widget = self.widgets[name_role] + except KeyError: + raise KeyError('No widget associated with the dictionary key `'+name_role+'`.') + else: + name, role = self.getNameAndRoleFromWidget(widget) widget_state = {} widget_state['enabled'] = widget.isEnabled() widget_state['visible'] = widget.isVisible() - + if isinstance(widget, QtWidgets.QLabel): widget_state['value'] = widget.text() elif isinstance(widget, (QtWidgets.QCheckBox, QtWidgets.QPushButton)): @@ -330,38 +353,60 @@ def getWidgetState(self, widget, role=None): elif isinstance(widget, (QtWidgets.QTextEdit, QtWidgets.QPlainTextEdit)): widget_state['value'] = widget.toPlainText() + if role == 'field': + widget_state['widget_number'] = self.widget_number_dictionary[name] + + return widget_state - def applyWidgetState(self, name, state, role=None): + def getNameAndRoleFromWidget(self, widget): + for key, value in self.widgets.items(): + if value == widget: + name_role = key + if '_field' in name_role: + name = name_role.removesuffix('_field') + role = 'field' + elif '_label' in name_role: + name = name_role.removesuffix('_label') + role = 'label' + return name, role + + def applyWidgetState(self, name_key, state, role=None): ''' - Applies the given `state` to the widget with the given `name`. + Applies the given `state` to the widget associated with key. Parameters ---------- - name: str - The name of the widget to apply the state to. + key: str + The key of the widget to apply the state to, e.g. name or f'{name}_field' or f'{name}_label' role: str, optional, default None, values: 'label', 'field', None. The role of the widget to apply the state to (only if `widget` is a `str`). - If unspecified, the widget is chosen based on `name`. + If unspecified, the widget is chosen based on key. state: dict - Format: {'value': str | bool | int, 'enabled': bool, 'visible': bool}, - e.g. {'value': 1, 'enabled': True, 'visible': True}. + Format: {'value': str | bool | int, 'enabled': bool, 'visible': bool, 'widget_number' : int}, + or {'value': str | bool | int, 'enabled': bool, 'visible': bool} + e.g. {'value': 1, 'enabled': True, 'visible': True}. ''' if role is not None: - if role not in ['label', 'field']: - raise ValueError('role must be either "label", "field" or None') - name = name + '_' + role + if role in ['label', 'field']: + name_role = name_key + '_' + role + else: + raise ValueError('Role must be either "label" or "field"') + else: + name_role = name_key try: - widget = self.widgets[name] + if name_role in self.widgets.keys(): + widget = self.widgets[name_role] + elif hasattr(self, 'removed_widgets_dictionary'): + if name_role in self.removed_widgets_dictionary.keys(): + widget = self.removed_widgets_dictionary[name_role] except KeyError: - if role is None: - try: - widget = self.widgets[name + '_field'] - except KeyError: - raise KeyError('No widget with name: ' + name + ' or ' + name + '_field') - else: - raise KeyError('No widget with name: ' + name) + raise KeyError('No widget associated with the dictionary key `'+name_role+'`.') + + + + for key, value in state.items(): if key == 'enabled': @@ -387,6 +432,10 @@ def applyWidgetState(self, name, state, role=None): widget.setChecked(value) elif isinstance(widget, (QtWidgets.QTextEdit, QtWidgets.QPlainTextEdit)): widget.setPlainText(value) + elif key == 'widget_number': + if value != self.widget_number_dictionary[name]: + self.widget_number_dictionary[name] = value + def applyWidgetStates(self, state): ''' @@ -400,8 +449,26 @@ def applyWidgetStates(self, state): e.g. {{'widget1': {'value': 1, 'enabled': True, 'visible': True}, 'widget2': {'value': 2, 'enabled': False, 'visible': False}}. ''' - for name, widget_state in state.items(): - self.applyWidgetState(name, widget_state) + print(state) + for key, widget_state in state.items(): + if key in self.widgets.keys(): + print("pass") + pass + elif hasattr(self, 'removed_widgets_dictionary'): + if key in self.removed_widgets_dictionary.keys(): + if '_field' in key: + print(self.removed_widgets_dictionary) + name = key.removesuffix('_field') + qwidget = self.removed_widgets_dictionary[key] + print(qwidget) + if f'{name}_label' in self.removed_widgets_dictionary.keys(): + print("label is there") + qlabel = self.removed_widgets_dictionary[key] + self.insertWidgetToFormLayout(state[key]['widget_number'],name,qwidget,qlabel) + else: + self.insertWidgetToFormLayout(state[key]['widget_number'],name,qwidget) + print("Hello rw") + self.applyWidgetState(key, widget_state) def saveAllWidgetStates(self): ''' @@ -409,6 +476,7 @@ def saveAllWidgetStates(self): To later restore the states, use `restoreAllSavedWidgetStates()`. ''' self.widget_states = self.getAllWidgetStates() + print(self.widget_states) def restoreAllSavedWidgetStates(self): ''' @@ -479,6 +547,10 @@ def getWidgets(self): '''returns a dictionary of all the widgets in the form''' return self.widget().getWidgets() + def getRemovedWidgets(self): + '''Invokes `getRemovedWidgets` from `UIFormWidget`.''' + return self.widget().getRemovedWidgets() + def setWidgetVisible(self, name, visible): '''Sets the visibility of the widget and associated label with the given name.''' self.widget().setWidgetVisible(name, visible) @@ -540,8 +612,9 @@ def applyWidgetState(self, name, state, role=None): The role of the widget to apply the state to. If unspecified, the widget is chosen based on `name`. state: dict - Format: {'value': str | bool | int, 'enabled': bool, 'visible': bool}, - e.g. {'value': 1, 'enabled': True, 'visible': True}. + Format: {'value': str | bool | int, 'enabled': bool, 'visible': bool, 'widget_number' : int}, + or {'value': str | bool | int, 'enabled': bool, 'visible': bool} + e.g. {'value': 1, 'enabled': True, 'visible': True}. ''' return self.widget().applyWidgetState(name, state, role) From 0239649af278a2d8ff38516a5563522297378697 Mon Sep 17 00:00:00 2001 From: Danica Sugic Date: Wed, 6 Dec 2023 19:49:00 +0000 Subject: [PATCH 44/96] modify unit test to meet new widget number --- eqt/ui/UIFormWidget.py | 87 ++++++++++++++++++++++---------- test/test__formUI_status_test.py | 70 ++++++++++--------------- 2 files changed, 86 insertions(+), 71 deletions(-) diff --git a/eqt/ui/UIFormWidget.py b/eqt/ui/UIFormWidget.py index 67d3126..0cd2cc8 100644 --- a/eqt/ui/UIFormWidget.py +++ b/eqt/ui/UIFormWidget.py @@ -177,9 +177,16 @@ def decreaseNumWidgets(self): def removeWidget(self, name): ''' - Removes a widget (and its label if present) from the layout. + If not present already, creates a dictionary to store the removed qwidgets. + Sets the parent of the qwidget (and qlabel if present) to `None`. Decreases the counter for the number of widgets in the layout. - Deletes the field (and label) from the dictionary. + Deletes the qwidget and qlabel from the widgets dictionary. + Deletes the widget number from the widget-number dictionary. + + Parameters: + -------------- + name : str + name of the widget to be removed ''' formLayout = self.uiElements['groupBoxFormLayout'] if not hasattr(self, 'removed_widgets_dictionary'): @@ -195,7 +202,8 @@ def removeWidget(self, name): else: self.populate_widget_dictionary(self.removed_widgets_dictionary, name, qwidget) print(formLayout.rowCount()) - self.getWidget(name, 'field').setParent(None) # removes the whole row from the layout + self.getWidget(name, 'field').setParent(None) + formLayout.removeRow(self.widget_number_dictionary[name]) # removes the whole row from the layout print(formLayout.rowCount()) self.decreaseNumWidgets() # updates total number of widgets self.remove_widget_from_dictionary(self.getWidgets(), name) @@ -266,7 +274,8 @@ def addSeparator(self, name): def populate_default_widget_states_dictionary(self, name): ''' Creates an attribute dictionary of default widget states. The entries are in the - format: {'value': str | bool | int, 'enabled': bool, 'visible': bool, 'widget_number': int}. + format: {'value': str | bool | int, 'enabled': bool, 'visible': bool, 'widget_number': int} + or {'value': str | bool | int, 'enabled': bool, 'visible': bool}. This can be used to restore the default states of the widgets invoking `applyWidgetStates`. ''' if not hasattr(self, 'default_widget_states'): @@ -276,7 +285,6 @@ def populate_default_widget_states_dictionary(self, name): # add the default state of the qlabel if f'{name}_label' in self.widgets.keys(): self.default_widget_states[f'{name}_label'] = self.getWidgetState(name, 'label') - print(self.default_widget_states) def set_default_widget_states_visible_true(self): ''' @@ -305,7 +313,7 @@ def getWidgetState(self, widget, role=None): Parameters ---------- widget: QWidget or str - The widget or its name to get the state of. + The widget or its name, or its name + "_field" or "_label" (when role is None) to get the state of. role: str, optional, default None, values: 'label', 'field', None. The role of the widget to apply the state to (only if `widget` is the widget name string.). @@ -321,15 +329,28 @@ def getWidgetState(self, widget, role=None): raise ValueError('The widget (or name of widget) must be given') if isinstance(widget, str): - if role is None or role not in ['label', 'field']: - raise ValueError('Role must be either "label" or "field" when the name string is inputted.') - else: + if role is not None: + if role not in ['label', 'field']: + raise ValueError('Role must be either "label", "field" or None') name_role = widget + '_' + role name = widget - try: - widget = self.widgets[name_role] - except KeyError: - raise KeyError('No widget associated with the dictionary key `'+name_role+'`.') + else: + name_role = widget + if '_field' in name_role: + name = name_role.removesuffix('_field') + role = 'field' + elif '_label' in name_role: + name = name_role.removesuffix('_label') + role = 'label' + else: + name = widget + role = 'field' + name_role = name + '_' + role + + try: + widget = self.widgets[name_role] + except KeyError: + raise KeyError('No widget associated with the dictionary key `'+ name_role) else: name, role = self.getNameAndRoleFromWidget(widget) widget_state = {} @@ -373,27 +394,36 @@ def getNameAndRoleFromWidget(self, widget): def applyWidgetState(self, name_key, state, role=None): ''' - Applies the given `state` to the widget associated with key. + Applies the given `state` to the widget associated with `name_key`. Parameters ---------- - key: str + name_key: str The key of the widget to apply the state to, e.g. name or f'{name}_field' or f'{name}_label' role: str, optional, default None, values: 'label', 'field', None. The role of the widget to apply the state to (only if `widget` is a `str`). - If unspecified, the widget is chosen based on key. + If unspecified, the widget is chosen based on name_key. state: dict Format: {'value': str | bool | int, 'enabled': bool, 'visible': bool, 'widget_number' : int}, or {'value': str | bool | int, 'enabled': bool, 'visible': bool} e.g. {'value': 1, 'enabled': True, 'visible': True}. ''' if role is not None: - if role in ['label', 'field']: - name_role = name_key + '_' + role - else: - raise ValueError('Role must be either "label" or "field"') + if role not in ['label', 'field']: + raise ValueError('Role must be either "label", "field" or None') + name_role = name_key + '_' + role + name = name_key else: name_role = name_key + if '_field' in name_role: + name = name_role.removesuffix('_field') + role = 'field' + elif '_label' in name_role: + name = name_role.removesuffix('_label') + role = 'label' + else: + name_role = name_key + '_field' + name = name_key try: if name_role in self.widgets.keys(): @@ -402,6 +432,16 @@ def applyWidgetState(self, name_key, state, role=None): if name_role in self.removed_widgets_dictionary.keys(): widget = self.removed_widgets_dictionary[name_role] except KeyError: + if role is None: + try: + name_role = name_key + '_field' + if name_role in self.widgets.keys(): + widget = self.widgets[name_role] + elif hasattr(self, 'removed_widgets_dictionary'): + if name_role in self.removed_widgets_dictionary.keys(): + widget = self.removed_widgets_dictionary[name_role] + except KeyError: + raise KeyError('No widget associated with the dictionary key `'+name_role+'`.') raise KeyError('No widget associated with the dictionary key `'+name_role+'`.') @@ -449,25 +489,19 @@ def applyWidgetStates(self, state): e.g. {{'widget1': {'value': 1, 'enabled': True, 'visible': True}, 'widget2': {'value': 2, 'enabled': False, 'visible': False}}. ''' - print(state) for key, widget_state in state.items(): if key in self.widgets.keys(): - print("pass") pass elif hasattr(self, 'removed_widgets_dictionary'): if key in self.removed_widgets_dictionary.keys(): if '_field' in key: - print(self.removed_widgets_dictionary) name = key.removesuffix('_field') qwidget = self.removed_widgets_dictionary[key] - print(qwidget) if f'{name}_label' in self.removed_widgets_dictionary.keys(): - print("label is there") qlabel = self.removed_widgets_dictionary[key] self.insertWidgetToFormLayout(state[key]['widget_number'],name,qwidget,qlabel) else: self.insertWidgetToFormLayout(state[key]['widget_number'],name,qwidget) - print("Hello rw") self.applyWidgetState(key, widget_state) def saveAllWidgetStates(self): @@ -476,7 +510,6 @@ def saveAllWidgetStates(self): To later restore the states, use `restoreAllSavedWidgetStates()`. ''' self.widget_states = self.getAllWidgetStates() - print(self.widget_states) def restoreAllSavedWidgetStates(self): ''' diff --git a/test/test__formUI_status_test.py b/test/test__formUI_status_test.py index 359852f..b9793b4 100644 --- a/test/test__formUI_status_test.py +++ b/test/test__formUI_status_test.py @@ -51,6 +51,16 @@ def list_all_widgets(self): QtWidgets.QLineEdit('test line edit'), QtWidgets.QPushButton('test push button')] return list_all_widgets + + @property + def state_simple_form(self): + state_simple_form = { + 'label_field': {'value': 'test label', 'enabled': True, 'visible': False, 'widget_number': 0}, + 'label_label': {'value': 'Label: ', 'enabled': True, 'visible': False}, + 'checkBox_field': {'value': False, 'enabled': True, 'visible': False,'widget_number': 1}, + 'checkBox_label': {'value': 'CheckBox: ', 'enabled': True, 'visible': False} + } + return state_simple_form def add_every_widget(self): """Generate every widget and add it to `self.form`""" @@ -391,46 +401,33 @@ def test_getWidgetState_returns_QRadioButton_value(self): self.assertEqual(self.form.getWidgetState('radioButton_field')['value'], final_radio_value) def test_applyWidgetStates(self): - state_to_set = { - 'checkBox_field': {'value': True, 'enabled': False, 'visible': False}, - 'label_field': {'value': 'applyWidgetStates Test', 'enabled': True, 'visible': False}} - - self.simple_form.applyWidgetStates(state_to_set) + self.simple_form.applyWidgetStates(self.state_simple_form) self.assertEqual(self.simple_form.getWidgetState('checkBox_field'), - state_to_set['checkBox_field']) + self.state_simple_form['checkBox_field']) self.assertEqual(self.simple_form.getWidgetState('label_field'), - state_to_set['label_field']) + self.state_simple_form['label_field']) def test_applyWidgetState(self): - state_to_set = {'value': True, 'enabled': False, 'visible': False} - self.simple_form.applyWidgetState('checkBox_field', state_to_set) - self.assertEqual(self.simple_form.getWidgetState('checkBox_field'), state_to_set) + self.simple_form.applyWidgetState('checkBox_field', self.state_simple_form['checkBox_field']) + self.assertEqual(self.simple_form.getWidgetState('checkBox_field'), self.state_simple_form['checkBox_field']) def test_applyWidgetState_using_role_parameter_field(self): - state_to_set = {'value': True, 'enabled': False, 'visible': False} - self.simple_form.applyWidgetState('checkBox', state_to_set, role='field') - self.assertEqual(self.simple_form.getWidgetState('checkBox', 'field'), state_to_set) + self.simple_form.applyWidgetState('checkBox', self.state_simple_form['checkBox_field'], role='field') + self.assertEqual(self.simple_form.getWidgetState('checkBox', 'field'), self.state_simple_form['checkBox_field']) def test_applyWidgetState_using_role_parameter_label(self): - state_to_set = {'value': 'test the checkbox:', 'enabled': False, 'visible': False} - self.simple_form.applyWidgetState('checkBox', state_to_set, role='label') - self.assertEqual(self.simple_form.getWidgetState('checkBox', 'label'), state_to_set) + + self.simple_form.applyWidgetState('checkBox', self.state_simple_form['checkBox_label'], role='label') + self.assertEqual(self.simple_form.getWidgetState('checkBox', 'label'), self.state_simple_form['checkBox_label']) def test_applyWidgetState_using_role_parameter_default(self): - state_to_set = {'value': True, 'enabled': False, 'visible': False} - self.simple_form.applyWidgetState('checkBox', state_to_set) - self.assertEqual(self.simple_form.getWidgetState('checkBox'), state_to_set) + self.simple_form.applyWidgetState('checkBox', self.state_simple_form['checkBox_field']) + self.assertEqual(self.simple_form.getWidgetState('checkBox'), self.state_simple_form['checkBox_field']) def test_getAllWidgetStates(self): """Check that the state of all widgets is returned""" - expected_state = { - 'checkBox_field': {'value': False, 'enabled': True, 'visible': False}, - 'label_field': {'value': 'test label', 'enabled': True, 'visible': False}, - 'checkBox_label': {'value': 'CheckBox: ', 'enabled': True, 'visible': False}, - 'label_label': {'value': 'Label: ', 'enabled': True, 'visible': False}} - - self.assertEqual(self.simple_form.getAllWidgetStates(), expected_state) + self.assertEqual(self.simple_form.getAllWidgetStates(), self.state_simple_form) @skip_ci @@ -506,13 +503,8 @@ def test_getWidgetState_returns_QLabel_value(self): def test_saveAllWidgetStates(self): """Check that the state of all widgets is saved to the state variable""" - expected_state = { - 'checkBox_field': {'value': False, 'enabled': True, 'visible': False}, - 'label_field': {'value': 'test label', 'enabled': True, 'visible': False}, - 'checkBox_label': {'value': 'CheckBox: ', 'enabled': True, 'visible': False}, - 'label_label': {'value': 'Label: ', 'enabled': True, 'visible': False}} self.simple_form.saveAllWidgetStates() - self.assertEqual(self.simple_form.formWidget.widget_states, expected_state) + self.assertEqual(self.simple_form.formWidget.widget_states, self.state_simple_form) def test_restoreAllSavedWidgetStates(self): """Check that the state of all widgets is restored from the state variable""" @@ -581,13 +573,8 @@ def test_getWidgetState_returns_QLabel_value(self): def test_saveAllWidgetStates(self): """Check that the state of all widgets is saved to the state variable""" - expected_state = { - 'checkBox_field': {'value': False, 'enabled': True, 'visible': False}, - 'label_field': {'value': 'test label', 'enabled': True, 'visible': False}, - 'checkBox_label': {'value': 'CheckBox: ', 'enabled': True, 'visible': False}, - 'label_label': {'value': 'Label: ', 'enabled': True, 'visible': False}} self.simple_form.saveAllWidgetStates() - self.assertEqual(self.simple_form.widget_states, expected_state) + self.assertEqual(self.simple_form.widget_states, self.state_simple_form) def test_restoreAllSavedWidgetStates(self): """Check that the state of all widgets is restored from the state variable""" @@ -662,13 +649,8 @@ def test_getWidgetState_returns_QLabel_value(self): def test_saveAllWidgetStates(self): """Check that the state of all widgets is saved to the state variable""" - expected_state = { - 'checkBox_field': {'value': False, 'enabled': True, 'visible': False}, - 'label_field': {'value': 'test label', 'enabled': True, 'visible': False}, - 'checkBox_label': {'value': 'CheckBox: ', 'enabled': True, 'visible': False}, - 'label_label': {'value': 'Label: ', 'enabled': True, 'visible': False}} self.simple_form.saveAllWidgetStates() - self.assertEqual(self.simple_form.widget().widget_states, expected_state) + self.assertEqual(self.simple_form.widget().widget_states, self.state_simple_form) def test_restoreAllSavedWidgetStates(self): """Check that the state of all widgets is restored from the state variable""" From 087eed8ce97bc8d2917323650fd5662d9c09e386 Mon Sep 17 00:00:00 2001 From: Danica Sugic Date: Thu, 7 Dec 2023 12:40:08 +0000 Subject: [PATCH 45/96] Some polishing of the code --- eqt/ui/FormDialog.py | 40 +------ eqt/ui/UIFormWidget.py | 243 +++++++++++++++++++---------------------- 2 files changed, 114 insertions(+), 169 deletions(-) diff --git a/eqt/ui/FormDialog.py b/eqt/ui/FormDialog.py index 07a1f3b..8af2139 100644 --- a/eqt/ui/FormDialog.py +++ b/eqt/ui/FormDialog.py @@ -188,50 +188,16 @@ def getAllWidgetStates(self): def getWidgetState(self, widget, role=None): ''' - Parameters - ---------- - widget: QWidget or str - The (name of) widget to get the state of. - role: str, optional, default None, values: 'label', 'field', None. - The role of the widget to get the state of (only if `widget` is a `str`). - If unspecified, the widget is chosen based on `name=widget`. - - Returns - ------- - dict - Widget state, format: {'value': str | bool | int, 'enabled': bool, 'visible': bool}, - e.g. {'value': 1, 'enabled': True, 'visible': True}. - This can be used to restore the state of the widget using `setWidgetState()`. + Invokes `getWidgetState` from `UIFormWidget`. ''' return self.formWidget.getWidgetState(widget, role) def applyWidgetState(self, name, state, role=None): - ''' - Applies the given state to the widget with the given name. - - Parameters - ---------- - name: str - The name of the widget to apply the state to. - role: str, optional, default None, values: 'label', 'field', None. - The role of the widget to apply the state to. - If unspecified, the widget is chosen based on `name`. - state: dict - Format: {'value': str | bool | int, 'enabled': bool, 'visible': bool}, - e.g. {'value': 1, 'enabled': True, 'visible': True}. - ''' + '''Invokes `applyWidgetState` from `UIFormWidget`.''' return self.formWidget.applyWidgetState(name, state, role) def applyWidgetStates(self, state): ''' - Applies the given states to the form's widgets. - - Parameters - ---------- - state: dict - Format: {'widget_name': {'value': str | bool | int, 'enabled': bool, 'visible': bool}, - ...}, - e.g. {{'widget1': {'value': 1, 'enabled': True, 'visible': True}, - 'widget2': {'value': 2, 'enabled': False, 'visible': False}}. + Invokes `applyWidgetStates` from `UIFormWidget`. ''' return self.formWidget.applyWidgetStates(state) diff --git a/eqt/ui/UIFormWidget.py b/eqt/ui/UIFormWidget.py index 0cd2cc8..a9a05e9 100644 --- a/eqt/ui/UIFormWidget.py +++ b/eqt/ui/UIFormWidget.py @@ -102,14 +102,13 @@ def _addWidget(self, name, qwidget, qlabel=None): self.insertWidgetToFormLayout(-1, name, qwidget, qlabel) def populate_widget_dictionary(self, dictionary, name, qwidget, qlabel = None): - """Adds the field (and label if present) in the widget dictionary.""" + '''Adds the field (and label if present) in the widget dictionary.''' dictionary[f'{name}_field'] = qwidget if qlabel is not None: dictionary[f'{name}_label'] = qlabel - def populate_widget_number_dictionary(self, name, widget_number): - """ + ''' Adds one item in the widget-number dictionary whose key is name and value is the current widget number (i.e. row) in the form layout. As one widget is inserted, the widget number associated to the other widgets @@ -121,7 +120,7 @@ def populate_widget_number_dictionary(self, name, widget_number): name of the widget widget_number : int position of the widget in the form layout, i.e. row, in the current state - """ + ''' if widget_number == -1: self.widget_number_dictionary[name] = self.num_widgets - 1 else: @@ -131,7 +130,7 @@ def populate_widget_number_dictionary(self, name, widget_number): self.widget_number_dictionary[name] = widget_number def pop_widget_number_dictionary(self, name, widget_number): - """ + ''' Removes one item in the widget-number dictionary whose key is name and value is the widget number (i.e. row) in the form layout. As one widget is removed, the widget number associated to the other widgets @@ -143,22 +142,35 @@ def pop_widget_number_dictionary(self, name, widget_number): name of the widget widget_number : int position of the widget in the form layout, i.e. row, in the current state - """ + ''' for key, value in self.widget_number_dictionary.items(): if value > widget_number: self.widget_number_dictionary[key] = value - 1 self.widget_number_dictionary.pop(name) - def remove_widget_from_dictionary(self, dictionary, name): - if f'{name}_field' in dictionary.keys(): - dictionary.pop(f'{name}_field') # removes field from the dictionary - if f'{name}_label' in dictionary.keys(): - dictionary.pop(f'{name}_label') + def remove_widget_from_dictionary(self, dictionary, name_key): + ''' + Removes the item associated with `name_key` from a dictionary. + + Parameters: + ----------------- + dictionary : dict + name_key: str + Format: {name} or {name}_field or {name}_label + ''' + if name_key in dictionary.keys(): + dictionary.pop(name_key) + if f'{name_key}_field' in dictionary.keys(): + dictionary.pop(f'{name_key}_field') + if f'{name_key}_label' in dictionary.keys(): + dictionary.pop(f'{name_key}_label') def addWidget(self, qwidget, qlabel, name): + '''Adds a qwidget and a qlabel widget in the same row of the form layout by invoking `_addWidget`.''' self._addWidget(name, qwidget, qlabel) def addSpanningWidget(self, qwidget, name): + '''Adds a spanning qwidget occupying the full row in the form layout by invoking `_addWidget`.''' self._addWidget(name, qwidget) def getNumWidgets(self): @@ -168,20 +180,23 @@ def getNumWidgets(self): return self.num_widgets def increaseNumWidgets(self): - """Increases `num_widget` by 1 unit.""" + '''Increases `num_widget` by 1 unit.''' self.num_widgets += 1 def decreaseNumWidgets(self): - """Decreases `num_widget` by 1 unit.""" + '''Decreases `num_widget` by 1 unit.''' self.num_widgets -= 1 def removeWidget(self, name): ''' If not present already, creates a dictionary to store the removed qwidgets. - Sets the parent of the qwidget (and qlabel if present) to `None`. - Decreases the counter for the number of widgets in the layout. + Sets the parent of the qwidget (and qlabel if present) to `None` and + stores the widgets in the removed-widgets dictionary. + Deletes the row in the form layout. Deletes the qwidget and qlabel from the widgets dictionary. Deletes the widget number from the widget-number dictionary. + Decreases the counter for the number of widgets in the layout. + Increases the counter for the removed widgets. Parameters: -------------- @@ -192,25 +207,19 @@ def removeWidget(self, name): if not hasattr(self, 'removed_widgets_dictionary'): self.removed_widgets_dictionary = {} widget_number = self.getWidgetNumber(name) - qwidget = self.getWidget(name, role='field') # retrieves the widget from its name + qwidget = self.getWidget(name, role='field') if f'{name}_label' in self.getWidgets().keys(): qlabel = self.getWidget(name, role='label') self.populate_widget_dictionary(self.removed_widgets_dictionary, name, qwidget, qlabel) - print(formLayout.rowCount()) self.getWidget(name, 'label').setParent(None) - print(formLayout.rowCount()) else: self.populate_widget_dictionary(self.removed_widgets_dictionary, name, qwidget) - print(formLayout.rowCount()) - self.getWidget(name, 'field').setParent(None) - formLayout.removeRow(self.widget_number_dictionary[name]) # removes the whole row from the layout - print(formLayout.rowCount()) - self.decreaseNumWidgets() # updates total number of widgets - self.remove_widget_from_dictionary(self.getWidgets(), name) - self.num_removed_widgets += 1 + self.getWidget(name, 'field').setParent(None) + formLayout.removeRow(self.widget_number_dictionary[name]) + self.remove_widget_from_dictionary(self.getWidgets(), name) self.pop_widget_number_dictionary(name, widget_number) - - + self.decreaseNumWidgets() + self.num_removed_widgets += 1 def getWidget(self, name, role='field'): '''returns the Widget by the name with which it has been added @@ -226,7 +235,7 @@ def getWidget(self, name, role='field'): raise ValueError(f'Unexpected role: expected any of {allowed_roles}, got {role}') def getWidgetNumber(self, name): - '''Returns the Widget number by the name with which it has been added.''' + '''Returns the widget number by the widget name.''' return self.widget_number_dictionary[name] def setWidgetVisible(self, name, visible): @@ -313,7 +322,7 @@ def getWidgetState(self, widget, role=None): Parameters ---------- widget: QWidget or str - The widget or its name, or its name + "_field" or "_label" (when role is None) to get the state of. + The widget or its name (or its name + '_field' or '_label', when role is None) to get the state of. role: str, optional, default None, values: 'label', 'field', None. The role of the widget to apply the state to (only if `widget` is the widget name string.). @@ -335,17 +344,8 @@ def getWidgetState(self, widget, role=None): name_role = widget + '_' + role name = widget else: - name_role = widget - if '_field' in name_role: - name = name_role.removesuffix('_field') - role = 'field' - elif '_label' in name_role: - name = name_role.removesuffix('_label') - role = 'label' - else: - name = widget - role = 'field' - name_role = name + '_' + role + name, role = self.getNameAndRoleFromNameKey(widget) + name_role = name + '_' + role try: widget = self.widgets[name_role] @@ -376,20 +376,40 @@ def getWidgetState(self, widget, role=None): if role == 'field': widget_state['widget_number'] = self.widget_number_dictionary[name] - - return widget_state + def getNameAndRoleFromNameKey(self, name_key): + ''' + Given a name key, returns the name and the role. + Role can be included as a suffix or is `field` by default. + + Parameters + ------------- + name_key: str + Format: name or name_field or name_label + ''' + if name_key.endswith('_field'): + name = name_key.removesuffix('_field') + role = 'field' + elif name_key.endswith('_label'): + name = name_key.removesuffix('_label') + role = 'label' + else: + name = name_key + role = 'field' + return name, role + def getNameAndRoleFromWidget(self, widget): + ''' + Given a widget, finds it in the widget dictionary and returns its name and role. + + Parameters + ------------- + widget: qwidget + ''' for key, value in self.widgets.items(): if value == widget: - name_role = key - if '_field' in name_role: - name = name_role.removesuffix('_field') - role = 'field' - elif '_label' in name_role: - name = name_role.removesuffix('_label') - role = 'label' + name, role = self.getNameAndRoleFromNameKey(key) return name, role def applyWidgetState(self, name_key, state, role=None): @@ -399,10 +419,10 @@ def applyWidgetState(self, name_key, state, role=None): Parameters ---------- name_key: str - The key of the widget to apply the state to, e.g. name or f'{name}_field' or f'{name}_label' + The key of the widget to apply the state to. Format: name or f'{name}_field' or f'{name}_label' role: str, optional, default None, values: 'label', 'field', None. The role of the widget to apply the state to (only if `widget` is a `str`). - If unspecified, the widget is chosen based on name_key. + If None, the widget is chosen based on the format of name_key. state: dict Format: {'value': str | bool | int, 'enabled': bool, 'visible': bool, 'widget_number' : int}, or {'value': str | bool | int, 'enabled': bool, 'visible': bool} @@ -411,20 +431,12 @@ def applyWidgetState(self, name_key, state, role=None): if role is not None: if role not in ['label', 'field']: raise ValueError('Role must be either "label", "field" or None') - name_role = name_key + '_' + role name = name_key else: - name_role = name_key - if '_field' in name_role: - name = name_role.removesuffix('_field') - role = 'field' - elif '_label' in name_role: - name = name_role.removesuffix('_label') - role = 'label' - else: - name_role = name_key + '_field' - name = name_key + name, role = self.getNameAndRoleFromNameKey(name_key) + name_role = name + '_' + role + #retrieve widget try: if name_role in self.widgets.keys(): widget = self.widgets[name_role] @@ -432,22 +444,8 @@ def applyWidgetState(self, name_key, state, role=None): if name_role in self.removed_widgets_dictionary.keys(): widget = self.removed_widgets_dictionary[name_role] except KeyError: - if role is None: - try: - name_role = name_key + '_field' - if name_role in self.widgets.keys(): - widget = self.widgets[name_role] - elif hasattr(self, 'removed_widgets_dictionary'): - if name_role in self.removed_widgets_dictionary.keys(): - widget = self.removed_widgets_dictionary[name_role] - except KeyError: - raise KeyError('No widget associated with the dictionary key `'+name_role+'`.') - raise KeyError('No widget associated with the dictionary key `'+name_role+'`.') - - - - - + raise KeyError('No widget associated with the dictionary key `'+name_role+'`') + #apply state for key, value in state.items(): if key == 'enabled': widget.setEnabled(value) @@ -476,37 +474,51 @@ def applyWidgetState(self, name_key, state, role=None): if value != self.widget_number_dictionary[name]: self.widget_number_dictionary[name] = value - - def applyWidgetStates(self, state): + def applyWidgetStates(self, states): ''' + Removes the widgets in the form which are not present in the states. + If the widgets in the states are not present in the form, + they are retrieved from the removed-widgets dictionary and inserted at position + given by the widget number recorded in the states. An error is raised when the + widget in thet state is not in the form nor in the removed widgets. Applies the given states to the form's widgets. Parameters ---------- - state: dict - Format: {'widget_name': {'value': str | bool | int, 'enabled': bool, 'visible': bool}, - ...}, - e.g. {{'widget1': {'value': 1, 'enabled': True, 'visible': True}, - 'widget2': {'value': 2, 'enabled': False, 'visible': False}}. - ''' - for key, widget_state in state.items(): + states: nested_dict + Format: {'name_field': {'value': str | bool | int, 'enabled': bool, 'visible': bool, 'widget_number' : int}, + 'name_label': {'value': str | bool | int, 'enabled': bool, 'visible': bool}, ...}, + e.g. {{'widget1': {'value': 1, 'enabled': True, 'visible': True, 'widget_number' : int}, + 'widget2': {'value': 2, 'enabled': False, 'visible': False}}. + ''' + # remove extra widgets + if self.widgets.keys() > states.keys(): + for key in self.widgets.keys(): + if key not in states.keys(): + name = self.getNameAndRoleFromNameKey(key)[0] + self.removeWidget(name) + # add widgets if necessary + for key, widget_state in states.items(): if key in self.widgets.keys(): pass elif hasattr(self, 'removed_widgets_dictionary'): if key in self.removed_widgets_dictionary.keys(): - if '_field' in key: + if key.endswith('_field'): name = key.removesuffix('_field') + widget_number = states[key]['widget_number'] qwidget = self.removed_widgets_dictionary[key] if f'{name}_label' in self.removed_widgets_dictionary.keys(): qlabel = self.removed_widgets_dictionary[key] - self.insertWidgetToFormLayout(state[key]['widget_number'],name,qwidget,qlabel) + self.insertWidgetToFormLayout(widget_number,name,qwidget,qlabel) else: - self.insertWidgetToFormLayout(state[key]['widget_number'],name,qwidget) + self.insertWidgetToFormLayout(widget_number,name,qwidget) + else: + raise KeyError('No widget associated with the dictionary key `'+key+'`') self.applyWidgetState(key, widget_state) def saveAllWidgetStates(self): ''' - Saves the state of all widgets in the form. + Saves the state of all widgets currently present in the form. To later restore the states, use `restoreAllSavedWidgetStates()`. ''' self.widget_states = self.getAllWidgetStates() @@ -606,62 +618,29 @@ def getAllWidgetStates(self): ''' Returns ------- - states: dict - Format: {'widget_name': {'value': str | bool | int, 'enabled': bool, 'visible': bool}, - ...}, - e.g. {{'widget1': {'value': 1, 'enabled': True, 'visible': True}, - 'widget2': {'value': 2, 'enabled': False, 'visible': False}}. + states: nested_dict + Format: {'name_field': {'value': str | bool | int, 'enabled': bool, 'visible': bool, 'widget_number' : int}, + 'name_label': {'value': str | bool | int, 'enabled': bool, 'visible': bool}, ...}, + e.g. {{'widget1': {'value': 1, 'enabled': True, 'visible': True, 'widget_number' : int}, + 'widget2': {'value': 2, 'enabled': False, 'visible': False}}. ''' return self.widget().getAllWidgetStates() def getWidgetState(self, widget, role=None): ''' - Parameters - ---------- - widget: QWidget or str - The (name of) widget to get the state of. - role: str, optional, default None, values: 'label', 'field', None. - The role of the widget to get the state of (only if `widget` is a `str`). - If unspecified, the widget is chosen based on `name=widget`. - - Returns - ------- - dict - Widget state, format: {'value': str | bool | int, 'enabled': bool, 'visible': bool}, - e.g. {'value': 1, 'enabled': True, 'visible': True}. - This can be used to restore the state of the widget using `setWidgetState()`. + Invokes `getWidgetState` from `UIFormWidget`. ''' return self.widget().getWidgetState(widget, role) def applyWidgetState(self, name, state, role=None): ''' - Applies the given state to the widget with the given name. - - Parameters - ---------- - name: str - The name of the widget to apply the state to. - role: str, optional, default None, values: 'label', 'field', None. - The role of the widget to apply the state to. - If unspecified, the widget is chosen based on `name`. - state: dict - Format: {'value': str | bool | int, 'enabled': bool, 'visible': bool, 'widget_number' : int}, - or {'value': str | bool | int, 'enabled': bool, 'visible': bool} - e.g. {'value': 1, 'enabled': True, 'visible': True}. + Invokes `applyWidgetState` from `UIFormWidget`. ''' return self.widget().applyWidgetState(name, state, role) def applyWidgetStates(self, state): ''' - Applies the given states to the form's widgets. - - Parameters - ---------- - state: dict - Format: {'widget_name': {'value': str | bool | int, 'enabled': bool, 'visible': bool}, - ...}, - e.g. {{'widget1': {'value': 1, 'enabled': True, 'visible': True}, - 'widget2': {'value': 2, 'enabled': False, 'visible': False}}. + Invokes `applyWidgetStates` from `UIFormWidget`. ''' return self.widget().applyWidgetStates(state) From d4e04acf71a103952cec8465acf7d54288b587ba Mon Sep 17 00:00:00 2001 From: Danica Sugic Date: Thu, 7 Dec 2023 17:06:01 +0000 Subject: [PATCH 46/96] Improve docstrings and namings --- eqt/ui/FormDialog.py | 14 +++--------- eqt/ui/UIFormWidget.py | 48 +++++++++++++++++++++--------------------- 2 files changed, 27 insertions(+), 35 deletions(-) diff --git a/eqt/ui/FormDialog.py b/eqt/ui/FormDialog.py index 8af2139..11f7500 100644 --- a/eqt/ui/FormDialog.py +++ b/eqt/ui/FormDialog.py @@ -118,26 +118,18 @@ def insertWidgetToVerticalLayout(self, row, qwidget): def removeWidget(self, name): ''' - Removes a widget (and its label if present) from the layout. - Decreases the counter for the number of widgets in the layout. - Deletes the field (and label) from the dictionary. + Invokes `removeWidget` from `UIFormWidget`. ''' self.formWidget.removeWidget(name) def getNumWidgets(self): ''' - Returns the number of widgets in the form. + Invokes `getNumWidgets` from `UIFormWidget`. ''' return self.formWidget.getNumWidgets() 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. - ''' + '''Invokes `getWidget` from `UIFormWidget`.''' return self.formWidget.getWidget(name, role) def getWidgets(self): diff --git a/eqt/ui/UIFormWidget.py b/eqt/ui/UIFormWidget.py index a9a05e9..224f9d0 100644 --- a/eqt/ui/UIFormWidget.py +++ b/eqt/ui/UIFormWidget.py @@ -82,11 +82,11 @@ def insertWidgetToFormLayout(self, row, name, qwidget, qlabel=None): self.uiElements['groupBoxFormLayout'].insertRow(row, qlabel, qwidget) else: self.uiElements['groupBoxFormLayout'].insertRow(row, qwidget) - self.increaseNumWidgets() - self.populate_widget_dictionary(self.widgets, name, qwidget, qlabel) - self.populate_widget_number_dictionary(name, row) - self.populate_widget_dictionary(self.default_widgets, name, qwidget, qlabel) - self.populate_default_widget_states_dictionary(name) + self._increaseNumWidgets() + self.populateWidgetDictionary(self.widgets, name, qwidget, qlabel) + self._populateWidgetNumberDictionary(name, row) + self.populateWidgetDictionary(self.default_widgets, name, qwidget, qlabel) + self.populateDefaultWidgetStatesDictionary(name) def _addWidget(self, name, qwidget, qlabel=None): ''' @@ -101,17 +101,17 @@ def _addWidget(self, name, qwidget, qlabel=None): ''' self.insertWidgetToFormLayout(-1, name, qwidget, qlabel) - def populate_widget_dictionary(self, dictionary, name, qwidget, qlabel = None): + def populateWidgetDictionary(self, dictionary, name, qwidget, qlabel = None): '''Adds the field (and label if present) in the widget dictionary.''' dictionary[f'{name}_field'] = qwidget if qlabel is not None: dictionary[f'{name}_label'] = qlabel - def populate_widget_number_dictionary(self, name, widget_number): + def _populateWidgetNumberDictionary(self, name, widget_number): ''' Adds one item in the widget-number dictionary whose key is name and value is the current widget number (i.e. row) in the form layout. - As one widget is inserted, the widget number associated to the other widgets + As one widget is inserted, the widget numbers associated to the other widgets in the layout are updated. Parameters: @@ -129,11 +129,11 @@ def populate_widget_number_dictionary(self, name, widget_number): self.widget_number_dictionary[key] = value + 1 self.widget_number_dictionary[name] = widget_number - def pop_widget_number_dictionary(self, name, widget_number): + def _popWidgetNumberDictionary(self, name, widget_number): ''' Removes one item in the widget-number dictionary whose key is name and value is the widget number (i.e. row) in the form layout. - As one widget is removed, the widget number associated to the other widgets + As one widget is removed, the widget numbers associated to the other widgets in the layout are updated. Parameters: @@ -179,11 +179,11 @@ def getNumWidgets(self): ''' return self.num_widgets - def increaseNumWidgets(self): + def _increaseNumWidgets(self): '''Increases `num_widget` by 1 unit.''' self.num_widgets += 1 - def decreaseNumWidgets(self): + def _decreaseNumWidgets(self): '''Decreases `num_widget` by 1 unit.''' self.num_widgets -= 1 @@ -210,15 +210,15 @@ def removeWidget(self, name): qwidget = self.getWidget(name, role='field') if f'{name}_label' in self.getWidgets().keys(): qlabel = self.getWidget(name, role='label') - self.populate_widget_dictionary(self.removed_widgets_dictionary, name, qwidget, qlabel) + self.populateWidgetDictionary(self.removed_widgets_dictionary, name, qwidget, qlabel) self.getWidget(name, 'label').setParent(None) else: - self.populate_widget_dictionary(self.removed_widgets_dictionary, name, qwidget) + self.populateWidgetDictionary(self.removed_widgets_dictionary, name, qwidget) self.getWidget(name, 'field').setParent(None) formLayout.removeRow(self.widget_number_dictionary[name]) self.remove_widget_from_dictionary(self.getWidgets(), name) - self.pop_widget_number_dictionary(name, widget_number) - self.decreaseNumWidgets() + self._popWidgetNumberDictionary(name, widget_number) + self._decreaseNumWidgets() self.num_removed_widgets += 1 def getWidget(self, name, role='field'): @@ -280,7 +280,7 @@ def addSeparator(self, name): frame.setFrameShadow(QtWidgets.QFrame.Raised) self._addWidget(name, frame) - def populate_default_widget_states_dictionary(self, name): + def populateDefaultWidgetStatesDictionary(self, name): ''' Creates an attribute dictionary of default widget states. The entries are in the format: {'value': str | bool | int, 'enabled': bool, 'visible': bool, 'widget_number': int} @@ -344,7 +344,7 @@ def getWidgetState(self, widget, role=None): name_role = widget + '_' + role name = widget else: - name, role = self.getNameAndRoleFromNameKey(widget) + name, role = self._getNameAndRoleFromNameKey(widget) name_role = name + '_' + role try: @@ -352,7 +352,7 @@ def getWidgetState(self, widget, role=None): except KeyError: raise KeyError('No widget associated with the dictionary key `'+ name_role) else: - name, role = self.getNameAndRoleFromWidget(widget) + name, role = self._getNameAndRoleFromWidget(widget) widget_state = {} widget_state['enabled'] = widget.isEnabled() widget_state['visible'] = widget.isVisible() @@ -378,7 +378,7 @@ def getWidgetState(self, widget, role=None): widget_state['widget_number'] = self.widget_number_dictionary[name] return widget_state - def getNameAndRoleFromNameKey(self, name_key): + def _getNameAndRoleFromNameKey(self, name_key): ''' Given a name key, returns the name and the role. Role can be included as a suffix or is `field` by default. @@ -399,7 +399,7 @@ def getNameAndRoleFromNameKey(self, name_key): role = 'field' return name, role - def getNameAndRoleFromWidget(self, widget): + def _getNameAndRoleFromWidget(self, widget): ''' Given a widget, finds it in the widget dictionary and returns its name and role. @@ -409,7 +409,7 @@ def getNameAndRoleFromWidget(self, widget): ''' for key, value in self.widgets.items(): if value == widget: - name, role = self.getNameAndRoleFromNameKey(key) + name, role = self._getNameAndRoleFromNameKey(key) return name, role def applyWidgetState(self, name_key, state, role=None): @@ -433,7 +433,7 @@ def applyWidgetState(self, name_key, state, role=None): raise ValueError('Role must be either "label", "field" or None') name = name_key else: - name, role = self.getNameAndRoleFromNameKey(name_key) + name, role = self._getNameAndRoleFromNameKey(name_key) name_role = name + '_' + role #retrieve widget @@ -495,7 +495,7 @@ def applyWidgetStates(self, states): if self.widgets.keys() > states.keys(): for key in self.widgets.keys(): if key not in states.keys(): - name = self.getNameAndRoleFromNameKey(key)[0] + name = self._getNameAndRoleFromNameKey(key)[0] self.removeWidget(name) # add widgets if necessary for key, widget_state in states.items(): From 13446af613502548c4c5700f090c8a8c4c25ea94 Mon Sep 17 00:00:00 2001 From: Danica Sugic Date: Thu, 7 Dec 2023 17:17:51 +0000 Subject: [PATCH 47/96] Improve formatting --- eqt/ui/UIFormWidget.py | 38 ++++++++++---------------------------- 1 file changed, 10 insertions(+), 28 deletions(-) diff --git a/eqt/ui/UIFormWidget.py b/eqt/ui/UIFormWidget.py index 224f9d0..3779544 100644 --- a/eqt/ui/UIFormWidget.py +++ b/eqt/ui/UIFormWidget.py @@ -60,7 +60,7 @@ def insertWidgetToFormLayout(self, row, name, qwidget, qlabel=None): ''' Inserts a widget, and a label widget, or a spanning widget to the form layout, `groupBoxFormLayout`, in the position specified by row. If row is out of bounds, the widget is added at the end. - It invokes `populate_widget_dictionaries` to populate the widget dictionary and the default states + It invokes `populateWidgetDictionary` to populate the widget dictionary and the default states dictionary. It increases "num_widgets" by 1 unit. It should not be used to move widgets in a form. @@ -148,7 +148,7 @@ def _popWidgetNumberDictionary(self, name, widget_number): self.widget_number_dictionary[key] = value - 1 self.widget_number_dictionary.pop(name) - def remove_widget_from_dictionary(self, dictionary, name_key): + def removeWidgetFromDictionary(self, dictionary, name_key): ''' Removes the item associated with `name_key` from a dictionary. @@ -216,7 +216,7 @@ def removeWidget(self, name): self.populateWidgetDictionary(self.removed_widgets_dictionary, name, qwidget) self.getWidget(name, 'field').setParent(None) formLayout.removeRow(self.widget_number_dictionary[name]) - self.remove_widget_from_dictionary(self.getWidgets(), name) + self.removeWidgetFromDictionary(self.getWidgets(), name) self._popWidgetNumberDictionary(name, widget_number) self._decreaseNumWidgets() self.num_removed_widgets += 1 @@ -295,7 +295,7 @@ def populateDefaultWidgetStatesDictionary(self, name): if f'{name}_label' in self.widgets.keys(): self.default_widget_states[f'{name}_label'] = self.getWidgetState(name, 'label') - def set_default_widget_states_visible_true(self): + def setDefaultWidgetStatesVisibleTrue(self): ''' Sets all of the entries 'visible' in the `default_widget_states` dictionary to be `True`. ''' @@ -530,7 +530,7 @@ def restoreAllSavedWidgetStates(self): `default_widget_states` are used instead, after being made visible. ''' if not hasattr(self, 'widget_states'): - self.set_default_widget_states_visible_true() + self.setDefaultWidgetStatesVisibleTrue() self.applyWidgetStates(self.default_widget_states) else: self.applyWidgetStates(self.widget_states) @@ -601,29 +601,15 @@ def setWidgetVisible(self, name, visible): self.widget().setWidgetVisible(name, visible) def saveAllWidgetStates(self): - ''' - Saves the state of all widgets in the form. - To later restore the states, use `restoreAllSavedWidgetStates()`. - ''' + '''Invokes `saveAllWidgetStates` from `UIFormWidget`.''' self.widget().saveAllWidgetStates() def restoreAllSavedWidgetStates(self): - ''' - Restore all widgets in the form to the state saved by `saveAllWidgetStates()`. - If `saveAllWidgetStates()` method was not previously invoked, do nothing. - ''' + '''Invokes `restoreAllSavedWidgetStates` from `UIFormWidget`.''' self.widget().restoreAllSavedWidgetStates() def getAllWidgetStates(self): - ''' - Returns - ------- - states: nested_dict - Format: {'name_field': {'value': str | bool | int, 'enabled': bool, 'visible': bool, 'widget_number' : int}, - 'name_label': {'value': str | bool | int, 'enabled': bool, 'visible': bool}, ...}, - e.g. {{'widget1': {'value': 1, 'enabled': True, 'visible': True, 'widget_number' : int}, - 'widget2': {'value': 2, 'enabled': False, 'visible': False}}. - ''' + '''Invokes `getAllWidgetStates` from `UIFormWidget`.''' return self.widget().getAllWidgetStates() def getWidgetState(self, widget, role=None): @@ -633,15 +619,11 @@ def getWidgetState(self, widget, role=None): return self.widget().getWidgetState(widget, role) def applyWidgetState(self, name, state, role=None): - ''' - Invokes `applyWidgetState` from `UIFormWidget`. - ''' + '''Invokes `applyWidgetState` from `UIFormWidget`.''' return self.widget().applyWidgetState(name, state, role) def applyWidgetStates(self, state): - ''' - Invokes `applyWidgetStates` from `UIFormWidget`. - ''' + '''Invokes `applyWidgetStates` from `UIFormWidget`.''' return self.widget().applyWidgetStates(state) From 0fbf7ca6b1489bd391307249546e29ab558b7bf3 Mon Sep 17 00:00:00 2001 From: Danica Sugic Date: Fri, 8 Dec 2023 10:17:13 +0000 Subject: [PATCH 48/96] Minor change --- eqt/ui/UIFormWidget.py | 1 - 1 file changed, 1 deletion(-) diff --git a/eqt/ui/UIFormWidget.py b/eqt/ui/UIFormWidget.py index d7a5ea1..3779544 100644 --- a/eqt/ui/UIFormWidget.py +++ b/eqt/ui/UIFormWidget.py @@ -51,7 +51,6 @@ def createForm(self): 'groupBoxFormLayout': groupBoxFormLayout} self.widgets = {} self.default_widgets = {} - self.default_widgets = {} @property def groupBox(self): From e0315832cc2db251a3da230d4e34c8e0433b977c Mon Sep 17 00:00:00 2001 From: Danica Sugic Date: Tue, 9 Jan 2024 11:45:05 +0000 Subject: [PATCH 49/96] Add widget number to label state --- eqt/ui/UIFormWidget.py | 4 ++-- test/test__formUI_status_test.py | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/eqt/ui/UIFormWidget.py b/eqt/ui/UIFormWidget.py index 3779544..931c9ab 100644 --- a/eqt/ui/UIFormWidget.py +++ b/eqt/ui/UIFormWidget.py @@ -374,8 +374,8 @@ def getWidgetState(self, widget, role=None): elif isinstance(widget, (QtWidgets.QTextEdit, QtWidgets.QPlainTextEdit)): widget_state['value'] = widget.toPlainText() - if role == 'field': - widget_state['widget_number'] = self.widget_number_dictionary[name] + widget_state['widget_number'] = self.widget_number_dictionary[name] + return widget_state def _getNameAndRoleFromNameKey(self, name_key): diff --git a/test/test__formUI_status_test.py b/test/test__formUI_status_test.py index 02ba870..5fe7c7b 100644 --- a/test/test__formUI_status_test.py +++ b/test/test__formUI_status_test.py @@ -56,9 +56,9 @@ def list_all_widgets(self): def state_simple_form(self): state_simple_form = { 'label_field': {'value': 'test label', 'enabled': True, 'visible': False, 'widget_number': 0}, - 'label_label': {'value': 'Label: ', 'enabled': True, 'visible': False}, + 'label_label': {'value': 'Label: ', 'enabled': True, 'visible': False, 'widget_number': 0}, 'checkBox_field': {'value': False, 'enabled': True, 'visible': False,'widget_number': 1}, - 'checkBox_label': {'value': 'CheckBox: ', 'enabled': True, 'visible': False} + 'checkBox_label': {'value': 'CheckBox: ', 'enabled': True, 'visible': False, 'widget_number': 1} } return state_simple_form From 56e226bd2809221f11e216d6ef5da82f0f300ab3 Mon Sep 17 00:00:00 2001 From: Danica Sugic Date: Tue, 9 Jan 2024 12:13:31 +0000 Subject: [PATCH 50/96] Num_widgets as a property --- eqt/ui/UIFormWidget.py | 25 ++++++------------------- 1 file changed, 6 insertions(+), 19 deletions(-) diff --git a/eqt/ui/UIFormWidget.py b/eqt/ui/UIFormWidget.py index 931c9ab..bf5d7c0 100644 --- a/eqt/ui/UIFormWidget.py +++ b/eqt/ui/UIFormWidget.py @@ -42,9 +42,6 @@ def createForm(self): verticalLayout.addWidget(groupBox) # number of widgets currently present in the groupBoxFormLayout - self.num_widgets = 0 - # number of widgets removed from the groupBoxFormLayout - self.num_removed_widgets = 0 self.widget_number_dictionary = {} self.uiElements = { 'verticalLayout': verticalLayout, 'groupBox': groupBox, @@ -52,6 +49,10 @@ def createForm(self): self.widgets = {} self.default_widgets = {} + @property + def num_widgets(self): + return self.uiElements['groupBoxFormLayout'].rowCount() + @property def groupBox(self): return self.uiElements['groupBox'] @@ -62,7 +63,6 @@ def insertWidgetToFormLayout(self, row, name, qwidget, qlabel=None): in the position specified by row. If row is out of bounds, the widget is added at the end. It invokes `populateWidgetDictionary` to populate the widget dictionary and the default states dictionary. - It increases "num_widgets" by 1 unit. It should not be used to move widgets in a form. Parameters: @@ -82,7 +82,6 @@ def insertWidgetToFormLayout(self, row, name, qwidget, qlabel=None): self.uiElements['groupBoxFormLayout'].insertRow(row, qlabel, qwidget) else: self.uiElements['groupBoxFormLayout'].insertRow(row, qwidget) - self._increaseNumWidgets() self.populateWidgetDictionary(self.widgets, name, qwidget, qlabel) self._populateWidgetNumberDictionary(name, row) self.populateWidgetDictionary(self.default_widgets, name, qwidget, qlabel) @@ -179,14 +178,6 @@ def getNumWidgets(self): ''' return self.num_widgets - def _increaseNumWidgets(self): - '''Increases `num_widget` by 1 unit.''' - self.num_widgets += 1 - - def _decreaseNumWidgets(self): - '''Decreases `num_widget` by 1 unit.''' - self.num_widgets -= 1 - def removeWidget(self, name): ''' If not present already, creates a dictionary to store the removed qwidgets. @@ -195,9 +186,7 @@ def removeWidget(self, name): Deletes the row in the form layout. Deletes the qwidget and qlabel from the widgets dictionary. Deletes the widget number from the widget-number dictionary. - Decreases the counter for the number of widgets in the layout. - Increases the counter for the removed widgets. - + Parameters: -------------- name : str @@ -217,9 +206,7 @@ def removeWidget(self, name): self.getWidget(name, 'field').setParent(None) formLayout.removeRow(self.widget_number_dictionary[name]) self.removeWidgetFromDictionary(self.getWidgets(), name) - self._popWidgetNumberDictionary(name, widget_number) - self._decreaseNumWidgets() - self.num_removed_widgets += 1 + self._popWidgetNumberDictionary(name, widget_number) def getWidget(self, name, role='field'): '''returns the Widget by the name with which it has been added From fc2fba7457b990406085cac332af901c48cf3501 Mon Sep 17 00:00:00 2001 From: Danica Sugic Date: Tue, 9 Jan 2024 17:18:12 +0000 Subject: [PATCH 51/96] Add reviewers changes --- eqt/ui/FormDialog.py | 6 +- eqt/ui/UIFormWidget.py | 131 +++++++++++++++---------------- test/test__formUI_status_test.py | 4 +- 3 files changed, 71 insertions(+), 70 deletions(-) diff --git a/eqt/ui/FormDialog.py b/eqt/ui/FormDialog.py index 11f7500..b06e4d9 100644 --- a/eqt/ui/FormDialog.py +++ b/eqt/ui/FormDialog.py @@ -40,6 +40,7 @@ def _onOk(self): '''saves the widget states and calls `onOk`''' self.saveAllWidgetStates() self.onOk() + print(self.getWidgets()) self.close() def _onCancel(self): @@ -48,6 +49,7 @@ def _onCancel(self): self.onCancel() self.close() self.restoreAllSavedWidgetStates() + print(self.getWidgets()) def onOk(self): '''Called when the dialog's "Ok" button is clicked. @@ -69,7 +71,7 @@ def groupBox(self): def addWidget(self, qwidget, qlabel=None, name=None, layout='form'): ''' - Adds a widget to the layout. + Adds a qwidget (and a qlabel widget) in the (same row of the) layout. layout = 'form' - adds to the FormLayout layout = 'vertical' - adds to the Vertical layout below the form. To add to the form layout, qlabel and name must be passed. @@ -89,7 +91,7 @@ def addWidget(self, qwidget, qlabel=None, name=None, layout='form'): def addSpanningWidget(self, qwidget, name=None, layout='form'): ''' - Adds a spanning widget to the layout. + Adds a spanning qwidget occupying the full row in the layout. layout = 'form' - adds the widget to the FormLayout layout = 'vertical' - adds the widget to the Vertical layout below the form. To add to the form layout, name must be passed. diff --git a/eqt/ui/UIFormWidget.py b/eqt/ui/UIFormWidget.py index bf5d7c0..07bcbdc 100644 --- a/eqt/ui/UIFormWidget.py +++ b/eqt/ui/UIFormWidget.py @@ -59,11 +59,10 @@ def groupBox(self): def insertWidgetToFormLayout(self, row, name, qwidget, qlabel=None): ''' - Inserts a widget, and a label widget, or a spanning widget to the form layout, `groupBoxFormLayout`, + Inserts a widget and a label widget, or a spanning widget if 'qlabel' is None, to the form layout, `groupBoxFormLayout`, in the position specified by row. If row is out of bounds, the widget is added at the end. - It invokes `populateWidgetDictionary` to populate the widget dictionary and the default states + It adds to the widget dictionary and the default states dictionary. - It should not be used to move widgets in a form. Parameters: ---------- @@ -82,10 +81,10 @@ def insertWidgetToFormLayout(self, row, name, qwidget, qlabel=None): self.uiElements['groupBoxFormLayout'].insertRow(row, qlabel, qwidget) else: self.uiElements['groupBoxFormLayout'].insertRow(row, qwidget) - self.populateWidgetDictionary(self.widgets, name, qwidget, qlabel) - self._populateWidgetNumberDictionary(name, row) - self.populateWidgetDictionary(self.default_widgets, name, qwidget, qlabel) - self.populateDefaultWidgetStatesDictionary(name) + self.addToWidgetDictionary(self.widgets, name, qwidget, qlabel) + self._addToWidgetNumberDictionary(name, row) + self.addToWidgetDictionary(self.default_widgets, name, qwidget, qlabel) + self.addToDefaultWidgetStatesDictionary(name) def _addWidget(self, name, qwidget, qlabel=None): ''' @@ -100,13 +99,13 @@ def _addWidget(self, name, qwidget, qlabel=None): ''' self.insertWidgetToFormLayout(-1, name, qwidget, qlabel) - def populateWidgetDictionary(self, dictionary, name, qwidget, qlabel = None): + def addToWidgetDictionary(self, dictionary, name, qwidget, qlabel = None): '''Adds the field (and label if present) in the widget dictionary.''' dictionary[f'{name}_field'] = qwidget if qlabel is not None: dictionary[f'{name}_label'] = qlabel - def _populateWidgetNumberDictionary(self, name, widget_number): + def _addToWidgetNumberDictionary(self, name, widget_number): ''' Adds one item in the widget-number dictionary whose key is name and value is the current widget number (i.e. row) in the form layout. @@ -147,29 +146,29 @@ def _popWidgetNumberDictionary(self, name, widget_number): self.widget_number_dictionary[key] = value - 1 self.widget_number_dictionary.pop(name) - def removeWidgetFromDictionary(self, dictionary, name_key): + def removeWidgetFromDictionary(self, dictionary, name): ''' - Removes the item associated with `name_key` from a dictionary. + Removes the item(s) associated with `name` from a dictionary. Parameters: ----------------- dictionary : dict - name_key: str - Format: {name} or {name}_field or {name}_label + name: str + Format: {name} ''' - if name_key in dictionary.keys(): - dictionary.pop(name_key) - if f'{name_key}_field' in dictionary.keys(): - dictionary.pop(f'{name_key}_field') - if f'{name_key}_label' in dictionary.keys(): - dictionary.pop(f'{name_key}_label') + if name in dictionary.keys(): + dictionary.pop(name) + if f'{name}_field' in dictionary.keys(): + dictionary.pop(f'{name}_field') + if f'{name}_label' in dictionary.keys(): + dictionary.pop(f'{name}_label') def addWidget(self, qwidget, qlabel, name): - '''Adds a qwidget and a qlabel widget in the same row of the form layout by invoking `_addWidget`.''' + '''Adds a qwidget and a qlabel widget in the same row of the form layout.''' self._addWidget(name, qwidget, qlabel) def addSpanningWidget(self, qwidget, name): - '''Adds a spanning qwidget occupying the full row in the form layout by invoking `_addWidget`.''' + '''Adds a spanning qwidget occupying the full row in the form layout.''' self._addWidget(name, qwidget) def getNumWidgets(self): @@ -199,10 +198,10 @@ def removeWidget(self, name): qwidget = self.getWidget(name, role='field') if f'{name}_label' in self.getWidgets().keys(): qlabel = self.getWidget(name, role='label') - self.populateWidgetDictionary(self.removed_widgets_dictionary, name, qwidget, qlabel) + self.addToWidgetDictionary(self.removed_widgets_dictionary, name, qwidget, qlabel) self.getWidget(name, 'label').setParent(None) else: - self.populateWidgetDictionary(self.removed_widgets_dictionary, name, qwidget) + self.addToWidgetDictionary(self.removed_widgets_dictionary, name, qwidget) self.getWidget(name, 'field').setParent(None) formLayout.removeRow(self.widget_number_dictionary[name]) self.removeWidgetFromDictionary(self.getWidgets(), name) @@ -267,7 +266,7 @@ def addSeparator(self, name): frame.setFrameShadow(QtWidgets.QFrame.Raised) self._addWidget(name, frame) - def populateDefaultWidgetStatesDictionary(self, name): + def addToDefaultWidgetStatesDictionary(self, name): ''' Creates an attribute dictionary of default widget states. The entries are in the format: {'value': str | bool | int, 'enabled': bool, 'visible': bool, 'widget_number': int} @@ -311,14 +310,13 @@ def getWidgetState(self, widget, role=None): widget: QWidget or str The widget or its name (or its name + '_field' or '_label', when role is None) to get the state of. role: str, optional, default None, values: 'label', 'field', None. - The role of the widget to apply the state to (only if `widget` is the widget name string.). + The role of the widget to apply the state to. This is used only if `widget` is the widget name string. Returns ------- state: dict Format: {'value': str | bool | int, 'enabled': bool, 'visible': bool, 'widget_number' : int}, - or {'value': str | bool | int, 'enabled': bool, 'visible': bool}, - e.g. {'value': 1, 'enabled': True, 'visible': True}. + e.g. {'value': 1, 'enabled': True, 'visible': True, 'widget_number' : 0}. This can be used to restore the state of the widget using `setWidgetState()`. ''' if widget is None: @@ -327,17 +325,17 @@ def getWidgetState(self, widget, role=None): if isinstance(widget, str): if role is not None: if role not in ['label', 'field']: - raise ValueError('Role must be either "label", "field" or None') + raise ValueError(f'Role must be either "label", "field" or None. Got {role}.') name_role = widget + '_' + role name = widget else: - name, role = self._getNameAndRoleFromNameKey(widget) + name, role = self._getNameAndRoleFromKey(widget) name_role = name + '_' + role try: widget = self.widgets[name_role] except KeyError: - raise KeyError('No widget associated with the dictionary key `'+ name_role) + raise KeyError('No widget associated with the dictionary key `'+ name_role) else: name, role = self._getNameAndRoleFromWidget(widget) widget_state = {} @@ -362,27 +360,26 @@ def getWidgetState(self, widget, role=None): widget_state['value'] = widget.toPlainText() widget_state['widget_number'] = self.widget_number_dictionary[name] - return widget_state - def _getNameAndRoleFromNameKey(self, name_key): + def _getNameAndRoleFromKey(self, key): ''' - Given a name key, returns the name and the role. + Given a key, returns the name and the role. Role can be included as a suffix or is `field` by default. Parameters ------------- - name_key: str + key: str Format: name or name_field or name_label ''' - if name_key.endswith('_field'): - name = name_key.removesuffix('_field') + if key.endswith('_field'): + name = key.removesuffix('_field') role = 'field' - elif name_key.endswith('_label'): - name = name_key.removesuffix('_label') + elif key.endswith('_label'): + name = key.removesuffix('_label') role = 'label' else: - name = name_key + name = key role = 'field' return name, role @@ -396,33 +393,32 @@ def _getNameAndRoleFromWidget(self, widget): ''' for key, value in self.widgets.items(): if value == widget: - name, role = self._getNameAndRoleFromNameKey(key) + name, role = self._getNameAndRoleFromKey(key) return name, role - def applyWidgetState(self, name_key, state, role=None): + def applyWidgetState(self, name, state, role=None): ''' - Applies the given `state` to the widget associated with `name_key`. + Applies the given `state` to the widget associated with `name` and `role`. + If role is None, the role is assigned to be 'field'. Parameters ---------- - name_key: str - The key of the widget to apply the state to. Format: name or f'{name}_field' or f'{name}_label' + name: str + The name of the widget to apply the state to. role: str, optional, default None, values: 'label', 'field', None. - The role of the widget to apply the state to (only if `widget` is a `str`). - If None, the widget is chosen based on the format of name_key. + The role of the widget to apply the state to. state: dict Format: {'value': str | bool | int, 'enabled': bool, 'visible': bool, 'widget_number' : int}, - or {'value': str | bool | int, 'enabled': bool, 'visible': bool} - e.g. {'value': 1, 'enabled': True, 'visible': True}. + e.g. {'value': 1, 'enabled': True, 'visible': True, 'widget_number' : 0}. ''' if role is not None: - if role not in ['label', 'field']: - raise ValueError('Role must be either "label", "field" or None') - name = name_key + if role in ['label', 'field']: + name_role = name + '_' + role + else: + raise ValueError(f'Role must be either "label", "field" or None. Got {role}.') else: - name, role = self._getNameAndRoleFromNameKey(name_key) - name_role = name + '_' + role - + name_role = f'{name}_field' + #retrieve widget try: if name_role in self.widgets.keys(): @@ -478,30 +474,31 @@ def applyWidgetStates(self, states): e.g. {{'widget1': {'value': 1, 'enabled': True, 'visible': True, 'widget_number' : int}, 'widget2': {'value': 2, 'enabled': False, 'visible': False}}. ''' - # remove extra widgets - if self.widgets.keys() > states.keys(): - for key in self.widgets.keys(): - if key not in states.keys(): - name = self._getNameAndRoleFromNameKey(key)[0] - self.removeWidget(name) + # add widgets if necessary for key, widget_state in states.items(): + name, role = self._getNameAndRoleFromKey(key) if key in self.widgets.keys(): pass elif hasattr(self, 'removed_widgets_dictionary'): if key in self.removed_widgets_dictionary.keys(): - if key.endswith('_field'): - name = key.removesuffix('_field') + if role == 'field': widget_number = states[key]['widget_number'] qwidget = self.removed_widgets_dictionary[key] if f'{name}_label' in self.removed_widgets_dictionary.keys(): qlabel = self.removed_widgets_dictionary[key] - self.insertWidgetToFormLayout(widget_number,name,qwidget,qlabel) + self.insertWidgetToFormLayout(widget_number, name, qwidget, qlabel) else: - self.insertWidgetToFormLayout(widget_number,name,qwidget) + self.insertWidgetToFormLayout(widget_number, name, qwidget) else: - raise KeyError('No widget associated with the dictionary key `'+key+'`') - self.applyWidgetState(key, widget_state) + raise KeyError('No widget associated with the dictionary key `' + key + '`') + self.applyWidgetState(name, widget_state, role) + # remove extra widgets + if self.widgets.keys() > states.keys(): + for key in self.widgets.keys(): + if key not in states.keys(): + name = self._getNameAndRoleFromKey(key)[0] + self.removeWidget(name) def saveAllWidgetStates(self): ''' @@ -542,9 +539,11 @@ def __init__(self, parent=None, title=None): self.setObjectName(title) def addWidget(self, qwidget, qlabel, name): + '''Adds a qwidget and a qlabel widget in the same row of the form layout.''' self.widget().addWidget(qwidget, qlabel, name) def addSpanningWidget(self, qwidget, name): + '''Adds a spanning qwidget occupying the full row in the form layout.''' self.widget().addSpanningWidget(qwidget, name) def insertWidgetToFormLayout(self, row, name, qwidget, qlabel=None): diff --git a/test/test__formUI_status_test.py b/test/test__formUI_status_test.py index 5fe7c7b..c70c477 100644 --- a/test/test__formUI_status_test.py +++ b/test/test__formUI_status_test.py @@ -409,8 +409,8 @@ def test_applyWidgetStates(self): self.state_simple_form['label_field']) def test_applyWidgetState(self): - self.simple_form.applyWidgetState('checkBox_field', self.state_simple_form['checkBox_field']) - self.assertEqual(self.simple_form.getWidgetState('checkBox_field'), self.state_simple_form['checkBox_field']) + self.simple_form.applyWidgetState('checkBox', self.state_simple_form['checkBox_field']) + self.assertEqual(self.simple_form.getWidgetState('checkBox'), self.state_simple_form['checkBox_field']) def test_applyWidgetState_using_role_parameter_field(self): self.simple_form.applyWidgetState('checkBox', self.state_simple_form['checkBox_field'], role='field') From 7a30b4237df71d564ab046a9c372242a26d8c7bf Mon Sep 17 00:00:00 2001 From: Danica Sugic Date: Tue, 9 Jan 2024 17:34:58 +0000 Subject: [PATCH 52/96] Fix save state example --- eqt/ui/FormDialog.py | 2 -- examples/dialog_save_state_example.py | 12 +----------- 2 files changed, 1 insertion(+), 13 deletions(-) diff --git a/eqt/ui/FormDialog.py b/eqt/ui/FormDialog.py index b06e4d9..81dd5f3 100644 --- a/eqt/ui/FormDialog.py +++ b/eqt/ui/FormDialog.py @@ -40,7 +40,6 @@ def _onOk(self): '''saves the widget states and calls `onOk`''' self.saveAllWidgetStates() self.onOk() - print(self.getWidgets()) self.close() def _onCancel(self): @@ -49,7 +48,6 @@ def _onCancel(self): self.onCancel() self.close() self.restoreAllSavedWidgetStates() - print(self.getWidgets()) def onOk(self): '''Called when the dialog's "Ok" button is clicked. diff --git a/examples/dialog_save_state_example.py b/examples/dialog_save_state_example.py index d138610..125ce0b 100644 --- a/examples/dialog_save_state_example.py +++ b/examples/dialog_save_state_example.py @@ -23,9 +23,7 @@ def __init__(self, parent=None): # create dialog to be opened later: dialog = FormDialog(parent=self, title='Example') - dialog.Ok.clicked.connect(lambda: self.accepted()) - dialog.Cancel.clicked.connect(lambda: self.rejected()) - + # ## Example on how to add elements to the dialog.addWidget(QtWidgets.QLabel('test label'), 'Label: ', 'label') dialog.addWidget(QtWidgets.QCheckBox('test checkbox'), 'CheckBox: ', 'checkBox') @@ -51,16 +49,8 @@ def __init__(self, parent=None): self.show() def openFormDialog(self): - self.dialog.restoreAllSavedWidgetStates() self.dialog.exec() - def accepted(self): - self.dialog.saveAllWidgetStates() - self.dialog.close() - - def rejected(self): - self.dialog.close() - if __name__ == "__main__": app = QtWidgets.QApplication(sys.argv) From 93dc36e8d6ba843f3c35a9af164bdccacf548961 Mon Sep 17 00:00:00 2001 From: Danica Sugic Date: Tue, 9 Jan 2024 18:15:30 +0000 Subject: [PATCH 53/96] Copy docstring 3 times --- eqt/ui/FormDialog.py | 92 +++++++++++++++++++++++++++++++++++------ eqt/ui/UIFormWidget.py | 94 +++++++++++++++++++++++++++++++++++------- 2 files changed, 159 insertions(+), 27 deletions(-) diff --git a/eqt/ui/FormDialog.py b/eqt/ui/FormDialog.py index 81dd5f3..c2266d9 100644 --- a/eqt/ui/FormDialog.py +++ b/eqt/ui/FormDialog.py @@ -28,22 +28,22 @@ def __init__(self, parent=None, title=None): @property def Ok(self): - '''returns a reference to the Dialog Ok button to connect its signals''' + '''Returns a reference to the Dialog Ok button to connect its signals''' return self.buttonBox.button(QtWidgets.QDialogButtonBox.Ok) @property def Cancel(self): - '''returns a reference to the Dialog Cancel button to connect its signals''' + '''Returns a reference to the Dialog Cancel button to connect its signals''' return self.buttonBox.button(QtWidgets.QDialogButtonBox.Cancel) def _onOk(self): - '''saves the widget states and calls `onOk`''' + '''Saves the widget states and calls `onOk`''' self.saveAllWidgetStates() self.onOk() self.close() def _onCancel(self): - '''calls `onCancel`, closes the FormDialog and restores the previously saved states + '''Calls `onCancel`, closes the FormDialog and restores the previously saved states or the default states.''' self.onCancel() self.close() @@ -107,7 +107,19 @@ def addSpanningWidget(self, qwidget, name=None, layout='form'): f"layout {layout} is not recognised, must be set to 'form' or 'vertical'") def insertWidgetToFormLayout(self, row, name, qwidget, qlabel=None): - '''Invokes `insertWidgetToFormLayout` in `UIFormWidget`.''' + ''' + Inserts a widget and a label widget, or a spanning widget if 'qlabel' is None, to the form layout, `groupBoxFormLayout`, + in the position specified by row. If row is out of bounds, the widget is added at the end. + It adds to the widget dictionary and the default states + dictionary. + + Parameters: + ---------- + row: int + name: str + qwidget: qwidget + qlabel: qlabel widget or str + ''' self.formWidget.insertWidgetToFormLayout(row, name, qwidget, qlabel) def insertWidgetToVerticalLayout(self, row, qwidget): @@ -118,26 +130,42 @@ def insertWidgetToVerticalLayout(self, row, qwidget): def removeWidget(self, name): ''' - Invokes `removeWidget` from `UIFormWidget`. + If not present already, creates a dictionary to store the removed qwidgets. + Sets the parent of the qwidget (and qlabel if present) to `None` and + stores the widgets in the removed-widgets dictionary. + Deletes the row in the form layout. + Deletes the qwidget and qlabel from the widgets dictionary. + Deletes the widget number from the widget-number dictionary. + + Parameters: + -------------- + name : str + name of the widget to be removed ''' self.formWidget.removeWidget(name) def getNumWidgets(self): ''' - Invokes `getNumWidgets` from `UIFormWidget`. + Returns the number of widgets in the form. ''' return self.formWidget.getNumWidgets() def getWidget(self, name, role='field'): - '''Invokes `getWidget` from `UIFormWidget`.''' + '''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. + ''' return self.formWidget.getWidget(name, role) def getWidgets(self): - '''Invokes `getWidgets` from `UIFormWidget`.''' + '''Returns a dictionary of the widgets currently present in the form.''' return self.formWidget.getWidgets() def getRemovedWidgets(self): - '''Invokes `getRemovedWidgets` from `UIFormWidget`.''' + '''Returns the dictionary of the removed widgets previously present in the form.''' return self.formWidget.getRemovedWidgets() def setWidgetVisible(self, name, visible): @@ -180,16 +208,54 @@ def getAllWidgetStates(self): def getWidgetState(self, widget, role=None): ''' - Invokes `getWidgetState` from `UIFormWidget`. + Parameters + ---------- + widget: QWidget or str + The widget or its name (or its name + '_field' or '_label', when role is None) to get the state of. + role: str, optional, default None, values: 'label', 'field', None. + The role of the widget to apply the state to. This is used only if `widget` is the widget name string. + + Returns + ------- + state: dict + Format: {'value': str | bool | int, 'enabled': bool, 'visible': bool, 'widget_number' : int}, + e.g. {'value': 1, 'enabled': True, 'visible': True, 'widget_number' : 0}. + This can be used to restore the state of the widget using `setWidgetState()`. ''' return self.formWidget.getWidgetState(widget, role) def applyWidgetState(self, name, state, role=None): - '''Invokes `applyWidgetState` from `UIFormWidget`.''' + ''' + Applies the given `state` to the widget associated with `name` and `role`. + If role is None, the role is assigned to be 'field'. + + Parameters + ---------- + name: str + The name of the widget to apply the state to. + role: str, optional, default None, values: 'label', 'field', None. + The role of the widget to apply the state to. + state: dict + Format: {'value': str | bool | int, 'enabled': bool, 'visible': bool, 'widget_number' : int}, + e.g. {'value': 1, 'enabled': True, 'visible': True, 'widget_number' : 0}. + ''' return self.formWidget.applyWidgetState(name, state, role) def applyWidgetStates(self, state): ''' - Invokes `applyWidgetStates` from `UIFormWidget`. + Removes the widgets in the form which are not present in the states. + If the widgets in the states are not present in the form, + they are retrieved from the removed-widgets dictionary and inserted at position + given by the widget number recorded in the states. An error is raised when the + widget in thet state is not in the form nor in the removed widgets. + Applies the given states to the form's widgets. + + Parameters + ---------- + states: nested_dict + Format: {'name_field': {'value': str | bool | int, 'enabled': bool, 'visible': bool, 'widget_number' : int}, + 'name_label': {'value': str | bool | int, 'enabled': bool, 'visible': bool, 'widget_number' : int}, ...}, + e.g. {{'widget1': {'value': 1, 'enabled': True, 'visible': True, 'widget_number' : 0}, + 'widget2': {'value': 2, 'enabled': False, 'visible': False, 'widget_number' : 1}}. ''' return self.formWidget.applyWidgetStates(state) diff --git a/eqt/ui/UIFormWidget.py b/eqt/ui/UIFormWidget.py index 07bcbdc..e4579dc 100644 --- a/eqt/ui/UIFormWidget.py +++ b/eqt/ui/UIFormWidget.py @@ -208,7 +208,7 @@ def removeWidget(self, name): self._popWidgetNumberDictionary(name, widget_number) def getWidget(self, name, role='field'): - '''returns the Widget by the name with which it has been added + '''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 @@ -269,8 +269,7 @@ def addSeparator(self, name): def addToDefaultWidgetStatesDictionary(self, name): ''' Creates an attribute dictionary of default widget states. The entries are in the - format: {'value': str | bool | int, 'enabled': bool, 'visible': bool, 'widget_number': int} - or {'value': str | bool | int, 'enabled': bool, 'visible': bool}. + format: {'value': str | bool | int, 'enabled': bool, 'visible': bool, 'widget_number': int}. This can be used to restore the default states of the widgets invoking `applyWidgetStates`. ''' if not hasattr(self, 'default_widget_states'): @@ -470,9 +469,9 @@ def applyWidgetStates(self, states): ---------- states: nested_dict Format: {'name_field': {'value': str | bool | int, 'enabled': bool, 'visible': bool, 'widget_number' : int}, - 'name_label': {'value': str | bool | int, 'enabled': bool, 'visible': bool}, ...}, - e.g. {{'widget1': {'value': 1, 'enabled': True, 'visible': True, 'widget_number' : int}, - 'widget2': {'value': 2, 'enabled': False, 'visible': False}}. + 'name_label': {'value': str | bool | int, 'enabled': bool, 'visible': bool, 'widget_number' : int}, ...}, + e.g. {{'widget1': {'value': 1, 'enabled': True, 'visible': True, 'widget_number' : 0}, + 'widget2': {'value': 2, 'enabled': False, 'visible': False, 'widget_number' : 1}}. ''' # add widgets if necessary @@ -547,7 +546,19 @@ def addSpanningWidget(self, qwidget, name): self.widget().addSpanningWidget(qwidget, name) def insertWidgetToFormLayout(self, row, name, qwidget, qlabel=None): - '''Invokes `insertWidgetToFormLayout` in `UIFormWidget`.''' + ''' + Inserts a widget and a label widget, or a spanning widget if 'qlabel' is None, to the form layout, `groupBoxFormLayout`, + in the position specified by row. If row is out of bounds, the widget is added at the end. + It adds to the widget dictionary and the default states + dictionary. + + Parameters: + ---------- + row: int + name: str + qwidget: qwidget + qlabel: qlabel widget or str + ''' self.widget().insertWidgetToFormLayout(row, name, qwidget, qlabel) def removeWidget(self, name): @@ -579,7 +590,7 @@ def getWidgets(self): return self.widget().getWidgets() def getRemovedWidgets(self): - '''Invokes `getRemovedWidgets` from `UIFormWidget`.''' + '''Returns the dictionary of the removed widgets previously present in the form.''' return self.widget().getRemovedWidgets() def setWidgetVisible(self, name, visible): @@ -587,29 +598,84 @@ def setWidgetVisible(self, name, visible): self.widget().setWidgetVisible(name, visible) def saveAllWidgetStates(self): - '''Invokes `saveAllWidgetStates` from `UIFormWidget`.''' + ''' + Saves the state of all widgets currently present in the form. + To later restore the states, use `restoreAllSavedWidgetStates()`. + ''' self.widget().saveAllWidgetStates() def restoreAllSavedWidgetStates(self): - '''Invokes `restoreAllSavedWidgetStates` from `UIFormWidget`.''' + ''' + All widgets in the form are restored to the saved states. There are saved states only if + `saveAllWidgetStates` was previously invoked. If there are no previously saved states, + `default_widget_states` are used instead, after being made visible. + ''' self.widget().restoreAllSavedWidgetStates() def getAllWidgetStates(self): - '''Invokes `getAllWidgetStates` from `UIFormWidget`.''' + ''' + Returns + ------- + dict + Format: {'widget_name': {'value': str | bool | int, 'enabled': bool, 'visible': bool}, + ...}, + e.g. {{'widget1': {'value': 1, 'enabled': True, 'visible': True}, + 'widget2': {'value': 2, 'enabled': False, 'visible': False}}. + ''' return self.widget().getAllWidgetStates() def getWidgetState(self, widget, role=None): ''' - Invokes `getWidgetState` from `UIFormWidget`. + Parameters + ---------- + widget: QWidget or str + The widget or its name (or its name + '_field' or '_label', when role is None) to get the state of. + role: str, optional, default None, values: 'label', 'field', None. + The role of the widget to apply the state to. This is used only if `widget` is the widget name string. + + Returns + ------- + state: dict + Format: {'value': str | bool | int, 'enabled': bool, 'visible': bool, 'widget_number' : int}, + e.g. {'value': 1, 'enabled': True, 'visible': True, 'widget_number' : 0}. + This can be used to restore the state of the widget using `setWidgetState()`. ''' return self.widget().getWidgetState(widget, role) def applyWidgetState(self, name, state, role=None): - '''Invokes `applyWidgetState` from `UIFormWidget`.''' + ''' + Applies the given `state` to the widget associated with `name` and `role`. + If role is None, the role is assigned to be 'field'. + + Parameters + ---------- + name: str + The name of the widget to apply the state to. + role: str, optional, default None, values: 'label', 'field', None. + The role of the widget to apply the state to. + state: dict + Format: {'value': str | bool | int, 'enabled': bool, 'visible': bool, 'widget_number' : int}, + e.g. {'value': 1, 'enabled': True, 'visible': True, 'widget_number' : 0}. + ''' return self.widget().applyWidgetState(name, state, role) def applyWidgetStates(self, state): - '''Invokes `applyWidgetStates` from `UIFormWidget`.''' + ''' + Removes the widgets in the form which are not present in the states. + If the widgets in the states are not present in the form, + they are retrieved from the removed-widgets dictionary and inserted at position + given by the widget number recorded in the states. An error is raised when the + widget in thet state is not in the form nor in the removed widgets. + Applies the given states to the form's widgets. + + Parameters + ---------- + states: nested_dict + Format: {'name_field': {'value': str | bool | int, 'enabled': bool, 'visible': bool, 'widget_number' : int}, + 'name_label': {'value': str | bool | int, 'enabled': bool, 'visible': bool, 'widget_number' : int}, ...}, + e.g. {{'widget1': {'value': 1, 'enabled': True, 'visible': True, 'widget_number' : 0}, + 'widget2': {'value': 2, 'enabled': False, 'visible': False, 'widget_number' : 1}}. + ''' return self.widget().applyWidgetStates(state) From 1c183b5f6e764bddcfb1786723a09323e07755ed Mon Sep 17 00:00:00 2001 From: Danica Sugic Date: Wed, 10 Jan 2024 16:41:19 +0000 Subject: [PATCH 54/96] Modify example insert widgets and fix problems with default states --- eqt/ui/FormDialog.py | 5 +++ eqt/ui/UIFormWidget.py | 33 ++++++++++++++----- examples/insert_widgets_example.py | 53 ++++++++++++++++++------------ 3 files changed, 62 insertions(+), 29 deletions(-) diff --git a/eqt/ui/FormDialog.py b/eqt/ui/FormDialog.py index c2266d9..2f0a8a9 100644 --- a/eqt/ui/FormDialog.py +++ b/eqt/ui/FormDialog.py @@ -39,6 +39,7 @@ def Cancel(self): def _onOk(self): '''Saves the widget states and calls `onOk`''' self.saveAllWidgetStates() + print("saving"+str(self.formWidget.widget_states)) self.onOk() self.close() @@ -168,6 +169,10 @@ def getRemovedWidgets(self): '''Returns the dictionary of the removed widgets previously present in the form.''' return self.formWidget.getRemovedWidgets() + def getWidgetNumberDictionary(self): + '''Returns the widget number dictionary.''' + return self.formWidget.getWidgetNumberDictionary() + def setWidgetVisible(self, name, visible): ''' Sets the visibility of the widget and associated label with the given name. diff --git a/eqt/ui/UIFormWidget.py b/eqt/ui/UIFormWidget.py index e4579dc..7965bee 100644 --- a/eqt/ui/UIFormWidget.py +++ b/eqt/ui/UIFormWidget.py @@ -59,10 +59,10 @@ def groupBox(self): def insertWidgetToFormLayout(self, row, name, qwidget, qlabel=None): ''' - Inserts a widget and a label widget, or a spanning widget if 'qlabel' is None, to the form layout, `groupBoxFormLayout`, - in the position specified by row. If row is out of bounds, the widget is added at the end. - It adds to the widget dictionary and the default states - dictionary. + Inserts a widget and a label widget , or a spanning widget if 'qlabel' is None, to the form layout + in the position specified by row. If row is out of bounds, the widget is added at the end. + If 'name' is already in use, it raises an error. + It adds to the widget dictionary and the default states dictionary. Parameters: ---------- @@ -71,6 +71,10 @@ def insertWidgetToFormLayout(self, row, name, qwidget, qlabel=None): qwidget: qwidget qlabel: qlabel widget or str ''' + + if f'{name}_field' in self.widgets.keys(): + raise ValueError(f'The name of widget you are trying to insert, {name}, is used already. Choose another name.') + formLayout = self.uiElements['groupBoxFormLayout'] if qlabel is not None: @@ -78,9 +82,9 @@ def insertWidgetToFormLayout(self, row, name, qwidget, qlabel=None): txt = qlabel qlabel = QtWidgets.QLabel(self) qlabel.setText(txt) - self.uiElements['groupBoxFormLayout'].insertRow(row, qlabel, qwidget) + formLayout.insertRow(row, qlabel, qwidget) else: - self.uiElements['groupBoxFormLayout'].insertRow(row, qwidget) + formLayout.insertRow(row, qwidget) self.addToWidgetDictionary(self.widgets, name, qwidget, qlabel) self._addToWidgetNumberDictionary(name, row) self.addToWidgetDictionary(self.default_widgets, name, qwidget, qlabel) @@ -222,7 +226,11 @@ def getWidget(self, name, role='field'): def getWidgetNumber(self, name): '''Returns the widget number by the widget name.''' - return self.widget_number_dictionary[name] + return self.widget_number_dictionary[f'{name}'] + + def getWidgetNumberDictionary(self): + '''Returns the widget number dictionary.''' + return self.widget_number_dictionary def setWidgetVisible(self, name, visible): ''' @@ -487,17 +495,22 @@ def applyWidgetStates(self, states): if f'{name}_label' in self.removed_widgets_dictionary.keys(): qlabel = self.removed_widgets_dictionary[key] self.insertWidgetToFormLayout(widget_number, name, qwidget, qlabel) + print("inserting"+str(name)) else: self.insertWidgetToFormLayout(widget_number, name, qwidget) + print("inserting spanning"+str(name)) else: raise KeyError('No widget associated with the dictionary key `' + key + '`') self.applyWidgetState(name, widget_state, role) # remove extra widgets + set_to_remove = set() if self.widgets.keys() > states.keys(): for key in self.widgets.keys(): if key not in states.keys(): name = self._getNameAndRoleFromKey(key)[0] - self.removeWidget(name) + set_to_remove.add(name) + for el in set_to_remove: + self.removeWidget(el) def saveAllWidgetStates(self): ''' @@ -589,6 +602,10 @@ def getWidgets(self): '''returns a dictionary of all the widgets in the form''' return self.widget().getWidgets() + def getWidgetNumberDictionary(self): + '''Returns the widget number dictionary.''' + return self.widget().getWidgetNumberDictionary() + def getRemovedWidgets(self): '''Returns the dictionary of the removed widgets previously present in the form.''' return self.widget().getRemovedWidgets() diff --git a/examples/insert_widgets_example.py b/examples/insert_widgets_example.py index 9179a74..2df1249 100644 --- a/examples/insert_widgets_example.py +++ b/examples/insert_widgets_example.py @@ -9,14 +9,21 @@ class MainUI(QtWidgets.QMainWindow): def __init__(self, parent=None): QtWidgets.QMainWindow.__init__(self, parent) + # dialog form + self.dialog = FormDialog(parent=self, title='Example insert widget') + self.addWidgetsToExampleForm(self.dialog) + buttoninsertvertical = QtWidgets.QPushButton() + buttoninsertvertical.setText("Insert widget in vertical layout") + self.dialog.addSpanningWidget(buttoninsertvertical, 'Button insert vertical') + buttoninsertvertical.clicked.connect(lambda: self.insert_vertical()) + # create a FormDockWidget dock = UIFormWidget.FormDockWidget(parent=self) dock.setWindowTitle('Example insert widget') self.addWidgetsToExampleForm(dock) - buttoninsert = QtWidgets.QPushButton(dock) - buttoninsert.setText("Insert widgets") - dock.addSpanningWidget(buttoninsert, 'Button insert widgets') - buttoninsert.clicked.connect(lambda: self.insert_form(dock, buttoninsert)) + + + # create button for Form Dialog pb = QtWidgets.QPushButton(self) @@ -32,42 +39,39 @@ def __init__(self, parent=None): self.setCentralWidget(widg) # print dictionary of all widgets in dock - print("\nDictionary of widgets in the Form Dock Widget:\n" + str(dock.getWidgets())) + #print("\nDictionary of widgets in the Form Dock Widget:\n" + str(dock.getWidgets())) + + self.dialog.onCancel = self.onCancel self.show() def openFormDialog(self): - dialog = FormDialog(parent=self, title='Example insert widget') - self.addWidgetsToExampleForm(dialog) - dialog.Ok.clicked.connect(lambda: self.insert_vertical(dialog)) - dialog.Ok.clicked.connect(lambda: self.insert_form(dialog, dialog.Ok)) - - # store a reference - self.dialog = dialog - self.dialog.onCancel = self.rejected # print dictionary of all widgets in dialog - print("\nDictionary of widgets in Form Dialog:\n" + str(self.dialog.getWidgets())) + #print("\nDictionary of widgets in Form Dialog:\n" + str(self.dialog.getWidgets())) + #print("\nDictionary of widget number in Form Dialog:\n" + str(self.dialog.getWidgetNumberDictionary())) - dialog.open() + self.dialog.open() def addWidgetsToExampleForm(self, form): - form.addWidget(QtWidgets.QLineEdit(), "Initial widget raw 0: ", 'Initial widget raw 0') + form.addWidget(QtWidgets.QLineEdit(), "Initial widget row 0: ", 'Initial widget row 0') form.addSpanningWidget(QtWidgets.QLabel("Initial widget row 1"), 'Initial widget row 1') # add QComboBox qwidget = QtWidgets.QComboBox(form) qwidget.addItem("0") qwidget.addItem("1") form.addWidget(qwidget, "Initial widget row 2", 'Initial widget row 2') + buttoninsert = QtWidgets.QPushButton() + buttoninsert.setText("Insert widgets") + form.addSpanningWidget(buttoninsert, 'Button insert widgets') + buttoninsert.clicked.connect(lambda: self.insert_form(form, buttoninsert)) - def rejected(self): - print("\nDialog closed.") - - def insert_vertical(self, form): - form.insertWidgetToVerticalLayout( + def insert_vertical(self): + self.dialog.insertWidgetToVerticalLayout( 1, QtWidgets.QPushButton("Inserted widget in vertical layout")) print( "\nThe dictionary of widgets does not change after insertion in the vertical layout.") + self.dialog.getWidget('Button insert vertical').setEnabled(False) def insert_form(self, form, button): qlabel = QtWidgets.QLabel(form) @@ -81,8 +85,15 @@ def insert_form(self, form, button): print('\nDictionary of widgets after insertion in the form layout:\n' + str(form.getWidgets())) + print("\nDictionary of widget number in the form layout:\n" + str(form.getWidgetNumberDictionary())) button.setEnabled(False) + def onCancel(self): + if not hasattr(self.dialog.formWidget, 'widget_states'): + if self.dialog.getWidget('Button insert widgets').isEnabled() == False: + self.dialog.formWidget.removeWidgetFromDictionary(self.dialog.formWidget.default_widget_states,'inserted widget') + self.dialog.formWidget.removeWidgetFromDictionary(self.dialog.formWidget.default_widget_states,'inserted spanning widget') + if __name__ == "__main__": app = QtWidgets.QApplication(sys.argv) From 3b7cd9ab61ba4c2961a491ef9ac58d9dbcd83f8e Mon Sep 17 00:00:00 2001 From: Danica Sugic Date: Wed, 10 Jan 2024 17:22:32 +0000 Subject: [PATCH 55/96] Add remove widget and get widget from vertical layout in form dialog --- eqt/ui/FormDialog.py | 10 ++++++++++ examples/insert_widgets_example.py | 3 ++- 2 files changed, 12 insertions(+), 1 deletion(-) diff --git a/eqt/ui/FormDialog.py b/eqt/ui/FormDialog.py index 2f0a8a9..afc7934 100644 --- a/eqt/ui/FormDialog.py +++ b/eqt/ui/FormDialog.py @@ -129,6 +129,16 @@ def insertWidgetToVerticalLayout(self, row, qwidget): ''' self.formWidget.uiElements['verticalLayout'].insertWidget(row, qwidget) + def removeWidgetFromVerticalLayout(self, qwidget): + ''' + Removes a widget from the vertical layout. + ''' + self.formWidget.uiElements['verticalLayout'].removeWidget(qwidget) + qwidget.setParent(None) + + def getWidgetFromVerticalLayout(self, index): + return self.formWidget.uiElements['verticalLayout'].itemAt(index).widget() + def removeWidget(self, name): ''' If not present already, creates a dictionary to store the removed qwidgets. diff --git a/examples/insert_widgets_example.py b/examples/insert_widgets_example.py index 2df1249..d5cebf0 100644 --- a/examples/insert_widgets_example.py +++ b/examples/insert_widgets_example.py @@ -93,7 +93,8 @@ def onCancel(self): if self.dialog.getWidget('Button insert widgets').isEnabled() == False: self.dialog.formWidget.removeWidgetFromDictionary(self.dialog.formWidget.default_widget_states,'inserted widget') self.dialog.formWidget.removeWidgetFromDictionary(self.dialog.formWidget.default_widget_states,'inserted spanning widget') - + if self.dialog.getWidget('Button insert vertical').isEnabled() == False: + self.dialog.removeWidgetFromVerticalLayout(self.dialog.getWidgetFromVerticalLayout(1)) if __name__ == "__main__": app = QtWidgets.QApplication(sys.argv) From 8b34ce7126bac0cf22ce58c6174fd306ebfb6e46 Mon Sep 17 00:00:00 2001 From: Danica Sugic Date: Thu, 11 Jan 2024 17:10:33 +0000 Subject: [PATCH 56/96] Add unit tests for some methods --- eqt/ui/FormDialog.py | 6 +- eqt/ui/UIFormWidget.py | 20 ++--- examples/insert_widgets_example.py | 4 +- test/test__formUI_status_test.py | 120 ++++++++++++++++------------- 4 files changed, 84 insertions(+), 66 deletions(-) diff --git a/eqt/ui/FormDialog.py b/eqt/ui/FormDialog.py index afc7934..975eac4 100644 --- a/eqt/ui/FormDialog.py +++ b/eqt/ui/FormDialog.py @@ -39,7 +39,6 @@ def Cancel(self): def _onOk(self): '''Saves the widget states and calls `onOk`''' self.saveAllWidgetStates() - print("saving"+str(self.formWidget.widget_states)) self.onOk() self.close() @@ -179,6 +178,11 @@ def getRemovedWidgets(self): '''Returns the dictionary of the removed widgets previously present in the form.''' return self.formWidget.getRemovedWidgets() + def getWidgetNumber(self, name): + '''Returns the widget number by the widget name.''' + return self.formWidget.getWidgetNumber(name) + + def getWidgetNumberDictionary(self): '''Returns the widget number dictionary.''' return self.formWidget.getWidgetNumberDictionary() diff --git a/eqt/ui/UIFormWidget.py b/eqt/ui/UIFormWidget.py index 7965bee..98bac93 100644 --- a/eqt/ui/UIFormWidget.py +++ b/eqt/ui/UIFormWidget.py @@ -85,9 +85,9 @@ def insertWidgetToFormLayout(self, row, name, qwidget, qlabel=None): formLayout.insertRow(row, qlabel, qwidget) else: formLayout.insertRow(row, qwidget) - self.addToWidgetDictionary(self.widgets, name, qwidget, qlabel) + self._addToWidgetDictionary(self.widgets, name, qwidget, qlabel) self._addToWidgetNumberDictionary(name, row) - self.addToWidgetDictionary(self.default_widgets, name, qwidget, qlabel) + self._addToWidgetDictionary(self.default_widgets, name, qwidget, qlabel) self.addToDefaultWidgetStatesDictionary(name) def _addWidget(self, name, qwidget, qlabel=None): @@ -103,7 +103,7 @@ def _addWidget(self, name, qwidget, qlabel=None): ''' self.insertWidgetToFormLayout(-1, name, qwidget, qlabel) - def addToWidgetDictionary(self, dictionary, name, qwidget, qlabel = None): + def _addToWidgetDictionary(self, dictionary, name, qwidget, qlabel = None): '''Adds the field (and label if present) in the widget dictionary.''' dictionary[f'{name}_field'] = qwidget if qlabel is not None: @@ -150,7 +150,7 @@ def _popWidgetNumberDictionary(self, name, widget_number): self.widget_number_dictionary[key] = value - 1 self.widget_number_dictionary.pop(name) - def removeWidgetFromDictionary(self, dictionary, name): + def _popWidgetFromDictionary(self, dictionary, name): ''' Removes the item(s) associated with `name` from a dictionary. @@ -202,13 +202,13 @@ def removeWidget(self, name): qwidget = self.getWidget(name, role='field') if f'{name}_label' in self.getWidgets().keys(): qlabel = self.getWidget(name, role='label') - self.addToWidgetDictionary(self.removed_widgets_dictionary, name, qwidget, qlabel) + self._addToWidgetDictionary(self.removed_widgets_dictionary, name, qwidget, qlabel) self.getWidget(name, 'label').setParent(None) else: - self.addToWidgetDictionary(self.removed_widgets_dictionary, name, qwidget) + self._addToWidgetDictionary(self.removed_widgets_dictionary, name, qwidget) self.getWidget(name, 'field').setParent(None) formLayout.removeRow(self.widget_number_dictionary[name]) - self.removeWidgetFromDictionary(self.getWidgets(), name) + self._popWidgetFromDictionary(self.getWidgets(), name) self._popWidgetNumberDictionary(name, widget_number) def getWidget(self, name, role='field'): @@ -495,10 +495,8 @@ def applyWidgetStates(self, states): if f'{name}_label' in self.removed_widgets_dictionary.keys(): qlabel = self.removed_widgets_dictionary[key] self.insertWidgetToFormLayout(widget_number, name, qwidget, qlabel) - print("inserting"+str(name)) else: self.insertWidgetToFormLayout(widget_number, name, qwidget) - print("inserting spanning"+str(name)) else: raise KeyError('No widget associated with the dictionary key `' + key + '`') self.applyWidgetState(name, widget_state, role) @@ -602,6 +600,10 @@ def getWidgets(self): '''returns a dictionary of all the widgets in the form''' return self.widget().getWidgets() + def getWidgetNumber(self, name): + '''Returns the widget number by the widget name.''' + return self.widget().getWidgetNumber(name) + def getWidgetNumberDictionary(self): '''Returns the widget number dictionary.''' return self.widget().getWidgetNumberDictionary() diff --git a/examples/insert_widgets_example.py b/examples/insert_widgets_example.py index d5cebf0..8810409 100644 --- a/examples/insert_widgets_example.py +++ b/examples/insert_widgets_example.py @@ -91,8 +91,8 @@ def insert_form(self, form, button): def onCancel(self): if not hasattr(self.dialog.formWidget, 'widget_states'): if self.dialog.getWidget('Button insert widgets').isEnabled() == False: - self.dialog.formWidget.removeWidgetFromDictionary(self.dialog.formWidget.default_widget_states,'inserted widget') - self.dialog.formWidget.removeWidgetFromDictionary(self.dialog.formWidget.default_widget_states,'inserted spanning widget') + self.dialog.formWidget._popWidgetFromDictionary(self.dialog.formWidget.default_widget_states,'inserted widget') + self.dialog.formWidget._popWidgetFromDictionary(self.dialog.formWidget.default_widget_states,'inserted spanning widget') if self.dialog.getWidget('Button insert vertical').isEnabled() == False: self.dialog.removeWidgetFromVerticalLayout(self.dialog.getWidgetFromVerticalLayout(1)) diff --git a/test/test__formUI_status_test.py b/test/test__formUI_status_test.py index c70c477..d4f7512 100644 --- a/test/test__formUI_status_test.py +++ b/test/test__formUI_status_test.py @@ -37,19 +37,19 @@ def exampleState(self): @property def list_all_widgets(self): - list_all_widgets = [ - QtWidgets.QLabel('test label'), - QtWidgets.QCheckBox('test checkbox'), - QtWidgets.QComboBox(), - QtWidgets.QDoubleSpinBox(), - QtWidgets.QSpinBox(), - QtWidgets.QSlider(), - UISliderWidget(QtWidgets.QLabel()), - QtWidgets.QRadioButton('test radio button'), - QtWidgets.QTextEdit('test text edit'), - QtWidgets.QPlainTextEdit('test plain text edit'), - QtWidgets.QLineEdit('test line edit'), - QtWidgets.QPushButton('test push button')] + 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 @property @@ -63,36 +63,16 @@ def state_simple_form(self): return state_simple_form def add_every_widget(self): - """Generate every widget and add it to `self.form`""" + """Generate every widget and add it to the form.""" form = self.form - form.addWidget(QtWidgets.QLabel('test label'), 'Label: ', 'label') - form.addWidget(QtWidgets.QCheckBox('test checkbox'), 'CheckBox: ', 'checkBox') - form.addWidget(QtWidgets.QComboBox(), 'ComboBox: ', 'comboBox') - form.addWidget(QtWidgets.QDoubleSpinBox(), 'DoubleSpinBox: ', 'doubleSpinBox') - form.addWidget(QtWidgets.QSpinBox(), 'SpinBox: ', 'spinBox') - form.addWidget(QtWidgets.QSlider(), 'Slider: ', 'slider') - form.addWidget(UISliderWidget(QtWidgets.QLabel()), 'UISliderWidget: ', 'uiSliderWidget') - form.addWidget(QtWidgets.QRadioButton('test'), 'RadioButton: ', 'radioButton') - form.addWidget(QtWidgets.QTextEdit('test'), 'TextEdit: ', 'textEdit') - form.addWidget(QtWidgets.QPlainTextEdit('test'), 'PlainTextEdit: ', 'plainTextEdit') - form.addWidget(QtWidgets.QLineEdit('test'), 'LineEdit: ', 'lineEdit') - form.addWidget(QtWidgets.QPushButton('test'), 'Button: ', 'button') + for key in self.list_all_widgets.keys(): + form.addWidget(self.list_all_widgets[key], key, key) def add_every_spanning_widget(self): - """Generate every spanning widget and add it to `self.form`""" + """Generate every spanning widget and add it to the form.""" form = self.form - form.addSpanningWidget(QtWidgets.QLabel('test label'), 'spanning label') - form.addSpanningWidget(QtWidgets.QCheckBox('test checkbox'), 'spanning checkBox') - form.addSpanningWidget(QtWidgets.QComboBox(), 'spanning comboBox') - form.addSpanningWidget(QtWidgets.QDoubleSpinBox(), 'spanning doubleSpinBox') - form.addSpanningWidget(QtWidgets.QSpinBox(), 'spanning spinBox') - form.addSpanningWidget(QtWidgets.QSlider(), 'spanning slider') - form.addSpanningWidget(UISliderWidget(QtWidgets.QLabel()), 'spanning uiSliderWidget') - form.addSpanningWidget(QtWidgets.QRadioButton('test'), 'spanning radioButton') - form.addSpanningWidget(QtWidgets.QTextEdit('test'), 'spanning textEdit') - form.addSpanningWidget(QtWidgets.QPlainTextEdit('test'), 'spanning plainTextEdit') - form.addSpanningWidget(QtWidgets.QLineEdit('test'), 'spanning lineEdit') - form.addSpanningWidget(QtWidgets.QPushButton('test'), 'spanning button') + for key in self.list_all_widgets.keys(): + form.addSpanningWidget(self.list_all_widgets[key], f'{key}_spanning') def add_two_widgets(self): """Generate two widgets and add them to `self.simple_form`""" @@ -152,16 +132,34 @@ def test_insert_every_widget(self): Inserts each widget, and then each spanning widget, in position 0 of the form layout. Tests the position of the widgets in the layout is 0. """ - list_widget_names = [ - 'label insert', 'checkBox insert', 'comboBox insert', 'doubleSpinBox insert', - 'spinBox insert', 'slider insert', 'uiSliderWidget insert', 'radioButton insert', - 'textEdit insert', 'plainTextEdit insert', 'lineEdit insert', 'button insert'] - for i in range(0, len(self.list_all_widgets)): - qwidget = self.list_all_widgets[i] - name = list_widget_names[i] + for key in self.list_all_widgets.keys(): + qwidget = self.list_all_widgets[key] + name = f'{key}_insert' self._test_insert_one_widget(0, name, qwidget, name) - qwidget = self.list_all_widgets[i] - self._test_insert_one_widget(0, name + ' spanning', qwidget) + qwidget = self.list_all_widgets[key] + self._test_insert_one_widget(0, name + '_spanning', qwidget) + + # def _test_add_one_widget(self, name): + # """ + # Invokes `insertWidgetToFormLayout`, therefore inserts the qwidget (and the qlabel) + # at position row in the layout. Checks the position of the widget in the form is `row`. + # """ + # position = self.layout.getWidgetPosition(self.form.getWidget(name, 'field'))[0] + # self.assertEqual(position, row) + + # def test_add_every_widget(self): + # list_widget_names = [ + # 'label', 'checkBox', 'comboBox', 'doubleSpinBox', + # 'spinBox', 'slider', 'uiSliderWidget', 'radioButton', + # 'textEdit', 'plainTextEdit', 'lineEdit', 'button'] + # for i in range(0, len(self.list_all_widgets)): + # qwidget = self.list_all_widgets[i] + # name = list_widget_names[i] + # self._test_add_one_widget_to_dictionary(self.widgets, name, qwidget, name) + # qwidget = self.list_all_widgets[i] + # self._test_insert_one_widget(0, name + '_spanning', qwidget) + + def _test_remove_one_widget(self, name): """ @@ -185,9 +183,10 @@ def _test_remove_one_widget(self, name): self.assertEqual(prenumwidgets, postnumwidgets + 1) self.assertEqual(prerowcount, postrowcount + 1) self.assertEqual(postrowcount, postnumwidgets) - + self.assertEqual(self.form.getRemovedWidgets()[f'{name}_field'], qwidget) + def test_remove_every_widget(self): - """Remove every widget from `self.form`""" + """Remove every widget from the form.""" list_widgets = [ 'label', 'checkBox', 'comboBox', 'doubleSpinBox', 'spinBox', 'slider', 'uiSliderWidget', 'radioButton', 'textEdit', 'plainTextEdit', 'lineEdit', 'button'] @@ -435,6 +434,7 @@ class FormDialogStatusTest(FormsCommonTests, unittest.TestCase): def setUp(self): self.form = FormDialog() self.add_every_widget() + self.add_every_spanning_widget() self.simple_form = FormDialog() self.add_two_widgets() self.layout = self.form.formWidget.uiElements['groupBoxFormLayout'] @@ -520,13 +520,12 @@ def _test_insert_one_widget_to_vertical_layout(self, row, qwidget): def test_insert_every_widget_to_vertical_layout(self): """Inserts each widget in position 0 of the vertical layout and tests its position in the layout is 0.""" - for i in range(0, len(self.list_all_widgets)): - qwidget = self.list_all_widgets[i] - self._test_insert_one_widget_to_vertical_layout(0, qwidget) + for key in self.list_all_widgets.keys(): + self._test_insert_one_widget_to_vertical_layout(0, self.list_all_widgets[key]) def test_getWidgetState_returns_QLabel_value(self): """Check that the value of the QLabel is saved to the state""" - initial_label_value = 'Label: ' + initial_label_value = 'label' self.assertEqual(self.form.getWidgetState('label_label')['value'], initial_label_value) final_label_value = 'final test label' @@ -590,10 +589,22 @@ class FormWidgetStateTest(FormsCommonTests, unittest.TestCase): def setUp(self): self.form = FormWidget() self.add_every_widget() + self.add_every_spanning_widget() self.simple_form = FormWidget() self.add_two_widgets() self.layout = self.form.uiElements['groupBoxFormLayout'] + def test_get_name_and_role_from_key_or_widget(self): + for name in self.list_all_widgets.keys(): + for role in {'field', 'label'}: + name_role = name + '_' + role + name_c, role_c = self.form._getNameAndRoleFromKey(name_role) + self.assertEqual(name_c, name) + self.assertEqual(role_c, role) + name_c, role_c = self.form._getNameAndRoleFromWidget(self.form.getWidget(name, role)) + self.assertEqual(name_c, name) + self.assertEqual(role_c, role) + def test_getWidgetState_returns_QLabel_value(self): """Check that the value of the QLabel is saved to the state""" initial_label_value = 'test label' @@ -660,6 +671,7 @@ class FormDockWidgetStateTest(FormsCommonTests, unittest.TestCase): def setUp(self): self.form = FormDockWidget() self.add_every_widget() + self.add_every_spanning_widget() self.simple_form = FormDockWidget() self.add_two_widgets() self.layout = self.form.widget().uiElements['groupBoxFormLayout'] From 457b6aa9b5a17d6b6ebe2f1de3e54f2bd71f7497 Mon Sep 17 00:00:00 2001 From: Danica Sugic Date: Thu, 11 Jan 2024 19:09:43 +0000 Subject: [PATCH 57/96] temporary commit --- eqt/ui/UIFormWidget.py | 5 +- examples/insert_widgets_example copy.py | 110 ++++++++++++++++++++++++ test/test__formUI_status_test.py | 28 ++++++ 3 files changed, 141 insertions(+), 2 deletions(-) create mode 100644 examples/insert_widgets_example copy.py diff --git a/eqt/ui/UIFormWidget.py b/eqt/ui/UIFormWidget.py index 98bac93..16d5454 100644 --- a/eqt/ui/UIFormWidget.py +++ b/eqt/ui/UIFormWidget.py @@ -445,7 +445,7 @@ def applyWidgetState(self, name, state, role=None): if isinstance(widget, QtWidgets.QLabel): widget.setText(value) elif isinstance(widget, QtWidgets.QCheckBox): - widget.setChecked(value) + widget.setChecked(bool(value)) elif isinstance(widget, QtWidgets.QComboBox): widget.setCurrentIndex(value) elif isinstance(widget, (UISliderWidget, QtWidgets.QSlider)): @@ -499,7 +499,7 @@ def applyWidgetStates(self, states): self.insertWidgetToFormLayout(widget_number, name, qwidget) else: raise KeyError('No widget associated with the dictionary key `' + key + '`') - self.applyWidgetState(name, widget_state, role) + self.applyWidgetState() # remove extra widgets set_to_remove = set() if self.widgets.keys() > states.keys(): @@ -510,6 +510,7 @@ def applyWidgetStates(self, states): for el in set_to_remove: self.removeWidget(el) + def saveAllWidgetStates(self): ''' Saves the state of all widgets currently present in the form. diff --git a/examples/insert_widgets_example copy.py b/examples/insert_widgets_example copy.py new file mode 100644 index 0000000..18e9dec --- /dev/null +++ b/examples/insert_widgets_example copy.py @@ -0,0 +1,110 @@ +import sys + +from PySide2 import QtWidgets + +from eqt.ui import FormDialog, UIFormWidget + + +class MainUI(QtWidgets.QMainWindow): + def __init__(self, parent=None): + QtWidgets.QMainWindow.__init__(self, parent) + + # dialog form + self.dialog = FormDialog(parent=self, title='Example insert widget') + self.addWidgetsToExampleForm(self.dialog) + buttoninsertvertical = QtWidgets.QPushButton() + buttoninsertvertical.setText("Insert widget in vertical layout") + self.dialog.addSpanningWidget(buttoninsertvertical, 'Button insert vertical') + buttoninsertvertical.clicked.connect(lambda: self.insert_vertical()) + + # create a FormDockWidget + dock = UIFormWidget.FormDockWidget(parent=self) + dock.setWindowTitle('Example insert widget') + self.addWidgetsToExampleForm(dock) + + + + + # create button for Form Dialog + pb = QtWidgets.QPushButton(self) + pb.setText("Open Form Dialog") + pb.clicked.connect(lambda: self.openFormDialog()) + + # create window layout + layout = QtWidgets.QHBoxLayout() + layout.addWidget(pb) + layout.addWidget(dock) + widg = QtWidgets.QWidget() + widg.setLayout(layout) + self.setCentralWidget(widg) + + # print dictionary of all widgets in dock + #print("\nDictionary of widgets in the Form Dock Widget:\n" + str(dock.getWidgets())) + + self.dialog.onCancel = self.onCancel + + self.show() + + def openFormDialog(self): + + # print dictionary of all widgets in dialog + #print("\nDictionary of widgets in Form Dialog:\n" + str(self.dialog.getWidgets())) + #print("\nDictionary of widget number in Form Dialog:\n" + str(self.dialog.getWidgetNumberDictionary())) + + self.dialog.open() + self.dialog.saveAllWidgetStates() + print(self.dialog.formWidget.widget_states) + self.state1=self.dialog.formWidget.widget_states + + def addWidgetsToExampleForm(self, form): + form.addWidget(QtWidgets.QLineEdit(), "Initial widget row 0: ", 'Initial widget row 0') + form.addSpanningWidget(QtWidgets.QLabel("Initial widget row 1"), 'Initial widget row 1') + # add QComboBox + qwidget = QtWidgets.QComboBox(form) + qwidget.addItem("0") + qwidget.addItem("1") + form.addWidget(qwidget, "Initial widget row 2", 'Initial widget row 2') + buttoninsert = QtWidgets.QPushButton() + buttoninsert.setText("Insert widgets") + form.addSpanningWidget(buttoninsert, 'Button insert widgets') + buttoninsert.clicked.connect(lambda: self.insert_form(form, buttoninsert)) + + def insert_vertical(self): + self.dialog.insertWidgetToVerticalLayout( + 1, QtWidgets.QPushButton("Inserted widget in vertical layout")) + print( + "\nThe dictionary of widgets does not change after insertion in the vertical layout.") + self.dialog.getWidget('Button insert vertical').setEnabled(False) + self.dialog.saveAllWidgetStates() + print(self.dialog.formWidget.widget_states) + + def insert_form(self, form, button): + qlabel = QtWidgets.QLabel(form) + qlabel.setText("Widget inserted in row 0: ") + qwidget = QtWidgets.QLineEdit(form) + form.insertWidgetToFormLayout(0, 'inserted widget', qwidget, qlabel) + + buttonspanning = QtWidgets.QPushButton(self) + buttonspanning.setText("Spanning widget inserted in row 2") + form.insertWidgetToFormLayout(2, 'inserted spanning widget', buttonspanning) + self.dialog.formWidget.applyWidgetStates(self.state1) + + print('\nDictionary of widgets after insertion in the form layout:\n' + + str(form.getWidgets())) + print("\nDictionary of widget number in the form layout:\n" + str(form.getWidgetNumberDictionary())) + button.setEnabled(False) + + def onCancel(self): + if not hasattr(self.dialog.formWidget, 'widget_states'): + if self.dialog.getWidget('Button insert widgets').isEnabled() == False: + self.dialog.formWidget._popWidgetFromDictionary(self.dialog.formWidget.default_widget_states,'inserted widget') + self.dialog.formWidget._popWidgetFromDictionary(self.dialog.formWidget.default_widget_states,'inserted spanning widget') + if self.dialog.getWidget('Button insert vertical').isEnabled() == False: + self.dialog.removeWidgetFromVerticalLayout(self.dialog.getWidgetFromVerticalLayout(1)) + +if __name__ == "__main__": + app = QtWidgets.QApplication(sys.argv) + + window = MainUI() + + sys.exit(app.exec_()) diff --git a/test/test__formUI_status_test.py b/test/test__formUI_status_test.py index d4f7512..c3ad46e 100644 --- a/test/test__formUI_status_test.py +++ b/test/test__formUI_status_test.py @@ -665,6 +665,34 @@ def test_restoreAllSavedWidgetStates(self): self.simple_form.getWidget('label', 'label').isVisible(), state_to_restore['label_label']['visible']) + def test_applyWidgetStates_after_remove_and_insert(self): + self.form.saveAllWidgetStates() + state1 = self.form.widget_states + for key in self.list_all_widgets.keys(): + qwidget = self.list_all_widgets[key] + name = f'{key}_insert' + self.form.insertWidgetToFormLayout(0, name, qwidget, name) + qwidget = self.list_all_widgets[key] + self.form.insertWidgetToFormLayout(0, name + '_spanning', qwidget) + self.form.saveAllWidgetStates() + state2 = self.form.widget_states + self.assertNotEqual(state1, state2) + self.form.applyWidgetStates(state1) + self.form.saveAllWidgetStates() + self.assertEqual(state1, self.form.widget_states) + print(state2) + for key in state2.keys(): + if 'comboBox' in key: + print(key) + for key2 in state2[key].keys(): + if key2 == 'value': + print(type(state2[key][key2])) + if key2 is int: + print(key2) + self.form.applyWidgetStates(state2) + #self.form.saveAllWidgetStates() + #self.assertEqual(state2, self.form.widget_states) + @skip_ci class FormDockWidgetStateTest(FormsCommonTests, unittest.TestCase): From 42f6141a635a0d3606dbc58a948299338fb09dd0 Mon Sep 17 00:00:00 2001 From: Danica Sugic Date: Thu, 11 Jan 2024 21:27:16 +0000 Subject: [PATCH 58/96] correct qlabel widget in applywidgetstates --- eqt/ui/UIFormWidget.py | 11 ++++-- examples/insert_widgets_example copy.py | 48 ++++++++++++++++--------- 2 files changed, 40 insertions(+), 19 deletions(-) diff --git a/eqt/ui/UIFormWidget.py b/eqt/ui/UIFormWidget.py index 16d5454..4a7481d 100644 --- a/eqt/ui/UIFormWidget.py +++ b/eqt/ui/UIFormWidget.py @@ -89,6 +89,7 @@ def insertWidgetToFormLayout(self, row, name, qwidget, qlabel=None): self._addToWidgetNumberDictionary(name, row) self._addToWidgetDictionary(self.default_widgets, name, qwidget, qlabel) self.addToDefaultWidgetStatesDictionary(name) + print("inserted") def _addWidget(self, name, qwidget, qlabel=None): ''' @@ -445,7 +446,7 @@ def applyWidgetState(self, name, state, role=None): if isinstance(widget, QtWidgets.QLabel): widget.setText(value) elif isinstance(widget, QtWidgets.QCheckBox): - widget.setChecked(bool(value)) + widget.setChecked(value) elif isinstance(widget, QtWidgets.QComboBox): widget.setCurrentIndex(value) elif isinstance(widget, (UISliderWidget, QtWidgets.QSlider)): @@ -492,14 +493,18 @@ def applyWidgetStates(self, states): if role == 'field': widget_number = states[key]['widget_number'] qwidget = self.removed_widgets_dictionary[key] + print(qwidget) + if f'{name}_label' in self.removed_widgets_dictionary.keys(): - qlabel = self.removed_widgets_dictionary[key] + qlabel = self.removed_widgets_dictionary[f'{name}_label'] + print(qlabel) self.insertWidgetToFormLayout(widget_number, name, qwidget, qlabel) else: self.insertWidgetToFormLayout(widget_number, name, qwidget) else: raise KeyError('No widget associated with the dictionary key `' + key + '`') - self.applyWidgetState() + + self.applyWidgetState(name, widget_state, role) # remove extra widgets set_to_remove = set() if self.widgets.keys() > states.keys(): diff --git a/examples/insert_widgets_example copy.py b/examples/insert_widgets_example copy.py index 18e9dec..03d8247 100644 --- a/examples/insert_widgets_example copy.py +++ b/examples/insert_widgets_example copy.py @@ -16,7 +16,7 @@ def __init__(self, parent=None): buttoninsertvertical.setText("Insert widget in vertical layout") self.dialog.addSpanningWidget(buttoninsertvertical, 'Button insert vertical') buttoninsertvertical.clicked.connect(lambda: self.insert_vertical()) - + # create a FormDockWidget dock = UIFormWidget.FormDockWidget(parent=self) dock.setWindowTitle('Example insert widget') @@ -47,14 +47,11 @@ def __init__(self, parent=None): def openFormDialog(self): - # print dictionary of all widgets in dialog - #print("\nDictionary of widgets in Form Dialog:\n" + str(self.dialog.getWidgets())) - #print("\nDictionary of widget number in Form Dialog:\n" + str(self.dialog.getWidgetNumberDictionary())) self.dialog.open() - self.dialog.saveAllWidgetStates() - print(self.dialog.formWidget.widget_states) - self.state1=self.dialog.formWidget.widget_states + #self.dialog.saveAllWidgetStates() + #print(self.dialog.formWidget.widget_states) + #self.state1=self.dialog.formWidget.widget_states def addWidgetsToExampleForm(self, form): form.addWidget(QtWidgets.QLineEdit(), "Initial widget row 0: ", 'Initial widget row 0') @@ -72,11 +69,17 @@ def addWidgetsToExampleForm(self, form): def insert_vertical(self): self.dialog.insertWidgetToVerticalLayout( 1, QtWidgets.QPushButton("Inserted widget in vertical layout")) - print( - "\nThe dictionary of widgets does not change after insertion in the vertical layout.") - self.dialog.getWidget('Button insert vertical').setEnabled(False) - self.dialog.saveAllWidgetStates() - print(self.dialog.formWidget.widget_states) + #print( + # "\nThe dictionary of widgets does not change after insertion in the vertical layout.") + #self.dialog.getWidget('Button insert vertical').setEnabled(False) + print('state2'+str(self.state2)) + self.dialog.applyWidgetStates(self.state2) + #self.dialog.saveAllWidgetStates() + #print(self.dialog.formWidget.widget_states) + #print(self.dialog.getWidgets()) + #print('removed2'+str(self.dialog.formWidget.getRemovedWidgets())) + + def insert_form(self, form, button): qlabel = QtWidgets.QLabel(form) @@ -87,12 +90,25 @@ def insert_form(self, form, button): buttonspanning = QtWidgets.QPushButton(self) buttonspanning.setText("Spanning widget inserted in row 2") form.insertWidgetToFormLayout(2, 'inserted spanning widget', buttonspanning) - self.dialog.formWidget.applyWidgetStates(self.state1) + + #('\nDictionary of widgets after insertion in the form layout:\n' + + # str(form.getWidgets())) + #print("\nDictionary of widget number in the form layout:\n" + str(form.getWidgetNumberDictionary())) + self.dialog.addWidget(QtWidgets.QComboBox(), 'combo', 'combo') - print('\nDictionary of widgets after insertion in the form layout:\n' + - str(form.getWidgets())) - print("\nDictionary of widget number in the form layout:\n" + str(form.getWidgetNumberDictionary())) button.setEnabled(False) + self.dialog.saveAllWidgetStates() + print('widgetstates'+str(self.dialog.formWidget.widget_states)) + self.state2=self.dialog.formWidget.widget_states + #print(self.state2) + #print('state1'+str(self.state1)) + + #print(self.dialog.getWidgets()) + + #self.dialog.applyWidgetStates(self.state1) + #print(self.dialog.formWidget.getRemovedWidgets()) + #print(self.dialog.getWidgets()) + def onCancel(self): if not hasattr(self.dialog.formWidget, 'widget_states'): From 75db82beb1704c34c55f0b9c8aa472f6a9331fa3 Mon Sep 17 00:00:00 2001 From: Danica Sugic Date: Fri, 12 Jan 2024 12:17:40 +0000 Subject: [PATCH 59/96] Add test for apply widgets remove and insert --- eqt/ui/FormDialog.py | 4 ++ eqt/ui/UIFormWidget.py | 14 +++++-- examples/insert_widgets_example copy.py | 54 +++++++++++++++++++------ test/test__formUI_status_test.py | 44 +++++++------------- 4 files changed, 69 insertions(+), 47 deletions(-) diff --git a/eqt/ui/FormDialog.py b/eqt/ui/FormDialog.py index 975eac4..54fd352 100644 --- a/eqt/ui/FormDialog.py +++ b/eqt/ui/FormDialog.py @@ -206,6 +206,10 @@ def saveAllWidgetStates(self): ''' self.formWidget.saveAllWidgetStates() + def getWidgetStates(self): + '''Returns the saved widget states.''' + self.formWidget.getWidgetStates() + def restoreAllSavedWidgetStates(self): ''' Restore all widgets in the form to the state saved by `saveAllWidgetStates()`. diff --git a/eqt/ui/UIFormWidget.py b/eqt/ui/UIFormWidget.py index 4a7481d..70dc099 100644 --- a/eqt/ui/UIFormWidget.py +++ b/eqt/ui/UIFormWidget.py @@ -89,7 +89,6 @@ def insertWidgetToFormLayout(self, row, name, qwidget, qlabel=None): self._addToWidgetNumberDictionary(name, row) self._addToWidgetDictionary(self.default_widgets, name, qwidget, qlabel) self.addToDefaultWidgetStatesDictionary(name) - print("inserted") def _addWidget(self, name, qwidget, qlabel=None): ''' @@ -467,6 +466,7 @@ def applyWidgetState(self, name, state, role=None): def applyWidgetStates(self, states): ''' + Reorders the states dictionary in order of crescend widget number. Removes the widgets in the form which are not present in the states. If the widgets in the states are not present in the form, they are retrieved from the removed-widgets dictionary and inserted at position @@ -484,6 +484,7 @@ def applyWidgetStates(self, states): ''' # add widgets if necessary + states = dict(sorted(states.items(), key = lambda tup: (tup[1]['widget_number']))) for key, widget_state in states.items(): name, role = self._getNameAndRoleFromKey(key) if key in self.widgets.keys(): @@ -493,17 +494,14 @@ def applyWidgetStates(self, states): if role == 'field': widget_number = states[key]['widget_number'] qwidget = self.removed_widgets_dictionary[key] - print(qwidget) if f'{name}_label' in self.removed_widgets_dictionary.keys(): qlabel = self.removed_widgets_dictionary[f'{name}_label'] - print(qlabel) self.insertWidgetToFormLayout(widget_number, name, qwidget, qlabel) else: self.insertWidgetToFormLayout(widget_number, name, qwidget) else: raise KeyError('No widget associated with the dictionary key `' + key + '`') - self.applyWidgetState(name, widget_state, role) # remove extra widgets set_to_remove = set() @@ -523,6 +521,10 @@ def saveAllWidgetStates(self): ''' self.widget_states = self.getAllWidgetStates() + def getWidgetStates(self): + '''Returns the saved widget states.''' + return self.widget_states + def restoreAllSavedWidgetStates(self): ''' All widgets in the form are restored to the saved states. There are saved states only if @@ -629,6 +631,10 @@ def saveAllWidgetStates(self): ''' self.widget().saveAllWidgetStates() + def getWidgetStates(self): + '''Returns the saved widget states.''' + self.widget().getWidgetStates() + def restoreAllSavedWidgetStates(self): ''' All widgets in the form are restored to the saved states. There are saved states only if diff --git a/examples/insert_widgets_example copy.py b/examples/insert_widgets_example copy.py index 03d8247..29d50dc 100644 --- a/examples/insert_widgets_example copy.py +++ b/examples/insert_widgets_example copy.py @@ -12,15 +12,16 @@ def __init__(self, parent=None): # dialog form self.dialog = FormDialog(parent=self, title='Example insert widget') self.addWidgetsToExampleForm(self.dialog) + buttoninsertvertical = QtWidgets.QPushButton() buttoninsertvertical.setText("Insert widget in vertical layout") self.dialog.addSpanningWidget(buttoninsertvertical, 'Button insert vertical') buttoninsertvertical.clicked.connect(lambda: self.insert_vertical()) - # create a FormDockWidget - dock = UIFormWidget.FormDockWidget(parent=self) - dock.setWindowTitle('Example insert widget') - self.addWidgetsToExampleForm(dock) + # # create a FormDockWidget + # dock = UIFormWidget.FormDockWidget(parent=self) + # dock.setWindowTitle('Example insert widget') + # self.addWidgetsToExampleForm(dock) @@ -33,7 +34,7 @@ def __init__(self, parent=None): # create window layout layout = QtWidgets.QHBoxLayout() layout.addWidget(pb) - layout.addWidget(dock) + #layout.addWidget(dock) widg = QtWidgets.QWidget() widg.setLayout(layout) self.setCentralWidget(widg) @@ -49,9 +50,28 @@ def openFormDialog(self): self.dialog.open() - #self.dialog.saveAllWidgetStates() + print('dialog open') + self.dialog.saveAllWidgetStates() #print(self.dialog.formWidget.widget_states) - #self.state1=self.dialog.formWidget.widget_states + + self.state1=self.dialog.formWidget.widget_states + print('state1'+str(self.state1)) + form = self.dialog + qlabel = QtWidgets.QLabel(form) + qlabel.setText("Widget inserted in row 0: ") + qwidget = QtWidgets.QLineEdit(form) + form.insertWidgetToFormLayout(0, 'inserted widget', qwidget, qlabel) + + buttonspanning = QtWidgets.QPushButton(self) + buttonspanning.setText("Spanning widget inserted in row 2") + form.insertWidgetToFormLayout(2, 'inserted spanning widget', buttonspanning) + + #('\nDictionary of widgets after insertion in the form layout:\n' + + # str(form.getWidgets())) + #print("\nDictionary of widget number in the form layout:\n" + str(form.getWidgetNumberDictionary())) + self.dialog.addWidget(QtWidgets.QComboBox(), 'combo', 'combo') + + def addWidgetsToExampleForm(self, form): form.addWidget(QtWidgets.QLineEdit(), "Initial widget row 0: ", 'Initial widget row 0') @@ -65,6 +85,14 @@ def addWidgetsToExampleForm(self, form): buttoninsert.setText("Insert widgets") form.addSpanningWidget(buttoninsert, 'Button insert widgets') buttoninsert.clicked.connect(lambda: self.insert_form(form, buttoninsert)) + + + + + #button.setEnabled(False) + self.dialog.saveAllWidgetStates() + print('widgetstates'+str(self.dialog.formWidget.widget_states)) + self.state2=self.dialog.formWidget.widget_states def insert_vertical(self): self.dialog.insertWidgetToVerticalLayout( @@ -72,8 +100,8 @@ def insert_vertical(self): #print( # "\nThe dictionary of widgets does not change after insertion in the vertical layout.") #self.dialog.getWidget('Button insert vertical').setEnabled(False) - print('state2'+str(self.state2)) - self.dialog.applyWidgetStates(self.state2) + #print('state2'+str(self.state2)) + self.dialog.applyWidgetStates(self.state1) #self.dialog.saveAllWidgetStates() #print(self.dialog.formWidget.widget_states) #print(self.dialog.getWidgets()) @@ -82,10 +110,10 @@ def insert_vertical(self): def insert_form(self, form, button): - qlabel = QtWidgets.QLabel(form) - qlabel.setText("Widget inserted in row 0: ") - qwidget = QtWidgets.QLineEdit(form) - form.insertWidgetToFormLayout(0, 'inserted widget', qwidget, qlabel) + #qlabel = QtWidgets.QLabel(form) + #qlabel.setText("Widget inserted in row 0: ") + #qwidget = QtWidgets.QLineEdit(form) + #form.insertWidgetToFormLayout(0, 'inserted widget', qwidget, qlabel) buttonspanning = QtWidgets.QPushButton(self) buttonspanning.setText("Spanning widget inserted in row 2") diff --git a/test/test__formUI_status_test.py b/test/test__formUI_status_test.py index c3ad46e..73378b0 100644 --- a/test/test__formUI_status_test.py +++ b/test/test__formUI_status_test.py @@ -35,6 +35,7 @@ def exampleState(self): 'pushButton_value': True}] return state + @property def list_all_widgets(self): list_all_widgets = { @@ -539,12 +540,8 @@ def test_saveAllWidgetStates(self): def test_restoreAllSavedWidgetStates(self): """Check that the state of all widgets is restored from the state variable""" - state_to_restore = { - 'checkBox_field': {'value': True, 'enabled': False, 'visible': False}, - 'label_field': {'value': 'applyWidgetStates Test', 'enabled': True, 'visible': False}, - 'checkBox_label': {'value': 'CheckBox Test: ', 'enabled': True, 'visible': False}, - 'label_label': {'value': 'Label Test: ', 'enabled': True, 'visible': False}} - self.simple_form.formWidget.widget_states = state_to_restore + state_to_restore = self.state_simple_form + self.simple_form.formWidget.widget_states = self.state_simple_form self.simple_form.restoreAllSavedWidgetStates() self.assertEqual( @@ -621,12 +618,8 @@ def test_saveAllWidgetStates(self): def test_restoreAllSavedWidgetStates(self): """Check that the state of all widgets is restored from the state variable""" - state_to_restore = { - 'checkBox_field': {'value': True, 'enabled': False, 'visible': False}, - 'label_field': {'value': 'applyWidgetStates Test', 'enabled': True, 'visible': False}, - 'checkBox_label': {'value': 'CheckBox Test: ', 'enabled': True, 'visible': False}, - 'label_label': {'value': 'Label Test: ', 'enabled': True, 'visible': False}} - self.simple_form.widget_states = state_to_restore + state_to_restore = self.state_simple_form + self.simple_form.widget_states = self.state_simple_form self.simple_form.restoreAllSavedWidgetStates() self.assertEqual( @@ -666,8 +659,11 @@ def test_restoreAllSavedWidgetStates(self): state_to_restore['label_label']['visible']) def test_applyWidgetStates_after_remove_and_insert(self): + """Save two states. Checks that the widgets are removed and inserted correctly when the states are applied.""" + # state 1 self.form.saveAllWidgetStates() state1 = self.form.widget_states + # state2 for key in self.list_all_widgets.keys(): qwidget = self.list_all_widgets[key] name = f'{key}_insert' @@ -677,22 +673,14 @@ def test_applyWidgetStates_after_remove_and_insert(self): self.form.saveAllWidgetStates() state2 = self.form.widget_states self.assertNotEqual(state1, state2) + # apply 1 self.form.applyWidgetStates(state1) self.form.saveAllWidgetStates() self.assertEqual(state1, self.form.widget_states) - print(state2) - for key in state2.keys(): - if 'comboBox' in key: - print(key) - for key2 in state2[key].keys(): - if key2 == 'value': - print(type(state2[key][key2])) - if key2 is int: - print(key2) + # apply 2 self.form.applyWidgetStates(state2) - #self.form.saveAllWidgetStates() - #self.assertEqual(state2, self.form.widget_states) - + self.form.saveAllWidgetStates() + self.assertEqual(state2, self.form.widget_states) @skip_ci class FormDockWidgetStateTest(FormsCommonTests, unittest.TestCase): @@ -726,12 +714,8 @@ def test_saveAllWidgetStates(self): def test_restoreAllSavedWidgetStates(self): """Check that the state of all widgets is restored from the state variable""" - state_to_restore = { - 'checkBox_field': {'value': True, 'enabled': False, 'visible': False}, - 'label_field': {'value': 'applyWidgetStates Test', 'enabled': True, 'visible': False}, - 'checkBox_label': {'value': 'CheckBox Test: ', 'enabled': True, 'visible': False}, - 'label_label': {'value': 'Label Test: ', 'enabled': True, 'visible': False}} - self.simple_form.widget().widget_states = state_to_restore + state_to_restore = self.state_simple_form + self.simple_form.widget().widget_states = self.state_simple_form self.simple_form.restoreAllSavedWidgetStates() self.assertEqual( From c93c7d322245e4afe3eb465577f2d6a5cf07c6e4 Mon Sep 17 00:00:00 2001 From: Danica Sugic Date: Fri, 12 Jan 2024 12:17:40 +0000 Subject: [PATCH 60/96] Add test for apply widgets remove and insert --- eqt/ui/FormDialog.py | 4 ++ eqt/ui/UIFormWidget.py | 16 +++++--- examples/insert_widgets_example copy.py | 54 +++++++++++++++++++------ test/test__formUI_status_test.py | 44 +++++++------------- 4 files changed, 70 insertions(+), 48 deletions(-) diff --git a/eqt/ui/FormDialog.py b/eqt/ui/FormDialog.py index 975eac4..54fd352 100644 --- a/eqt/ui/FormDialog.py +++ b/eqt/ui/FormDialog.py @@ -206,6 +206,10 @@ def saveAllWidgetStates(self): ''' self.formWidget.saveAllWidgetStates() + def getWidgetStates(self): + '''Returns the saved widget states.''' + self.formWidget.getWidgetStates() + def restoreAllSavedWidgetStates(self): ''' Restore all widgets in the form to the state saved by `saveAllWidgetStates()`. diff --git a/eqt/ui/UIFormWidget.py b/eqt/ui/UIFormWidget.py index 4a7481d..51b9d21 100644 --- a/eqt/ui/UIFormWidget.py +++ b/eqt/ui/UIFormWidget.py @@ -89,7 +89,6 @@ def insertWidgetToFormLayout(self, row, name, qwidget, qlabel=None): self._addToWidgetNumberDictionary(name, row) self._addToWidgetDictionary(self.default_widgets, name, qwidget, qlabel) self.addToDefaultWidgetStatesDictionary(name) - print("inserted") def _addWidget(self, name, qwidget, qlabel=None): ''' @@ -213,7 +212,7 @@ def removeWidget(self, name): self._popWidgetNumberDictionary(name, widget_number) def getWidget(self, name, role='field'): - '''Returns the Widget by the name with which it has been added + '''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 @@ -467,6 +466,7 @@ def applyWidgetState(self, name, state, role=None): def applyWidgetStates(self, states): ''' + Reorders the states dictionary in order of crescend widget number. Removes the widgets in the form which are not present in the states. If the widgets in the states are not present in the form, they are retrieved from the removed-widgets dictionary and inserted at position @@ -484,6 +484,7 @@ def applyWidgetStates(self, states): ''' # add widgets if necessary + states = dict(sorted(states.items(), key = lambda tup: (tup[1]['widget_number']))) for key, widget_state in states.items(): name, role = self._getNameAndRoleFromKey(key) if key in self.widgets.keys(): @@ -493,17 +494,14 @@ def applyWidgetStates(self, states): if role == 'field': widget_number = states[key]['widget_number'] qwidget = self.removed_widgets_dictionary[key] - print(qwidget) if f'{name}_label' in self.removed_widgets_dictionary.keys(): qlabel = self.removed_widgets_dictionary[f'{name}_label'] - print(qlabel) self.insertWidgetToFormLayout(widget_number, name, qwidget, qlabel) else: self.insertWidgetToFormLayout(widget_number, name, qwidget) else: raise KeyError('No widget associated with the dictionary key `' + key + '`') - self.applyWidgetState(name, widget_state, role) # remove extra widgets set_to_remove = set() @@ -523,6 +521,10 @@ def saveAllWidgetStates(self): ''' self.widget_states = self.getAllWidgetStates() + def getWidgetStates(self): + '''Returns the saved widget states.''' + return self.widget_states + def restoreAllSavedWidgetStates(self): ''' All widgets in the form are restored to the saved states. There are saved states only if @@ -629,6 +631,10 @@ def saveAllWidgetStates(self): ''' self.widget().saveAllWidgetStates() + def getWidgetStates(self): + '''Returns the saved widget states.''' + self.widget().getWidgetStates() + def restoreAllSavedWidgetStates(self): ''' All widgets in the form are restored to the saved states. There are saved states only if diff --git a/examples/insert_widgets_example copy.py b/examples/insert_widgets_example copy.py index 03d8247..29d50dc 100644 --- a/examples/insert_widgets_example copy.py +++ b/examples/insert_widgets_example copy.py @@ -12,15 +12,16 @@ def __init__(self, parent=None): # dialog form self.dialog = FormDialog(parent=self, title='Example insert widget') self.addWidgetsToExampleForm(self.dialog) + buttoninsertvertical = QtWidgets.QPushButton() buttoninsertvertical.setText("Insert widget in vertical layout") self.dialog.addSpanningWidget(buttoninsertvertical, 'Button insert vertical') buttoninsertvertical.clicked.connect(lambda: self.insert_vertical()) - # create a FormDockWidget - dock = UIFormWidget.FormDockWidget(parent=self) - dock.setWindowTitle('Example insert widget') - self.addWidgetsToExampleForm(dock) + # # create a FormDockWidget + # dock = UIFormWidget.FormDockWidget(parent=self) + # dock.setWindowTitle('Example insert widget') + # self.addWidgetsToExampleForm(dock) @@ -33,7 +34,7 @@ def __init__(self, parent=None): # create window layout layout = QtWidgets.QHBoxLayout() layout.addWidget(pb) - layout.addWidget(dock) + #layout.addWidget(dock) widg = QtWidgets.QWidget() widg.setLayout(layout) self.setCentralWidget(widg) @@ -49,9 +50,28 @@ def openFormDialog(self): self.dialog.open() - #self.dialog.saveAllWidgetStates() + print('dialog open') + self.dialog.saveAllWidgetStates() #print(self.dialog.formWidget.widget_states) - #self.state1=self.dialog.formWidget.widget_states + + self.state1=self.dialog.formWidget.widget_states + print('state1'+str(self.state1)) + form = self.dialog + qlabel = QtWidgets.QLabel(form) + qlabel.setText("Widget inserted in row 0: ") + qwidget = QtWidgets.QLineEdit(form) + form.insertWidgetToFormLayout(0, 'inserted widget', qwidget, qlabel) + + buttonspanning = QtWidgets.QPushButton(self) + buttonspanning.setText("Spanning widget inserted in row 2") + form.insertWidgetToFormLayout(2, 'inserted spanning widget', buttonspanning) + + #('\nDictionary of widgets after insertion in the form layout:\n' + + # str(form.getWidgets())) + #print("\nDictionary of widget number in the form layout:\n" + str(form.getWidgetNumberDictionary())) + self.dialog.addWidget(QtWidgets.QComboBox(), 'combo', 'combo') + + def addWidgetsToExampleForm(self, form): form.addWidget(QtWidgets.QLineEdit(), "Initial widget row 0: ", 'Initial widget row 0') @@ -65,6 +85,14 @@ def addWidgetsToExampleForm(self, form): buttoninsert.setText("Insert widgets") form.addSpanningWidget(buttoninsert, 'Button insert widgets') buttoninsert.clicked.connect(lambda: self.insert_form(form, buttoninsert)) + + + + + #button.setEnabled(False) + self.dialog.saveAllWidgetStates() + print('widgetstates'+str(self.dialog.formWidget.widget_states)) + self.state2=self.dialog.formWidget.widget_states def insert_vertical(self): self.dialog.insertWidgetToVerticalLayout( @@ -72,8 +100,8 @@ def insert_vertical(self): #print( # "\nThe dictionary of widgets does not change after insertion in the vertical layout.") #self.dialog.getWidget('Button insert vertical').setEnabled(False) - print('state2'+str(self.state2)) - self.dialog.applyWidgetStates(self.state2) + #print('state2'+str(self.state2)) + self.dialog.applyWidgetStates(self.state1) #self.dialog.saveAllWidgetStates() #print(self.dialog.formWidget.widget_states) #print(self.dialog.getWidgets()) @@ -82,10 +110,10 @@ def insert_vertical(self): def insert_form(self, form, button): - qlabel = QtWidgets.QLabel(form) - qlabel.setText("Widget inserted in row 0: ") - qwidget = QtWidgets.QLineEdit(form) - form.insertWidgetToFormLayout(0, 'inserted widget', qwidget, qlabel) + #qlabel = QtWidgets.QLabel(form) + #qlabel.setText("Widget inserted in row 0: ") + #qwidget = QtWidgets.QLineEdit(form) + #form.insertWidgetToFormLayout(0, 'inserted widget', qwidget, qlabel) buttonspanning = QtWidgets.QPushButton(self) buttonspanning.setText("Spanning widget inserted in row 2") diff --git a/test/test__formUI_status_test.py b/test/test__formUI_status_test.py index c3ad46e..73378b0 100644 --- a/test/test__formUI_status_test.py +++ b/test/test__formUI_status_test.py @@ -35,6 +35,7 @@ def exampleState(self): 'pushButton_value': True}] return state + @property def list_all_widgets(self): list_all_widgets = { @@ -539,12 +540,8 @@ def test_saveAllWidgetStates(self): def test_restoreAllSavedWidgetStates(self): """Check that the state of all widgets is restored from the state variable""" - state_to_restore = { - 'checkBox_field': {'value': True, 'enabled': False, 'visible': False}, - 'label_field': {'value': 'applyWidgetStates Test', 'enabled': True, 'visible': False}, - 'checkBox_label': {'value': 'CheckBox Test: ', 'enabled': True, 'visible': False}, - 'label_label': {'value': 'Label Test: ', 'enabled': True, 'visible': False}} - self.simple_form.formWidget.widget_states = state_to_restore + state_to_restore = self.state_simple_form + self.simple_form.formWidget.widget_states = self.state_simple_form self.simple_form.restoreAllSavedWidgetStates() self.assertEqual( @@ -621,12 +618,8 @@ def test_saveAllWidgetStates(self): def test_restoreAllSavedWidgetStates(self): """Check that the state of all widgets is restored from the state variable""" - state_to_restore = { - 'checkBox_field': {'value': True, 'enabled': False, 'visible': False}, - 'label_field': {'value': 'applyWidgetStates Test', 'enabled': True, 'visible': False}, - 'checkBox_label': {'value': 'CheckBox Test: ', 'enabled': True, 'visible': False}, - 'label_label': {'value': 'Label Test: ', 'enabled': True, 'visible': False}} - self.simple_form.widget_states = state_to_restore + state_to_restore = self.state_simple_form + self.simple_form.widget_states = self.state_simple_form self.simple_form.restoreAllSavedWidgetStates() self.assertEqual( @@ -666,8 +659,11 @@ def test_restoreAllSavedWidgetStates(self): state_to_restore['label_label']['visible']) def test_applyWidgetStates_after_remove_and_insert(self): + """Save two states. Checks that the widgets are removed and inserted correctly when the states are applied.""" + # state 1 self.form.saveAllWidgetStates() state1 = self.form.widget_states + # state2 for key in self.list_all_widgets.keys(): qwidget = self.list_all_widgets[key] name = f'{key}_insert' @@ -677,22 +673,14 @@ def test_applyWidgetStates_after_remove_and_insert(self): self.form.saveAllWidgetStates() state2 = self.form.widget_states self.assertNotEqual(state1, state2) + # apply 1 self.form.applyWidgetStates(state1) self.form.saveAllWidgetStates() self.assertEqual(state1, self.form.widget_states) - print(state2) - for key in state2.keys(): - if 'comboBox' in key: - print(key) - for key2 in state2[key].keys(): - if key2 == 'value': - print(type(state2[key][key2])) - if key2 is int: - print(key2) + # apply 2 self.form.applyWidgetStates(state2) - #self.form.saveAllWidgetStates() - #self.assertEqual(state2, self.form.widget_states) - + self.form.saveAllWidgetStates() + self.assertEqual(state2, self.form.widget_states) @skip_ci class FormDockWidgetStateTest(FormsCommonTests, unittest.TestCase): @@ -726,12 +714,8 @@ def test_saveAllWidgetStates(self): def test_restoreAllSavedWidgetStates(self): """Check that the state of all widgets is restored from the state variable""" - state_to_restore = { - 'checkBox_field': {'value': True, 'enabled': False, 'visible': False}, - 'label_field': {'value': 'applyWidgetStates Test', 'enabled': True, 'visible': False}, - 'checkBox_label': {'value': 'CheckBox Test: ', 'enabled': True, 'visible': False}, - 'label_label': {'value': 'Label Test: ', 'enabled': True, 'visible': False}} - self.simple_form.widget().widget_states = state_to_restore + state_to_restore = self.state_simple_form + self.simple_form.widget().widget_states = self.state_simple_form self.simple_form.restoreAllSavedWidgetStates() self.assertEqual( From 37156a758b3dfc71c127c70eacece58bd7b2a87b Mon Sep 17 00:00:00 2001 From: Danica Sugic Date: Fri, 12 Jan 2024 14:27:25 +0000 Subject: [PATCH 61/96] Delete extra example --- examples/insert_widgets_example copy.py | 154 ------------------------ 1 file changed, 154 deletions(-) delete mode 100644 examples/insert_widgets_example copy.py diff --git a/examples/insert_widgets_example copy.py b/examples/insert_widgets_example copy.py deleted file mode 100644 index 29d50dc..0000000 --- a/examples/insert_widgets_example copy.py +++ /dev/null @@ -1,154 +0,0 @@ -import sys - -from PySide2 import QtWidgets - -from eqt.ui import FormDialog, UIFormWidget - - -class MainUI(QtWidgets.QMainWindow): - def __init__(self, parent=None): - QtWidgets.QMainWindow.__init__(self, parent) - - # dialog form - self.dialog = FormDialog(parent=self, title='Example insert widget') - self.addWidgetsToExampleForm(self.dialog) - - buttoninsertvertical = QtWidgets.QPushButton() - buttoninsertvertical.setText("Insert widget in vertical layout") - self.dialog.addSpanningWidget(buttoninsertvertical, 'Button insert vertical') - buttoninsertvertical.clicked.connect(lambda: self.insert_vertical()) - - # # create a FormDockWidget - # dock = UIFormWidget.FormDockWidget(parent=self) - # dock.setWindowTitle('Example insert widget') - # self.addWidgetsToExampleForm(dock) - - - - - # create button for Form Dialog - pb = QtWidgets.QPushButton(self) - pb.setText("Open Form Dialog") - pb.clicked.connect(lambda: self.openFormDialog()) - - # create window layout - layout = QtWidgets.QHBoxLayout() - layout.addWidget(pb) - #layout.addWidget(dock) - widg = QtWidgets.QWidget() - widg.setLayout(layout) - self.setCentralWidget(widg) - - # print dictionary of all widgets in dock - #print("\nDictionary of widgets in the Form Dock Widget:\n" + str(dock.getWidgets())) - - self.dialog.onCancel = self.onCancel - - self.show() - - def openFormDialog(self): - - - self.dialog.open() - print('dialog open') - self.dialog.saveAllWidgetStates() - #print(self.dialog.formWidget.widget_states) - - self.state1=self.dialog.formWidget.widget_states - print('state1'+str(self.state1)) - form = self.dialog - qlabel = QtWidgets.QLabel(form) - qlabel.setText("Widget inserted in row 0: ") - qwidget = QtWidgets.QLineEdit(form) - form.insertWidgetToFormLayout(0, 'inserted widget', qwidget, qlabel) - - buttonspanning = QtWidgets.QPushButton(self) - buttonspanning.setText("Spanning widget inserted in row 2") - form.insertWidgetToFormLayout(2, 'inserted spanning widget', buttonspanning) - - #('\nDictionary of widgets after insertion in the form layout:\n' + - # str(form.getWidgets())) - #print("\nDictionary of widget number in the form layout:\n" + str(form.getWidgetNumberDictionary())) - self.dialog.addWidget(QtWidgets.QComboBox(), 'combo', 'combo') - - - - def addWidgetsToExampleForm(self, form): - form.addWidget(QtWidgets.QLineEdit(), "Initial widget row 0: ", 'Initial widget row 0') - form.addSpanningWidget(QtWidgets.QLabel("Initial widget row 1"), 'Initial widget row 1') - # add QComboBox - qwidget = QtWidgets.QComboBox(form) - qwidget.addItem("0") - qwidget.addItem("1") - form.addWidget(qwidget, "Initial widget row 2", 'Initial widget row 2') - buttoninsert = QtWidgets.QPushButton() - buttoninsert.setText("Insert widgets") - form.addSpanningWidget(buttoninsert, 'Button insert widgets') - buttoninsert.clicked.connect(lambda: self.insert_form(form, buttoninsert)) - - - - - #button.setEnabled(False) - self.dialog.saveAllWidgetStates() - print('widgetstates'+str(self.dialog.formWidget.widget_states)) - self.state2=self.dialog.formWidget.widget_states - - def insert_vertical(self): - self.dialog.insertWidgetToVerticalLayout( - 1, QtWidgets.QPushButton("Inserted widget in vertical layout")) - #print( - # "\nThe dictionary of widgets does not change after insertion in the vertical layout.") - #self.dialog.getWidget('Button insert vertical').setEnabled(False) - #print('state2'+str(self.state2)) - self.dialog.applyWidgetStates(self.state1) - #self.dialog.saveAllWidgetStates() - #print(self.dialog.formWidget.widget_states) - #print(self.dialog.getWidgets()) - #print('removed2'+str(self.dialog.formWidget.getRemovedWidgets())) - - - - def insert_form(self, form, button): - #qlabel = QtWidgets.QLabel(form) - #qlabel.setText("Widget inserted in row 0: ") - #qwidget = QtWidgets.QLineEdit(form) - #form.insertWidgetToFormLayout(0, 'inserted widget', qwidget, qlabel) - - buttonspanning = QtWidgets.QPushButton(self) - buttonspanning.setText("Spanning widget inserted in row 2") - form.insertWidgetToFormLayout(2, 'inserted spanning widget', buttonspanning) - - #('\nDictionary of widgets after insertion in the form layout:\n' + - # str(form.getWidgets())) - #print("\nDictionary of widget number in the form layout:\n" + str(form.getWidgetNumberDictionary())) - self.dialog.addWidget(QtWidgets.QComboBox(), 'combo', 'combo') - - button.setEnabled(False) - self.dialog.saveAllWidgetStates() - print('widgetstates'+str(self.dialog.formWidget.widget_states)) - self.state2=self.dialog.formWidget.widget_states - #print(self.state2) - #print('state1'+str(self.state1)) - - #print(self.dialog.getWidgets()) - - #self.dialog.applyWidgetStates(self.state1) - #print(self.dialog.formWidget.getRemovedWidgets()) - #print(self.dialog.getWidgets()) - - - def onCancel(self): - if not hasattr(self.dialog.formWidget, 'widget_states'): - if self.dialog.getWidget('Button insert widgets').isEnabled() == False: - self.dialog.formWidget._popWidgetFromDictionary(self.dialog.formWidget.default_widget_states,'inserted widget') - self.dialog.formWidget._popWidgetFromDictionary(self.dialog.formWidget.default_widget_states,'inserted spanning widget') - if self.dialog.getWidget('Button insert vertical').isEnabled() == False: - self.dialog.removeWidgetFromVerticalLayout(self.dialog.getWidgetFromVerticalLayout(1)) - -if __name__ == "__main__": - app = QtWidgets.QApplication(sys.argv) - - window = MainUI() - - sys.exit(app.exec_()) From a098fc925ec5fde6c936fbb7174f21b77b555d07 Mon Sep 17 00:00:00 2001 From: Danica Sugic Date: Thu, 18 Jan 2024 10:41:04 +0000 Subject: [PATCH 62/96] Change applywidgetstates and add adaptFormToStates --- eqt/ui/UIFormWidget.py | 22 +++++++++++++++++++++- test/test__formUI_status_test.py | 8 ++++---- 2 files changed, 25 insertions(+), 5 deletions(-) diff --git a/eqt/ui/UIFormWidget.py b/eqt/ui/UIFormWidget.py index f15f775..b0bbed3 100644 --- a/eqt/ui/UIFormWidget.py +++ b/eqt/ui/UIFormWidget.py @@ -465,6 +465,27 @@ def applyWidgetState(self, name, state, role=None): self.widget_number_dictionary[name] = value def applyWidgetStates(self, states): + ''' + Applies the given states to the form's widgets. + This assumes the states in the form and the widgets in the states have the same name. + If this is false, it raises an error. + + Parameters + ---------- + states: nested_dict Reorders the states dictionary in ascending widget number. + Format: {'name_field': {'value': str | bool | int, 'enabled': bool, 'visible': bool, 'widget_number' : int}, + 'name_label': {'value': str | bool | int, 'enabled': bool, 'visible': bool, 'widget_number' : int}, ...}, + e.g. {{'widget1': {'value': 1, 'enabled': True, 'visible': True, 'widget_number' : 0}, + 'widget2': {'value': 2, 'enabled': False, 'visible': False, 'widget_number' : 1}}. + ''' + if self.widgets.keys() == states.keys(): + for key, widget_state in states.items(): + name, role = self._getNameAndRoleFromKey(key) + self.applyWidgetState(name, widget_state, role) + else: + raise KeyError(f'The widgets in the form are {self.widgets.keys()} whereas the widgets in the states are {states.keys()}. These must be equal for the states to be applied to the form.') + + def adaptFormToStates(self, states): ''' Reorders the states dictionary in ascending widget number. Removes the widgets in the form which are not present in the states. @@ -513,7 +534,6 @@ def applyWidgetStates(self, states): for el in set_to_remove: self.removeWidget(el) - def saveAllWidgetStates(self): ''' Saves the state of all widgets currently present in the form. diff --git a/test/test__formUI_status_test.py b/test/test__formUI_status_test.py index 73378b0..5231618 100644 --- a/test/test__formUI_status_test.py +++ b/test/test__formUI_status_test.py @@ -658,8 +658,8 @@ def test_restoreAllSavedWidgetStates(self): self.simple_form.getWidget('label', 'label').isVisible(), state_to_restore['label_label']['visible']) - def test_applyWidgetStates_after_remove_and_insert(self): - """Save two states. Checks that the widgets are removed and inserted correctly when the states are applied.""" + def test_adaptFormToStates_after_remove_and_insert(self): + """Saves two states. Checks that the widgets are removed and inserted correctly when the states are applied.""" # state 1 self.form.saveAllWidgetStates() state1 = self.form.widget_states @@ -674,11 +674,11 @@ def test_applyWidgetStates_after_remove_and_insert(self): state2 = self.form.widget_states self.assertNotEqual(state1, state2) # apply 1 - self.form.applyWidgetStates(state1) + self.form.adaptFormToStates(state1) self.form.saveAllWidgetStates() self.assertEqual(state1, self.form.widget_states) # apply 2 - self.form.applyWidgetStates(state2) + self.form.adaptFormToStates(state2) self.form.saveAllWidgetStates() self.assertEqual(state2, self.form.widget_states) From 918fa26087103cbf806aeaa3f5b13482d89ec27a Mon Sep 17 00:00:00 2001 From: Danica Sugic Date: Thu, 18 Jan 2024 11:51:25 +0000 Subject: [PATCH 63/96] Change example insert widget with adaptFormToStates --- examples/insert_widgets_example.py | 24 ++++++------------------ 1 file changed, 6 insertions(+), 18 deletions(-) diff --git a/examples/insert_widgets_example.py b/examples/insert_widgets_example.py index 8810409..9b0758d 100644 --- a/examples/insert_widgets_example.py +++ b/examples/insert_widgets_example.py @@ -10,7 +10,7 @@ def __init__(self, parent=None): QtWidgets.QMainWindow.__init__(self, parent) # dialog form - self.dialog = FormDialog(parent=self, title='Example insert widget') + self.dialog = FormDialog(parent=self, title='Form Dialog example insert widget') self.addWidgetsToExampleForm(self.dialog) buttoninsertvertical = QtWidgets.QPushButton() buttoninsertvertical.setText("Insert widget in vertical layout") @@ -19,12 +19,9 @@ def __init__(self, parent=None): # create a FormDockWidget dock = UIFormWidget.FormDockWidget(parent=self) - dock.setWindowTitle('Example insert widget') + dock.setWindowTitle('Dock Widget Example insert widget') self.addWidgetsToExampleForm(dock) - - - # create button for Form Dialog pb = QtWidgets.QPushButton(self) pb.setText("Open Form Dialog") @@ -38,19 +35,10 @@ def __init__(self, parent=None): widg.setLayout(layout) self.setCentralWidget(widg) - # print dictionary of all widgets in dock - #print("\nDictionary of widgets in the Form Dock Widget:\n" + str(dock.getWidgets())) - self.dialog.onCancel = self.onCancel - self.show() def openFormDialog(self): - - # print dictionary of all widgets in dialog - #print("\nDictionary of widgets in Form Dialog:\n" + str(self.dialog.getWidgets())) - #print("\nDictionary of widget number in Form Dialog:\n" + str(self.dialog.getWidgetNumberDictionary())) - self.dialog.open() def addWidgetsToExampleForm(self, form): @@ -78,11 +66,9 @@ def insert_form(self, form, button): qlabel.setText("Widget inserted in row 0: ") qwidget = QtWidgets.QLineEdit(form) form.insertWidgetToFormLayout(0, 'inserted widget', qwidget, qlabel) - buttonspanning = QtWidgets.QPushButton(self) buttonspanning.setText("Spanning widget inserted in row 2") form.insertWidgetToFormLayout(2, 'inserted spanning widget', buttonspanning) - print('\nDictionary of widgets after insertion in the form layout:\n' + str(form.getWidgets())) print("\nDictionary of widget number in the form layout:\n" + str(form.getWidgetNumberDictionary())) @@ -90,11 +76,13 @@ def insert_form(self, form, button): def onCancel(self): if not hasattr(self.dialog.formWidget, 'widget_states'): + if self.dialog.getWidget('Button insert vertical').isEnabled() == False: + self.dialog.removeWidgetFromVerticalLayout(self.dialog.getWidgetFromVerticalLayout(1)) if self.dialog.getWidget('Button insert widgets').isEnabled() == False: self.dialog.formWidget._popWidgetFromDictionary(self.dialog.formWidget.default_widget_states,'inserted widget') self.dialog.formWidget._popWidgetFromDictionary(self.dialog.formWidget.default_widget_states,'inserted spanning widget') - if self.dialog.getWidget('Button insert vertical').isEnabled() == False: - self.dialog.removeWidgetFromVerticalLayout(self.dialog.getWidgetFromVerticalLayout(1)) + self.dialog.formWidget.adaptFormToStates(self.dialog.formWidget.default_widget_states) + if __name__ == "__main__": app = QtWidgets.QApplication(sys.argv) From 7a9776ed3963fe69d93eb47346805bb62ac54278 Mon Sep 17 00:00:00 2001 From: Danica Sugic Date: Fri, 19 Jan 2024 17:36:23 +0000 Subject: [PATCH 64/96] Add advanced dialog to form dialog and its example file --- eqt/ui/FormDialog.py | 76 ++++++++++++++++++++++++++++- eqt/ui/UIFormWidget.py | 25 ++++++---- examples/advanced_dialog_example.py | 68 ++++++++++++++++++++++++++ test/test__formUI_status_test.py | 2 - 4 files changed, 159 insertions(+), 12 deletions(-) create mode 100644 examples/advanced_dialog_example.py diff --git a/eqt/ui/FormDialog.py b/eqt/ui/FormDialog.py index 54fd352..3a17e8d 100644 --- a/eqt/ui/FormDialog.py +++ b/eqt/ui/FormDialog.py @@ -208,7 +208,11 @@ def saveAllWidgetStates(self): def getWidgetStates(self): '''Returns the saved widget states.''' - self.formWidget.getWidgetStates() + return self.formWidget.getWidgetStates() + + def getDefaultWidgetStates(self): + '''Returns the saved default widget states.''' + return self.formWidget.getDefaultWidgetStates() def restoreAllSavedWidgetStates(self): ''' @@ -282,3 +286,73 @@ def applyWidgetStates(self, state): 'widget2': {'value': 2, 'enabled': False, 'visible': False, 'widget_number' : 1}}. ''' return self.formWidget.applyWidgetStates(state) + +class AdvancedFormDialog(FormDialog): + def __init__(self, parent=None, title=None): + "Creates a form dialog. Adds default button to the vertical layout.""" + if parent is None: + print("parent is actually none") + if parent is not None: + self.dialog_parent = parent + self.display_on_parent_dict = {} + print(parent) + FormDialog.__init__(self, parent, title) + + # add default button to vertical layout + button_default = QtWidgets.QPushButton("Set default values") + self.insertWidgetToVerticalLayout(1, button_default) + button_default.clicked.connect(lambda: self.setDefaultValues()) + + 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`''' + self.saveAllWidgetStates() + self.onOk() + self.formWidget.setDefaultWidgetStatesVisibleTrue() + self.close() + + if hasattr(self, 'display_on_parent_dict'): + if self.getWidgetStates() == self.getDefaultWidgetStates(): + self.removeWidgetsFromParent() + else: + self.addWidgetsToParent() + + def addWidgetsToParent(self): + for name in self.display_on_parent_dict.keys(): + print(name) + value = str(self.getWidgetStates()[f'{name}_field']['value']) + label = str(self.getWidgetStates()[f'{name}_label']['value']) + if f'{name}_field' not in self.dialog_parent.getWidgets(): + self.dialog_parent.insertWidgetToFormLayout(-1, name, QtWidgets.QLabel(value), label) + else: + self.dialog_parent.getWidget(name, 'field').setText(value) + + def removeWidgetsFromParent(self): + for name in self.display_on_parent_dict.keys(): + 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): + 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.""" + if not hasattr(self, 'dialog_parent'): + raise KeyError('''The advanced-dialog-form parent is None. + Set the parent if you want to add widgets to it.''') + self.display_on_parent_dict[name] = None + + def getDisplayOnParentSet(self): + return self.display_on_parent_dict + + diff --git a/eqt/ui/UIFormWidget.py b/eqt/ui/UIFormWidget.py index b0bbed3..8bd55d1 100644 --- a/eqt/ui/UIFormWidget.py +++ b/eqt/ui/UIFormWidget.py @@ -71,7 +71,6 @@ def insertWidgetToFormLayout(self, row, name, qwidget, qlabel=None): qwidget: qwidget qlabel: qlabel widget or str ''' - if f'{name}_field' in self.widgets.keys(): raise ValueError(f'The name of widget you are trying to insert, {name}, is used already. Choose another name.') @@ -478,13 +477,13 @@ def applyWidgetStates(self, states): e.g. {{'widget1': {'value': 1, 'enabled': True, 'visible': True, 'widget_number' : 0}, 'widget2': {'value': 2, 'enabled': False, 'visible': False, 'widget_number' : 1}}. ''' - if self.widgets.keys() == states.keys(): - for key, widget_state in states.items(): - name, role = self._getNameAndRoleFromKey(key) - self.applyWidgetState(name, widget_state, role) - else: - raise KeyError(f'The widgets in the form are {self.widgets.keys()} whereas the widgets in the states are {states.keys()}. These must be equal for the states to be applied to the form.') - + if self.widgets.keys() != states.keys(): + raise KeyError(f'''The widgets in the form are {self.widgets.keys()} whereas the widgets in the states are {states.keys()}. + These must be equal for the states to be applied to the form.''') + for key, widget_state in states.items(): + name, role = self._getNameAndRoleFromKey(key) + self.applyWidgetState(name, widget_state, role) + def adaptFormToStates(self, states): ''' Reorders the states dictionary in ascending widget number. @@ -544,6 +543,10 @@ def saveAllWidgetStates(self): def getWidgetStates(self): '''Returns the saved widget states.''' return self.widget_states + + def getDefaultWidgetStates(self): + '''Returns the saved default widget states.''' + return self.default_widget_states def restoreAllSavedWidgetStates(self): ''' @@ -653,7 +656,11 @@ def saveAllWidgetStates(self): def getWidgetStates(self): '''Returns the saved widget states.''' - self.widget().getWidgetStates() + return self.widget().getWidgetStates() + + def getDefaultWidgetStates(self): + '''Returns the saved default widget states.''' + return self.widget().getDefaultWidgetStates() def restoreAllSavedWidgetStates(self): ''' diff --git a/examples/advanced_dialog_example.py b/examples/advanced_dialog_example.py new file mode 100644 index 0000000..92747ba --- /dev/null +++ b/examples/advanced_dialog_example.py @@ -0,0 +1,68 @@ +import sys + +from PySide2 import QtWidgets + +from eqt.ui.FormDialog import AdvancedFormDialog +from eqt.ui.UIFormWidget import FormWidget + + +class FormExample(FormWidget): + def __init__(self, parent=None): + FormWidget.__init__(self, parent) + + pb = QtWidgets.QPushButton(self) + pb.setText("Open Advanced Dialog with form layout") + pb.clicked.connect(lambda: self.openFormDialog()) + self.addSpanningWidget(pb, 'buttadv') + #dialog = AdvancedFormDialog(parent=self, title='Example') + dialog = AdvancedFormDialog(parent=None, title='Example') + + dialog.Ok.clicked.connect(lambda: self.accepted()) + # Example on how to add elements to the FormDialog + # add input 1 as QLineEdit + qlabel = QtWidgets.QLabel(dialog.groupBox) + qlabel.setText("Input 1: ") + qwidget = QtWidgets.QLineEdit(dialog.groupBox) + qwidget.setClearButtonEnabled(True) + # finally add to the form widget + dialog.insertWidgetToFormLayout(0, 'input_title', QtWidgets.QLabel("Input Values: ")) + dialog.insertWidgetToFormLayout(1, 'input1', qwidget, qlabel) + dialog.addToDictionaryDisplayOnParent('input1') + + # add input 2 as QComboBox + qlabel = QtWidgets.QLabel(dialog.groupBox) + qlabel.setText("Input 2: ") + qwidget = QtWidgets.QComboBox(dialog.groupBox) + qwidget.addItem("option 1") + qwidget.addItem("option 2") + qwidget.setCurrentIndex(0) + qwidget.setEnabled(True) + # finally add to the form widget + dialog.addWidget(qwidget, qlabel, 'input2') + dialog.addToDictionaryDisplayOnParent('input2') + print(dialog.getDisplayOnParentSet()) + dialog.addWidget(QtWidgets.QLabel("Example Vertical Layout Text"), layout="vertical") + + # store a reference + self.dialog = dialog + self.dialog.onCancel = self.rejected + self.show() + + def openFormDialog(self): + self.dialog.exec() + + def accepted(self): + print(self.dialog.widgets['input1_field'].text()) + print(self.dialog.widgets['input2_field'].currentText()) + self.dialog.close() + + def rejected(self): + print("rejected") + + +if __name__ == "__main__": + app = QtWidgets.QApplication(sys.argv) + + window = FormExample() + + sys.exit(app.exec_()) diff --git a/test/test__formUI_status_test.py b/test/test__formUI_status_test.py index 5231618..b009f3b 100644 --- a/test/test__formUI_status_test.py +++ b/test/test__formUI_status_test.py @@ -35,7 +35,6 @@ def exampleState(self): 'pushButton_value': True}] return state - @property def list_all_widgets(self): list_all_widgets = { @@ -580,7 +579,6 @@ def test_restoreAllSavedWidgetStates(self): self.simple_form.getWidget('label', 'label').isVisible(), state_to_restore['label_label']['visible']) - @skip_ci class FormWidgetStateTest(FormsCommonTests, unittest.TestCase): def setUp(self): From cd7559b2076ee8629441a955f4902bed742a4d27 Mon Sep 17 00:00:00 2001 From: Danica Sugic Date: Fri, 19 Jan 2024 18:17:15 +0000 Subject: [PATCH 65/96] Add button argument to advanced dialog --- eqt/ui/FormDialog.py | 26 +++++++++++++++++++------- examples/advanced_dialog_example.py | 6 ++++-- 2 files changed, 23 insertions(+), 9 deletions(-) diff --git a/eqt/ui/FormDialog.py b/eqt/ui/FormDialog.py index 3a17e8d..8300c0e 100644 --- a/eqt/ui/FormDialog.py +++ b/eqt/ui/FormDialog.py @@ -288,16 +288,21 @@ def applyWidgetStates(self, state): return self.formWidget.applyWidgetStates(state) class AdvancedFormDialog(FormDialog): - def __init__(self, parent=None, title=None): - "Creates a form dialog. Adds default button to the vertical layout.""" - if parent is None: - print("parent is actually none") + def __init__(self, parent = None, title = None, button_name = None): + """Creates a form dialog. Adds default button to the vertical layout. + + Parameters + -------------------- + button_name : 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 = {} - print(parent) + if button_name is not None: + self.button_widget_number = self.dialog_parent.getWidgetNumber(button_name) FormDialog.__init__(self, parent, title) + + # add default button to vertical layout button_default = QtWidgets.QPushButton("Set default values") self.insertWidgetToVerticalLayout(1, button_default) @@ -321,12 +326,19 @@ def _onOk(self): self.addWidgetsToParent() def addWidgetsToParent(self): + i = 0 for name in self.display_on_parent_dict.keys(): + i += 1 + if hasattr(self, 'button_widget_number'): + widget_number = self.button_widget_number + i + else: + widget_number = - 1 + print(name) value = str(self.getWidgetStates()[f'{name}_field']['value']) label = str(self.getWidgetStates()[f'{name}_label']['value']) if f'{name}_field' not in self.dialog_parent.getWidgets(): - self.dialog_parent.insertWidgetToFormLayout(-1, name, QtWidgets.QLabel(value), label) + self.dialog_parent.insertWidgetToFormLayout(widget_number, name, QtWidgets.QLabel(value), label) else: self.dialog_parent.getWidget(name, 'field').setText(value) @@ -352,7 +364,7 @@ def addToDictionaryDisplayOnParent(self, name): Set the parent if you want to add widgets to it.''') self.display_on_parent_dict[name] = None - def getDisplayOnParentSet(self): + def getDisplayOnParentDictionary(self): return self.display_on_parent_dict diff --git a/examples/advanced_dialog_example.py b/examples/advanced_dialog_example.py index 92747ba..16b653c 100644 --- a/examples/advanced_dialog_example.py +++ b/examples/advanced_dialog_example.py @@ -14,8 +14,11 @@ def __init__(self, parent=None): pb.setText("Open Advanced Dialog with form layout") 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=None, title='Example') + dialog = AdvancedFormDialog(parent=self, title='Example', button_name = 'buttadv') dialog.Ok.clicked.connect(lambda: self.accepted()) # Example on how to add elements to the FormDialog @@ -40,7 +43,6 @@ def __init__(self, parent=None): # finally add to the form widget dialog.addWidget(qwidget, qlabel, 'input2') dialog.addToDictionaryDisplayOnParent('input2') - print(dialog.getDisplayOnParentSet()) dialog.addWidget(QtWidgets.QLabel("Example Vertical Layout Text"), layout="vertical") # store a reference From b63bf36837942aa956fa88b0c8a944a89550bf49 Mon Sep 17 00:00:00 2001 From: Danica Sugic Date: Mon, 22 Jan 2024 13:24:11 +0000 Subject: [PATCH 66/96] Improve docstrings and other minor things --- eqt/ui/FormDialog.py | 139 +++++------------------ eqt/ui/UIFormWidget.py | 168 ++++++++++++---------------- examples/advanced_dialog_example.py | 70 ------------ test/test__formUI_status_test.py | 49 +------- 4 files changed, 101 insertions(+), 325 deletions(-) delete mode 100644 examples/advanced_dialog_example.py diff --git a/eqt/ui/FormDialog.py b/eqt/ui/FormDialog.py index 8300c0e..358e843 100644 --- a/eqt/ui/FormDialog.py +++ b/eqt/ui/FormDialog.py @@ -28,16 +28,16 @@ def __init__(self, parent=None, title=None): @property def Ok(self): - '''Returns a reference to the Dialog Ok button to connect its signals''' + '''Returns a reference to the Dialog Ok button to connect its signals.''' return self.buttonBox.button(QtWidgets.QDialogButtonBox.Ok) @property def Cancel(self): - '''Returns a reference to the Dialog Cancel button to connect its signals''' + '''Returns a reference to the Dialog Cancel button to connect its signals.''' return self.buttonBox.button(QtWidgets.QDialogButtonBox.Cancel) def _onOk(self): - '''Saves the widget states and calls `onOk`''' + '''Saves the widget states and calls `onOk`.''' self.saveAllWidgetStates() self.onOk() self.close() @@ -51,7 +51,7 @@ def _onCancel(self): def onOk(self): '''Called when the dialog's "Ok" button is clicked. - Can be redefined to add additional functionality on "Ok"''' + Can be redefined to add additional functionality on "Ok".''' pass def onCancel(self): @@ -69,10 +69,12 @@ def groupBox(self): def addWidget(self, qwidget, qlabel=None, name=None, layout='form'): ''' - Adds a qwidget (and a qlabel widget) in the (same row of the) layout. - layout = 'form' - adds to the FormLayout layout = 'vertical' - adds to the Vertical layout below the form. - To add to the form layout, qlabel and name must be passed. + `qlabel` and `name` are unsupported when layout is vertical. + + layout = 'form' - adds to the FormLayout + Name and qlabel must be passed to add to the form layout . + Adds a qwidget and a qlabel widget in the same row of the form layout. ''' if layout == 'vertical': if name is not None or qlabel is not None: @@ -89,7 +91,7 @@ def addWidget(self, qwidget, qlabel=None, name=None, layout='form'): def addSpanningWidget(self, qwidget, name=None, layout='form'): ''' - Adds a spanning qwidget occupying the full row in the layout. + Adds a spanning widget occupying the full row in the layout. layout = 'form' - adds the widget to the FormLayout layout = 'vertical' - adds the widget to the Vertical layout below the form. To add to the form layout, name must be passed. @@ -108,10 +110,9 @@ def addSpanningWidget(self, qwidget, name=None, layout='form'): def insertWidgetToFormLayout(self, row, name, qwidget, qlabel=None): ''' - Inserts a widget and a label widget, or a spanning widget if 'qlabel' is None, to the form layout, `groupBoxFormLayout`, + Inserts a widget and a label widget, or a spanning widget if 'qlabel' is None, to the form layout in the position specified by row. If row is out of bounds, the widget is added at the end. - It adds to the widget dictionary and the default states - dictionary. + It adds to the widget dictionary, the widget number dictionary, and the default widget states dictionary. Parameters: ---------- @@ -136,12 +137,14 @@ def removeWidgetFromVerticalLayout(self, qwidget): qwidget.setParent(None) def getWidgetFromVerticalLayout(self, index): + ''' + Returns the widget in the vertical layout located at position index.''' return self.formWidget.uiElements['verticalLayout'].itemAt(index).widget() def removeWidget(self, name): ''' If not present already, creates a dictionary to store the removed qwidgets. - Sets the parent of the qwidget (and qlabel if present) to `None` and + Sets the parent of the qwidget, and qlabel if present, to `None` and stores the widgets in the removed-widgets dictionary. Deletes the row in the form layout. Deletes the qwidget and qlabel from the widgets dictionary. @@ -161,11 +164,10 @@ def getNumWidgets(self): return self.formWidget.getNumWidgets() def getWidget(self, name, role='field'): - '''Returns the Widget by the name with which it has been added - + ''' + 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 - + The user can get the label by specifying the role to be label. Raises ValueError if the role is not field or label. ''' return self.formWidget.getWidget(name, role) @@ -182,7 +184,6 @@ def getWidgetNumber(self, name): '''Returns the widget number by the widget name.''' return self.formWidget.getWidgetNumber(name) - def getWidgetNumberDictionary(self): '''Returns the widget number dictionary.''' return self.formWidget.getWidgetNumberDictionary() @@ -201,7 +202,7 @@ def setWidgetVisible(self, name, visible): def saveAllWidgetStates(self): ''' - Saves the state of all widgets in the form. + Saves the state of all widgets currently present in the form. To later restore the states, use `restoreAllSavedWidgetStates()`. ''' self.formWidget.saveAllWidgetStates() @@ -225,16 +226,18 @@ def getAllWidgetStates(self): ''' Returns ------- - states: dict - Format: {'widget_name': {'value': str | bool | int, 'enabled': bool, 'visible': bool}, + dict + Format: {'widget_name': {'value': str | bool | int, 'enabled': bool, 'visible': bool, 'widget_number': int}, ...}, - e.g. {{'widget1': {'value': 1, 'enabled': True, 'visible': True}, - 'widget2': {'value': 2, 'enabled': False, 'visible': False}}. + e.g. {{'widget1': {'value': 1, 'enabled': True, 'visible': True, 'widget_number': 0}, + 'widget2': {'value': 2, 'enabled': False, 'visible': False, 'widget_number': 1}}. ''' return self.formWidget.getAllWidgetStates() def getWidgetState(self, widget, role=None): ''' + Returns the current state of the widget in the form. + Parameters ---------- widget: QWidget or str @@ -270,16 +273,13 @@ def applyWidgetState(self, name, state, role=None): def applyWidgetStates(self, state): ''' - Removes the widgets in the form which are not present in the states. - If the widgets in the states are not present in the form, - they are retrieved from the removed-widgets dictionary and inserted at position - given by the widget number recorded in the states. An error is raised when the - widget in thet state is not in the form nor in the removed widgets. - Applies the given states to the form's widgets. - + Applies the given states to the form's widgets. + This assumes the states in the form and the widgets in the states have the same name. + If this is false, it raises an error. + Parameters ---------- - states: nested_dict + states: nested_dict Format: {'name_field': {'value': str | bool | int, 'enabled': bool, 'visible': bool, 'widget_number' : int}, 'name_label': {'value': str | bool | int, 'enabled': bool, 'visible': bool, 'widget_number' : int}, ...}, e.g. {{'widget1': {'value': 1, 'enabled': True, 'visible': True, 'widget_number' : 0}, @@ -287,84 +287,5 @@ def applyWidgetStates(self, state): ''' return self.formWidget.applyWidgetStates(state) -class AdvancedFormDialog(FormDialog): - def __init__(self, parent = None, title = None, button_name = None): - """Creates a form dialog. Adds default button to the vertical layout. - Parameters - -------------------- - button_name : 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_number = self.dialog_parent.getWidgetNumber(button_name) - FormDialog.__init__(self, parent, title) - - - - # add default button to vertical layout - button_default = QtWidgets.QPushButton("Set default values") - self.insertWidgetToVerticalLayout(1, button_default) - button_default.clicked.connect(lambda: self.setDefaultValues()) - - 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`''' - self.saveAllWidgetStates() - self.onOk() - self.formWidget.setDefaultWidgetStatesVisibleTrue() - self.close() - - if hasattr(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_number'): - widget_number = self.button_widget_number + i - else: - widget_number = - 1 - - print(name) - value = str(self.getWidgetStates()[f'{name}_field']['value']) - label = str(self.getWidgetStates()[f'{name}_label']['value']) - if f'{name}_field' not in self.dialog_parent.getWidgets(): - self.dialog_parent.insertWidgetToFormLayout(widget_number, name, QtWidgets.QLabel(value), label) - else: - self.dialog_parent.getWidget(name, 'field').setText(value) - - def removeWidgetsFromParent(self): - for name in self.display_on_parent_dict.keys(): - 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): - 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.""" - if not hasattr(self, 'dialog_parent'): - raise KeyError('''The advanced-dialog-form 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 - diff --git a/eqt/ui/UIFormWidget.py b/eqt/ui/UIFormWidget.py index 8bd55d1..f5ae760 100644 --- a/eqt/ui/UIFormWidget.py +++ b/eqt/ui/UIFormWidget.py @@ -47,7 +47,6 @@ def createForm(self): 'verticalLayout': verticalLayout, 'groupBox': groupBox, 'groupBoxFormLayout': groupBoxFormLayout} self.widgets = {} - self.default_widgets = {} @property def num_widgets(self): @@ -59,10 +58,9 @@ def groupBox(self): def insertWidgetToFormLayout(self, row, name, qwidget, qlabel=None): ''' - Inserts a widget and a label widget , or a spanning widget if 'qlabel' is None, to the form layout - in the position specified by row. If row is out of bounds, the widget is added at the end. - If 'name' is already in use, it raises an error. - It adds to the widget dictionary and the default states dictionary. + Inserts a widget and a label widget, or a spanning widget if 'qlabel' is None, to the form layout + in the position specified by row. If row is out of bounds, the widget is added at the end. + It adds to the widget dictionary, the widget number dictionary, and the default widget states dictionary. Parameters: ---------- @@ -86,13 +84,12 @@ def insertWidgetToFormLayout(self, row, name, qwidget, qlabel=None): formLayout.insertRow(row, qwidget) self._addToWidgetDictionary(self.widgets, name, qwidget, qlabel) self._addToWidgetNumberDictionary(name, row) - self._addToWidgetDictionary(self.default_widgets, name, qwidget, qlabel) self.addToDefaultWidgetStatesDictionary(name) def _addWidget(self, name, qwidget, qlabel=None): ''' - Adds a widget, and a label widget, or a spanning widget at the the end of - the `groupBoxFormLayout` by invoking `insertWidgetToFormLayout`, where row is out of bounds. + Adds a widget and a label widget, or a spanning widget, at the the end of + the form layout. Parameters: ---------- @@ -103,7 +100,7 @@ def _addWidget(self, name, qwidget, qlabel=None): self.insertWidgetToFormLayout(-1, name, qwidget, qlabel) def _addToWidgetDictionary(self, dictionary, name, qwidget, qlabel = None): - '''Adds the field (and label if present) in the widget dictionary.''' + '''Adds the field, and label if present, in the widget dictionary.''' dictionary[f'{name}_field'] = qwidget if qlabel is not None: dictionary[f'{name}_label'] = qlabel @@ -130,10 +127,9 @@ def _addToWidgetNumberDictionary(self, name, widget_number): self.widget_number_dictionary[key] = value + 1 self.widget_number_dictionary[name] = widget_number - def _popWidgetNumberDictionary(self, name, widget_number): + def _popWidgetNumberDictionary(self, name): ''' - Removes one item in the widget-number dictionary whose key is name and value is - the widget number (i.e. row) in the form layout. + Removes one item in the widget-number dictionary whose key is name. As one widget is removed, the widget numbers associated to the other widgets in the layout are updated. @@ -141,9 +137,8 @@ def _popWidgetNumberDictionary(self, name, widget_number): --------------- name: string name of the widget - widget_number : int - position of the widget in the form layout, i.e. row, in the current state ''' + widget_number = self.getWidgetNumber(name) for key, value in self.widget_number_dictionary.items(): if value > widget_number: self.widget_number_dictionary[key] = value - 1 @@ -167,7 +162,16 @@ def _popWidgetFromDictionary(self, dictionary, name): dictionary.pop(f'{name}_label') def addWidget(self, qwidget, qlabel, name): - '''Adds a qwidget and a qlabel widget in the same row of the form layout.''' + ''' + Adds a widget and a label widget, or a spanning widget, at the the end of + the form layout. + + Parameters: + ---------- + name: str + qwidget: widget + qlabel: qlabel widget or str + ''' self._addWidget(name, qwidget, qlabel) def addSpanningWidget(self, qwidget, name): @@ -183,7 +187,7 @@ def getNumWidgets(self): def removeWidget(self, name): ''' If not present already, creates a dictionary to store the removed qwidgets. - Sets the parent of the qwidget (and qlabel if present) to `None` and + Sets the parent of the qwidget, and qlabel if present, to `None` and stores the widgets in the removed-widgets dictionary. Deletes the row in the form layout. Deletes the qwidget and qlabel from the widgets dictionary. @@ -211,11 +215,10 @@ def removeWidget(self, name): self._popWidgetNumberDictionary(name, widget_number) def getWidget(self, name, role='field'): - '''Returns the widget by the name with which it has been added - + ''' + 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 - + The user can get the label by specifying the role to be label. Raises ValueError if the role is not field or label. ''' allowed_roles = 'field', 'label' @@ -275,7 +278,7 @@ def addSeparator(self, name): def addToDefaultWidgetStatesDictionary(self, name): ''' - Creates an attribute dictionary of default widget states. The entries are in the + If not present already, creates an attribute dictionary of default widget states. The entries are in the format: {'value': str | bool | int, 'enabled': bool, 'visible': bool, 'widget_number': int}. This can be used to restore the default states of the widgets invoking `applyWidgetStates`. ''' @@ -299,10 +302,10 @@ def getAllWidgetStates(self): Returns ------- dict - Format: {'widget_name': {'value': str | bool | int, 'enabled': bool, 'visible': bool}, + Format: {'widget_name': {'value': str | bool | int, 'enabled': bool, 'visible': bool, 'widget_number': int}, ...}, - e.g. {{'widget1': {'value': 1, 'enabled': True, 'visible': True}, - 'widget2': {'value': 2, 'enabled': False, 'visible': False}}. + e.g. {{'widget1': {'value': 1, 'enabled': True, 'visible': True, 'widget_number': 0}, + 'widget2': {'value': 2, 'enabled': False, 'visible': False, 'widget_number': 1}}. ''' all_widget_states = {} for key, widget in self.widgets.items(): @@ -311,6 +314,8 @@ def getAllWidgetStates(self): def getWidgetState(self, widget, role=None): ''' + Returns the current state of the widget in the form. + Parameters ---------- widget: QWidget or str @@ -326,7 +331,7 @@ def getWidgetState(self, widget, role=None): This can be used to restore the state of the widget using `setWidgetState()`. ''' if widget is None: - raise ValueError('The widget (or name of widget) must be given') + raise ValueError('The widget or the name of widget must be given.') if isinstance(widget, str): if role is not None: @@ -371,7 +376,7 @@ def getWidgetState(self, widget, role=None): def _getNameAndRoleFromKey(self, key): ''' Given a key, returns the name and the role. - Role can be included as a suffix or is `field` by default. + Role can be extracted as the suffix to key or is set as `field` by default. Parameters ------------- @@ -471,7 +476,7 @@ def applyWidgetStates(self, states): Parameters ---------- - states: nested_dict Reorders the states dictionary in ascending widget number. + states: nested_dict Format: {'name_field': {'value': str | bool | int, 'enabled': bool, 'visible': bool, 'widget_number' : int}, 'name_label': {'value': str | bool | int, 'enabled': bool, 'visible': bool, 'widget_number' : int}, ...}, e.g. {{'widget1': {'value': 1, 'enabled': True, 'visible': True, 'widget_number' : 0}, @@ -483,55 +488,6 @@ def applyWidgetStates(self, states): for key, widget_state in states.items(): name, role = self._getNameAndRoleFromKey(key) self.applyWidgetState(name, widget_state, role) - - def adaptFormToStates(self, states): - ''' - Reorders the states dictionary in ascending widget number. - Removes the widgets in the form which are not present in the states. - If the widgets in the states are not present in the form, - they are retrieved from the removed-widgets dictionary and inserted at position - given by the widget number recorded in the states. An error is raised when the - widget in thet state is not in the form nor in the removed widgets. - Applies the given states to the form's widgets. - - Parameters - ---------- - states: nested_dict Reorders the states dictionary in ascending widget number. - Format: {'name_field': {'value': str | bool | int, 'enabled': bool, 'visible': bool, 'widget_number' : int}, - 'name_label': {'value': str | bool | int, 'enabled': bool, 'visible': bool, 'widget_number' : int}, ...}, - e.g. {{'widget1': {'value': 1, 'enabled': True, 'visible': True, 'widget_number' : 0}, - 'widget2': {'value': 2, 'enabled': False, 'visible': False, 'widget_number' : 1}}. - ''' - - # add widgets if necessary - states = dict(sorted(states.items(), key = lambda tup: (tup[1]['widget_number']))) - for key, widget_state in states.items(): - name, role = self._getNameAndRoleFromKey(key) - if key in self.widgets.keys(): - pass - elif hasattr(self, 'removed_widgets_dictionary'): - if key in self.removed_widgets_dictionary.keys(): - if role == 'field': - widget_number = states[key]['widget_number'] - qwidget = self.removed_widgets_dictionary[key] - - if f'{name}_label' in self.removed_widgets_dictionary.keys(): - qlabel = self.removed_widgets_dictionary[f'{name}_label'] - self.insertWidgetToFormLayout(widget_number, name, qwidget, qlabel) - else: - self.insertWidgetToFormLayout(widget_number, name, qwidget) - else: - raise KeyError('No widget associated with the dictionary key `' + key + '`') - self.applyWidgetState(name, widget_state, role) - # remove extra widgets - set_to_remove = set() - if self.widgets.keys() > states.keys(): - for key in self.widgets.keys(): - if key not in states.keys(): - name = self._getNameAndRoleFromKey(key)[0] - set_to_remove.add(name) - for el in set_to_remove: - self.removeWidget(el) def saveAllWidgetStates(self): ''' @@ -589,10 +545,9 @@ def addSpanningWidget(self, qwidget, name): def insertWidgetToFormLayout(self, row, name, qwidget, qlabel=None): ''' - Inserts a widget and a label widget, or a spanning widget if 'qlabel' is None, to the form layout, `groupBoxFormLayout`, + Inserts a widget and a label widget, or a spanning widget if 'qlabel' is None, to the form layout in the position specified by row. If row is out of bounds, the widget is added at the end. - It adds to the widget dictionary and the default states - dictionary. + It adds to the widget dictionary, the widget number dictionary, and the default widget states dictionary. Parameters: ---------- @@ -605,9 +560,17 @@ def insertWidgetToFormLayout(self, row, name, qwidget, qlabel=None): def removeWidget(self, name): ''' - Removes a widget (and its label if present) from the layout. - Decreases the counter for the number of widgets in the layout. - Deletes the field (and label) from the dictionary. + If not present already, creates a dictionary to store the removed qwidgets. + Sets the parent of the qwidget, and qlabel if present, to `None` and + stores the widgets in the removed-widgets dictionary. + Deletes the row in the form layout. + Deletes the qwidget and qlabel from the widgets dictionary. + Deletes the widget number from the widget-number dictionary. + + Parameters: + -------------- + name : str + name of the widget to be removed ''' self.widget().removeWidget(name) @@ -618,17 +581,16 @@ def getNumWidgets(self): return self.widget().getNumWidgets() def getWidget(self, name, role='field'): - '''returns the Widget by the name with which it has been added - + ''' + 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 - + The user can get the label by specifying the role to be label. Raises ValueError if the role is not field or label. ''' return self.widget().getWidget(name, role) def getWidgets(self): - '''returns a dictionary of all the widgets in the form''' + '''Returns a dictionary of the widgets currently present in the form.''' return self.widget().getWidgets() def getWidgetNumber(self, name): @@ -644,7 +606,16 @@ def getRemovedWidgets(self): return self.widget().getRemovedWidgets() def setWidgetVisible(self, name, visible): - '''Sets the visibility of the widget and associated label with the given name.''' + ''' + Sets the visibility of the widget and associated label with the given name. + + Parameters + ---------- + name: str + The name of the widget to set visible/invisible + visible: bool + True to set the widget visible, False to hide it + ''' self.widget().setWidgetVisible(name, visible) def saveAllWidgetStates(self): @@ -675,15 +646,17 @@ def getAllWidgetStates(self): Returns ------- dict - Format: {'widget_name': {'value': str | bool | int, 'enabled': bool, 'visible': bool}, + Format: {'widget_name': {'value': str | bool | int, 'enabled': bool, 'visible': bool, 'widget_number': int}, ...}, - e.g. {{'widget1': {'value': 1, 'enabled': True, 'visible': True}, - 'widget2': {'value': 2, 'enabled': False, 'visible': False}}. + e.g. {{'widget1': {'value': 1, 'enabled': True, 'visible': True, 'widget_number': 0}, + 'widget2': {'value': 2, 'enabled': False, 'visible': False, 'widget_number': 1}}. ''' return self.widget().getAllWidgetStates() def getWidgetState(self, widget, role=None): ''' + Returns the current state of the widget in the form. + Parameters ---------- widget: QWidget or str @@ -719,16 +692,13 @@ def applyWidgetState(self, name, state, role=None): def applyWidgetStates(self, state): ''' - Removes the widgets in the form which are not present in the states. - If the widgets in the states are not present in the form, - they are retrieved from the removed-widgets dictionary and inserted at position - given by the widget number recorded in the states. An error is raised when the - widget in thet state is not in the form nor in the removed widgets. - Applies the given states to the form's widgets. - + Applies the given states to the form's widgets. + This assumes the states in the form and the widgets in the states have the same name. + If this is false, it raises an error. + Parameters ---------- - states: nested_dict + states: nested_dict Format: {'name_field': {'value': str | bool | int, 'enabled': bool, 'visible': bool, 'widget_number' : int}, 'name_label': {'value': str | bool | int, 'enabled': bool, 'visible': bool, 'widget_number' : int}, ...}, e.g. {{'widget1': {'value': 1, 'enabled': True, 'visible': True, 'widget_number' : 0}, diff --git a/examples/advanced_dialog_example.py b/examples/advanced_dialog_example.py deleted file mode 100644 index 16b653c..0000000 --- a/examples/advanced_dialog_example.py +++ /dev/null @@ -1,70 +0,0 @@ -import sys - -from PySide2 import QtWidgets - -from eqt.ui.FormDialog import AdvancedFormDialog -from eqt.ui.UIFormWidget import FormWidget - - -class FormExample(FormWidget): - def __init__(self, parent=None): - FormWidget.__init__(self, parent) - - pb = QtWidgets.QPushButton(self) - pb.setText("Open Advanced Dialog with form layout") - 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.Ok.clicked.connect(lambda: self.accepted()) - # Example on how to add elements to the FormDialog - # add input 1 as QLineEdit - qlabel = QtWidgets.QLabel(dialog.groupBox) - qlabel.setText("Input 1: ") - qwidget = QtWidgets.QLineEdit(dialog.groupBox) - qwidget.setClearButtonEnabled(True) - # finally add to the form widget - dialog.insertWidgetToFormLayout(0, 'input_title', QtWidgets.QLabel("Input Values: ")) - dialog.insertWidgetToFormLayout(1, 'input1', qwidget, qlabel) - dialog.addToDictionaryDisplayOnParent('input1') - - # add input 2 as QComboBox - qlabel = QtWidgets.QLabel(dialog.groupBox) - qlabel.setText("Input 2: ") - qwidget = QtWidgets.QComboBox(dialog.groupBox) - qwidget.addItem("option 1") - qwidget.addItem("option 2") - qwidget.setCurrentIndex(0) - qwidget.setEnabled(True) - # finally add to the form widget - dialog.addWidget(qwidget, qlabel, 'input2') - dialog.addToDictionaryDisplayOnParent('input2') - dialog.addWidget(QtWidgets.QLabel("Example Vertical Layout Text"), layout="vertical") - - # store a reference - self.dialog = dialog - self.dialog.onCancel = self.rejected - self.show() - - def openFormDialog(self): - self.dialog.exec() - - def accepted(self): - print(self.dialog.widgets['input1_field'].text()) - print(self.dialog.widgets['input2_field'].currentText()) - self.dialog.close() - - def rejected(self): - print("rejected") - - -if __name__ == "__main__": - app = QtWidgets.QApplication(sys.argv) - - window = FormExample() - - sys.exit(app.exec_()) diff --git a/test/test__formUI_status_test.py b/test/test__formUI_status_test.py index b009f3b..bb74628 100644 --- a/test/test__formUI_status_test.py +++ b/test/test__formUI_status_test.py @@ -139,28 +139,6 @@ def test_insert_every_widget(self): qwidget = self.list_all_widgets[key] self._test_insert_one_widget(0, name + '_spanning', qwidget) - # def _test_add_one_widget(self, name): - # """ - # Invokes `insertWidgetToFormLayout`, therefore inserts the qwidget (and the qlabel) - # at position row in the layout. Checks the position of the widget in the form is `row`. - # """ - # position = self.layout.getWidgetPosition(self.form.getWidget(name, 'field'))[0] - # self.assertEqual(position, row) - - # def test_add_every_widget(self): - # list_widget_names = [ - # 'label', 'checkBox', 'comboBox', 'doubleSpinBox', - # 'spinBox', 'slider', 'uiSliderWidget', 'radioButton', - # 'textEdit', 'plainTextEdit', 'lineEdit', 'button'] - # for i in range(0, len(self.list_all_widgets)): - # qwidget = self.list_all_widgets[i] - # name = list_widget_names[i] - # self._test_add_one_widget_to_dictionary(self.widgets, name, qwidget, name) - # qwidget = self.list_all_widgets[i] - # self._test_insert_one_widget(0, name + '_spanning', qwidget) - - - def _test_remove_one_widget(self, name): """ Remove one widget. @@ -416,7 +394,6 @@ def test_applyWidgetState_using_role_parameter_field(self): self.assertEqual(self.simple_form.getWidgetState('checkBox', 'field'), self.state_simple_form['checkBox_field']) def test_applyWidgetState_using_role_parameter_label(self): - self.simple_form.applyWidgetState('checkBox', self.state_simple_form['checkBox_label'], role='label') self.assertEqual(self.simple_form.getWidgetState('checkBox', 'label'), self.state_simple_form['checkBox_label']) @@ -439,6 +416,7 @@ def setUp(self): self.add_two_widgets() self.layout = self.form.formWidget.uiElements['groupBoxFormLayout'] self.vertical_layout = self.form.formWidget.uiElements['verticalLayout'] + def click_Ok(self): QTest.mouseClick(self.form.Ok, Qt.LeftButton) @@ -590,6 +568,7 @@ def setUp(self): self.layout = self.form.uiElements['groupBoxFormLayout'] def test_get_name_and_role_from_key_or_widget(self): + """Checks that the method `_getNameAndRoleFromKey` returns the correct name and role in all widgets.""" for name in self.list_all_widgets.keys(): for role in {'field', 'label'}: name_role = name + '_' + role @@ -656,30 +635,6 @@ def test_restoreAllSavedWidgetStates(self): self.simple_form.getWidget('label', 'label').isVisible(), state_to_restore['label_label']['visible']) - def test_adaptFormToStates_after_remove_and_insert(self): - """Saves two states. Checks that the widgets are removed and inserted correctly when the states are applied.""" - # state 1 - self.form.saveAllWidgetStates() - state1 = self.form.widget_states - # state2 - for key in self.list_all_widgets.keys(): - qwidget = self.list_all_widgets[key] - name = f'{key}_insert' - self.form.insertWidgetToFormLayout(0, name, qwidget, name) - qwidget = self.list_all_widgets[key] - self.form.insertWidgetToFormLayout(0, name + '_spanning', qwidget) - self.form.saveAllWidgetStates() - state2 = self.form.widget_states - self.assertNotEqual(state1, state2) - # apply 1 - self.form.adaptFormToStates(state1) - self.form.saveAllWidgetStates() - self.assertEqual(state1, self.form.widget_states) - # apply 2 - self.form.adaptFormToStates(state2) - self.form.saveAllWidgetStates() - self.assertEqual(state2, self.form.widget_states) - @skip_ci class FormDockWidgetStateTest(FormsCommonTests, unittest.TestCase): def setUp(self): From 6c5e408096d732d6c3e37de4f17947d37444402d Mon Sep 17 00:00:00 2001 From: Danica Sugic Date: Mon, 22 Jan 2024 14:49:45 +0000 Subject: [PATCH 67/96] Change pop widget number dictionary dictionary arguments --- eqt/ui/UIFormWidget.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/eqt/ui/UIFormWidget.py b/eqt/ui/UIFormWidget.py index f5ae760..d3626f9 100644 --- a/eqt/ui/UIFormWidget.py +++ b/eqt/ui/UIFormWidget.py @@ -212,7 +212,7 @@ def removeWidget(self, name): self.getWidget(name, 'field').setParent(None) formLayout.removeRow(self.widget_number_dictionary[name]) self._popWidgetFromDictionary(self.getWidgets(), name) - self._popWidgetNumberDictionary(name, widget_number) + self._popWidgetNumberDictionary(name) def getWidget(self, name, role='field'): ''' From 11caf76c6c87c6d212057a6c9b8eed88e0276c27 Mon Sep 17 00:00:00 2001 From: Danica Sugic Date: Mon, 22 Jan 2024 16:01:58 +0000 Subject: [PATCH 68/96] Fixed insert widget example --- examples/insert_widgets_example.py | 14 +++++++++++--- 1 file changed, 11 insertions(+), 3 deletions(-) diff --git a/examples/insert_widgets_example.py b/examples/insert_widgets_example.py index 9b0758d..58a9241 100644 --- a/examples/insert_widgets_example.py +++ b/examples/insert_widgets_example.py @@ -78,12 +78,20 @@ def onCancel(self): if not hasattr(self.dialog.formWidget, 'widget_states'): if self.dialog.getWidget('Button insert vertical').isEnabled() == False: self.dialog.removeWidgetFromVerticalLayout(self.dialog.getWidgetFromVerticalLayout(1)) + if self.dialog.getWidget('Button insert widgets').isEnabled() == False: self.dialog.formWidget._popWidgetFromDictionary(self.dialog.formWidget.default_widget_states,'inserted widget') self.dialog.formWidget._popWidgetFromDictionary(self.dialog.formWidget.default_widget_states,'inserted spanning widget') - self.dialog.formWidget.adaptFormToStates(self.dialog.formWidget.default_widget_states) - - + self.dialog.formWidget.removeWidget('inserted widget') + self.dialog.formWidget.removeWidget('inserted spanning widget') + else: + if self.dialog.getWidget('Button insert vertical').isEnabled() != self.dialog.getWidgetStates()['Button insert vertical_field']['enabled'] == True: + self.dialog.removeWidgetFromVerticalLayout(self.dialog.getWidgetFromVerticalLayout(1)) + if self.dialog.getWidget('Button insert widgets').isEnabled() != self.dialog.getWidgetStates()['Button insert widgets_field']['enabled'] == True: + self.dialog.formWidget.removeWidget('inserted widget') + self.dialog.formWidget.removeWidget('inserted spanning widget') + + if __name__ == "__main__": app = QtWidgets.QApplication(sys.argv) From 8bd14a5dd72d4b9a92864818f9ba08fae8b1e06a Mon Sep 17 00:00:00 2001 From: Danica Sugic Date: Mon, 22 Jan 2024 16:51:22 +0000 Subject: [PATCH 69/96] Delete _addwidget and other changes from 2nd review --- eqt/ui/FormDialog.py | 19 +++++++++++++------ eqt/ui/UIFormWidget.py | 43 +++++++++++++----------------------------- 2 files changed, 26 insertions(+), 36 deletions(-) diff --git a/eqt/ui/FormDialog.py b/eqt/ui/FormDialog.py index 358e843..f155726 100644 --- a/eqt/ui/FormDialog.py +++ b/eqt/ui/FormDialog.py @@ -67,14 +67,21 @@ def widgets(self): def groupBox(self): return self.formWidget.groupBox - def addWidget(self, qwidget, qlabel=None, name=None, layout='form'): + def addWidget(self, qwidget, qlabel = None, name = None, layout = 'form'): ''' - layout = 'vertical' - adds to the Vertical layout below the form. - `qlabel` and `name` are unsupported when layout is vertical. + Adds a widget to the layout. In particular, adds a qwidget and a qlabel widget + in the same row of the form layout if layout is 'form' and adds a spanning widget + to the vertical layout if layout is 'vertical'. - layout = 'form' - adds to the FormLayout - Name and qlabel must be passed to add to the form layout . - Adds a qwidget and a qlabel widget in the same row of the form layout. + Parameters + ---------------- + qwidget : widget + qlabel : qlabel widget or str + only supported when layout is 'form' + name : str + only supported when layout is 'form' + layout : 'form' or 'vertical' + 'form' - adds to the FormLayout, 'vertical' - adds to the Vertical layout below the form. ''' if layout == 'vertical': if name is not None or qlabel is not None: diff --git a/eqt/ui/UIFormWidget.py b/eqt/ui/UIFormWidget.py index d3626f9..67be645 100644 --- a/eqt/ui/UIFormWidget.py +++ b/eqt/ui/UIFormWidget.py @@ -47,6 +47,7 @@ def createForm(self): 'verticalLayout': verticalLayout, 'groupBox': groupBox, 'groupBoxFormLayout': groupBoxFormLayout} self.widgets = {} + self.removed_widgets_dictionary = {} @property def num_widgets(self): @@ -84,20 +85,7 @@ def insertWidgetToFormLayout(self, row, name, qwidget, qlabel=None): formLayout.insertRow(row, qwidget) self._addToWidgetDictionary(self.widgets, name, qwidget, qlabel) self._addToWidgetNumberDictionary(name, row) - self.addToDefaultWidgetStatesDictionary(name) - - def _addWidget(self, name, qwidget, qlabel=None): - ''' - Adds a widget and a label widget, or a spanning widget, at the the end of - the form layout. - - Parameters: - ---------- - name: str - qwidget: widget - qlabel: qlabel widget or str - ''' - self.insertWidgetToFormLayout(-1, name, qwidget, qlabel) + self._addToDefaultWidgetStatesDictionary(name) def _addToWidgetDictionary(self, dictionary, name, qwidget, qlabel = None): '''Adds the field, and label if present, in the widget dictionary.''' @@ -172,11 +160,11 @@ def addWidget(self, qwidget, qlabel, name): qwidget: widget qlabel: qlabel widget or str ''' - self._addWidget(name, qwidget, qlabel) + self.insertWidgetToFormLayout(-1, name, qwidget, qlabel) def addSpanningWidget(self, qwidget, name): '''Adds a spanning qwidget occupying the full row in the form layout.''' - self._addWidget(name, qwidget) + self.insertWidgetToFormLayout(-1, name, qwidget) def getNumWidgets(self): ''' @@ -186,12 +174,10 @@ def getNumWidgets(self): def removeWidget(self, name): ''' - If not present already, creates a dictionary to store the removed qwidgets. - Sets the parent of the qwidget, and qlabel if present, to `None` and - stores the widgets in the removed-widgets dictionary. - Deletes the row in the form layout. - Deletes the qwidget and qlabel from the widgets dictionary. - Deletes the widget number from the widget-number dictionary. + Removes the widget with name `name` from the widgets in the form layout. In particular, + it deletes the row in the form layout, the qwidget and qlabel from the widgets dictionary + and the widget number from the widget-number dictionary. Sets the parent of the qwidget, and qlabel if present, + to `None` allowing to store the removed widget in the removed-widgets dictionary. Parameters: -------------- @@ -199,8 +185,6 @@ def removeWidget(self, name): name of the widget to be removed ''' formLayout = self.uiElements['groupBoxFormLayout'] - if not hasattr(self, 'removed_widgets_dictionary'): - self.removed_widgets_dictionary = {} widget_number = self.getWidgetNumber(name) qwidget = self.getWidget(name, role='field') if f'{name}_label' in self.getWidgets().keys(): @@ -267,16 +251,16 @@ def addTitle(self, qlabel, name): qlabel = QtWidgets.QLabel(self.uiElements['groupBox']) qlabel.setText(txt) qlabel.setStyleSheet("font-weight: bold") - self._addWidget(name, qlabel) + self.insertWidgetToFormLayout(-1, name, qlabel) def addSeparator(self, name): # Adds horizontal separator to the form frame = QtWidgets.QFrame() frame.setFrameShape(QtWidgets.QFrame.HLine) frame.setFrameShadow(QtWidgets.QFrame.Raised) - self._addWidget(name, frame) + self.insertWidgetToFormLayout(-1, name, frame) - def addToDefaultWidgetStatesDictionary(self, name): + def _addToDefaultWidgetStatesDictionary(self, name): ''' If not present already, creates an attribute dictionary of default widget states. The entries are in the format: {'value': str | bool | int, 'enabled': bool, 'visible': bool, 'widget_number': int}. @@ -434,9 +418,8 @@ def applyWidgetState(self, name, state, role=None): try: if name_role in self.widgets.keys(): widget = self.widgets[name_role] - elif hasattr(self, 'removed_widgets_dictionary'): - if name_role in self.removed_widgets_dictionary.keys(): - widget = self.removed_widgets_dictionary[name_role] + elif name_role in self.removed_widgets_dictionary.keys(): + widget = self.removed_widgets_dictionary[name_role] except KeyError: raise KeyError('No widget associated with the dictionary key `'+name_role+'`') #apply state From d77ba26abcb18b0f0441ebf2919b48f911a1b2c1 Mon Sep 17 00:00:00 2001 From: Danica Sugic Date: Mon, 22 Jan 2024 17:13:14 +0000 Subject: [PATCH 70/96] Run pre-commit --- eqt/ui/FormDialog.py | 66 +++++---- eqt/ui/UIFormWidget.py | 194 ++++++++++++++------------ examples/dialog_save_state_example.py | 2 +- examples/insert_widgets_example.py | 31 ++-- test/test__formUI_status_test.py | 107 ++++++-------- 5 files changed, 204 insertions(+), 196 deletions(-) diff --git a/eqt/ui/FormDialog.py b/eqt/ui/FormDialog.py index f155726..bca9e67 100644 --- a/eqt/ui/FormDialog.py +++ b/eqt/ui/FormDialog.py @@ -67,10 +67,10 @@ def widgets(self): def groupBox(self): return self.formWidget.groupBox - def addWidget(self, qwidget, qlabel = None, name = None, layout = 'form'): + def addWidget(self, qwidget, qlabel=None, name=None, layout='form'): ''' - Adds a widget to the layout. In particular, adds a qwidget and a qlabel widget - in the same row of the form layout if layout is 'form' and adds a spanning widget + Adds a widget to the layout. In particular, adds a qwidget and a qlabel widget + in the same row of the form layout if layout is 'form' and adds a spanning widget to the vertical layout if layout is 'vertical'. Parameters @@ -80,8 +80,9 @@ def addWidget(self, qwidget, qlabel = None, name = None, layout = 'form'): only supported when layout is 'form' name : str only supported when layout is 'form' - layout : 'form' or 'vertical' - 'form' - adds to the FormLayout, 'vertical' - adds to the Vertical layout below the form. + layout : 'form' or 'vertical' + 'form' - adds to the FormLayout, 'vertical' - adds to the Vertical layout below + the form. ''' if layout == 'vertical': if name is not None or qlabel is not None: @@ -117,9 +118,10 @@ def addSpanningWidget(self, qwidget, name=None, layout='form'): def insertWidgetToFormLayout(self, row, name, qwidget, qlabel=None): ''' - Inserts a widget and a label widget, or a spanning widget if 'qlabel' is None, to the form layout - in the position specified by row. If row is out of bounds, the widget is added at the end. - It adds to the widget dictionary, the widget number dictionary, and the default widget states dictionary. + Inserts a widget and a label widget, or a spanning widget if 'qlabel' is None, to the form + layout in the position specified by row. If row is out of bounds, the widget is added at + the end. It adds to the widget dictionary, the widget number dictionary, and the default + widget states dictionary. Parameters: ---------- @@ -151,12 +153,12 @@ def getWidgetFromVerticalLayout(self, index): def removeWidget(self, name): ''' If not present already, creates a dictionary to store the removed qwidgets. - Sets the parent of the qwidget, and qlabel if present, to `None` and + Sets the parent of the qwidget, and qlabel if present, to `None` and stores the widgets in the removed-widgets dictionary. Deletes the row in the form layout. Deletes the qwidget and qlabel from the widgets dictionary. Deletes the widget number from the widget-number dictionary. - + Parameters: -------------- name : str @@ -234,9 +236,9 @@ def getAllWidgetStates(self): Returns ------- dict - Format: {'widget_name': {'value': str | bool | int, 'enabled': bool, 'visible': bool, 'widget_number': int}, - ...}, - e.g. {{'widget1': {'value': 1, 'enabled': True, 'visible': True, 'widget_number': 0}, + Format: {'widget_name': {'value': str | bool | int, 'enabled': bool, 'visible': bool, + 'widget_number': int}, ...}, + e.g. {'widget1': {'value': 1, 'enabled': True, 'visible': True, 'widget_number': 0}, 'widget2': {'value': 2, 'enabled': False, 'visible': False, 'widget_number': 1}}. ''' return self.formWidget.getAllWidgetStates() @@ -244,18 +246,21 @@ def getAllWidgetStates(self): def getWidgetState(self, widget, role=None): ''' Returns the current state of the widget in the form. - + Parameters ---------- widget: QWidget or str - The widget or its name (or its name + '_field' or '_label', when role is None) to get the state of. + The widget or its name (or its name + '_field' or '_label', when role is None) to get + the state of. role: str, optional, default None, values: 'label', 'field', None. - The role of the widget to apply the state to. This is used only if `widget` is the widget name string. + The role of the widget to apply the state to. This is used only if `widget` is the + widget name string. Returns ------- state: dict - Format: {'value': str | bool | int, 'enabled': bool, 'visible': bool, 'widget_number' : int}, + Format: {'value': str | bool | int, 'enabled': bool, 'visible': bool, + 'widget_number' : int}, e.g. {'value': 1, 'enabled': True, 'visible': True, 'widget_number' : 0}. This can be used to restore the state of the widget using `setWidgetState()`. ''' @@ -263,36 +268,35 @@ def getWidgetState(self, widget, role=None): def applyWidgetState(self, name, state, role=None): ''' - Applies the given `state` to the widget associated with `name` and `role`. + Applies the given `state` to the widget associated with `name` and `role`. If role is None, the role is assigned to be 'field'. Parameters ---------- name: str - The name of the widget to apply the state to. + The name of the widget to apply the state to. role: str, optional, default None, values: 'label', 'field', None. The role of the widget to apply the state to. state: dict - Format: {'value': str | bool | int, 'enabled': bool, 'visible': bool, 'widget_number' : int}, - e.g. {'value': 1, 'enabled': True, 'visible': True, 'widget_number' : 0}. + Format: {'value': str | bool | int, 'enabled': bool, 'visible': bool, + 'widget_number' : int}, + e.g. {'value': 1, 'enabled': True, 'visible': True, 'widget_number' : 0}. ''' return self.formWidget.applyWidgetState(name, state, role) def applyWidgetStates(self, state): ''' - Applies the given states to the form's widgets. + Applies the given states to the form's widgets. This assumes the states in the form and the widgets in the states have the same name. If this is false, it raises an error. - + Parameters ---------- - states: nested_dict - Format: {'name_field': {'value': str | bool | int, 'enabled': bool, 'visible': bool, 'widget_number' : int}, - 'name_label': {'value': str | bool | int, 'enabled': bool, 'visible': bool, 'widget_number' : int}, ...}, - e.g. {{'widget1': {'value': 1, 'enabled': True, 'visible': True, 'widget_number' : 0}, - 'widget2': {'value': 2, 'enabled': False, 'visible': False, 'widget_number' : 1}}. + states: nested_dict + Format: {'name_field': {'value': str | bool | int, 'enabled': bool, 'visible': bool, + 'widget_number' : int}, 'name_label': {'value': str | bool | int, 'enabled': bool, + 'visible': bool, 'widget_number' : int}, ...}. + e.g. {'widget1': {'value': 1, 'enabled': True, 'visible': True, 'widget_number' : 0}, + 'widget2': {'value': 2, 'enabled': False, 'visible': False, 'widget_number' : 1}}. ''' return self.formWidget.applyWidgetStates(state) - - - diff --git a/eqt/ui/UIFormWidget.py b/eqt/ui/UIFormWidget.py index 67be645..5a950b9 100644 --- a/eqt/ui/UIFormWidget.py +++ b/eqt/ui/UIFormWidget.py @@ -1,5 +1,3 @@ -import logging - from PySide2 import QtWidgets from .UISliderWidget import UISliderWidget @@ -59,9 +57,10 @@ def groupBox(self): def insertWidgetToFormLayout(self, row, name, qwidget, qlabel=None): ''' - Inserts a widget and a label widget, or a spanning widget if 'qlabel' is None, to the form layout - in the position specified by row. If row is out of bounds, the widget is added at the end. - It adds to the widget dictionary, the widget number dictionary, and the default widget states dictionary. + Inserts a widget and a label widget, or a spanning widget if 'qlabel' is None, to the form + layout in the position specified by row. If row is out of bounds, the widget is added at + the end. It adds to the widget dictionary, the widget number dictionary, and the default + widget states dictionary. Parameters: ---------- @@ -71,7 +70,8 @@ def insertWidgetToFormLayout(self, row, name, qwidget, qlabel=None): qlabel: qlabel widget or str ''' if f'{name}_field' in self.widgets.keys(): - raise ValueError(f'The name of widget you are trying to insert, {name}, is used already. Choose another name.') + raise ValueError(f'''The name of widget you are trying to insert, {name}, + is used already. Choose another name.''') formLayout = self.uiElements['groupBoxFormLayout'] @@ -87,17 +87,17 @@ def insertWidgetToFormLayout(self, row, name, qwidget, qlabel=None): self._addToWidgetNumberDictionary(name, row) self._addToDefaultWidgetStatesDictionary(name) - def _addToWidgetDictionary(self, dictionary, name, qwidget, qlabel = None): + def _addToWidgetDictionary(self, dictionary, name, qwidget, qlabel=None): '''Adds the field, and label if present, in the widget dictionary.''' dictionary[f'{name}_field'] = qwidget if qlabel is not None: dictionary[f'{name}_label'] = qlabel - - def _addToWidgetNumberDictionary(self, name, widget_number): + + def _addToWidgetNumberDictionary(self, name, widget_number): ''' - Adds one item in the widget-number dictionary whose key is name and value is + Adds one item in the widget-number dictionary whose key is name and value is the current widget number (i.e. row) in the form layout. - As one widget is inserted, the widget numbers associated to the other widgets + As one widget is inserted, the widget numbers associated to the other widgets in the layout are updated. Parameters: @@ -108,7 +108,7 @@ def _addToWidgetNumberDictionary(self, name, widget_number): position of the widget in the form layout, i.e. row, in the current state ''' if widget_number == -1: - self.widget_number_dictionary[name] = self.num_widgets - 1 + self.widget_number_dictionary[name] = self.num_widgets - 1 else: for key, value in self.widget_number_dictionary.items(): if value >= widget_number: @@ -118,7 +118,7 @@ def _addToWidgetNumberDictionary(self, name, widget_number): def _popWidgetNumberDictionary(self, name): ''' Removes one item in the widget-number dictionary whose key is name. - As one widget is removed, the widget numbers associated to the other widgets + As one widget is removed, the widget numbers associated to the other widgets in the layout are updated. Parameters: @@ -130,7 +130,7 @@ def _popWidgetNumberDictionary(self, name): for key, value in self.widget_number_dictionary.items(): if value > widget_number: self.widget_number_dictionary[key] = value - 1 - self.widget_number_dictionary.pop(name) + self.widget_number_dictionary.pop(name) def _popWidgetFromDictionary(self, dictionary, name): ''' @@ -143,16 +143,16 @@ def _popWidgetFromDictionary(self, dictionary, name): Format: {name} ''' if name in dictionary.keys(): - dictionary.pop(name) + dictionary.pop(name) if f'{name}_field' in dictionary.keys(): - dictionary.pop(f'{name}_field') + dictionary.pop(f'{name}_field') if f'{name}_label' in dictionary.keys(): - dictionary.pop(f'{name}_label') + dictionary.pop(f'{name}_label') def addWidget(self, qwidget, qlabel, name): ''' Adds a widget and a label widget, or a spanning widget, at the the end of - the form layout. + the form layout. Parameters: ---------- @@ -161,11 +161,11 @@ def addWidget(self, qwidget, qlabel, name): qlabel: qlabel widget or str ''' self.insertWidgetToFormLayout(-1, name, qwidget, qlabel) - + def addSpanningWidget(self, qwidget, name): '''Adds a spanning qwidget occupying the full row in the form layout.''' self.insertWidgetToFormLayout(-1, name, qwidget) - + def getNumWidgets(self): ''' Returns the number of widgets in the form. @@ -175,28 +175,28 @@ def getNumWidgets(self): def removeWidget(self, name): ''' Removes the widget with name `name` from the widgets in the form layout. In particular, - it deletes the row in the form layout, the qwidget and qlabel from the widgets dictionary - and the widget number from the widget-number dictionary. Sets the parent of the qwidget, and qlabel if present, - to `None` allowing to store the removed widget in the removed-widgets dictionary. - + it deletes the row in the form layout, the qwidget and qlabel from the widgets dictionary + and the widget number from the widget-number dictionary. Sets the parent of the qwidget, + and qlabel if present, to `None` allowing to store the removed widget in the + removed-widgets dictionary. + Parameters: -------------- name : str name of the widget to be removed ''' formLayout = self.uiElements['groupBoxFormLayout'] - widget_number = self.getWidgetNumber(name) - qwidget = self.getWidget(name, role='field') + qwidget = self.getWidget(name, role='field') if f'{name}_label' in self.getWidgets().keys(): - qlabel = self.getWidget(name, role='label') + qlabel = self.getWidget(name, role='label') self._addToWidgetDictionary(self.removed_widgets_dictionary, name, qwidget, qlabel) self.getWidget(name, 'label').setParent(None) else: self._addToWidgetDictionary(self.removed_widgets_dictionary, name, qwidget) - self.getWidget(name, 'field').setParent(None) - formLayout.removeRow(self.widget_number_dictionary[name]) - self._popWidgetFromDictionary(self.getWidgets(), name) - self._popWidgetNumberDictionary(name) + self.getWidget(name, 'field').setParent(None) + formLayout.removeRow(self.widget_number_dictionary[name]) + self._popWidgetFromDictionary(self.getWidgets(), name) + self._popWidgetNumberDictionary(name) def getWidget(self, name, role='field'): ''' @@ -240,7 +240,7 @@ def setWidgetVisible(self, name, visible): def getWidgets(self): '''Returns a dictionary of the widgets currently present in the form.''' return self.widgets - + def getRemovedWidgets(self): '''Returns the dictionary of the removed widgets previously present in the form.''' return self.removed_widgets_dictionary @@ -262,9 +262,10 @@ def addSeparator(self, name): def _addToDefaultWidgetStatesDictionary(self, name): ''' - If not present already, creates an attribute dictionary of default widget states. The entries are in the - format: {'value': str | bool | int, 'enabled': bool, 'visible': bool, 'widget_number': int}. - This can be used to restore the default states of the widgets invoking `applyWidgetStates`. + If not present already, creates an attribute dictionary of default widget states. The + entries are in the format: {'value': str | bool | int, 'enabled': bool, 'visible': bool, + 'widget_number': int}. This can be used to restore the default states of the widgets + invoking `applyWidgetStates`. ''' if not hasattr(self, 'default_widget_states'): self.default_widget_states = {} @@ -273,7 +274,7 @@ def _addToDefaultWidgetStatesDictionary(self, name): # add the default state of the qlabel if f'{name}_label' in self.widgets.keys(): self.default_widget_states[f'{name}_label'] = self.getWidgetState(name, 'label') - + def setDefaultWidgetStatesVisibleTrue(self): ''' Sets all of the entries 'visible' in the `default_widget_states` dictionary to be `True`. @@ -286,14 +287,14 @@ def getAllWidgetStates(self): Returns ------- dict - Format: {'widget_name': {'value': str | bool | int, 'enabled': bool, 'visible': bool, 'widget_number': int}, - ...}, - e.g. {{'widget1': {'value': 1, 'enabled': True, 'visible': True, 'widget_number': 0}, - 'widget2': {'value': 2, 'enabled': False, 'visible': False, 'widget_number': 1}}. + Format: {'widget_name': {'value': str | bool | int, 'enabled': bool, 'visible': bool, + 'widget_number': int}, ...}. + e.g. {'widget1': {'value': 1, 'enabled': True, 'visible': True, 'widget_number': 0}, + 'widget2': {'value': 2, 'enabled': False, 'visible': False, 'widget_number': 1}}. ''' all_widget_states = {} for key, widget in self.widgets.items(): - all_widget_states[key] = self.getWidgetState(widget) + all_widget_states[key] = self.getWidgetState(widget) return all_widget_states def getWidgetState(self, widget, role=None): @@ -303,14 +304,17 @@ def getWidgetState(self, widget, role=None): Parameters ---------- widget: QWidget or str - The widget or its name (or its name + '_field' or '_label', when role is None) to get the state of. + The widget or its name (or its name + '_field' or '_label', when role is None) to get + the state of. role: str, optional, default None, values: 'label', 'field', None. - The role of the widget to apply the state to. This is used only if `widget` is the widget name string. + The role of the widget to apply the state to. This is used only if `widget` is the + widget name string. Returns ------- state: dict - Format: {'value': str | bool | int, 'enabled': bool, 'visible': bool, 'widget_number' : int}, + Format: {'value': str | bool | int, 'enabled': bool, 'visible': bool, + 'widget_number' : int}. e.g. {'value': 1, 'enabled': True, 'visible': True, 'widget_number' : 0}. This can be used to restore the state of the widget using `setWidgetState()`. ''' @@ -330,13 +334,13 @@ def getWidgetState(self, widget, role=None): try: widget = self.widgets[name_role] except KeyError: - raise KeyError('No widget associated with the dictionary key `'+ name_role) + raise KeyError('No widget associated with the dictionary key `' + name_role) else: name, role = self._getNameAndRoleFromWidget(widget) widget_state = {} widget_state['enabled'] = widget.isEnabled() widget_state['visible'] = widget.isVisible() - + if isinstance(widget, QtWidgets.QLabel): widget_state['value'] = widget.text() elif isinstance(widget, (QtWidgets.QCheckBox, QtWidgets.QPushButton)): @@ -359,9 +363,9 @@ def getWidgetState(self, widget, role=None): def _getNameAndRoleFromKey(self, key): ''' - Given a key, returns the name and the role. + Given a key, returns the name and the role. Role can be extracted as the suffix to key or is set as `field` by default. - + Parameters ------------- key: str @@ -379,9 +383,9 @@ def _getNameAndRoleFromKey(self, key): return name, role def _getNameAndRoleFromWidget(self, widget): - ''' - Given a widget, finds it in the widget dictionary and returns its name and role. - + ''' + Given a widget, finds it in the widget dictionary and returns its name and role. + Parameters ------------- widget: qwidget @@ -393,18 +397,19 @@ def _getNameAndRoleFromWidget(self, widget): def applyWidgetState(self, name, state, role=None): ''' - Applies the given `state` to the widget associated with `name` and `role`. + Applies the given `state` to the widget associated with `name` and `role`. If role is None, the role is assigned to be 'field'. Parameters ---------- name: str - The name of the widget to apply the state to. + The name of the widget to apply the state to. role: str, optional, default None, values: 'label', 'field', None. The role of the widget to apply the state to. state: dict - Format: {'value': str | bool | int, 'enabled': bool, 'visible': bool, 'widget_number' : int}, - e.g. {'value': 1, 'enabled': True, 'visible': True, 'widget_number' : 0}. + Format: {'value': str | bool | int, 'enabled': bool, 'visible': bool, + 'widget_number' : int}. + e.g. {'value': 1, 'enabled': True, 'visible': True, 'widget_number' : 0}. ''' if role is not None: if role in ['label', 'field']: @@ -413,16 +418,16 @@ def applyWidgetState(self, name, state, role=None): raise ValueError(f'Role must be either "label", "field" or None. Got {role}.') else: name_role = f'{name}_field' - - #retrieve widget + + # retrieve widget try: if name_role in self.widgets.keys(): widget = self.widgets[name_role] elif name_role in self.removed_widgets_dictionary.keys(): widget = self.removed_widgets_dictionary[name_role] except KeyError: - raise KeyError('No widget associated with the dictionary key `'+name_role+'`') - #apply state + raise KeyError('No widget associated with the dictionary key `' + name_role + '`') + # apply state for key, value in state.items(): if key == 'enabled': widget.setEnabled(value) @@ -453,21 +458,23 @@ def applyWidgetState(self, name, state, role=None): def applyWidgetStates(self, states): ''' - Applies the given states to the form's widgets. + Applies the given states to the form's widgets. This assumes the states in the form and the widgets in the states have the same name. If this is false, it raises an error. - + Parameters ---------- - states: nested_dict - Format: {'name_field': {'value': str | bool | int, 'enabled': bool, 'visible': bool, 'widget_number' : int}, - 'name_label': {'value': str | bool | int, 'enabled': bool, 'visible': bool, 'widget_number' : int}, ...}, - e.g. {{'widget1': {'value': 1, 'enabled': True, 'visible': True, 'widget_number' : 0}, - 'widget2': {'value': 2, 'enabled': False, 'visible': False, 'widget_number' : 1}}. + states: nested_dict + Format: {'name_field': {'value': str | bool | int, 'enabled': bool, 'visible': bool, + 'widget_number' : int}, 'name_label': {'value': str | bool | int, 'enabled': bool, + 'visible': bool, 'widget_number' : int}, ...}. + e.g. {'widget1': {'value': 1, 'enabled': True, 'visible': True, 'widget_number' : 0}, + 'widget2': {'value': 2, 'enabled': False, 'visible': False, 'widget_number' : 1}}. ''' if self.widgets.keys() != states.keys(): - raise KeyError(f'''The widgets in the form are {self.widgets.keys()} whereas the widgets in the states are {states.keys()}. - These must be equal for the states to be applied to the form.''') + raise KeyError(f'''The widgets in the form are {self.widgets.keys()} whereas + the widgets in the states are {states.keys()}. These must be + equal for the states to be applied to the form.''') for key, widget_state in states.items(): name, role = self._getNameAndRoleFromKey(key) self.applyWidgetState(name, widget_state, role) @@ -482,7 +489,7 @@ def saveAllWidgetStates(self): def getWidgetStates(self): '''Returns the saved widget states.''' return self.widget_states - + def getDefaultWidgetStates(self): '''Returns the saved default widget states.''' return self.default_widget_states @@ -528,9 +535,10 @@ def addSpanningWidget(self, qwidget, name): def insertWidgetToFormLayout(self, row, name, qwidget, qlabel=None): ''' - Inserts a widget and a label widget, or a spanning widget if 'qlabel' is None, to the form layout - in the position specified by row. If row is out of bounds, the widget is added at the end. - It adds to the widget dictionary, the widget number dictionary, and the default widget states dictionary. + Inserts a widget and a label widget, or a spanning widget if 'qlabel' is None, to the form + layout in the position specified by row. If row is out of bounds, the widget is added at + the end. It adds to the widget dictionary, the widget number dictionary, and the default + widget states dictionary. Parameters: ---------- @@ -544,12 +552,12 @@ def insertWidgetToFormLayout(self, row, name, qwidget, qlabel=None): def removeWidget(self, name): ''' If not present already, creates a dictionary to store the removed qwidgets. - Sets the parent of the qwidget, and qlabel if present, to `None` and + Sets the parent of the qwidget, and qlabel if present, to `None` and stores the widgets in the removed-widgets dictionary. Deletes the row in the form layout. Deletes the qwidget and qlabel from the widgets dictionary. Deletes the widget number from the widget-number dictionary. - + Parameters: -------------- name : str @@ -629,7 +637,8 @@ def getAllWidgetStates(self): Returns ------- dict - Format: {'widget_name': {'value': str | bool | int, 'enabled': bool, 'visible': bool, 'widget_number': int}, + Format: {'widget_name': {'value': str | bool | int, 'enabled': bool, 'visible': bool, + 'widget_number': int}, ...}, e.g. {{'widget1': {'value': 1, 'enabled': True, 'visible': True, 'widget_number': 0}, 'widget2': {'value': 2, 'enabled': False, 'visible': False, 'widget_number': 1}}. @@ -639,18 +648,21 @@ def getAllWidgetStates(self): def getWidgetState(self, widget, role=None): ''' Returns the current state of the widget in the form. - + Parameters ---------- widget: QWidget or str - The widget or its name (or its name + '_field' or '_label', when role is None) to get the state of. + The widget or its name (or its name + '_field' or '_label', when role is None) to get + the state of. role: str, optional, default None, values: 'label', 'field', None. - The role of the widget to apply the state to. This is used only if `widget` is the widget name string. + The role of the widget to apply the state to. This is used only if `widget` is the + widget name string. Returns ------- state: dict - Format: {'value': str | bool | int, 'enabled': bool, 'visible': bool, 'widget_number' : int}, + Format: {'value': str | bool | int, 'enabled': bool, 'visible': bool, + 'widget_number' : int}. e.g. {'value': 1, 'enabled': True, 'visible': True, 'widget_number' : 0}. This can be used to restore the state of the widget using `setWidgetState()`. ''' @@ -658,34 +670,36 @@ def getWidgetState(self, widget, role=None): def applyWidgetState(self, name, state, role=None): ''' - Applies the given `state` to the widget associated with `name` and `role`. + Applies the given `state` to the widget associated with `name` and `role`. If role is None, the role is assigned to be 'field'. Parameters ---------- name: str - The name of the widget to apply the state to. + The name of the widget to apply the state to. role: str, optional, default None, values: 'label', 'field', None. The role of the widget to apply the state to. state: dict - Format: {'value': str | bool | int, 'enabled': bool, 'visible': bool, 'widget_number' : int}, - e.g. {'value': 1, 'enabled': True, 'visible': True, 'widget_number' : 0}. + Format: {'value': str | bool | int, 'enabled': bool, 'visible': bool, + 'widget_number' : int}. + e.g. {'value': 1, 'enabled': True, 'visible': True, 'widget_number' : 0}. ''' return self.widget().applyWidgetState(name, state, role) def applyWidgetStates(self, state): ''' - Applies the given states to the form's widgets. + Applies the given states to the form's widgets. This assumes the states in the form and the widgets in the states have the same name. If this is false, it raises an error. - + Parameters ---------- - states: nested_dict - Format: {'name_field': {'value': str | bool | int, 'enabled': bool, 'visible': bool, 'widget_number' : int}, - 'name_label': {'value': str | bool | int, 'enabled': bool, 'visible': bool, 'widget_number' : int}, ...}, - e.g. {{'widget1': {'value': 1, 'enabled': True, 'visible': True, 'widget_number' : 0}, - 'widget2': {'value': 2, 'enabled': False, 'visible': False, 'widget_number' : 1}}. + states: nested_dict + Format: {'name_field': {'value': str | bool | int, 'enabled': bool, 'visible': bool, + 'widget_number' : int}, 'name_label': {'value': str | bool | int, 'enabled': bool, + 'visible': bool, 'widget_number' : int}, ...}. + e.g. {'widget1': {'value': 1, 'enabled': True, 'visible': True, 'widget_number' : 0}, + 'widget2': {'value': 2, 'enabled': False, 'visible': False, 'widget_number' : 1}}. ''' return self.widget().applyWidgetStates(state) diff --git a/examples/dialog_save_state_example.py b/examples/dialog_save_state_example.py index 125ce0b..d0ccf2c 100644 --- a/examples/dialog_save_state_example.py +++ b/examples/dialog_save_state_example.py @@ -23,7 +23,7 @@ def __init__(self, parent=None): # create dialog to be opened later: dialog = FormDialog(parent=self, title='Example') - + # ## Example on how to add elements to the dialog.addWidget(QtWidgets.QLabel('test label'), 'Label: ', 'label') dialog.addWidget(QtWidgets.QCheckBox('test checkbox'), 'CheckBox: ', 'checkBox') diff --git a/examples/insert_widgets_example.py b/examples/insert_widgets_example.py index 58a9241..ed234f0 100644 --- a/examples/insert_widgets_example.py +++ b/examples/insert_widgets_example.py @@ -71,27 +71,34 @@ def insert_form(self, form, button): form.insertWidgetToFormLayout(2, 'inserted spanning widget', buttonspanning) print('\nDictionary of widgets after insertion in the form layout:\n' + str(form.getWidgets())) - print("\nDictionary of widget number in the form layout:\n" + str(form.getWidgetNumberDictionary())) + print("\nDictionary of widget number in the form layout:\n" + + str(form.getWidgetNumberDictionary())) button.setEnabled(False) def onCancel(self): if not hasattr(self.dialog.formWidget, 'widget_states'): - if self.dialog.getWidget('Button insert vertical').isEnabled() == False: - self.dialog.removeWidgetFromVerticalLayout(self.dialog.getWidgetFromVerticalLayout(1)) - - if self.dialog.getWidget('Button insert widgets').isEnabled() == False: - self.dialog.formWidget._popWidgetFromDictionary(self.dialog.formWidget.default_widget_states,'inserted widget') - self.dialog.formWidget._popWidgetFromDictionary(self.dialog.formWidget.default_widget_states,'inserted spanning widget') + if self.dialog.getWidget('Button insert vertical').isEnabled() is False: + self.dialog.removeWidgetFromVerticalLayout( + self.dialog.getWidgetFromVerticalLayout(1)) + + if self.dialog.getWidget('Button insert widgets').isEnabled() is False: + self.dialog.formWidget._popWidgetFromDictionary( + self.dialog.formWidget.default_widget_states, 'inserted widget') + self.dialog.formWidget._popWidgetFromDictionary( + self.dialog.formWidget.default_widget_states, 'inserted spanning widget') self.dialog.formWidget.removeWidget('inserted widget') self.dialog.formWidget.removeWidget('inserted spanning widget') else: - if self.dialog.getWidget('Button insert vertical').isEnabled() != self.dialog.getWidgetStates()['Button insert vertical_field']['enabled'] == True: - self.dialog.removeWidgetFromVerticalLayout(self.dialog.getWidgetFromVerticalLayout(1)) - if self.dialog.getWidget('Button insert widgets').isEnabled() != self.dialog.getWidgetStates()['Button insert widgets_field']['enabled'] == True: + if self.dialog.getWidget('Button insert vertical').isEnabled( + ) != self.dialog.getWidgetStates()['Button insert vertical_field']['enabled'] is True: + self.dialog.removeWidgetFromVerticalLayout( + self.dialog.getWidgetFromVerticalLayout(1)) + if self.dialog.getWidget('Button insert widgets').isEnabled( + ) != self.dialog.getWidgetStates()['Button insert widgets_field']['enabled'] is True: self.dialog.formWidget.removeWidget('inserted widget') self.dialog.formWidget.removeWidget('inserted spanning widget') - - + + if __name__ == "__main__": app = QtWidgets.QApplication(sys.argv) diff --git a/test/test__formUI_status_test.py b/test/test__formUI_status_test.py index bb74628..356a29b 100644 --- a/test/test__formUI_status_test.py +++ b/test/test__formUI_status_test.py @@ -39,27 +39,27 @@ def exampleState(self): def list_all_widgets(self): 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')} + '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 - + @property def state_simple_form(self): state_simple_form = { - 'label_field': {'value': 'test label', 'enabled': True, 'visible': False, 'widget_number': 0}, - 'label_label': {'value': 'Label: ', 'enabled': True, 'visible': False, 'widget_number': 0}, - 'checkBox_field': {'value': False, 'enabled': True, 'visible': False,'widget_number': 1}, - 'checkBox_label': {'value': 'CheckBox: ', 'enabled': True, 'visible': False, 'widget_number': 1} - } + 'label_field': { + 'value': 'test label', 'enabled': True, 'visible': False, + 'widget_number': 0}, 'label_label': { + 'value': 'Label: ', 'enabled': True, 'visible': False, + 'widget_number': 0}, 'checkBox_field': { + 'value': False, 'enabled': True, 'visible': False, 'widget_number': 1}, + 'checkBox_label': { + 'value': 'CheckBox: ', 'enabled': True, 'visible': False, 'widget_number': 1}} return state_simple_form def add_every_widget(self): @@ -129,7 +129,7 @@ def _test_insert_one_widget(self, row, name, qwidget, qlabel=None): def test_insert_every_widget(self): """ - Inserts each widget, and then each spanning widget, in position 0 of the form layout. + Inserts each widget, and then each spanning widget, in position 0 of the form layout. Tests the position of the widgets in the layout is 0. """ for key in self.list_all_widgets.keys(): @@ -162,7 +162,7 @@ def _test_remove_one_widget(self, name): self.assertEqual(prerowcount, postrowcount + 1) self.assertEqual(postrowcount, postnumwidgets) self.assertEqual(self.form.getRemovedWidgets()[f'{name}_field'], qwidget) - + def test_remove_every_widget(self): """Remove every widget from the form.""" list_widgets = [ @@ -387,19 +387,25 @@ def test_applyWidgetStates(self): def test_applyWidgetState(self): self.simple_form.applyWidgetState('checkBox', self.state_simple_form['checkBox_field']) - self.assertEqual(self.simple_form.getWidgetState('checkBox'), self.state_simple_form['checkBox_field']) + self.assertEqual(self.simple_form.getWidgetState('checkBox'), + self.state_simple_form['checkBox_field']) def test_applyWidgetState_using_role_parameter_field(self): - self.simple_form.applyWidgetState('checkBox', self.state_simple_form['checkBox_field'], role='field') - self.assertEqual(self.simple_form.getWidgetState('checkBox', 'field'), self.state_simple_form['checkBox_field']) + self.simple_form.applyWidgetState('checkBox', self.state_simple_form['checkBox_field'], + role='field') + self.assertEqual(self.simple_form.getWidgetState('checkBox', 'field'), + self.state_simple_form['checkBox_field']) def test_applyWidgetState_using_role_parameter_label(self): - self.simple_form.applyWidgetState('checkBox', self.state_simple_form['checkBox_label'], role='label') - self.assertEqual(self.simple_form.getWidgetState('checkBox', 'label'), self.state_simple_form['checkBox_label']) + self.simple_form.applyWidgetState('checkBox', self.state_simple_form['checkBox_label'], + role='label') + self.assertEqual(self.simple_form.getWidgetState('checkBox', 'label'), + self.state_simple_form['checkBox_label']) def test_applyWidgetState_using_role_parameter_default(self): self.simple_form.applyWidgetState('checkBox', self.state_simple_form['checkBox_field']) - self.assertEqual(self.simple_form.getWidgetState('checkBox'), self.state_simple_form['checkBox_field']) + self.assertEqual(self.simple_form.getWidgetState('checkBox'), + self.state_simple_form['checkBox_field']) def test_getAllWidgetStates(self): """Check that the state of all widgets is returned""" @@ -449,38 +455,6 @@ def test_dialog_buttons_default_behaviour(self): self.click_Cancel() self.assertEqual(states1, self.form.getAllWidgetStates()) - def click_Ok(self): - QTest.mouseClick(self.form.Ok, Qt.LeftButton) - - def click_Cancel(self): - QTest.mouseClick(self.form.Cancel, Qt.LeftButton) - - def test_dialog_buttons_default_behaviour(self): - # create the states dictionary - self.set_state(1) - states1 = self.form.getAllWidgetStates() - self.set_state(0) - states0 = self.form.getAllWidgetStates() - # check state 0 and 1 are not saved when Cancel is pressed - self.click_Cancel() - self.assertNotEqual(states0, self.form.getAllWidgetStates()) - self.assertNotEqual(states1, self.form.getAllWidgetStates()) - # save state 0 - self.set_state(0) - self.assertEqual(states0, self.form.getAllWidgetStates()) - self.click_Ok() - self.assertEqual(states0, self.form.getAllWidgetStates()) - # save state 1 - self.set_state(1) - self.assertEqual(states1, self.form.getAllWidgetStates()) - self.click_Ok() - self.assertEqual(states1, self.form.getAllWidgetStates()) - # change to state 0 without saving - self.set_state(0) - self.assertEqual(states0, self.form.getAllWidgetStates()) - self.click_Cancel() - self.assertEqual(states1, self.form.getAllWidgetStates()) - def test_form_init_title(self): """Tests if the FormDialog is created correctly with or without the title argument.""" FormDialog() @@ -489,7 +463,7 @@ def test_form_init_title(self): def _test_insert_one_widget_to_vertical_layout(self, row, qwidget): """ - Invokes `insertWidgetToVerticalLayout`, therefore inserts the qwidget at position + Invokes `insertWidgetToVerticalLayout`, therefore inserts the qwidget at position row in the layout. Checks the position of the widget in the form is `row`. """ self.form.insertWidgetToVerticalLayout(row, qwidget) @@ -497,10 +471,13 @@ def _test_insert_one_widget_to_vertical_layout(self, row, qwidget): self.assertEqual(position, row) def test_insert_every_widget_to_vertical_layout(self): - """Inserts each widget in position 0 of the vertical layout and tests its position in the layout is 0.""" + """ + Inserts each widget in position 0 of the vertical layout and tests its position in + the layout is 0. + """ for key in self.list_all_widgets.keys(): self._test_insert_one_widget_to_vertical_layout(0, self.list_all_widgets[key]) - + def test_getWidgetState_returns_QLabel_value(self): """Check that the value of the QLabel is saved to the state""" initial_label_value = 'label' @@ -557,6 +534,7 @@ def test_restoreAllSavedWidgetStates(self): self.simple_form.getWidget('label', 'label').isVisible(), state_to_restore['label_label']['visible']) + @skip_ci class FormWidgetStateTest(FormsCommonTests, unittest.TestCase): def setUp(self): @@ -568,14 +546,18 @@ def setUp(self): self.layout = self.form.uiElements['groupBoxFormLayout'] def test_get_name_and_role_from_key_or_widget(self): - """Checks that the method `_getNameAndRoleFromKey` returns the correct name and role in all widgets.""" + """ + Checks that the method `_getNameAndRoleFromKey` returns the correct name and role in + all widgets. + """ for name in self.list_all_widgets.keys(): for role in {'field', 'label'}: name_role = name + '_' + role name_c, role_c = self.form._getNameAndRoleFromKey(name_role) self.assertEqual(name_c, name) self.assertEqual(role_c, role) - name_c, role_c = self.form._getNameAndRoleFromWidget(self.form.getWidget(name, role)) + name_c, role_c = self.form._getNameAndRoleFromWidget( + self.form.getWidget(name, role)) self.assertEqual(name_c, name) self.assertEqual(role_c, role) @@ -635,6 +617,7 @@ def test_restoreAllSavedWidgetStates(self): self.simple_form.getWidget('label', 'label').isVisible(), state_to_restore['label_label']['visible']) + @skip_ci class FormDockWidgetStateTest(FormsCommonTests, unittest.TestCase): def setUp(self): From 2ad7405d7b6fa965159e69fd99b68ab734c72786 Mon Sep 17 00:00:00 2001 From: Danica Sugic Date: Mon, 22 Jan 2024 18:24:53 +0000 Subject: [PATCH 71/96] Change docstring in insert widget --- eqt/ui/FormDialog.py | 27 ++++++++----- eqt/ui/UIFormWidget.py | 86 ++++++++++++++++++++++++++++++++---------- 2 files changed, 84 insertions(+), 29 deletions(-) diff --git a/eqt/ui/FormDialog.py b/eqt/ui/FormDialog.py index bca9e67..b130de3 100644 --- a/eqt/ui/FormDialog.py +++ b/eqt/ui/FormDialog.py @@ -118,17 +118,24 @@ def addSpanningWidget(self, qwidget, name=None, layout='form'): def insertWidgetToFormLayout(self, row, name, qwidget, qlabel=None): ''' - Inserts a widget and a label widget, or a spanning widget if 'qlabel' is None, to the form - layout in the position specified by row. If row is out of bounds, the widget is added at - the end. It adds to the widget dictionary, the widget number dictionary, and the default - widget states dictionary. + Inserts a labelled widget, or a spanning widget, to the form layout. + The position in the form is specified by row. If row is out of bounds, the widget + is added at the end of the form. The entries associated with the widget are added + to the widget dictionary, the widget-number dictionary, and the default-widget-states + dictionary. Parameters: ---------- row: int + The position in the form where the widget is added. name: str - qwidget: qwidget + The string associated to the qwidget and qlabel. + qwidget: widget + The widget to be added on the right hand side of the form or as a spanning widget. qlabel: qlabel widget or str + The qlabel widget, or a str from which a qlabel widget is created, to be added + on the left hand side of the form. If qlabel is `None` the widget spans the full + width of the form. ''' self.formWidget.insertWidgetToFormLayout(row, name, qwidget, qlabel) @@ -284,11 +291,11 @@ def applyWidgetState(self, name, state, role=None): ''' return self.formWidget.applyWidgetState(name, state, role) - def applyWidgetStates(self, state): + def applyWidgetStates(self, states): ''' - Applies the given states to the form's widgets. - This assumes the states in the form and the widgets in the states have the same name. - If this is false, it raises an error. + Applies the given states to the form's widgets. It raises an error if the keys in the + dicitonary of states and the keys in the dictionary of widgets in the form are not the + same. Parameters ---------- @@ -299,4 +306,4 @@ def applyWidgetStates(self, state): e.g. {'widget1': {'value': 1, 'enabled': True, 'visible': True, 'widget_number' : 0}, 'widget2': {'value': 2, 'enabled': False, 'visible': False, 'widget_number' : 1}}. ''' - return self.formWidget.applyWidgetStates(state) + return self.formWidget.applyWidgetStates(states) diff --git a/eqt/ui/UIFormWidget.py b/eqt/ui/UIFormWidget.py index 5a950b9..95c2f06 100644 --- a/eqt/ui/UIFormWidget.py +++ b/eqt/ui/UIFormWidget.py @@ -57,17 +57,24 @@ def groupBox(self): def insertWidgetToFormLayout(self, row, name, qwidget, qlabel=None): ''' - Inserts a widget and a label widget, or a spanning widget if 'qlabel' is None, to the form - layout in the position specified by row. If row is out of bounds, the widget is added at - the end. It adds to the widget dictionary, the widget number dictionary, and the default - widget states dictionary. + Inserts a labelled widget, or a spanning widget, to the form layout. + The position in the form is specified by row. If row is out of bounds, the widget + is added at the end of the form. The entries associated with the widget are added + to the widget dictionary, the widget-number dictionary, and the default-widget-states + dictionary. Parameters: ---------- row: int + The position in the form where the widget is added. name: str - qwidget: qwidget + The string associated to the qwidget and qlabel. + qwidget: widget + The widget to be added on the right hand side of the form or as a spanning widget. qlabel: qlabel widget or str + The qlabel widget, or a str from which a qlabel widget is created, to be added + on the left hand side of the form. If qlabel is `None` the widget spans the full + width of the form. ''' if f'{name}_field' in self.widgets.keys(): raise ValueError(f'''The name of widget you are trying to insert, {name}, @@ -151,19 +158,32 @@ def _popWidgetFromDictionary(self, dictionary, name): def addWidget(self, qwidget, qlabel, name): ''' - Adds a widget and a label widget, or a spanning widget, at the the end of + Adds a widget and a label widget at the the end of the form layout. Parameters: ---------- - name: str qwidget: widget + The widget to be added on the right hand side of the form. qlabel: qlabel widget or str + The qlabel widget, or a str from which a qlabel widget is created, to be added + on the left hand side of the form. + name: str + The string associated to the qwidget and qlabel. ''' self.insertWidgetToFormLayout(-1, name, qwidget, qlabel) def addSpanningWidget(self, qwidget, name): - '''Adds a spanning qwidget occupying the full row in the form layout.''' + ''' + Adds a spanning qwidget occupying the full row in the form layout. + + Parameters: + ---------- + qwidget: widget + The widget to be added on the form. + name: str + The string associated to the qwidget. + ''' self.insertWidgetToFormLayout(-1, name, qwidget) def getNumWidgets(self): @@ -458,9 +478,9 @@ def applyWidgetState(self, name, state, role=None): def applyWidgetStates(self, states): ''' - Applies the given states to the form's widgets. - This assumes the states in the form and the widgets in the states have the same name. - If this is false, it raises an error. + Applies the given states to the form's widgets. It raises an error if the keys in the + dicitonary of states and the keys in the dictionary of widgets in the form are not the + same. Parameters ---------- @@ -526,11 +546,33 @@ def __init__(self, parent=None, title=None): self.setObjectName(title) def addWidget(self, qwidget, qlabel, name): - '''Adds a qwidget and a qlabel widget in the same row of the form layout.''' + ''' + Adds a widget and a label widget at the the end of + the form layout. + + Parameters: + ---------- + qwidget: widget + The widget to be added on the right hand side of the form. + qlabel: qlabel widget or str + The qlabel widget, or a str from which a qlabel widget is created, to be added + on the left hand side of the form. + name: str + The string associated to the qwidget and qlabel. + ''' self.widget().addWidget(qwidget, qlabel, name) def addSpanningWidget(self, qwidget, name): - '''Adds a spanning qwidget occupying the full row in the form layout.''' + ''' + Adds a spanning qwidget occupying the full row in the form layout. + + Parameters: + ---------- + qwidget: widget + The widget to be added on the form. + name: str + The string associated to the qwidget. + ''' self.widget().addSpanningWidget(qwidget, name) def insertWidgetToFormLayout(self, row, name, qwidget, qlabel=None): @@ -544,8 +586,14 @@ def insertWidgetToFormLayout(self, row, name, qwidget, qlabel=None): ---------- row: int name: str - qwidget: qwidget + The string associated to the qwidget and qlabel. + qwidget: widget + The widget to be added on the right hand side of the form or as a spanning widget. qlabel: qlabel widget or str + The qlabel widget, or a str from which a qlabel widget is created, to be added + on the left hand side of the form. If qlabel is `None` the widget spans the full + width of the form. + ''' self.widget().insertWidgetToFormLayout(row, name, qwidget, qlabel) @@ -686,11 +734,11 @@ def applyWidgetState(self, name, state, role=None): ''' return self.widget().applyWidgetState(name, state, role) - def applyWidgetStates(self, state): + def applyWidgetStates(self, states): ''' - Applies the given states to the form's widgets. - This assumes the states in the form and the widgets in the states have the same name. - If this is false, it raises an error. + Applies the given states to the form's widgets. It raises an error if the keys in the + dicitonary of states and the keys in the dictionary of widgets in the form are not the + same. Parameters ---------- @@ -701,7 +749,7 @@ def applyWidgetStates(self, state): e.g. {'widget1': {'value': 1, 'enabled': True, 'visible': True, 'widget_number' : 0}, 'widget2': {'value': 2, 'enabled': False, 'visible': False, 'widget_number' : 1}}. ''' - return self.widget().applyWidgetStates(state) + return self.widget().applyWidgetStates(states) class UIFormFactory(QtWidgets.QWidget): From 9ebe624dab785b83965c77f24589b8b42dcc3a7c Mon Sep 17 00:00:00 2001 From: Danica Sugic Date: Thu, 25 Jan 2024 10:19:59 +0000 Subject: [PATCH 72/96] Change docstring remove widget --- eqt/ui/FormDialog.py | 11 +++++------ eqt/ui/UIFormWidget.py | 11 +++++------ 2 files changed, 10 insertions(+), 12 deletions(-) diff --git a/eqt/ui/FormDialog.py b/eqt/ui/FormDialog.py index b130de3..f9ba6eb 100644 --- a/eqt/ui/FormDialog.py +++ b/eqt/ui/FormDialog.py @@ -159,12 +159,11 @@ def getWidgetFromVerticalLayout(self, index): def removeWidget(self, name): ''' - If not present already, creates a dictionary to store the removed qwidgets. - Sets the parent of the qwidget, and qlabel if present, to `None` and - stores the widgets in the removed-widgets dictionary. - Deletes the row in the form layout. - Deletes the qwidget and qlabel from the widgets dictionary. - Deletes the widget number from the widget-number dictionary. + Removes the widget with name `name` from the widgets in the form layout. In particular, + it deletes the row in the form layout, the qwidget and qlabel from the widgets dictionary + and the widget number from the widget-number dictionary. Sets the parent of the qwidget, + and qlabel if present, to `None` allowing to store the removed widget in the + removed-widgets dictionary. Parameters: -------------- diff --git a/eqt/ui/UIFormWidget.py b/eqt/ui/UIFormWidget.py index 95c2f06..3a9197c 100644 --- a/eqt/ui/UIFormWidget.py +++ b/eqt/ui/UIFormWidget.py @@ -599,12 +599,11 @@ def insertWidgetToFormLayout(self, row, name, qwidget, qlabel=None): def removeWidget(self, name): ''' - If not present already, creates a dictionary to store the removed qwidgets. - Sets the parent of the qwidget, and qlabel if present, to `None` and - stores the widgets in the removed-widgets dictionary. - Deletes the row in the form layout. - Deletes the qwidget and qlabel from the widgets dictionary. - Deletes the widget number from the widget-number dictionary. + Removes the widget with name `name` from the widgets in the form layout. In particular, + it deletes the row in the form layout, the qwidget and qlabel from the widgets dictionary + and the widget number from the widget-number dictionary. Sets the parent of the qwidget, + and qlabel if present, to `None` allowing to store the removed widget in the + removed-widgets dictionary. Parameters: -------------- From bfb31f5810ddbe4a12f3e9b85a60799bf822b089 Mon Sep 17 00:00:00 2001 From: Danica Sugic Date: Thu, 25 Jan 2024 10:26:16 +0000 Subject: [PATCH 73/96] Change error message --- eqt/ui/UIFormWidget.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/eqt/ui/UIFormWidget.py b/eqt/ui/UIFormWidget.py index 3a9197c..e8a03e2 100644 --- a/eqt/ui/UIFormWidget.py +++ b/eqt/ui/UIFormWidget.py @@ -354,7 +354,7 @@ def getWidgetState(self, widget, role=None): try: widget = self.widgets[name_role] except KeyError: - raise KeyError('No widget associated with the dictionary key `' + name_role) + raise KeyError(f'No widget associated with the dictionary key `{name_role}`.') else: name, role = self._getNameAndRoleFromWidget(widget) widget_state = {} @@ -446,7 +446,7 @@ def applyWidgetState(self, name, state, role=None): elif name_role in self.removed_widgets_dictionary.keys(): widget = self.removed_widgets_dictionary[name_role] except KeyError: - raise KeyError('No widget associated with the dictionary key `' + name_role + '`') + raise KeyError(f'No widget associated with the dictionary key `{name_role}`.') # apply state for key, value in state.items(): if key == 'enabled': From 00d751a76737954d1a32a350c44fa9229fc6ee6a Mon Sep 17 00:00:00 2001 From: Danica Sugic Date: Thu, 25 Jan 2024 10:38:17 +0000 Subject: [PATCH 74/96] Change insert widget docstring --- eqt/ui/FormDialog.py | 3 ++- eqt/ui/UIFormWidget.py | 15 +++++++++------ 2 files changed, 11 insertions(+), 7 deletions(-) diff --git a/eqt/ui/FormDialog.py b/eqt/ui/FormDialog.py index f9ba6eb..ea3f014 100644 --- a/eqt/ui/FormDialog.py +++ b/eqt/ui/FormDialog.py @@ -120,7 +120,8 @@ def insertWidgetToFormLayout(self, row, name, qwidget, qlabel=None): ''' Inserts a labelled widget, or a spanning widget, to the form layout. The position in the form is specified by row. If row is out of bounds, the widget - is added at the end of the form. The entries associated with the widget are added + is added at the end of the form. An error is raised if `name` is already in use + by another widget in the form. The entries associated with the widget are added to the widget dictionary, the widget-number dictionary, and the default-widget-states dictionary. diff --git a/eqt/ui/UIFormWidget.py b/eqt/ui/UIFormWidget.py index e8a03e2..5d3f918 100644 --- a/eqt/ui/UIFormWidget.py +++ b/eqt/ui/UIFormWidget.py @@ -59,7 +59,8 @@ def insertWidgetToFormLayout(self, row, name, qwidget, qlabel=None): ''' Inserts a labelled widget, or a spanning widget, to the form layout. The position in the form is specified by row. If row is out of bounds, the widget - is added at the end of the form. The entries associated with the widget are added + is added at the end of the form. An error is raised if `name` is already in use + by another widget in the form. The entries associated with the widget are added to the widget dictionary, the widget-number dictionary, and the default-widget-states dictionary. @@ -577,14 +578,17 @@ def addSpanningWidget(self, qwidget, name): def insertWidgetToFormLayout(self, row, name, qwidget, qlabel=None): ''' - Inserts a widget and a label widget, or a spanning widget if 'qlabel' is None, to the form - layout in the position specified by row. If row is out of bounds, the widget is added at - the end. It adds to the widget dictionary, the widget number dictionary, and the default - widget states dictionary. + Inserts a labelled widget, or a spanning widget, to the form layout. + The position in the form is specified by row. If row is out of bounds, the widget + is added at the end of the form. An error is raised if `name` is already in use + by another widget in the form. The entries associated with the widget are added + to the widget dictionary, the widget-number dictionary, and the default-widget-states + dictionary. Parameters: ---------- row: int + The position in the form where the widget is added. name: str The string associated to the qwidget and qlabel. qwidget: widget @@ -593,7 +597,6 @@ def insertWidgetToFormLayout(self, row, name, qwidget, qlabel=None): The qlabel widget, or a str from which a qlabel widget is created, to be added on the left hand side of the form. If qlabel is `None` the widget spans the full width of the form. - ''' self.widget().insertWidgetToFormLayout(row, name, qwidget, qlabel) From bdecb2780bdbba609efd4902c934303e6bfae408 Mon Sep 17 00:00:00 2001 From: Danica Sugic Date: Thu, 25 Jan 2024 10:53:49 +0000 Subject: [PATCH 75/96] Change test list --- test/test__formUI_status_test.py | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/test/test__formUI_status_test.py b/test/test__formUI_status_test.py index 356a29b..eca6904 100644 --- a/test/test__formUI_status_test.py +++ b/test/test__formUI_status_test.py @@ -165,10 +165,7 @@ def _test_remove_one_widget(self, name): def test_remove_every_widget(self): """Remove every widget from the form.""" - list_widgets = [ - 'label', 'checkBox', 'comboBox', 'doubleSpinBox', 'spinBox', 'slider', - 'uiSliderWidget', 'radioButton', 'textEdit', 'plainTextEdit', 'lineEdit', 'button'] - for name in list_widgets: + for name in self.list_all_widgets.keys(): self._test_remove_one_widget(name) def test_getWidgetState_returns_visibility(self): From 86659da04611b0401855857411a1ad926ba914f6 Mon Sep 17 00:00:00 2001 From: Danica Sugic Date: Thu, 25 Jan 2024 11:13:41 +0000 Subject: [PATCH 76/96] Update changelog --- CHANGELOG.md | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index b6a139b..b33d6fb 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,4 +1,10 @@ # Version x.x.x +- Adds the methods to insert widgets in the forms, their unit tests, and the example file. + `_addWidget` is removed and substituted by an insert method. + Adds a dictionary of removed widgets. + Adds the widget-number dictionary and saves the widget number as a value in the widget-states dictionary. + Adds a method to get the name and role of a widget from a dictionary key. + Changes the attribute representing the number of widgets in the form to be the property corresponding to the number of rows in the form. (#109) - Reinstates changelog (#99) - Adds `title` to `FormDockWidget` & update tests/examples (#102) - Stops `pre-commit` committing corrections to user PRs (#112) From d6e556ace56938927229ae6b80ef5a4d0f299e24 Mon Sep 17 00:00:00 2001 From: Danica Sugic Date: Tue, 30 Jan 2024 13:43:41 +0000 Subject: [PATCH 77/96] Delete removed widget dict and widget number dict and change getWidgetNumber --- eqt/ui/FormDialog.py | 32 +++--- eqt/ui/UIFormWidget.py | 166 ++++++++++++------------------- test/test__formUI_status_test.py | 1 - 3 files changed, 81 insertions(+), 118 deletions(-) diff --git a/eqt/ui/FormDialog.py b/eqt/ui/FormDialog.py index ea3f014..a0ea1ac 100644 --- a/eqt/ui/FormDialog.py +++ b/eqt/ui/FormDialog.py @@ -160,16 +160,20 @@ def getWidgetFromVerticalLayout(self, index): def removeWidget(self, name): ''' - Removes the widget with name `name` from the widgets in the form layout. In particular, - it deletes the row in the form layout, the qwidget and qlabel from the widgets dictionary - and the widget number from the widget-number dictionary. Sets the parent of the qwidget, - and qlabel if present, to `None` allowing to store the removed widget in the - removed-widgets dictionary. + Removes the widget with the specified name from the form layout. + This method delete the qwidget, and qlabel if present, from the widgets dictionary + and sets their parent to `None`. Parameters: -------------- name : str - name of the widget to be removed + The name of the widget to be removed. + + Returns: + -------------- + tuple or QWidget + If the widget has a corresponding label, a tuple containing the widget and label is returned. + Otherwise, only the widget is returned. ''' self.formWidget.removeWidget(name) @@ -192,17 +196,11 @@ def getWidgets(self): '''Returns a dictionary of the widgets currently present in the form.''' return self.formWidget.getWidgets() - def getRemovedWidgets(self): - '''Returns the dictionary of the removed widgets previously present in the form.''' - return self.formWidget.getRemovedWidgets() - - def getWidgetNumber(self, name): - '''Returns the widget number by the widget name.''' - return self.formWidget.getWidgetNumber(name) - - def getWidgetNumberDictionary(self): - '''Returns the widget number dictionary.''' - return self.formWidget.getWidgetNumberDictionary() + def getWidgetNumber(self, name, role = 'field'): + ''' + Returns the widget number by the widget name. This is the row of the widget in the form layout. + ''' + return self.formWidget.getWidgetNumber(name, role) def setWidgetVisible(self, name, visible): ''' diff --git a/eqt/ui/UIFormWidget.py b/eqt/ui/UIFormWidget.py index 5d3f918..f366241 100644 --- a/eqt/ui/UIFormWidget.py +++ b/eqt/ui/UIFormWidget.py @@ -39,13 +39,10 @@ def createForm(self): # Add elements to layout verticalLayout.addWidget(groupBox) - # number of widgets currently present in the groupBoxFormLayout - self.widget_number_dictionary = {} self.uiElements = { 'verticalLayout': verticalLayout, 'groupBox': groupBox, 'groupBoxFormLayout': groupBoxFormLayout} self.widgets = {} - self.removed_widgets_dictionary = {} @property def num_widgets(self): @@ -92,7 +89,6 @@ def insertWidgetToFormLayout(self, row, name, qwidget, qlabel=None): else: formLayout.insertRow(row, qwidget) self._addToWidgetDictionary(self.widgets, name, qwidget, qlabel) - self._addToWidgetNumberDictionary(name, row) self._addToDefaultWidgetStatesDictionary(name) def _addToWidgetDictionary(self, dictionary, name, qwidget, qlabel=None): @@ -101,61 +97,42 @@ def _addToWidgetDictionary(self, dictionary, name, qwidget, qlabel=None): if qlabel is not None: dictionary[f'{name}_label'] = qlabel - def _addToWidgetNumberDictionary(self, name, widget_number): + def _popWidgetFromDictionary(self, dictionary, name): ''' - Adds one item in the widget-number dictionary whose key is name and value is - the current widget number (i.e. row) in the form layout. - As one widget is inserted, the widget numbers associated to the other widgets - in the layout are updated. + Removes the item(s) associated with `name` from a dictionary. Parameters: - --------------- - name: string - name of the widget - widget_number : int - position of the widget in the form layout, i.e. row, in the current state - ''' - if widget_number == -1: - self.widget_number_dictionary[name] = self.num_widgets - 1 - else: - for key, value in self.widget_number_dictionary.items(): - if value >= widget_number: - self.widget_number_dictionary[key] = value + 1 - self.widget_number_dictionary[name] = widget_number + ----------------- + dictionary : dict + The dictionary from which to remove the items. + name : str + The name of the item(s) to be removed. - def _popWidgetNumberDictionary(self, name): - ''' - Removes one item in the widget-number dictionary whose key is name. - As one widget is removed, the widget numbers associated to the other widgets - in the layout are updated. + Returns: + ------- + qwidget : QWidget + The removed widget associated with `name`, if it exists in the dictionary. - Parameters: - --------------- - name: string - name of the widget - ''' - widget_number = self.getWidgetNumber(name) - for key, value in self.widget_number_dictionary.items(): - if value > widget_number: - self.widget_number_dictionary[key] = value - 1 - self.widget_number_dictionary.pop(name) + qlabel : QLabel, optional + The removed label associated with `name`, if it exists in the dictionary. - def _popWidgetFromDictionary(self, dictionary, name): - ''' - Removes the item(s) associated with `name` from a dictionary. + Raises: + ------ + KeyError + If no widget associated with the dictionary key `name` or `{name}_field` is found. - Parameters: - ----------------- - dictionary : dict - name: str - Format: {name} ''' if name in dictionary.keys(): - dictionary.pop(name) - if f'{name}_field' in dictionary.keys(): - dictionary.pop(f'{name}_field') + qwidget = dictionary.pop(name) + elif f'{name}_field' in dictionary.keys(): + qwidget = dictionary.pop(f'{name}_field') + else: + raise KeyError(f'No widget associated with the dictionary key `{name}` or `{name}_field`.') if f'{name}_label' in dictionary.keys(): - dictionary.pop(f'{name}_label') + qlabel = dictionary.pop(f'{name}_label') + return qwidget, qlabel + else: + return qwidget def addWidget(self, qwidget, qlabel, name): ''' @@ -195,29 +172,32 @@ def getNumWidgets(self): def removeWidget(self, name): ''' - Removes the widget with name `name` from the widgets in the form layout. In particular, - it deletes the row in the form layout, the qwidget and qlabel from the widgets dictionary - and the widget number from the widget-number dictionary. Sets the parent of the qwidget, - and qlabel if present, to `None` allowing to store the removed widget in the - removed-widgets dictionary. + Removes the widget with the specified name from the form layout. + This method delete the qwidget, and qlabel if present, from the widgets dictionary + and sets their parent to `None`. Parameters: -------------- name : str - name of the widget to be removed + The name of the widget to be removed. + + Returns: + -------------- + tuple or QWidget + If the widget has a corresponding label, a tuple containing the widget and label is returned. + Otherwise, only the widget is returned. ''' - formLayout = self.uiElements['groupBoxFormLayout'] - qwidget = self.getWidget(name, role='field') + widget_number = self.getWidgetNumber(name) if f'{name}_label' in self.getWidgets().keys(): - qlabel = self.getWidget(name, role='label') - self._addToWidgetDictionary(self.removed_widgets_dictionary, name, qwidget, qlabel) self.getWidget(name, 'label').setParent(None) - else: - self._addToWidgetDictionary(self.removed_widgets_dictionary, name, qwidget) + qwidget, qlabel = self._popWidgetFromDictionary(self.getWidgets(), name) + self.uiElements['groupBoxFormLayout'].removeRow(widget_number) + return qwidget, qlabel self.getWidget(name, 'field').setParent(None) - formLayout.removeRow(self.widget_number_dictionary[name]) - self._popWidgetFromDictionary(self.getWidgets(), name) - self._popWidgetNumberDictionary(name) + qwidget = self._popWidgetFromDictionary(self.getWidgets(), name) + self.uiElements['groupBoxFormLayout'].removeRow(widget_number) + return qwidget + def getWidget(self, name, role='field'): ''' @@ -231,13 +211,11 @@ def getWidget(self, name, role='field'): return self.widgets[f'{name}_{role}'] raise ValueError(f'Unexpected role: expected any of {allowed_roles}, got {role}') - def getWidgetNumber(self, name): - '''Returns the widget number by the widget name.''' - return self.widget_number_dictionary[f'{name}'] - - def getWidgetNumberDictionary(self): - '''Returns the widget number dictionary.''' - return self.widget_number_dictionary + def getWidgetNumber(self, name, role = 'field'): + ''' + Returns the widget number by the widget name. This is the row of the widget in the form layout. + ''' + return self.uiElements['groupBoxFormLayout'].getWidgetPosition(self.getWidget(name, role))[0] def setWidgetVisible(self, name, visible): ''' @@ -262,10 +240,6 @@ def getWidgets(self): '''Returns a dictionary of the widgets currently present in the form.''' return self.widgets - def getRemovedWidgets(self): - '''Returns the dictionary of the removed widgets previously present in the form.''' - return self.removed_widgets_dictionary - def addTitle(self, qlabel, name): if isinstance(qlabel, str): txt = qlabel @@ -379,7 +353,7 @@ def getWidgetState(self, widget, role=None): elif isinstance(widget, (QtWidgets.QTextEdit, QtWidgets.QPlainTextEdit)): widget_state['value'] = widget.toPlainText() - widget_state['widget_number'] = self.widget_number_dictionary[name] + widget_state['widget_number'] = self.getWidgetNumber(name, role) return widget_state def _getNameAndRoleFromKey(self, key): @@ -442,10 +416,7 @@ def applyWidgetState(self, name, state, role=None): # retrieve widget try: - if name_role in self.widgets.keys(): - widget = self.widgets[name_role] - elif name_role in self.removed_widgets_dictionary.keys(): - widget = self.removed_widgets_dictionary[name_role] + widget = self.widgets[name_role] except KeyError: raise KeyError(f'No widget associated with the dictionary key `{name_role}`.') # apply state @@ -473,9 +444,6 @@ def applyWidgetState(self, name, state, role=None): widget.setChecked(value) elif isinstance(widget, (QtWidgets.QTextEdit, QtWidgets.QPlainTextEdit)): widget.setPlainText(value) - elif key == 'widget_number': - if value != self.widget_number_dictionary[name]: - self.widget_number_dictionary[name] = value def applyWidgetStates(self, states): ''' @@ -602,16 +570,20 @@ def insertWidgetToFormLayout(self, row, name, qwidget, qlabel=None): def removeWidget(self, name): ''' - Removes the widget with name `name` from the widgets in the form layout. In particular, - it deletes the row in the form layout, the qwidget and qlabel from the widgets dictionary - and the widget number from the widget-number dictionary. Sets the parent of the qwidget, - and qlabel if present, to `None` allowing to store the removed widget in the - removed-widgets dictionary. + Removes the widget with the specified name from the form layout. + This method delete the qwidget, and qlabel if present, from the widgets dictionary + and sets their parent to `None`. Parameters: -------------- name : str - name of the widget to be removed + The name of the widget to be removed. + + Returns: + -------------- + tuple or QWidget + If the widget has a corresponding label, a tuple containing the widget and label is returned. + Otherwise, only the widget is returned. ''' self.widget().removeWidget(name) @@ -634,17 +606,11 @@ def getWidgets(self): '''Returns a dictionary of the widgets currently present in the form.''' return self.widget().getWidgets() - def getWidgetNumber(self, name): - '''Returns the widget number by the widget name.''' - return self.widget().getWidgetNumber(name) - - def getWidgetNumberDictionary(self): - '''Returns the widget number dictionary.''' - return self.widget().getWidgetNumberDictionary() - - def getRemovedWidgets(self): - '''Returns the dictionary of the removed widgets previously present in the form.''' - return self.widget().getRemovedWidgets() + def getWidgetNumber(self, name, role = 'field'): + ''' + Returns the widget number by the widget name. This is the row of the widget in the form layout. + ''' + return self.widget().getWidgetNumber(name, role) def setWidgetVisible(self, name, visible): ''' diff --git a/test/test__formUI_status_test.py b/test/test__formUI_status_test.py index eca6904..2e3ee94 100644 --- a/test/test__formUI_status_test.py +++ b/test/test__formUI_status_test.py @@ -161,7 +161,6 @@ def _test_remove_one_widget(self, name): self.assertEqual(prenumwidgets, postnumwidgets + 1) self.assertEqual(prerowcount, postrowcount + 1) self.assertEqual(postrowcount, postnumwidgets) - self.assertEqual(self.form.getRemovedWidgets()[f'{name}_field'], qwidget) def test_remove_every_widget(self): """Remove every widget from the form.""" From 3199989cd3a2331d975253219dbb774e67f5ebd4 Mon Sep 17 00:00:00 2001 From: Danica Sugic Date: Tue, 30 Jan 2024 13:51:08 +0000 Subject: [PATCH 78/96] Change docstring --- eqt/ui/FormDialog.py | 2 +- eqt/ui/UIFormWidget.py | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/eqt/ui/FormDialog.py b/eqt/ui/FormDialog.py index a0ea1ac..55dd4a0 100644 --- a/eqt/ui/FormDialog.py +++ b/eqt/ui/FormDialog.py @@ -122,7 +122,7 @@ def insertWidgetToFormLayout(self, row, name, qwidget, qlabel=None): The position in the form is specified by row. If row is out of bounds, the widget is added at the end of the form. An error is raised if `name` is already in use by another widget in the form. The entries associated with the widget are added - to the widget dictionary, the widget-number dictionary, and the default-widget-states + to the widget dictionary and the default-widget-states dictionary. Parameters: diff --git a/eqt/ui/UIFormWidget.py b/eqt/ui/UIFormWidget.py index f366241..9976922 100644 --- a/eqt/ui/UIFormWidget.py +++ b/eqt/ui/UIFormWidget.py @@ -58,7 +58,7 @@ def insertWidgetToFormLayout(self, row, name, qwidget, qlabel=None): The position in the form is specified by row. If row is out of bounds, the widget is added at the end of the form. An error is raised if `name` is already in use by another widget in the form. The entries associated with the widget are added - to the widget dictionary, the widget-number dictionary, and the default-widget-states + to the widget dictionary and the default-widget-states dictionary. Parameters: @@ -550,7 +550,7 @@ def insertWidgetToFormLayout(self, row, name, qwidget, qlabel=None): The position in the form is specified by row. If row is out of bounds, the widget is added at the end of the form. An error is raised if `name` is already in use by another widget in the form. The entries associated with the widget are added - to the widget dictionary, the widget-number dictionary, and the default-widget-states + to the widget dictionary and the default-widget-states dictionary. Parameters: From 28a82f6d0008640c35b6fb4c4667396261890606 Mon Sep 17 00:00:00 2001 From: Danica Sugic Date: Tue, 30 Jan 2024 13:56:57 +0000 Subject: [PATCH 79/96] Change docstring --- eqt/ui/FormDialog.py | 9 +++++---- eqt/ui/UIFormWidget.py | 27 +++++++++++++++------------ 2 files changed, 20 insertions(+), 16 deletions(-) diff --git a/eqt/ui/FormDialog.py b/eqt/ui/FormDialog.py index 55dd4a0..7449ed9 100644 --- a/eqt/ui/FormDialog.py +++ b/eqt/ui/FormDialog.py @@ -172,8 +172,8 @@ def removeWidget(self, name): Returns: -------------- tuple or QWidget - If the widget has a corresponding label, a tuple containing the widget and label is returned. - Otherwise, only the widget is returned. + If the widget has a corresponding label, a tuple containing the widget + and label is returned. Otherwise, only the widget is returned. ''' self.formWidget.removeWidget(name) @@ -196,9 +196,10 @@ def getWidgets(self): '''Returns a dictionary of the widgets currently present in the form.''' return self.formWidget.getWidgets() - def getWidgetNumber(self, name, role = 'field'): + def getWidgetNumber(self, name, role='field'): ''' - Returns the widget number by the widget name. This is the row of the widget in the form layout. + Returns the widget number by the widget name. + This is the row of the widget in the form layout. ''' return self.formWidget.getWidgetNumber(name, role) diff --git a/eqt/ui/UIFormWidget.py b/eqt/ui/UIFormWidget.py index 9976922..3f4ba06 100644 --- a/eqt/ui/UIFormWidget.py +++ b/eqt/ui/UIFormWidget.py @@ -110,7 +110,7 @@ def _popWidgetFromDictionary(self, dictionary, name): Returns: ------- - qwidget : QWidget + qwidget : QWidget The removed widget associated with `name`, if it exists in the dictionary. qlabel : QLabel, optional @@ -127,7 +127,8 @@ def _popWidgetFromDictionary(self, dictionary, name): elif f'{name}_field' in dictionary.keys(): qwidget = dictionary.pop(f'{name}_field') else: - raise KeyError(f'No widget associated with the dictionary key `{name}` or `{name}_field`.') + raise KeyError( + f'No widget associated with the dictionary key `{name}` or `{name}_field`.') if f'{name}_label' in dictionary.keys(): qlabel = dictionary.pop(f'{name}_label') return qwidget, qlabel @@ -184,8 +185,8 @@ def removeWidget(self, name): Returns: -------------- tuple or QWidget - If the widget has a corresponding label, a tuple containing the widget and label is returned. - Otherwise, only the widget is returned. + If the widget has a corresponding label, a tuple containing the widget + and label is returned. Otherwise, only the widget is returned. ''' widget_number = self.getWidgetNumber(name) if f'{name}_label' in self.getWidgets().keys(): @@ -198,7 +199,6 @@ def removeWidget(self, name): self.uiElements['groupBoxFormLayout'].removeRow(widget_number) return qwidget - def getWidget(self, name, role='field'): ''' Returns the widget by the name with which it has been added. @@ -211,11 +211,13 @@ def getWidget(self, name, role='field'): return self.widgets[f'{name}_{role}'] raise ValueError(f'Unexpected role: expected any of {allowed_roles}, got {role}') - def getWidgetNumber(self, name, role = 'field'): + def getWidgetNumber(self, name, role='field'): ''' - Returns the widget number by the widget name. This is the row of the widget in the form layout. + Returns the widget number by the widget name. + This is the row of the widget in the form layout. ''' - return self.uiElements['groupBoxFormLayout'].getWidgetPosition(self.getWidget(name, role))[0] + return self.uiElements['groupBoxFormLayout'].getWidgetPosition(self.getWidget(name, + role))[0] def setWidgetVisible(self, name, visible): ''' @@ -582,8 +584,8 @@ def removeWidget(self, name): Returns: -------------- tuple or QWidget - If the widget has a corresponding label, a tuple containing the widget and label is returned. - Otherwise, only the widget is returned. + If the widget has a corresponding label, a tuple containing the widget + and label is returned. Otherwise, only the widget is returned. ''' self.widget().removeWidget(name) @@ -606,9 +608,10 @@ def getWidgets(self): '''Returns a dictionary of the widgets currently present in the form.''' return self.widget().getWidgets() - def getWidgetNumber(self, name, role = 'field'): + def getWidgetNumber(self, name, role='field'): ''' - Returns the widget number by the widget name. This is the row of the widget in the form layout. + Returns the widget number by the widget name. + This is the row of the widget in the form layout. ''' return self.widget().getWidgetNumber(name, role) From 07dd2c152382fcd95af0d46211f65f3e5b7b9df7 Mon Sep 17 00:00:00 2001 From: Danica Sugic Date: Tue, 30 Jan 2024 14:08:53 +0000 Subject: [PATCH 80/96] Update changelog --- CHANGELOG.md | 11 +++++------ 1 file changed, 5 insertions(+), 6 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index b33d6fb..575a51c 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,10 +1,9 @@ # Version x.x.x -- Adds the methods to insert widgets in the forms, their unit tests, and the example file. - `_addWidget` is removed and substituted by an insert method. - Adds a dictionary of removed widgets. - Adds the widget-number dictionary and saves the widget number as a value in the widget-states dictionary. - Adds a method to get the name and role of a widget from a dictionary key. - Changes the attribute representing the number of widgets in the form to be the property corresponding to the number of rows in the form. (#109) +- Adds methods to insert widgets in the forms & tests/example + Removes `_addWidget` + Adds `getWidgetNumber`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) From 1c93d2c41ef31e5b42637470dbef54ee483e7e17 Mon Sep 17 00:00:00 2001 From: Casper da Costa-Luis Date: Wed, 31 Jan 2024 16:20:31 +0000 Subject: [PATCH 81/96] fixup docstrings --- eqt/ui/FormDialog.py | 76 +++++++++++++++++++++--------------------- eqt/ui/UIFormWidget.py | 16 ++++----- 2 files changed, 46 insertions(+), 46 deletions(-) diff --git a/eqt/ui/FormDialog.py b/eqt/ui/FormDialog.py index 7449ed9..57bb2c1 100644 --- a/eqt/ui/FormDialog.py +++ b/eqt/ui/FormDialog.py @@ -74,15 +74,15 @@ def addWidget(self, qwidget, qlabel=None, name=None, layout='form'): to the vertical layout if layout is 'vertical'. Parameters - ---------------- - qwidget : widget - qlabel : qlabel widget or str - only supported when layout is 'form' - name : str - only supported when layout is 'form' - layout : 'form' or 'vertical' - 'form' - adds to the FormLayout, 'vertical' - adds to the Vertical layout below - the form. + ---------- + qwidget: widget + qlabel: qlabel widget or str + Only supported for layout='form'. + name: str + Only supported for layout='form'. + layout: 'form' or 'vertical' + 'form' adds to the `FormLayout`, 'vertical' adds to the `VerticalLayout` below + the form. ''' if layout == 'vertical': if name is not None or qlabel is not None: @@ -99,10 +99,15 @@ def addWidget(self, qwidget, qlabel=None, name=None, layout='form'): def addSpanningWidget(self, qwidget, name=None, layout='form'): ''' - Adds a spanning widget occupying the full row in the layout. - layout = 'form' - adds the widget to the FormLayout - layout = 'vertical' - adds the widget to the Vertical layout below the form. - To add to the form layout, name must be passed. + Adds a widget spanning the full row in the layout. + + Parameters + ---------- + name: str + Required for `layout='form'`. + layout: 'form' or 'vertical' + 'form': adds the widget to the `FormLayout` (requires `name`). + 'vertical': adds the widget to the `VerticalLayout` below the form. ''' if layout == 'vertical': if name is not None: @@ -155,7 +160,8 @@ def removeWidgetFromVerticalLayout(self, qwidget): def getWidgetFromVerticalLayout(self, index): ''' - Returns the widget in the vertical layout located at position index.''' + Returns the widget in the vertical layout located at position index. + ''' return self.formWidget.uiElements['verticalLayout'].itemAt(index).widget() def removeWidget(self, name): @@ -164,13 +170,13 @@ def removeWidget(self, name): This method delete the qwidget, and qlabel if present, from the widgets dictionary and sets their parent to `None`. - Parameters: - -------------- - name : str + Parameters + ---------- + name: str The name of the widget to be removed. - Returns: - -------------- + Returns + ------- tuple or QWidget If the widget has a corresponding label, a tuple containing the widget and label is returned. Otherwise, only the widget is returned. @@ -205,14 +211,8 @@ def getWidgetNumber(self, name, role='field'): def setWidgetVisible(self, name, visible): ''' - Sets the visibility of the widget and associated label with the given name. - Parameters: - visible: bool - True to set the widget visible, False to hide it - name: str - The name of the widget to set visible/invisible + Sets the visibility of the named widget (and associated label). ''' - self.formWidget.setWidgetVisible(name, visible) def saveAllWidgetStates(self): @@ -241,11 +241,11 @@ def getAllWidgetStates(self): ''' Returns ------- - dict - Format: {'widget_name': {'value': str | bool | int, 'enabled': bool, 'visible': bool, - 'widget_number': int}, ...}, - e.g. {'widget1': {'value': 1, 'enabled': True, 'visible': True, 'widget_number': 0}, - 'widget2': {'value': 2, 'enabled': False, 'visible': False, 'widget_number': 1}}. + states: dict + Format: {'widget_name': {'value': str | bool | int, 'enabled': bool, 'visible': bool, + 'widget_number': int}, ...}, + e.g. {'widget1': {'value': 1, 'enabled': True, 'visible': True, 'widget_number': 0}, + 'widget2': {'value': 2, 'enabled': False, 'visible': False, 'widget_number': 1}}. ''' return self.formWidget.getAllWidgetStates() @@ -266,7 +266,7 @@ def getWidgetState(self, widget, role=None): ------- state: dict Format: {'value': str | bool | int, 'enabled': bool, 'visible': bool, - 'widget_number' : int}, + 'widget_number' : int}, e.g. {'value': 1, 'enabled': True, 'visible': True, 'widget_number' : 0}. This can be used to restore the state of the widget using `setWidgetState()`. ''' @@ -285,7 +285,7 @@ def applyWidgetState(self, name, state, role=None): The role of the widget to apply the state to. state: dict Format: {'value': str | bool | int, 'enabled': bool, 'visible': bool, - 'widget_number' : int}, + 'widget_number' : int}, e.g. {'value': 1, 'enabled': True, 'visible': True, 'widget_number' : 0}. ''' return self.formWidget.applyWidgetState(name, state, role) @@ -298,11 +298,11 @@ def applyWidgetStates(self, states): Parameters ---------- - states: nested_dict + states: dict Format: {'name_field': {'value': str | bool | int, 'enabled': bool, 'visible': bool, - 'widget_number' : int}, 'name_label': {'value': str | bool | int, 'enabled': bool, - 'visible': bool, 'widget_number' : int}, ...}. - e.g. {'widget1': {'value': 1, 'enabled': True, 'visible': True, 'widget_number' : 0}, - 'widget2': {'value': 2, 'enabled': False, 'visible': False, 'widget_number' : 1}}. + 'widget_number' : int}, 'name_label': {'value': str | bool | int, + 'enabled': bool, 'visible': bool, 'widget_number' : int}, ...}. + e.g. {'widget1': {'value': 1, 'enabled': True, 'visible': True, 'widget_number': 0}, + 'widget2': {'value': 2, 'enabled': False, 'visible': False, 'widget_number': 1}}. ''' return self.formWidget.applyWidgetStates(states) diff --git a/eqt/ui/UIFormWidget.py b/eqt/ui/UIFormWidget.py index 3f4ba06..6ad2a09 100644 --- a/eqt/ui/UIFormWidget.py +++ b/eqt/ui/UIFormWidget.py @@ -455,12 +455,12 @@ def applyWidgetStates(self, states): Parameters ---------- - states: nested_dict + states: dict Format: {'name_field': {'value': str | bool | int, 'enabled': bool, 'visible': bool, 'widget_number' : int}, 'name_label': {'value': str | bool | int, 'enabled': bool, 'visible': bool, 'widget_number' : int}, ...}. - e.g. {'widget1': {'value': 1, 'enabled': True, 'visible': True, 'widget_number' : 0}, - 'widget2': {'value': 2, 'enabled': False, 'visible': False, 'widget_number' : 1}}. + e.g. {'widget1': {'value': 1, 'enabled': True, 'visible': True, 'widget_number': 0}, + 'widget2': {'value': 2, 'enabled': False, 'visible': False, 'widget_number': 1}}. ''' if self.widgets.keys() != states.keys(): raise KeyError(f'''The widgets in the form are {self.widgets.keys()} whereas @@ -713,12 +713,12 @@ def applyWidgetStates(self, states): Parameters ---------- - states: nested_dict + states: dict Format: {'name_field': {'value': str | bool | int, 'enabled': bool, 'visible': bool, - 'widget_number' : int}, 'name_label': {'value': str | bool | int, 'enabled': bool, - 'visible': bool, 'widget_number' : int}, ...}. - e.g. {'widget1': {'value': 1, 'enabled': True, 'visible': True, 'widget_number' : 0}, - 'widget2': {'value': 2, 'enabled': False, 'visible': False, 'widget_number' : 1}}. + 'widget_number' : int}, 'name_label': {'value': str | bool | int, + 'enabled': bool, 'visible': bool, 'widget_number' : int}, ...}. + e.g. {'widget1': {'value': 1, 'enabled': True, 'visible': True, 'widget_number': 0}, + 'widget2': {'value': 2, 'enabled': False, 'visible': False, 'widget_number': 1}}. ''' return self.widget().applyWidgetStates(states) From 77b56a7cb6f6f0c1f43c62efa17f091fafb318e7 Mon Sep 17 00:00:00 2001 From: Casper da Costa-Luis Date: Wed, 31 Jan 2024 16:20:50 +0000 Subject: [PATCH 82/96] misc tidy --- eqt/ui/UIFormWidget.py | 68 +++++++++++++----------------- eqt/ui/UIMultiStepWidget.py | 15 ++----- examples/insert_widgets_example.py | 12 +++--- test/test__formUI_status_test.py | 13 +++--- 4 files changed, 45 insertions(+), 63 deletions(-) diff --git a/eqt/ui/UIFormWidget.py b/eqt/ui/UIFormWidget.py index 6ad2a09..7b8b2d6 100644 --- a/eqt/ui/UIFormWidget.py +++ b/eqt/ui/UIFormWidget.py @@ -21,6 +21,13 @@ class UIFormWidget: | | +----------------------------------------------------------+ ''' + def __init__(self, *args, **kwargs): + super().__init__(*args, **kwargs) + # Format: {'value': str | bool | int, 'enabled': bool, 'visible': bool, + # 'widget_number': int}. + # Can be used to restore the default states of the widgets invoking `applyWidgetStates`. + self.default_widget_states = {} + def createForm(self): # Add vertical layout to dock contents verticalLayout = QtWidgets.QVBoxLayout(self) @@ -74,9 +81,8 @@ def insertWidgetToFormLayout(self, row, name, qwidget, qlabel=None): on the left hand side of the form. If qlabel is `None` the widget spans the full width of the form. ''' - if f'{name}_field' in self.widgets.keys(): - raise ValueError(f'''The name of widget you are trying to insert, {name}, - is used already. Choose another name.''') + if f'{name}_field' in self.widgets: + raise KeyError(f"Widget name ({name}) already defined. Choose another name.") formLayout = self.uiElements['groupBoxFormLayout'] @@ -88,16 +94,18 @@ def insertWidgetToFormLayout(self, row, name, qwidget, qlabel=None): formLayout.insertRow(row, qlabel, qwidget) else: formLayout.insertRow(row, qwidget) - self._addToWidgetDictionary(self.widgets, name, qwidget, qlabel) - self._addToDefaultWidgetStatesDictionary(name) - def _addToWidgetDictionary(self, dictionary, name, qwidget, qlabel=None): - '''Adds the field, and label if present, in the widget dictionary.''' - dictionary[f'{name}_field'] = qwidget + self.widgets[f'{name}_field'] = qwidget if qlabel is not None: - dictionary[f'{name}_label'] = qlabel + self.widgets[f'{name}_label'] = qlabel + + # add the default state of the qwidget + self.default_widget_states[f'{name}_field'] = self.getWidgetState(name, 'field') + # add the default state of the qlabel + if f'{name}_label' in self.widgets: + self.default_widget_states[f'{name}_label'] = self.getWidgetState(name, 'label') - def _popWidgetFromDictionary(self, dictionary, name): + def _popWidget(self, dictionary, name): ''' Removes the item(s) associated with `name` from a dictionary. @@ -122,18 +130,17 @@ def _popWidgetFromDictionary(self, dictionary, name): If no widget associated with the dictionary key `name` or `{name}_field` is found. ''' - if name in dictionary.keys(): + if name in dictionary: qwidget = dictionary.pop(name) - elif f'{name}_field' in dictionary.keys(): + elif f'{name}_field' in dictionary: qwidget = dictionary.pop(f'{name}_field') else: raise KeyError( f'No widget associated with the dictionary key `{name}` or `{name}_field`.') - if f'{name}_label' in dictionary.keys(): + if f'{name}_label' in dictionary: qlabel = dictionary.pop(f'{name}_label') return qwidget, qlabel - else: - return qwidget + return qwidget def addWidget(self, qwidget, qlabel, name): ''' @@ -189,13 +196,13 @@ def removeWidget(self, name): and label is returned. Otherwise, only the widget is returned. ''' widget_number = self.getWidgetNumber(name) - if f'{name}_label' in self.getWidgets().keys(): + if f'{name}_label' in self.widgets: self.getWidget(name, 'label').setParent(None) - qwidget, qlabel = self._popWidgetFromDictionary(self.getWidgets(), name) + qwidget, qlabel = self._popWidget(self.widgets, name) self.uiElements['groupBoxFormLayout'].removeRow(widget_number) return qwidget, qlabel self.getWidget(name, 'field').setParent(None) - qwidget = self._popWidgetFromDictionary(self.getWidgets(), name) + qwidget = self._popWidget(self.widgets, name) self.uiElements['groupBoxFormLayout'].removeRow(widget_number) return qwidget @@ -257,27 +264,12 @@ def addSeparator(self, name): frame.setFrameShadow(QtWidgets.QFrame.Raised) self.insertWidgetToFormLayout(-1, name, frame) - def _addToDefaultWidgetStatesDictionary(self, name): - ''' - If not present already, creates an attribute dictionary of default widget states. The - entries are in the format: {'value': str | bool | int, 'enabled': bool, 'visible': bool, - 'widget_number': int}. This can be used to restore the default states of the widgets - invoking `applyWidgetStates`. - ''' - if not hasattr(self, 'default_widget_states'): - self.default_widget_states = {} - # add the default state of the qwidget - self.default_widget_states[f'{name}_field'] = self.getWidgetState(name, 'field') - # add the default state of the qlabel - if f'{name}_label' in self.widgets.keys(): - self.default_widget_states[f'{name}_label'] = self.getWidgetState(name, 'label') - def setDefaultWidgetStatesVisibleTrue(self): ''' Sets all of the entries 'visible' in the `default_widget_states` dictionary to be `True`. ''' - for key in self.default_widget_states.keys(): - self.default_widget_states[key]['visible'] = True + for state in self.default_widget_states.values(): + state['visible'] = True def getAllWidgetStates(self): ''' @@ -462,10 +454,8 @@ def applyWidgetStates(self, states): e.g. {'widget1': {'value': 1, 'enabled': True, 'visible': True, 'widget_number': 0}, 'widget2': {'value': 2, 'enabled': False, 'visible': False, 'widget_number': 1}}. ''' - if self.widgets.keys() != states.keys(): - raise KeyError(f'''The widgets in the form are {self.widgets.keys()} whereas - the widgets in the states are {states.keys()}. These must be - equal for the states to be applied to the form.''') + if set(self.widgets) != set(states): + raise KeyError("states={set(states)} do not match Form widgets ({set(self.widgets)})") for key, widget_state in states.items(): name, role = self._getNameAndRoleFromKey(key) self.applyWidgetState(name, widget_state, role) diff --git a/eqt/ui/UIMultiStepWidget.py b/eqt/ui/UIMultiStepWidget.py index f87207b..359d00b 100644 --- a/eqt/ui/UIMultiStepWidget.py +++ b/eqt/ui/UIMultiStepWidget.py @@ -51,25 +51,18 @@ def createWidget(self): self.widgets = {} def updateStep(self, go_to="next"): - steps = list(self.widgets.keys()) + steps = list(self.widgets) step_widgets = list(self.widgets.values()) current_step_index = steps.index(self.current_step) if go_to == 'next': self.prev_button.setEnabled(True) next_index = current_step_index + 1 - if next_index == len(steps) - 1: - self.next_button.setEnabled(False) - else: - self.next_button.setEnabled(True) - - if go_to == 'prev': + self.next_button.setEnabled(next_index == len(steps) - 1) + elif go_to == 'prev': self.next_button.setEnabled(True) next_index = current_step_index - 1 - if next_index == 0: - self.prev_button.setEnabled(False) - else: - self.prev_button.setEnabled(True) + self.prev_button.setEnabled(next_index == 0) self.current_step = steps[next_index] diff --git a/examples/insert_widgets_example.py b/examples/insert_widgets_example.py index ed234f0..c05b665 100644 --- a/examples/insert_widgets_example.py +++ b/examples/insert_widgets_example.py @@ -15,7 +15,7 @@ def __init__(self, parent=None): buttoninsertvertical = QtWidgets.QPushButton() buttoninsertvertical.setText("Insert widget in vertical layout") self.dialog.addSpanningWidget(buttoninsertvertical, 'Button insert vertical') - buttoninsertvertical.clicked.connect(lambda: self.insert_vertical()) + buttoninsertvertical.clicked.connect(self.insert_vertical) # create a FormDockWidget dock = UIFormWidget.FormDockWidget(parent=self) @@ -25,7 +25,7 @@ def __init__(self, parent=None): # create button for Form Dialog pb = QtWidgets.QPushButton(self) pb.setText("Open Form Dialog") - pb.clicked.connect(lambda: self.openFormDialog()) + pb.clicked.connect(self.openFormDialog) # create window layout layout = QtWidgets.QHBoxLayout() @@ -82,10 +82,10 @@ def onCancel(self): self.dialog.getWidgetFromVerticalLayout(1)) if self.dialog.getWidget('Button insert widgets').isEnabled() is False: - self.dialog.formWidget._popWidgetFromDictionary( - self.dialog.formWidget.default_widget_states, 'inserted widget') - self.dialog.formWidget._popWidgetFromDictionary( - self.dialog.formWidget.default_widget_states, 'inserted spanning widget') + self.dialog.formWidget._popWidget(self.dialog.formWidget.default_widget_states, + 'inserted widget') + self.dialog.formWidget._popWidget(self.dialog.formWidget.default_widget_states, + 'inserted spanning widget') self.dialog.formWidget.removeWidget('inserted widget') self.dialog.formWidget.removeWidget('inserted spanning widget') else: diff --git a/test/test__formUI_status_test.py b/test/test__formUI_status_test.py index 2e3ee94..92e3fa2 100644 --- a/test/test__formUI_status_test.py +++ b/test/test__formUI_status_test.py @@ -65,13 +65,13 @@ def state_simple_form(self): def add_every_widget(self): """Generate every widget and add it to the form.""" form = self.form - for key in self.list_all_widgets.keys(): + for key in self.list_all_widgets: form.addWidget(self.list_all_widgets[key], key, key) def add_every_spanning_widget(self): """Generate every spanning widget and add it to the form.""" form = self.form - for key in self.list_all_widgets.keys(): + for key in self.list_all_widgets: form.addSpanningWidget(self.list_all_widgets[key], f'{key}_spanning') def add_two_widgets(self): @@ -132,8 +132,7 @@ def test_insert_every_widget(self): Inserts each widget, and then each spanning widget, in position 0 of the form layout. Tests the position of the widgets in the layout is 0. """ - for key in self.list_all_widgets.keys(): - qwidget = self.list_all_widgets[key] + for key, qwidget in self.list_all_widgets.items(): name = f'{key}_insert' self._test_insert_one_widget(0, name, qwidget, name) qwidget = self.list_all_widgets[key] @@ -164,7 +163,7 @@ def _test_remove_one_widget(self, name): def test_remove_every_widget(self): """Remove every widget from the form.""" - for name in self.list_all_widgets.keys(): + for name in self.list_all_widgets: self._test_remove_one_widget(name) def test_getWidgetState_returns_visibility(self): @@ -471,7 +470,7 @@ def test_insert_every_widget_to_vertical_layout(self): Inserts each widget in position 0 of the vertical layout and tests its position in the layout is 0. """ - for key in self.list_all_widgets.keys(): + for key in self.list_all_widgets: self._test_insert_one_widget_to_vertical_layout(0, self.list_all_widgets[key]) def test_getWidgetState_returns_QLabel_value(self): @@ -546,7 +545,7 @@ def test_get_name_and_role_from_key_or_widget(self): Checks that the method `_getNameAndRoleFromKey` returns the correct name and role in all widgets. """ - for name in self.list_all_widgets.keys(): + for name in self.list_all_widgets: for role in {'field', 'label'}: name_role = name + '_' + role name_c, role_c = self.form._getNameAndRoleFromKey(name_role) From 7f490fedb714176cc7768ce2e36df579d54b0cc8 Mon Sep 17 00:00:00 2001 From: Casper da Costa-Luis Date: Wed, 31 Jan 2024 16:44:50 +0000 Subject: [PATCH 83/96] more whitespace fixes --- eqt/ui/FormDialog.py | 2 +- eqt/ui/UIFormWidget.py | 46 ++++++++++++++++++++---------------------- 2 files changed, 23 insertions(+), 25 deletions(-) diff --git a/eqt/ui/FormDialog.py b/eqt/ui/FormDialog.py index 57bb2c1..861543c 100644 --- a/eqt/ui/FormDialog.py +++ b/eqt/ui/FormDialog.py @@ -130,7 +130,7 @@ def insertWidgetToFormLayout(self, row, name, qwidget, qlabel=None): to the widget dictionary and the default-widget-states dictionary. - Parameters: + Parameters ---------- row: int The position in the form where the widget is added. diff --git a/eqt/ui/UIFormWidget.py b/eqt/ui/UIFormWidget.py index 7b8b2d6..d9fb664 100644 --- a/eqt/ui/UIFormWidget.py +++ b/eqt/ui/UIFormWidget.py @@ -68,7 +68,7 @@ def insertWidgetToFormLayout(self, row, name, qwidget, qlabel=None): to the widget dictionary and the default-widget-states dictionary. - Parameters: + Parameters ---------- row: int The position in the form where the widget is added. @@ -109,26 +109,24 @@ def _popWidget(self, dictionary, name): ''' Removes the item(s) associated with `name` from a dictionary. - Parameters: - ----------------- - dictionary : dict + Parameters + ---------- + dictionary: dict The dictionary from which to remove the items. - name : str + name: str The name of the item(s) to be removed. - Returns: + Returns ------- - qwidget : QWidget + qwidget: QWidget The removed widget associated with `name`, if it exists in the dictionary. - - qlabel : QLabel, optional + qlabel: QLabel, optional The removed label associated with `name`, if it exists in the dictionary. - Raises: + Raises ------ KeyError If no widget associated with the dictionary key `name` or `{name}_field` is found. - ''' if name in dictionary: qwidget = dictionary.pop(name) @@ -147,7 +145,7 @@ def addWidget(self, qwidget, qlabel, name): Adds a widget and a label widget at the the end of the form layout. - Parameters: + Parameters ---------- qwidget: widget The widget to be added on the right hand side of the form. @@ -163,7 +161,7 @@ def addSpanningWidget(self, qwidget, name): ''' Adds a spanning qwidget occupying the full row in the form layout. - Parameters: + Parameters ---------- qwidget: widget The widget to be added on the form. @@ -184,13 +182,13 @@ def removeWidget(self, name): This method delete the qwidget, and qlabel if present, from the widgets dictionary and sets their parent to `None`. - Parameters: - -------------- - name : str + Parameters + ---------- + name: str The name of the widget to be removed. - Returns: - -------------- + Returns + ------- tuple or QWidget If the widget has a corresponding label, a tuple containing the widget and label is returned. Otherwise, only the widget is returned. @@ -511,7 +509,7 @@ def addWidget(self, qwidget, qlabel, name): Adds a widget and a label widget at the the end of the form layout. - Parameters: + Parameters ---------- qwidget: widget The widget to be added on the right hand side of the form. @@ -527,7 +525,7 @@ def addSpanningWidget(self, qwidget, name): ''' Adds a spanning qwidget occupying the full row in the form layout. - Parameters: + Parameters ---------- qwidget: widget The widget to be added on the form. @@ -545,7 +543,7 @@ def insertWidgetToFormLayout(self, row, name, qwidget, qlabel=None): to the widget dictionary and the default-widget-states dictionary. - Parameters: + Parameters ---------- row: int The position in the form where the widget is added. @@ -566,9 +564,9 @@ def removeWidget(self, name): This method delete the qwidget, and qlabel if present, from the widgets dictionary and sets their parent to `None`. - Parameters: - -------------- - name : str + Parameters + ---------- + name: str The name of the widget to be removed. Returns: From 325d45e0823a52a91167530433cd338c1f8ac311 Mon Sep 17 00:00:00 2001 From: Danica Sugic Date: Thu, 1 Feb 2024 11:46:20 +0000 Subject: [PATCH 84/96] Change docstring --- eqt/ui/FormDialog.py | 77 ++++++++++++++++++++++---------------------- 1 file changed, 39 insertions(+), 38 deletions(-) diff --git a/eqt/ui/FormDialog.py b/eqt/ui/FormDialog.py index 861543c..c80ff20 100644 --- a/eqt/ui/FormDialog.py +++ b/eqt/ui/FormDialog.py @@ -75,14 +75,14 @@ def addWidget(self, qwidget, qlabel=None, name=None, layout='form'): Parameters ---------- - qwidget: widget - qlabel: qlabel widget or str - Only supported for layout='form'. - name: str - Only supported for layout='form'. - layout: 'form' or 'vertical' - 'form' adds to the `FormLayout`, 'vertical' adds to the `VerticalLayout` below - the form. + qwidget : widget + qlabel : qlabel widget or str + only supported when layout is 'form' + name : str + only supported when layout is 'form' + layout : 'form' or 'vertical' + 'form' - adds to the `groupBoxFormLayout`, 'vertical' - adds to the `verticalLayout` below + the form. ''' if layout == 'vertical': if name is not None or qlabel is not None: @@ -99,15 +99,10 @@ def addWidget(self, qwidget, qlabel=None, name=None, layout='form'): def addSpanningWidget(self, qwidget, name=None, layout='form'): ''' - Adds a widget spanning the full row in the layout. - - Parameters - ---------- - name: str - Required for `layout='form'`. - layout: 'form' or 'vertical' - 'form': adds the widget to the `FormLayout` (requires `name`). - 'vertical': adds the widget to the `VerticalLayout` below the form. + Adds a spanning widget occupying the full row in the layout. + layout = 'form' - adds the widget to the form layout + layout = 'vertical' - adds the widget to the vertical layout below the form. + To add to the form layout, name must be passed. ''' if layout == 'vertical': if name is not None: @@ -132,13 +127,13 @@ def insertWidgetToFormLayout(self, row, name, qwidget, qlabel=None): Parameters ---------- - row: int + row : int The position in the form where the widget is added. - name: str + name : str The string associated to the qwidget and qlabel. - qwidget: widget + qwidget : widget The widget to be added on the right hand side of the form or as a spanning widget. - qlabel: qlabel widget or str + qlabel : qlabel widget or str The qlabel widget, or a str from which a qlabel widget is created, to be added on the left hand side of the form. If qlabel is `None` the widget spans the full width of the form. @@ -160,8 +155,7 @@ def removeWidgetFromVerticalLayout(self, qwidget): def getWidgetFromVerticalLayout(self, index): ''' - Returns the widget in the vertical layout located at position index. - ''' + Returns the widget in the vertical layout located at position index.''' return self.formWidget.uiElements['verticalLayout'].itemAt(index).widget() def removeWidget(self, name): @@ -172,7 +166,7 @@ def removeWidget(self, name): Parameters ---------- - name: str + name : str The name of the widget to be removed. Returns @@ -211,7 +205,14 @@ def getWidgetNumber(self, name, role='field'): def setWidgetVisible(self, name, visible): ''' - Sets the visibility of the named widget (and associated label). + Sets the visibility of the widget associated with name, and that of its label if present. + + Parameters + ---------- + visible: bool + True to set the widget visible, False to hide it + name: str + The name of the widget to set visible/invisible ''' self.formWidget.setWidgetVisible(name, visible) @@ -241,11 +242,11 @@ def getAllWidgetStates(self): ''' Returns ------- - states: dict - Format: {'widget_name': {'value': str | bool | int, 'enabled': bool, 'visible': bool, - 'widget_number': int}, ...}, - e.g. {'widget1': {'value': 1, 'enabled': True, 'visible': True, 'widget_number': 0}, - 'widget2': {'value': 2, 'enabled': False, 'visible': False, 'widget_number': 1}}. + dict + Format: {'widget_name': {'value': str | bool | int, 'enabled': bool, 'visible': bool, + 'widget_number': int}, ...}, + e.g. {'widget1': {'value': 1, 'enabled': True, 'visible': True, 'widget_number': 0}, + 'widget2': {'value': 2, 'enabled': False, 'visible': False, 'widget_number': 1}}. ''' return self.formWidget.getAllWidgetStates() @@ -264,9 +265,9 @@ def getWidgetState(self, widget, role=None): Returns ------- - state: dict + dict Format: {'value': str | bool | int, 'enabled': bool, 'visible': bool, - 'widget_number' : int}, + 'widget_number' : int}, e.g. {'value': 1, 'enabled': True, 'visible': True, 'widget_number' : 0}. This can be used to restore the state of the widget using `setWidgetState()`. ''' @@ -285,7 +286,7 @@ def applyWidgetState(self, name, state, role=None): The role of the widget to apply the state to. state: dict Format: {'value': str | bool | int, 'enabled': bool, 'visible': bool, - 'widget_number' : int}, + 'widget_number' : int}, e.g. {'value': 1, 'enabled': True, 'visible': True, 'widget_number' : 0}. ''' return self.formWidget.applyWidgetState(name, state, role) @@ -298,11 +299,11 @@ def applyWidgetStates(self, states): Parameters ---------- - states: dict + states: nested_dict Format: {'name_field': {'value': str | bool | int, 'enabled': bool, 'visible': bool, - 'widget_number' : int}, 'name_label': {'value': str | bool | int, - 'enabled': bool, 'visible': bool, 'widget_number' : int}, ...}. - e.g. {'widget1': {'value': 1, 'enabled': True, 'visible': True, 'widget_number': 0}, - 'widget2': {'value': 2, 'enabled': False, 'visible': False, 'widget_number': 1}}. + 'widget_number' : int}, 'name_label': {'value': str | bool | int, 'enabled': bool, + 'visible': bool, 'widget_number' : int}, ...}. + e.g. {'widget1': {'value': 1, 'enabled': True, 'visible': True, 'widget_number' : 0}, + 'widget2': {'value': 2, 'enabled': False, 'visible': False, 'widget_number' : 1}}. ''' return self.formWidget.applyWidgetStates(states) From b19c095998c6fc7bad893e3ae387b341881ff6fd Mon Sep 17 00:00:00 2001 From: Danica Sugic Date: Thu, 1 Feb 2024 12:32:21 +0000 Subject: [PATCH 85/96] Fix tests --- eqt/ui/UIFormWidget.py | 59 +++++++++++++----------------- examples/insert_widgets_example.py | 4 +- 2 files changed, 27 insertions(+), 36 deletions(-) diff --git a/eqt/ui/UIFormWidget.py b/eqt/ui/UIFormWidget.py index d9fb664..9722e06 100644 --- a/eqt/ui/UIFormWidget.py +++ b/eqt/ui/UIFormWidget.py @@ -23,10 +23,6 @@ class UIFormWidget: ''' def __init__(self, *args, **kwargs): super().__init__(*args, **kwargs) - # Format: {'value': str | bool | int, 'enabled': bool, 'visible': bool, - # 'widget_number': int}. - # Can be used to restore the default states of the widgets invoking `applyWidgetStates`. - self.default_widget_states = {} def createForm(self): # Add vertical layout to dock contents @@ -50,6 +46,7 @@ def createForm(self): 'verticalLayout': verticalLayout, 'groupBox': groupBox, 'groupBoxFormLayout': groupBoxFormLayout} self.widgets = {} + self.default_widget_states = {} @property def num_widgets(self): @@ -70,13 +67,13 @@ def insertWidgetToFormLayout(self, row, name, qwidget, qlabel=None): Parameters ---------- - row: int + row : int The position in the form where the widget is added. - name: str + name : str The string associated to the qwidget and qlabel. - qwidget: widget + qwidget : widget The widget to be added on the right hand side of the form or as a spanning widget. - qlabel: qlabel widget or str + qlabel : qlabel widget or str The qlabel widget, or a str from which a qlabel widget is created, to be added on the left hand side of the form. If qlabel is `None` the widget spans the full width of the form. @@ -92,35 +89,31 @@ def insertWidgetToFormLayout(self, row, name, qwidget, qlabel=None): qlabel = QtWidgets.QLabel(self) qlabel.setText(txt) formLayout.insertRow(row, qlabel, qwidget) + self.widgets[f'{name}_label'] = qlabel + self.default_widget_states[f'{name}_label'] = self.getWidgetState(name, 'label') + else: formLayout.insertRow(row, qwidget) - + self.widgets[f'{name}_field'] = qwidget - if qlabel is not None: - self.widgets[f'{name}_label'] = qlabel - - # add the default state of the qwidget self.default_widget_states[f'{name}_field'] = self.getWidgetState(name, 'field') - # add the default state of the qlabel - if f'{name}_label' in self.widgets: - self.default_widget_states[f'{name}_label'] = self.getWidgetState(name, 'label') - + def _popWidget(self, dictionary, name): ''' Removes the item(s) associated with `name` from a dictionary. Parameters ---------- - dictionary: dict + dictionary : dict The dictionary from which to remove the items. - name: str + name : str The name of the item(s) to be removed. Returns ------- - qwidget: QWidget + qwidget : QWidget The removed widget associated with `name`, if it exists in the dictionary. - qlabel: QLabel, optional + qlabel : QLabel, optional The removed label associated with `name`, if it exists in the dictionary. Raises @@ -147,12 +140,12 @@ def addWidget(self, qwidget, qlabel, name): Parameters ---------- - qwidget: widget + qwidget : widget The widget to be added on the right hand side of the form. - qlabel: qlabel widget or str + qlabel : qlabel widget or str The qlabel widget, or a str from which a qlabel widget is created, to be added on the left hand side of the form. - name: str + name : str The string associated to the qwidget and qlabel. ''' self.insertWidgetToFormLayout(-1, name, qwidget, qlabel) @@ -163,9 +156,9 @@ def addSpanningWidget(self, qwidget, name): Parameters ---------- - qwidget: widget + qwidget : widget The widget to be added on the form. - name: str + name : str The string associated to the qwidget. ''' self.insertWidgetToFormLayout(-1, name, qwidget) @@ -184,7 +177,7 @@ def removeWidget(self, name): Parameters ---------- - name: str + name : str The name of the widget to be removed. Returns @@ -230,9 +223,9 @@ def setWidgetVisible(self, name, visible): Parameters ---------- - name: str + name : str The name of the widget to set visible/invisible - visible: bool + visible : bool True to set the widget visible, False to hide it ''' allowed_roles = ['field', 'label'] @@ -445,7 +438,7 @@ def applyWidgetStates(self, states): Parameters ---------- - states: dict + states : dict Format: {'name_field': {'value': str | bool | int, 'enabled': bool, 'visible': bool, 'widget_number' : int}, 'name_label': {'value': str | bool | int, 'enabled': bool, 'visible': bool, 'widget_number' : int}, ...}. @@ -453,7 +446,7 @@ def applyWidgetStates(self, states): 'widget2': {'value': 2, 'enabled': False, 'visible': False, 'widget_number': 1}}. ''' if set(self.widgets) != set(states): - raise KeyError("states={set(states)} do not match Form widgets ({set(self.widgets)})") + raise KeyError("states={set(states)} do not match form widgets ({set(self.widgets)})") for key, widget_state in states.items(): name, role = self._getNameAndRoleFromKey(key) self.applyWidgetState(name, widget_state, role) @@ -569,8 +562,8 @@ def removeWidget(self, name): name: str The name of the widget to be removed. - Returns: - -------------- + Returns + ------- tuple or QWidget If the widget has a corresponding label, a tuple containing the widget and label is returned. Otherwise, only the widget is returned. diff --git a/examples/insert_widgets_example.py b/examples/insert_widgets_example.py index c05b665..5bc3c5f 100644 --- a/examples/insert_widgets_example.py +++ b/examples/insert_widgets_example.py @@ -15,7 +15,7 @@ def __init__(self, parent=None): buttoninsertvertical = QtWidgets.QPushButton() buttoninsertvertical.setText("Insert widget in vertical layout") self.dialog.addSpanningWidget(buttoninsertvertical, 'Button insert vertical') - buttoninsertvertical.clicked.connect(self.insert_vertical) + buttoninsertvertical.clicked.connect(lambda: self.insert_vertical()) # create a FormDockWidget dock = UIFormWidget.FormDockWidget(parent=self) @@ -71,8 +71,6 @@ def insert_form(self, form, button): form.insertWidgetToFormLayout(2, 'inserted spanning widget', buttonspanning) print('\nDictionary of widgets after insertion in the form layout:\n' + str(form.getWidgets())) - print("\nDictionary of widget number in the form layout:\n" + - str(form.getWidgetNumberDictionary())) button.setEnabled(False) def onCancel(self): From 1f4bd80f5b7c7d055ec730f738e8f048a9244d89 Mon Sep 17 00:00:00 2001 From: Danica Sugic Date: Thu, 1 Feb 2024 12:59:18 +0000 Subject: [PATCH 86/96] Change docstring --- eqt/ui/FormDialog.py | 38 +++++++++++++------------- eqt/ui/UIFormWidget.py | 61 +++++++++++++++++++++--------------------- 2 files changed, 49 insertions(+), 50 deletions(-) diff --git a/eqt/ui/FormDialog.py b/eqt/ui/FormDialog.py index c80ff20..e97e641 100644 --- a/eqt/ui/FormDialog.py +++ b/eqt/ui/FormDialog.py @@ -205,14 +205,14 @@ def getWidgetNumber(self, name, role='field'): def setWidgetVisible(self, name, visible): ''' - Sets the visibility of the widget associated with name, and that of its label if present. + Sets the visibility of the widget and associated label with the given name. Parameters ---------- - visible: bool - True to set the widget visible, False to hide it - name: str + name : str The name of the widget to set visible/invisible + visible : bool + True to set the widget visible, False to hide it ''' self.formWidget.setWidgetVisible(name, visible) @@ -243,10 +243,10 @@ def getAllWidgetStates(self): Returns ------- dict - Format: {'widget_name': {'value': str | bool | int, 'enabled': bool, 'visible': bool, - 'widget_number': int}, ...}, - e.g. {'widget1': {'value': 1, 'enabled': True, 'visible': True, 'widget_number': 0}, - 'widget2': {'value': 2, 'enabled': False, 'visible': False, 'widget_number': 1}}. + Format: {'widget_name': {'value': str | bool | int, 'enabled': bool, 'visible': bool, + 'widget_number': int}, ...}. + e.g. {'widget1': {'value': 1, 'enabled': True, 'visible': True, 'widget_number': 0}, + 'widget2': {'value': 2, 'enabled': False, 'visible': False, 'widget_number': 1}}. ''' return self.formWidget.getAllWidgetStates() @@ -256,18 +256,18 @@ def getWidgetState(self, widget, role=None): Parameters ---------- - widget: QWidget or str + widget : QWidget or str The widget or its name (or its name + '_field' or '_label', when role is None) to get the state of. - role: str, optional, default None, values: 'label', 'field', None. + role : str, optional, default None, values: 'label', 'field', None. The role of the widget to apply the state to. This is used only if `widget` is the widget name string. Returns ------- - dict + state : dict Format: {'value': str | bool | int, 'enabled': bool, 'visible': bool, - 'widget_number' : int}, + 'widget_number' : int}. e.g. {'value': 1, 'enabled': True, 'visible': True, 'widget_number' : 0}. This can be used to restore the state of the widget using `setWidgetState()`. ''' @@ -280,13 +280,13 @@ def applyWidgetState(self, name, state, role=None): Parameters ---------- - name: str + name : str The name of the widget to apply the state to. - role: str, optional, default None, values: 'label', 'field', None. + role : str, optional, default None, values: 'label', 'field', None. The role of the widget to apply the state to. - state: dict + state : dict Format: {'value': str | bool | int, 'enabled': bool, 'visible': bool, - 'widget_number' : int}, + 'widget_number' : int}. e.g. {'value': 1, 'enabled': True, 'visible': True, 'widget_number' : 0}. ''' return self.formWidget.applyWidgetState(name, state, role) @@ -299,11 +299,11 @@ def applyWidgetStates(self, states): Parameters ---------- - states: nested_dict + states : dict Format: {'name_field': {'value': str | bool | int, 'enabled': bool, 'visible': bool, 'widget_number' : int}, 'name_label': {'value': str | bool | int, 'enabled': bool, 'visible': bool, 'widget_number' : int}, ...}. - e.g. {'widget1': {'value': 1, 'enabled': True, 'visible': True, 'widget_number' : 0}, - 'widget2': {'value': 2, 'enabled': False, 'visible': False, 'widget_number' : 1}}. + e.g. {'widget1': {'value': 1, 'enabled': True, 'visible': True, 'widget_number': 0}, + 'widget2': {'value': 2, 'enabled': False, 'visible': False, 'widget_number': 1}}. ''' return self.formWidget.applyWidgetStates(states) diff --git a/eqt/ui/UIFormWidget.py b/eqt/ui/UIFormWidget.py index 9722e06..4a5f003 100644 --- a/eqt/ui/UIFormWidget.py +++ b/eqt/ui/UIFormWidget.py @@ -283,16 +283,16 @@ def getWidgetState(self, widget, role=None): Parameters ---------- - widget: QWidget or str + widget : QWidget or str The widget or its name (or its name + '_field' or '_label', when role is None) to get the state of. - role: str, optional, default None, values: 'label', 'field', None. + role : str, optional, default None, values: 'label', 'field', None. The role of the widget to apply the state to. This is used only if `widget` is the widget name string. Returns ------- - state: dict + state : dict Format: {'value': str | bool | int, 'enabled': bool, 'visible': bool, 'widget_number' : int}. e.g. {'value': 1, 'enabled': True, 'visible': True, 'widget_number' : 0}. @@ -348,7 +348,7 @@ def _getNameAndRoleFromKey(self, key): Parameters ------------- - key: str + key : str Format: name or name_field or name_label ''' if key.endswith('_field'): @@ -368,7 +368,7 @@ def _getNameAndRoleFromWidget(self, widget): Parameters ------------- - widget: qwidget + widget : qwidget ''' for key, value in self.widgets.items(): if value == widget: @@ -382,11 +382,11 @@ def applyWidgetState(self, name, state, role=None): Parameters ---------- - name: str + name : str The name of the widget to apply the state to. - role: str, optional, default None, values: 'label', 'field', None. + role : str, optional, default None, values: 'label', 'field', None. The role of the widget to apply the state to. - state: dict + state : dict Format: {'value': str | bool | int, 'enabled': bool, 'visible': bool, 'widget_number' : int}. e.g. {'value': 1, 'enabled': True, 'visible': True, 'widget_number' : 0}. @@ -504,12 +504,12 @@ def addWidget(self, qwidget, qlabel, name): Parameters ---------- - qwidget: widget + qwidget : widget The widget to be added on the right hand side of the form. - qlabel: qlabel widget or str + qlabel : qlabel widget or str The qlabel widget, or a str from which a qlabel widget is created, to be added on the left hand side of the form. - name: str + name : str The string associated to the qwidget and qlabel. ''' self.widget().addWidget(qwidget, qlabel, name) @@ -520,9 +520,9 @@ def addSpanningWidget(self, qwidget, name): Parameters ---------- - qwidget: widget + qwidget : widget The widget to be added on the form. - name: str + name : str The string associated to the qwidget. ''' self.widget().addSpanningWidget(qwidget, name) @@ -538,13 +538,13 @@ def insertWidgetToFormLayout(self, row, name, qwidget, qlabel=None): Parameters ---------- - row: int + row : int The position in the form where the widget is added. - name: str + name : str The string associated to the qwidget and qlabel. - qwidget: widget + qwidget : widget The widget to be added on the right hand side of the form or as a spanning widget. - qlabel: qlabel widget or str + qlabel : qlabel widget or str The qlabel widget, or a str from which a qlabel widget is created, to be added on the left hand side of the form. If qlabel is `None` the widget spans the full width of the form. @@ -559,7 +559,7 @@ def removeWidget(self, name): Parameters ---------- - name: str + name : str The name of the widget to be removed. Returns @@ -602,9 +602,9 @@ def setWidgetVisible(self, name, visible): Parameters ---------- - name: str + name : str The name of the widget to set visible/invisible - visible: bool + visible : bool True to set the widget visible, False to hide it ''' self.widget().setWidgetVisible(name, visible) @@ -637,11 +637,10 @@ def getAllWidgetStates(self): Returns ------- dict - Format: {'widget_name': {'value': str | bool | int, 'enabled': bool, 'visible': bool, - 'widget_number': int}, - ...}, - e.g. {{'widget1': {'value': 1, 'enabled': True, 'visible': True, 'widget_number': 0}, - 'widget2': {'value': 2, 'enabled': False, 'visible': False, 'widget_number': 1}}. + Format: {'widget_name': {'value': str | bool | int, 'enabled': bool, 'visible': bool, + 'widget_number': int}, ...}. + e.g. {'widget1': {'value': 1, 'enabled': True, 'visible': True, 'widget_number': 0}, + 'widget2': {'value': 2, 'enabled': False, 'visible': False, 'widget_number': 1}}. ''' return self.widget().getAllWidgetStates() @@ -651,10 +650,10 @@ def getWidgetState(self, widget, role=None): Parameters ---------- - widget: QWidget or str + widget : QWidget or str The widget or its name (or its name + '_field' or '_label', when role is None) to get the state of. - role: str, optional, default None, values: 'label', 'field', None. + role : str, optional, default None, values: 'label', 'field', None. The role of the widget to apply the state to. This is used only if `widget` is the widget name string. @@ -675,11 +674,11 @@ def applyWidgetState(self, name, state, role=None): Parameters ---------- - name: str + name : str The name of the widget to apply the state to. - role: str, optional, default None, values: 'label', 'field', None. + role : str, optional, default None, values: 'label', 'field', None. The role of the widget to apply the state to. - state: dict + state : dict Format: {'value': str | bool | int, 'enabled': bool, 'visible': bool, 'widget_number' : int}. e.g. {'value': 1, 'enabled': True, 'visible': True, 'widget_number' : 0}. @@ -694,7 +693,7 @@ def applyWidgetStates(self, states): Parameters ---------- - states: dict + states : dict Format: {'name_field': {'value': str | bool | int, 'enabled': bool, 'visible': bool, 'widget_number' : int}, 'name_label': {'value': str | bool | int, 'enabled': bool, 'visible': bool, 'widget_number' : int}, ...}. From 3c320d2225828633065f811d2a5a8a3eecd7e5d4 Mon Sep 17 00:00:00 2001 From: Danica Sugic Date: Thu, 1 Feb 2024 15:12:06 +0000 Subject: [PATCH 87/96] Merge the removed methods and change example. Change widget number to widget row --- eqt/ui/FormDialog.py | 53 ++++++++++++------------ eqt/ui/UIFormWidget.py | 66 +++++++++++++++--------------- examples/remove_widgets_example.py | 16 +++++++- test/test__formUI_status_test.py | 8 ++-- 4 files changed, 78 insertions(+), 65 deletions(-) diff --git a/eqt/ui/FormDialog.py b/eqt/ui/FormDialog.py index e97e641..44f86da 100644 --- a/eqt/ui/FormDialog.py +++ b/eqt/ui/FormDialog.py @@ -146,28 +146,24 @@ def insertWidgetToVerticalLayout(self, row, qwidget): ''' self.formWidget.uiElements['verticalLayout'].insertWidget(row, qwidget) - def removeWidgetFromVerticalLayout(self, qwidget): - ''' - Removes a widget from the vertical layout. - ''' - self.formWidget.uiElements['verticalLayout'].removeWidget(qwidget) - qwidget.setParent(None) def getWidgetFromVerticalLayout(self, index): ''' Returns the widget in the vertical layout located at position index.''' return self.formWidget.uiElements['verticalLayout'].itemAt(index).widget() - def removeWidget(self, name): + def removeWidget(self, widget): ''' - Removes the widget with the specified name from the form layout. - This method delete the qwidget, and qlabel if present, from the widgets dictionary + Removes the specified widget from the form layout. + If `widget` is the name of the widget, this method deletes the qwidget, and qlabel if present, from the widgets dictionary and sets their parent to `None`. + If `widget` is a qwidget, this method removes a widget from the vertical layout. Parameters ---------- - name : str - The name of the widget to be removed. + widget : str or qwidget + The name of the widget to be removed in the form layout or + the qwidget to be removed in the vertical layout. Returns ------- @@ -175,7 +171,12 @@ def removeWidget(self, name): If the widget has a corresponding label, a tuple containing the widget and label is returned. Otherwise, only the widget is returned. ''' - self.formWidget.removeWidget(name) + if isinstance(widget, str): + return self.formWidget.removeWidget(widget) + elif isinstance(widget, QtWidgets.QWidget): + self.formWidget.uiElements['verticalLayout'].removeWidget(widget) + widget.setParent(None) + return widget def getNumWidgets(self): ''' @@ -196,12 +197,12 @@ def getWidgets(self): '''Returns a dictionary of the widgets currently present in the form.''' return self.formWidget.getWidgets() - def getWidgetNumber(self, name, role='field'): + def getWidgetRow(self, name, role='field'): ''' - Returns the widget number by the widget name. + Returns the widget row in the form layout by the widget name. This is the row of the widget in the form layout. ''' - return self.formWidget.getWidgetNumber(name, role) + return self.formWidget.getWidgetRow(name, role) def setWidgetVisible(self, name, visible): ''' @@ -244,9 +245,9 @@ def getAllWidgetStates(self): ------- dict Format: {'widget_name': {'value': str | bool | int, 'enabled': bool, 'visible': bool, - 'widget_number': int}, ...}. - e.g. {'widget1': {'value': 1, 'enabled': True, 'visible': True, 'widget_number': 0}, - 'widget2': {'value': 2, 'enabled': False, 'visible': False, 'widget_number': 1}}. + 'widget_row': int}, ...}. + e.g. {'widget1': {'value': 1, 'enabled': True, 'visible': True, 'widget_row': 0}, + 'widget2': {'value': 2, 'enabled': False, 'visible': False, 'widget_row': 1}}. ''' return self.formWidget.getAllWidgetStates() @@ -267,8 +268,8 @@ def getWidgetState(self, widget, role=None): ------- state : dict Format: {'value': str | bool | int, 'enabled': bool, 'visible': bool, - 'widget_number' : int}. - e.g. {'value': 1, 'enabled': True, 'visible': True, 'widget_number' : 0}. + 'widget_row' : int}. + e.g. {'value': 1, 'enabled': True, 'visible': True, 'widget_row' : 0}. This can be used to restore the state of the widget using `setWidgetState()`. ''' return self.formWidget.getWidgetState(widget, role) @@ -286,8 +287,8 @@ def applyWidgetState(self, name, state, role=None): The role of the widget to apply the state to. state : dict Format: {'value': str | bool | int, 'enabled': bool, 'visible': bool, - 'widget_number' : int}. - e.g. {'value': 1, 'enabled': True, 'visible': True, 'widget_number' : 0}. + 'widget_row' : int}. + e.g. {'value': 1, 'enabled': True, 'visible': True, 'widget_row' : 0}. ''' return self.formWidget.applyWidgetState(name, state, role) @@ -301,9 +302,9 @@ def applyWidgetStates(self, states): ---------- states : dict Format: {'name_field': {'value': str | bool | int, 'enabled': bool, 'visible': bool, - 'widget_number' : int}, 'name_label': {'value': str | bool | int, 'enabled': bool, - 'visible': bool, 'widget_number' : int}, ...}. - e.g. {'widget1': {'value': 1, 'enabled': True, 'visible': True, 'widget_number': 0}, - 'widget2': {'value': 2, 'enabled': False, 'visible': False, 'widget_number': 1}}. + 'widget_row' : int}, 'name_label': {'value': str | bool | int, 'enabled': bool, + 'visible': bool, 'widget_row' : int}, ...}. + e.g. {'widget1': {'value': 1, 'enabled': True, 'visible': True, 'widget_row': 0}, + 'widget2': {'value': 2, 'enabled': False, 'visible': False, 'widget_row': 1}}. ''' return self.formWidget.applyWidgetStates(states) diff --git a/eqt/ui/UIFormWidget.py b/eqt/ui/UIFormWidget.py index 4a5f003..878b22f 100644 --- a/eqt/ui/UIFormWidget.py +++ b/eqt/ui/UIFormWidget.py @@ -186,15 +186,15 @@ def removeWidget(self, name): If the widget has a corresponding label, a tuple containing the widget and label is returned. Otherwise, only the widget is returned. ''' - widget_number = self.getWidgetNumber(name) + widget_row = self.getWidgetRow(name) + self.getWidget(name, 'field').setParent(None) if f'{name}_label' in self.widgets: self.getWidget(name, 'label').setParent(None) qwidget, qlabel = self._popWidget(self.widgets, name) - self.uiElements['groupBoxFormLayout'].removeRow(widget_number) + self.uiElements['groupBoxFormLayout'].removeRow(widget_row) return qwidget, qlabel - self.getWidget(name, 'field').setParent(None) qwidget = self._popWidget(self.widgets, name) - self.uiElements['groupBoxFormLayout'].removeRow(widget_number) + self.uiElements['groupBoxFormLayout'].removeRow(widget_row) return qwidget def getWidget(self, name, role='field'): @@ -209,9 +209,9 @@ def getWidget(self, name, role='field'): return self.widgets[f'{name}_{role}'] raise ValueError(f'Unexpected role: expected any of {allowed_roles}, got {role}') - def getWidgetNumber(self, name, role='field'): + def getWidgetRow(self, name, role='field'): ''' - Returns the widget number by the widget name. + Returns the widget row in the form layout by the widget name. This is the row of the widget in the form layout. ''' return self.uiElements['groupBoxFormLayout'].getWidgetPosition(self.getWidget(name, @@ -268,9 +268,9 @@ def getAllWidgetStates(self): ------- dict Format: {'widget_name': {'value': str | bool | int, 'enabled': bool, 'visible': bool, - 'widget_number': int}, ...}. - e.g. {'widget1': {'value': 1, 'enabled': True, 'visible': True, 'widget_number': 0}, - 'widget2': {'value': 2, 'enabled': False, 'visible': False, 'widget_number': 1}}. + 'widget_row': int}, ...}. + e.g. {'widget1': {'value': 1, 'enabled': True, 'visible': True, 'widget_row': 0}, + 'widget2': {'value': 2, 'enabled': False, 'visible': False, 'widget_row': 1}}. ''' all_widget_states = {} for key, widget in self.widgets.items(): @@ -294,8 +294,8 @@ def getWidgetState(self, widget, role=None): ------- state : dict Format: {'value': str | bool | int, 'enabled': bool, 'visible': bool, - 'widget_number' : int}. - e.g. {'value': 1, 'enabled': True, 'visible': True, 'widget_number' : 0}. + 'widget_row' : int}. + e.g. {'value': 1, 'enabled': True, 'visible': True, 'widget_row' : 0}. This can be used to restore the state of the widget using `setWidgetState()`. ''' if widget is None: @@ -338,7 +338,7 @@ def getWidgetState(self, widget, role=None): elif isinstance(widget, (QtWidgets.QTextEdit, QtWidgets.QPlainTextEdit)): widget_state['value'] = widget.toPlainText() - widget_state['widget_number'] = self.getWidgetNumber(name, role) + widget_state['widget_row'] = self.getWidgetRow(name, role) return widget_state def _getNameAndRoleFromKey(self, key): @@ -388,8 +388,8 @@ def applyWidgetState(self, name, state, role=None): The role of the widget to apply the state to. state : dict Format: {'value': str | bool | int, 'enabled': bool, 'visible': bool, - 'widget_number' : int}. - e.g. {'value': 1, 'enabled': True, 'visible': True, 'widget_number' : 0}. + 'widget_row' : int}. + e.g. {'value': 1, 'enabled': True, 'visible': True, 'widget_row' : 0}. ''' if role is not None: if role in ['label', 'field']: @@ -440,10 +440,10 @@ def applyWidgetStates(self, states): ---------- states : dict Format: {'name_field': {'value': str | bool | int, 'enabled': bool, 'visible': bool, - 'widget_number' : int}, 'name_label': {'value': str | bool | int, 'enabled': bool, - 'visible': bool, 'widget_number' : int}, ...}. - e.g. {'widget1': {'value': 1, 'enabled': True, 'visible': True, 'widget_number': 0}, - 'widget2': {'value': 2, 'enabled': False, 'visible': False, 'widget_number': 1}}. + 'widget_row' : int}, 'name_label': {'value': str | bool | int, 'enabled': bool, + 'visible': bool, 'widget_row' : int}, ...}. + e.g. {'widget1': {'value': 1, 'enabled': True, 'visible': True, 'widget_row': 0}, + 'widget2': {'value': 2, 'enabled': False, 'visible': False, 'widget_row': 1}}. ''' if set(self.widgets) != set(states): raise KeyError("states={set(states)} do not match form widgets ({set(self.widgets)})") @@ -568,7 +568,7 @@ def removeWidget(self, name): If the widget has a corresponding label, a tuple containing the widget and label is returned. Otherwise, only the widget is returned. ''' - self.widget().removeWidget(name) + return self.widget().removeWidget(name) def getNumWidgets(self): ''' @@ -589,12 +589,12 @@ def getWidgets(self): '''Returns a dictionary of the widgets currently present in the form.''' return self.widget().getWidgets() - def getWidgetNumber(self, name, role='field'): + def getWidgetRow(self, name, role='field'): ''' - Returns the widget number by the widget name. + Returns the widget row in the form layout by the widget name. This is the row of the widget in the form layout. ''' - return self.widget().getWidgetNumber(name, role) + return self.widget().getWidgetRow(name, role) def setWidgetVisible(self, name, visible): ''' @@ -638,9 +638,9 @@ def getAllWidgetStates(self): ------- dict Format: {'widget_name': {'value': str | bool | int, 'enabled': bool, 'visible': bool, - 'widget_number': int}, ...}. - e.g. {'widget1': {'value': 1, 'enabled': True, 'visible': True, 'widget_number': 0}, - 'widget2': {'value': 2, 'enabled': False, 'visible': False, 'widget_number': 1}}. + 'widget_row': int}, ...}. + e.g. {'widget1': {'value': 1, 'enabled': True, 'visible': True, 'widget_row': 0}, + 'widget2': {'value': 2, 'enabled': False, 'visible': False, 'widget_row': 1}}. ''' return self.widget().getAllWidgetStates() @@ -661,8 +661,8 @@ def getWidgetState(self, widget, role=None): ------- state: dict Format: {'value': str | bool | int, 'enabled': bool, 'visible': bool, - 'widget_number' : int}. - e.g. {'value': 1, 'enabled': True, 'visible': True, 'widget_number' : 0}. + 'widget_row' : int}. + e.g. {'value': 1, 'enabled': True, 'visible': True, 'widget_row' : 0}. This can be used to restore the state of the widget using `setWidgetState()`. ''' return self.widget().getWidgetState(widget, role) @@ -680,8 +680,8 @@ def applyWidgetState(self, name, state, role=None): The role of the widget to apply the state to. state : dict Format: {'value': str | bool | int, 'enabled': bool, 'visible': bool, - 'widget_number' : int}. - e.g. {'value': 1, 'enabled': True, 'visible': True, 'widget_number' : 0}. + 'widget_row' : int}. + e.g. {'value': 1, 'enabled': True, 'visible': True, 'widget_row' : 0}. ''' return self.widget().applyWidgetState(name, state, role) @@ -695,10 +695,10 @@ def applyWidgetStates(self, states): ---------- states : dict Format: {'name_field': {'value': str | bool | int, 'enabled': bool, 'visible': bool, - 'widget_number' : int}, 'name_label': {'value': str | bool | int, - 'enabled': bool, 'visible': bool, 'widget_number' : int}, ...}. - e.g. {'widget1': {'value': 1, 'enabled': True, 'visible': True, 'widget_number': 0}, - 'widget2': {'value': 2, 'enabled': False, 'visible': False, 'widget_number': 1}}. + 'widget_row' : int}, 'name_label': {'value': str | bool | int, + 'enabled': bool, 'visible': bool, 'widget_row' : int}, ...}. + e.g. {'widget1': {'value': 1, 'enabled': True, 'visible': True, 'widget_row': 0}, + 'widget2': {'value': 2, 'enabled': False, 'visible': False, 'widget_row': 1}}. ''' return self.widget().applyWidgetStates(states) diff --git a/examples/remove_widgets_example.py b/examples/remove_widgets_example.py index d553373..bd21582 100644 --- a/examples/remove_widgets_example.py +++ b/examples/remove_widgets_example.py @@ -41,6 +41,12 @@ def openFormDialog(self): dialog = FormDialog(parent=self, title='Example remove widget') dialog.Ok.clicked.connect(lambda: self.remove(dialog, dialog.Ok)) self.addWidgetsToExampleForm(dialog) + buttonremovevertical = QtWidgets.QPushButton() + buttonremovevertical.setText("Remove widget in vertical layout") + dialog.addSpanningWidget(buttonremovevertical, 'Button remove vertical') + vertical_button = QtWidgets.QPushButton("Widget in vertical layout") + buttonremovevertical.clicked.connect(lambda: self.remove_vertical(vertical_button)) + dialog.insertWidgetToVerticalLayout(1, vertical_button) dialog.addSpanningWidget( QtWidgets.QLabel( "Press `Ok` to remove the user selected widget and `Cancel` to close the dialog:"), @@ -108,6 +114,11 @@ def addWidgetsToExampleForm(self, form): form.addSpanningWidget(buttonspanning, 'Button Remove Spanning') buttonspanning.clicked.connect(lambda: self.remove(form, buttonspanning, 'input_title')) + def remove_vertical(self, button): + widget = self.dialog.removeWidget(button) + print(f'\nRemoved widget in the vertical layout is {widget}.') + self.dialog.getWidget('Button remove vertical').setEnabled(False) + def rejected(self): print("\nDialog closed.") @@ -115,8 +126,9 @@ def remove(self, form, button, userselection=False): if userselection is False: userselection = form.getWidget('userinput').currentText() form.getWidget('userinput').removeItem(form.getWidget('userinput').currentIndex()) - print("\nRemove " + userselection) - form.removeWidget(userselection) + + widget = form.removeWidget(userselection) + print(f'\nRemove {userselection} returning {widget}.') if form.getWidget('userinput').currentIndex() == -1: button.setEnabled(False) if button == form.getWidget('Button Remove w1') or button == form.getWidget( diff --git a/test/test__formUI_status_test.py b/test/test__formUI_status_test.py index 92e3fa2..16bec2a 100644 --- a/test/test__formUI_status_test.py +++ b/test/test__formUI_status_test.py @@ -54,12 +54,12 @@ def state_simple_form(self): state_simple_form = { 'label_field': { 'value': 'test label', 'enabled': True, 'visible': False, - 'widget_number': 0}, 'label_label': { + 'widget_row': 0}, 'label_label': { 'value': 'Label: ', 'enabled': True, 'visible': False, - 'widget_number': 0}, 'checkBox_field': { - 'value': False, 'enabled': True, 'visible': False, 'widget_number': 1}, + 'widget_row': 0}, 'checkBox_field': { + 'value': False, 'enabled': True, 'visible': False, 'widget_row': 1}, 'checkBox_label': { - 'value': 'CheckBox: ', 'enabled': True, 'visible': False, 'widget_number': 1}} + 'value': 'CheckBox: ', 'enabled': True, 'visible': False, 'widget_row': 1}} return state_simple_form def add_every_widget(self): From 88c8889b820404321509da5c81238d6b00ae845a Mon Sep 17 00:00:00 2001 From: Danica Sugic Date: Thu, 1 Feb 2024 15:39:36 +0000 Subject: [PATCH 88/96] run pre-commit --- eqt/ui/FormDialog.py | 9 ++++----- eqt/ui/UIFormWidget.py | 4 ++-- examples/remove_widgets_example.py | 2 +- test/test__formUI_status_test.py | 5 ++--- 4 files changed, 9 insertions(+), 11 deletions(-) diff --git a/eqt/ui/FormDialog.py b/eqt/ui/FormDialog.py index 44f86da..b18b9bd 100644 --- a/eqt/ui/FormDialog.py +++ b/eqt/ui/FormDialog.py @@ -81,8 +81,8 @@ def addWidget(self, qwidget, qlabel=None, name=None, layout='form'): name : str only supported when layout is 'form' layout : 'form' or 'vertical' - 'form' - adds to the `groupBoxFormLayout`, 'vertical' - adds to the `verticalLayout` below - the form. + 'form' - adds to the `groupBoxFormLayout`, + 'vertical' - adds to the `verticalLayout` below the form. ''' if layout == 'vertical': if name is not None or qlabel is not None: @@ -146,7 +146,6 @@ def insertWidgetToVerticalLayout(self, row, qwidget): ''' self.formWidget.uiElements['verticalLayout'].insertWidget(row, qwidget) - def getWidgetFromVerticalLayout(self, index): ''' Returns the widget in the vertical layout located at position index.''' @@ -155,8 +154,8 @@ def getWidgetFromVerticalLayout(self, index): def removeWidget(self, widget): ''' Removes the specified widget from the form layout. - If `widget` is the name of the widget, this method deletes the qwidget, and qlabel if present, from the widgets dictionary - and sets their parent to `None`. + If `widget` is the name of the widget, this method deletes the qwidget, and qlabel if + present, from the widgets dictionary and sets their parent to `None`. If `widget` is a qwidget, this method removes a widget from the vertical layout. Parameters diff --git a/eqt/ui/UIFormWidget.py b/eqt/ui/UIFormWidget.py index 878b22f..e640eba 100644 --- a/eqt/ui/UIFormWidget.py +++ b/eqt/ui/UIFormWidget.py @@ -94,10 +94,10 @@ def insertWidgetToFormLayout(self, row, name, qwidget, qlabel=None): else: formLayout.insertRow(row, qwidget) - + self.widgets[f'{name}_field'] = qwidget self.default_widget_states[f'{name}_field'] = self.getWidgetState(name, 'field') - + def _popWidget(self, dictionary, name): ''' Removes the item(s) associated with `name` from a dictionary. diff --git a/examples/remove_widgets_example.py b/examples/remove_widgets_example.py index bd21582..365dced 100644 --- a/examples/remove_widgets_example.py +++ b/examples/remove_widgets_example.py @@ -126,7 +126,7 @@ def remove(self, form, button, userselection=False): if userselection is False: userselection = form.getWidget('userinput').currentText() form.getWidget('userinput').removeItem(form.getWidget('userinput').currentIndex()) - + widget = form.removeWidget(userselection) print(f'\nRemove {userselection} returning {widget}.') if form.getWidget('userinput').currentIndex() == -1: diff --git a/test/test__formUI_status_test.py b/test/test__formUI_status_test.py index 16bec2a..10e2c94 100644 --- a/test/test__formUI_status_test.py +++ b/test/test__formUI_status_test.py @@ -55,9 +55,8 @@ def state_simple_form(self): 'label_field': { 'value': 'test label', 'enabled': True, 'visible': False, 'widget_row': 0}, 'label_label': { - 'value': 'Label: ', 'enabled': True, 'visible': False, - 'widget_row': 0}, 'checkBox_field': { - 'value': False, 'enabled': True, 'visible': False, 'widget_row': 1}, + 'value': 'Label: ', 'enabled': True, 'visible': False, 'widget_row': 0}, + 'checkBox_field': {'value': False, 'enabled': True, 'visible': False, 'widget_row': 1}, 'checkBox_label': { 'value': 'CheckBox: ', 'enabled': True, 'visible': False, 'widget_row': 1}} return state_simple_form From 22465693017a23da90c6e5d710658b4eef1ba124 Mon Sep 17 00:00:00 2001 From: DanicaSTFC <138598662+DanicaSTFC@users.noreply.github.com> Date: Thu, 1 Feb 2024 15:55:04 +0000 Subject: [PATCH 89/96] commit string Co-authored-by: Edoardo Pasca <14138589+paskino@users.noreply.github.com> --- eqt/ui/FormDialog.py | 1 + 1 file changed, 1 insertion(+) diff --git a/eqt/ui/FormDialog.py b/eqt/ui/FormDialog.py index b18b9bd..b5da52e 100644 --- a/eqt/ui/FormDialog.py +++ b/eqt/ui/FormDialog.py @@ -186,6 +186,7 @@ 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. From 99de23e5cb37a88e8366ee4b5683e19cf6cd0194 Mon Sep 17 00:00:00 2001 From: Danica Sugic Date: Thu, 1 Feb 2024 18:18:52 +0000 Subject: [PATCH 90/96] Update changelog --- CHANGELOG.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 575a51c..603f573 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,7 +1,7 @@ # Version x.x.x - Adds methods to insert widgets in the forms & tests/example Removes `_addWidget` - Adds `getWidgetNumber`and updates states dictionary and related methods + Adds `getWidgetRow`and updates states dictionary and related methods Adds `getNameAndRole*`. Changes `num_widgets` to be a property (#109) - Reinstates changelog (#99) From e58107973e1ee39804e3a98d6f2ccec471144be4 Mon Sep 17 00:00:00 2001 From: Danica Sugic Date: Thu, 1 Feb 2024 18:48:15 +0000 Subject: [PATCH 91/96] Add tests for remove widgets from vertical layout --- test/test__formUI_status_test.py | 26 ++++++++++++++++++++++++++ 1 file changed, 26 insertions(+) diff --git a/test/test__formUI_status_test.py b/test/test__formUI_status_test.py index 10e2c94..62fd993 100644 --- a/test/test__formUI_status_test.py +++ b/test/test__formUI_status_test.py @@ -412,6 +412,7 @@ def setUp(self): self.form = FormDialog() self.add_every_widget() self.add_every_spanning_widget() + self.add_every_widget_to_vertical_layout() self.simple_form = FormDialog() self.add_two_widgets() self.layout = self.form.formWidget.uiElements['groupBoxFormLayout'] @@ -423,6 +424,11 @@ def click_Ok(self): def click_Cancel(self): QTest.mouseClick(self.form.Cancel, Qt.LeftButton) + def add_every_widget_to_vertical_layout(self): + """Add every widget to the vertical layout.""" + for key in self.list_all_widgets: + self.form.addWidget(self.list_all_widgets[key], qlabel=None, name=None, layout='vertical') + def test_dialog_buttons_default_behaviour(self): # create the states dictionary self.set_state(1) @@ -472,6 +478,26 @@ def test_insert_every_widget_to_vertical_layout(self): for key in self.list_all_widgets: self._test_insert_one_widget_to_vertical_layout(0, self.list_all_widgets[key]) + def _test_remove_one_widget_from_vertical_layout(self, widget): + """ + Removes one widget from the vertical layout. + Checks the number of items in the layout before and after deletion are consistent. + + Parameters + ---------- + widget: qwidget to be removed + """ + qwidget = self.form.getWidgetFromVerticalLayout(2) + prerowcount = self.vertical_layout.count() + self.form.removeWidget(qwidget) + postrowcount = self.vertical_layout.count() + self.assertEqual(prerowcount, postrowcount + 1) + + def test_remove_every_widget_from_vertical_layout(self): + """Remove every widget from the vertical layout.""" + for widget in self.list_all_widgets.items(): + self._test_remove_one_widget_from_vertical_layout(widget) + def test_getWidgetState_returns_QLabel_value(self): """Check that the value of the QLabel is saved to the state""" initial_label_value = 'label' From 4825df8589940c1be85dc85b8fd27713d4300fd8 Mon Sep 17 00:00:00 2001 From: Danica Sugic Date: Mon, 5 Feb 2024 16:19:36 +0000 Subject: [PATCH 92/96] Change names to remove widget and insert widget --- eqt/ui/FormDialog.py | 31 +++++++++++++++--------------- eqt/ui/UIFormWidget.py | 14 +++++++------- examples/insert_widgets_example.py | 4 ++-- examples/remove_widgets_example.py | 2 +- test/test__formUI_status_test.py | 8 ++++---- 5 files changed, 30 insertions(+), 29 deletions(-) diff --git a/eqt/ui/FormDialog.py b/eqt/ui/FormDialog.py index b5da52e..83160e4 100644 --- a/eqt/ui/FormDialog.py +++ b/eqt/ui/FormDialog.py @@ -116,7 +116,7 @@ def addSpanningWidget(self, qwidget, name=None, layout='form'): raise ValueError( f"layout {layout} is not recognised, must be set to 'form' or 'vertical'") - def insertWidgetToFormLayout(self, row, name, qwidget, qlabel=None): + def insertWidget(self, row, name, qwidget, qlabel=None): ''' Inserts a labelled widget, or a spanning widget, to the form layout. The position in the form is specified by row. If row is out of bounds, the widget @@ -138,7 +138,7 @@ def insertWidgetToFormLayout(self, row, name, qwidget, qlabel=None): on the left hand side of the form. If qlabel is `None` the widget spans the full width of the form. ''' - self.formWidget.insertWidgetToFormLayout(row, name, qwidget, qlabel) + self.formWidget.insertWidget(row, name, qwidget, qlabel) def insertWidgetToVerticalLayout(self, row, qwidget): ''' @@ -153,16 +153,14 @@ def getWidgetFromVerticalLayout(self, index): def removeWidget(self, widget): ''' - Removes the specified widget from the form layout. - If `widget` is the name of the widget, this method deletes the qwidget, and qlabel if - present, from the widgets dictionary and sets their parent to `None`. - If `widget` is a qwidget, this method removes a widget from the vertical layout. + Removes the widget with the specified name from the form layout. + This method delete the qwidget, and qlabel if present, from the widgets dictionary + and sets their parent to `None`. Parameters ---------- - widget : str or qwidget - The name of the widget to be removed in the form layout or - the qwidget to be removed in the vertical layout. + name : str + The name of the widget to be removed. Returns ------- @@ -170,12 +168,15 @@ def removeWidget(self, widget): If the widget has a corresponding label, a tuple containing the widget and label is returned. Otherwise, only the widget is returned. ''' - if isinstance(widget, str): - return self.formWidget.removeWidget(widget) - elif isinstance(widget, QtWidgets.QWidget): - self.formWidget.uiElements['verticalLayout'].removeWidget(widget) - widget.setParent(None) - return widget + return self.formWidget.removeWidget(widget) + + def removeWidgetFromVerticalLayout(self, widget): + ''' + Removes a widget from the vertical layout. + ''' + self.formWidget.uiElements['verticalLayout'].removeWidget(widget) + widget.setParent(None) + return widget def getNumWidgets(self): ''' diff --git a/eqt/ui/UIFormWidget.py b/eqt/ui/UIFormWidget.py index e640eba..fd7c0e5 100644 --- a/eqt/ui/UIFormWidget.py +++ b/eqt/ui/UIFormWidget.py @@ -56,7 +56,7 @@ def num_widgets(self): def groupBox(self): return self.uiElements['groupBox'] - def insertWidgetToFormLayout(self, row, name, qwidget, qlabel=None): + def insertWidget(self, row, name, qwidget, qlabel=None): ''' Inserts a labelled widget, or a spanning widget, to the form layout. The position in the form is specified by row. If row is out of bounds, the widget @@ -148,7 +148,7 @@ def addWidget(self, qwidget, qlabel, name): name : str The string associated to the qwidget and qlabel. ''' - self.insertWidgetToFormLayout(-1, name, qwidget, qlabel) + self.insertWidget(-1, name, qwidget, qlabel) def addSpanningWidget(self, qwidget, name): ''' @@ -161,7 +161,7 @@ def addSpanningWidget(self, qwidget, name): name : str The string associated to the qwidget. ''' - self.insertWidgetToFormLayout(-1, name, qwidget) + self.insertWidget(-1, name, qwidget) def getNumWidgets(self): ''' @@ -246,14 +246,14 @@ def addTitle(self, qlabel, name): qlabel = QtWidgets.QLabel(self.uiElements['groupBox']) qlabel.setText(txt) qlabel.setStyleSheet("font-weight: bold") - self.insertWidgetToFormLayout(-1, name, qlabel) + self.insertWidget(-1, name, qlabel) def addSeparator(self, name): # Adds horizontal separator to the form frame = QtWidgets.QFrame() frame.setFrameShape(QtWidgets.QFrame.HLine) frame.setFrameShadow(QtWidgets.QFrame.Raised) - self.insertWidgetToFormLayout(-1, name, frame) + self.insertWidget(-1, name, frame) def setDefaultWidgetStatesVisibleTrue(self): ''' @@ -527,7 +527,7 @@ def addSpanningWidget(self, qwidget, name): ''' self.widget().addSpanningWidget(qwidget, name) - def insertWidgetToFormLayout(self, row, name, qwidget, qlabel=None): + def insertWidget(self, row, name, qwidget, qlabel=None): ''' Inserts a labelled widget, or a spanning widget, to the form layout. The position in the form is specified by row. If row is out of bounds, the widget @@ -549,7 +549,7 @@ def insertWidgetToFormLayout(self, row, name, qwidget, qlabel=None): on the left hand side of the form. If qlabel is `None` the widget spans the full width of the form. ''' - self.widget().insertWidgetToFormLayout(row, name, qwidget, qlabel) + self.widget().insertWidget(row, name, qwidget, qlabel) def removeWidget(self, name): ''' diff --git a/examples/insert_widgets_example.py b/examples/insert_widgets_example.py index 5bc3c5f..29e8cba 100644 --- a/examples/insert_widgets_example.py +++ b/examples/insert_widgets_example.py @@ -65,10 +65,10 @@ def insert_form(self, form, button): qlabel = QtWidgets.QLabel(form) qlabel.setText("Widget inserted in row 0: ") qwidget = QtWidgets.QLineEdit(form) - form.insertWidgetToFormLayout(0, 'inserted widget', qwidget, qlabel) + form.insertWidget(0, 'inserted widget', qwidget, qlabel) buttonspanning = QtWidgets.QPushButton(self) buttonspanning.setText("Spanning widget inserted in row 2") - form.insertWidgetToFormLayout(2, 'inserted spanning widget', buttonspanning) + form.insertWidget(2, 'inserted spanning widget', buttonspanning) print('\nDictionary of widgets after insertion in the form layout:\n' + str(form.getWidgets())) button.setEnabled(False) diff --git a/examples/remove_widgets_example.py b/examples/remove_widgets_example.py index 365dced..74e0b57 100644 --- a/examples/remove_widgets_example.py +++ b/examples/remove_widgets_example.py @@ -115,7 +115,7 @@ def addWidgetsToExampleForm(self, form): buttonspanning.clicked.connect(lambda: self.remove(form, buttonspanning, 'input_title')) def remove_vertical(self, button): - widget = self.dialog.removeWidget(button) + widget = self.dialog.removeWidgetFromVerticalLayout(button) print(f'\nRemoved widget in the vertical layout is {widget}.') self.dialog.getWidget('Button remove vertical').setEnabled(False) diff --git a/test/test__formUI_status_test.py b/test/test__formUI_status_test.py index 62fd993..15149bf 100644 --- a/test/test__formUI_status_test.py +++ b/test/test__formUI_status_test.py @@ -119,10 +119,10 @@ def set_state(self, i): def _test_insert_one_widget(self, row, name, qwidget, qlabel=None): """ - Invokes `insertWidgetToFormLayout`, therefore inserts the qwidget (and the qlabel) + Invokes `insertWidget`, therefore inserts the qwidget (and the qlabel) at position row in the layout. Checks the position of the widget in the form is `row`. """ - self.form.insertWidgetToFormLayout(row, f'{name}', qwidget, qlabel) + self.form.insertWidget(row, f'{name}', qwidget, qlabel) position = self.layout.getWidgetPosition(self.form.getWidget(name, 'field'))[0] self.assertEqual(position, row) @@ -412,7 +412,6 @@ def setUp(self): self.form = FormDialog() self.add_every_widget() self.add_every_spanning_widget() - self.add_every_widget_to_vertical_layout() self.simple_form = FormDialog() self.add_two_widgets() self.layout = self.form.formWidget.uiElements['groupBoxFormLayout'] @@ -489,12 +488,13 @@ def _test_remove_one_widget_from_vertical_layout(self, widget): """ qwidget = self.form.getWidgetFromVerticalLayout(2) prerowcount = self.vertical_layout.count() - self.form.removeWidget(qwidget) + self.form.removeWidgetFromVerticalLayout(qwidget) postrowcount = self.vertical_layout.count() self.assertEqual(prerowcount, postrowcount + 1) def test_remove_every_widget_from_vertical_layout(self): """Remove every widget from the vertical layout.""" + self.add_every_widget_to_vertical_layout() for widget in self.list_all_widgets.items(): self._test_remove_one_widget_from_vertical_layout(widget) From 6609812dd3a0823ed28ffec4fc42f12ddd79a029 Mon Sep 17 00:00:00 2001 From: Danica Sugic Date: Wed, 14 Feb 2024 12:00:08 +0000 Subject: [PATCH 93/96] Change getNameAndRoleFromWidget error --- eqt/ui/UIFormWidget.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/eqt/ui/UIFormWidget.py b/eqt/ui/UIFormWidget.py index fd7c0e5..0d1ee56 100644 --- a/eqt/ui/UIFormWidget.py +++ b/eqt/ui/UIFormWidget.py @@ -372,8 +372,8 @@ def _getNameAndRoleFromWidget(self, widget): ''' for key, value in self.widgets.items(): if value == widget: - name, role = self._getNameAndRoleFromKey(key) - return name, role + return self._getNameAndRoleFromKey(key) + raise KeyError(f'There is no widget {widget} in the form.') def applyWidgetState(self, name, state, role=None): ''' From e6e687654a309d787234a4bb967d28ee957a206a Mon Sep 17 00:00:00 2001 From: Danica Sugic Date: Wed, 14 Feb 2024 12:03:38 +0000 Subject: [PATCH 94/96] run pre-commit --- test/test__formUI_status_test.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/test/test__formUI_status_test.py b/test/test__formUI_status_test.py index 15149bf..a0e201d 100644 --- a/test/test__formUI_status_test.py +++ b/test/test__formUI_status_test.py @@ -426,7 +426,8 @@ def click_Cancel(self): def add_every_widget_to_vertical_layout(self): """Add every widget to the vertical layout.""" for key in self.list_all_widgets: - self.form.addWidget(self.list_all_widgets[key], qlabel=None, name=None, layout='vertical') + self.form.addWidget(self.list_all_widgets[key], qlabel=None, name=None, + layout='vertical') def test_dialog_buttons_default_behaviour(self): # create the states dictionary From 61c55602fd9db84e9a13b3531415ee139bc5c432 Mon Sep 17 00:00:00 2001 From: Danica Sugic Date: Wed, 14 Feb 2024 12:06:03 +0000 Subject: [PATCH 95/96] run pre-commit --- eqt/ui/FormDialog.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/eqt/ui/FormDialog.py b/eqt/ui/FormDialog.py index 83160e4..50b2a8d 100644 --- a/eqt/ui/FormDialog.py +++ b/eqt/ui/FormDialog.py @@ -169,7 +169,7 @@ def removeWidget(self, widget): and label is returned. Otherwise, only the widget is returned. ''' return self.formWidget.removeWidget(widget) - + def removeWidgetFromVerticalLayout(self, widget): ''' Removes a widget from the vertical layout. From e7d039cfb412e5109416427cc9ddc77b9b2e6925 Mon Sep 17 00:00:00 2001 From: Casper da Costa-Luis Date: Wed, 14 Feb 2024 12:27:32 +0000 Subject: [PATCH 96/96] fix flake8 --- eqt/threading/QtThreading.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/eqt/threading/QtThreading.py b/eqt/threading/QtThreading.py index dacd0a7..faec586 100644 --- a/eqt/threading/QtThreading.py +++ b/eqt/threading/QtThreading.py @@ -47,7 +47,7 @@ def run(self): """ try: result = self.fn(*self.args, **self.kwargs) - except BaseException: + except BaseException: # NOQA: B036 traceback.print_exc() exctype, value = sys.exc_info()[:2] self.signals.error.emit((exctype, value, traceback.format_exc()))