88from .utils import iter_layout_widgets , state_property , is_concrete_schema
99
1010
11- class WidgetMixin :
11+ class SchemaWidgetMixin :
1212 on_changed = Signal ()
1313
1414 VALID_COLOUR = '#ffffff'
@@ -53,7 +53,7 @@ def _set_valid_state(self, error: Exception = None):
5353 self .setToolTip ("" if error is None else error .message ) # TODO
5454
5555
56- class TextWidget ( WidgetMixin , QtWidgets .QLineEdit ):
56+ class TextSchemaWidget ( SchemaWidgetMixin , QtWidgets .QLineEdit ):
5757
5858 def configure (self ):
5959 self .textChanged .connect (self .on_changed .emit )
@@ -67,15 +67,15 @@ def state(self, state: str):
6767 self .setText (state )
6868
6969
70- class PasswordWidget (TextWidget ):
70+ class PasswordWidget (TextSchemaWidget ):
7171
7272 def configure (self ):
7373 super ().configure ()
7474
7575 self .setEchoMode (self .Password )
7676
7777
78- class TextAreaWidget ( WidgetMixin , QtWidgets .QTextEdit ):
78+ class TextAreaSchemaWidget ( SchemaWidgetMixin , QtWidgets .QTextEdit ):
7979
8080 @state_property
8181 def state (self ) -> str :
@@ -89,7 +89,7 @@ def configure(self):
8989 self .textChanged .connect (lambda : self .on_changed .emit (self .state ))
9090
9191
92- class CheckboxWidget ( WidgetMixin , QtWidgets .QCheckBox ):
92+ class CheckboxSchemaWidget ( SchemaWidgetMixin , QtWidgets .QCheckBox ):
9393
9494 @state_property
9595 def state (self ) -> bool :
@@ -103,7 +103,7 @@ def configure(self):
103103 self .stateChanged .connect (lambda _ : self .on_changed .emit (self .state ))
104104
105105
106- class SpinDoubleWidget ( WidgetMixin , QtWidgets .QDoubleSpinBox ):
106+ class SpinDoubleSchemaWidget ( SchemaWidgetMixin , QtWidgets .QDoubleSpinBox ):
107107
108108 @state_property
109109 def state (self ) -> float :
@@ -117,7 +117,7 @@ def configure(self):
117117 self .valueChanged .connect (self .on_changed .emit )
118118
119119
120- class SpinWidget ( WidgetMixin , QtWidgets .QSpinBox ):
120+ class SpinSchemaWidget ( SchemaWidgetMixin , QtWidgets .QSpinBox ):
121121
122122 @state_property
123123 def state (self ) -> int :
@@ -131,7 +131,7 @@ def configure(self):
131131 self .valueChanged .connect (self .on_changed .emit )
132132
133133
134- class IntegerRangeWidget ( WidgetMixin , QtWidgets .QSlider ):
134+ class IntegerRangeSchemaWidget ( SchemaWidgetMixin , QtWidgets .QSlider ):
135135
136136 def __init__ (self , schema : dict , ui_schema : dict , widget_builder : 'WidgetBuilder' ):
137137 super ().__init__ (schema , ui_schema , widget_builder , orientation = QtCore .Qt .Horizontal )
@@ -209,7 +209,7 @@ def mousePressEvent(self, event):
209209 return super (QColorButton , self ).mousePressEvent (event )
210210
211211
212- class ColorWidget ( WidgetMixin , QColorButton ):
212+ class ColorSchemaWidget ( SchemaWidgetMixin , QColorButton ):
213213 """Widget representation of a string with the 'color' format keyword."""
214214
215215 def configure (self ):
@@ -224,7 +224,7 @@ def state(self, data: str):
224224 self .setColor (data )
225225
226226
227- class FilepathWidget ( WidgetMixin , QtWidgets .QWidget ):
227+ class FilepathSchemaWidget ( SchemaWidgetMixin , QtWidgets .QWidget ):
228228
229229 def __init__ (self , schema : dict , ui_schema : dict , widget_builder : 'WidgetBuilder' ):
230230 super ().__init__ (schema , ui_schema , widget_builder )
@@ -298,7 +298,7 @@ def __init__(self, widget: QtWidgets.QWidget, controls: ArrayControlsWidget):
298298 self .controls = controls
299299
300300
301- class ArrayWidget ( WidgetMixin , QtWidgets .QWidget ):
301+ class ArraySchemaWidget ( SchemaWidgetMixin , QtWidgets .QWidget ):
302302
303303 @property
304304 def rows (self ) -> List [ArrayRowWidget ]:
@@ -434,7 +434,7 @@ def widget_on_changed(self, row: ArrayRowWidget, value):
434434 self .on_changed .emit (self .state )
435435
436436
437- class ObjectWidget ( WidgetMixin , QtWidgets .QGroupBox ):
437+ class ObjectSchemaWidget ( SchemaWidgetMixin , QtWidgets .QGroupBox ):
438438
439439 def __init__ (self , schema : dict , ui_schema : dict , widget_builder : 'WidgetBuilder' ):
440440 super ().__init__ (schema , ui_schema , widget_builder )
@@ -485,7 +485,7 @@ def populate_from_schema(self, schema: dict, ui_schema: dict, widget_builder: 'W
485485 return widgets
486486
487487
488- class EnumWidget ( WidgetMixin , QtWidgets .QComboBox ):
488+ class EnumSchemaWidget ( SchemaWidgetMixin , QtWidgets .QComboBox ):
489489
490490 @state_property
491491 def state (self ):
@@ -507,5 +507,40 @@ def configure(self):
507507 self .currentIndexChanged .connect (lambda _ : self .on_changed .emit (self .state ))
508508
509509 def _index_changed (self , index : int ):
510- value = self .itemData (index )
511- self .on_changed .emit (self .state )
510+ self .on_changed .emit (self .state )
511+
512+
513+ class FormWidget (QtWidgets .QWidget ):
514+
515+ def __init__ (self , widget ):
516+ super ().__init__ ()
517+ layout = QtWidgets .QVBoxLayout ()
518+ self .setLayout (layout )
519+
520+ self .error_widget = QtWidgets .QGroupBox ()
521+ self .error_widget .setTitle ("Errors" )
522+ self .error_layout = QtWidgets .QVBoxLayout ()
523+ self .error_widget .setLayout (self .error_layout )
524+ self .error_widget .hide ()
525+
526+ layout .addWidget (self .error_widget )
527+ layout .addWidget (widget )
528+
529+ self .widget = widget
530+
531+ def display_errors (self , errors : List [Exception ]):
532+ self .error_widget .show ()
533+
534+ layout = self .error_widget .layout ()
535+ while True :
536+ item = layout .takeAt (0 )
537+ if not item :
538+ break
539+ item .widget ().deleteLater ()
540+
541+ for err in errors :
542+ widget = QtWidgets .QLabel (f"<b>.{ '.' .join (err .path )} </b> { err .message } " )
543+ layout .addWidget (widget )
544+
545+ def clear_errors (self ):
546+ self .error_widget .hide ()
0 commit comments