3
3
formlayout
4
4
==========
5
5
6
- Module creating PyQt4 form dialogs/layouts to edit various type of parameters
6
+ Module creating Qt form dialogs/layouts to edit various type of parameters
7
7
8
8
9
9
formlayout License Agreement (MIT License)
34
34
"""
35
35
36
36
# History:
37
+ # 1.0.10: added float validator (disable "Ok" and "Apply" button when not valid)
37
38
# 1.0.7: added support for "Apply" button
38
39
# 1.0.6: code cleaning
39
40
40
- __version__ = '1.0.9 '
41
+ __version__ = '1.0.10 '
41
42
__license__ = __doc__
42
43
43
44
DEBUG = False
53
54
QDialogButtonBox , QHBoxLayout , QVBoxLayout , QDialog , QColor , QPushButton ,
54
55
QCheckBox , QColorDialog , QPixmap , QTabWidget , QApplication , QStackedWidget ,
55
56
QDateEdit , QDateTimeEdit , QFont , QFontComboBox , QFontDatabase , QGridLayout ,
56
- QFormLayout ) = \
57
+ QFormLayout , QDoubleValidator ) = \
57
58
(QtGui .QWidget , QtGui .QLineEdit , QtGui .QComboBox , QtGui .QLabel ,
58
59
QtGui .QSpinBox , QtGui .QIcon , QtGui .QStyle , QtGui .QDialogButtonBox ,
59
60
QtGui .QHBoxLayout , QtGui .QVBoxLayout , QtGui .QDialog , QtGui .QColor ,
60
61
QtGui .QPushButton , QtGui .QCheckBox , QtGui .QColorDialog , QtGui .QPixmap ,
61
62
QtGui .QTabWidget , QtGui .QApplication , QtGui .QStackedWidget , QtGui .QDateEdit ,
62
63
QtGui .QDateTimeEdit , QtGui .QFont , QtGui .QFontComboBox , QtGui .QFontDatabase ,
63
- QtGui .QGridLayout , QtGui .QFormLayout )
64
+ QtGui .QGridLayout , QtGui .QFormLayout , QtGui . QDoubleValidator )
64
65
65
66
(Qt , SIGNAL , SLOT , QObject , QSize ,pyqtSignature , pyqtProperty ) = \
66
67
(QtCore .Qt , QtCore .SIGNAL , QtCore .SLOT , QtCore .QObject , QtCore .QSize ,
@@ -177,7 +178,6 @@ def qfont_to_tuple(font):
177
178
return (unicode (font .family ()), int (font .pointSize ()),
178
179
font .italic (), font .bold ())
179
180
180
-
181
181
class FontLayout (QGridLayout ):
182
182
"""Font selection"""
183
183
def __init__ (self , value , parent = None ):
@@ -220,9 +220,15 @@ def get_font(self):
220
220
return qfont_to_tuple (font )
221
221
222
222
223
+ def is_edit_valid (edit ):
224
+ text = edit .text ()
225
+ state = edit .validator ().validate (text , 0 )[0 ]
226
+
227
+ return state == QDoubleValidator .Acceptable
228
+
223
229
class FormWidget (QWidget ):
224
230
def __init__ (self , data , comment = "" , parent = None ):
225
- super ( FormWidget , self ) .__init__ (parent )
231
+ QWidget .__init__ (self , parent )
226
232
from copy import deepcopy
227
233
self .data = deepcopy (data )
228
234
self .widgets = []
@@ -236,7 +242,13 @@ def __init__(self, data, comment="", parent=None):
236
242
print "*" * 80
237
243
print "COMMENT:" , comment
238
244
print "*" * 80
239
- self .setup ()
245
+
246
+ def get_dialog (self ):
247
+ """Return FormDialog instance"""
248
+ dialog = self .parent ()
249
+ while not isinstance (dialog , QDialog ):
250
+ dialog = dialog .parent ()
251
+ return dialog
240
252
241
253
def setup (self ):
242
254
for label , value in self .data :
@@ -284,6 +296,11 @@ def setup(self):
284
296
field .setCheckState (Qt .Unchecked )
285
297
elif isinstance (value , float ):
286
298
field = QLineEdit (repr (value ), self )
299
+ field .setValidator (QDoubleValidator (field ))
300
+ dialog = self .get_dialog ()
301
+ dialog .register_float_field (field )
302
+ self .connect (field , SIGNAL ('textChanged(QString)' ),
303
+ lambda text : dialog .update_buttons ())
287
304
elif isinstance (value , int ):
288
305
field = QSpinBox (self )
289
306
field .setRange (- 1e9 , 1e9 )
@@ -334,7 +351,7 @@ def get(self):
334
351
335
352
class FormComboWidget (QWidget ):
336
353
def __init__ (self , datalist , comment = "" , parent = None ):
337
- super ( FormComboWidget , self ) .__init__ (parent )
354
+ QWidget .__init__ (self , parent )
338
355
layout = QVBoxLayout ()
339
356
self .setLayout (layout )
340
357
self .combobox = QComboBox ()
@@ -351,14 +368,18 @@ def __init__(self, datalist, comment="", parent=None):
351
368
widget = FormWidget (data , comment = comment , parent = self )
352
369
self .stackwidget .addWidget (widget )
353
370
self .widgetlist .append (widget )
371
+
372
+ def setup (self ):
373
+ for widget in self .widgetlist :
374
+ widget .setup ()
354
375
355
376
def get (self ):
356
377
return [ widget .get () for widget in self .widgetlist ]
357
378
358
379
359
380
class FormTabWidget (QWidget ):
360
381
def __init__ (self , datalist , comment = "" , parent = None ):
361
- super ( FormTabWidget , self ) .__init__ (parent )
382
+ QWidget .__init__ (self , parent )
362
383
layout = QVBoxLayout ()
363
384
self .tabwidget = QTabWidget ()
364
385
layout .addWidget (self .tabwidget )
@@ -373,6 +394,10 @@ def __init__(self, datalist, comment="", parent=None):
373
394
self .tabwidget .setTabToolTip (index , comment )
374
395
self .widgetlist .append (widget )
375
396
397
+ def setup (self ):
398
+ for widget in self .widgetlist :
399
+ widget .setup ()
400
+
376
401
def get (self ):
377
402
return [ widget .get () for widget in self .widgetlist ]
378
403
@@ -381,7 +406,7 @@ class FormDialog(QDialog):
381
406
"""Form Dialog"""
382
407
def __init__ (self , data , title = "" , comment = "" ,
383
408
icon = None , parent = None , apply = None ):
384
- super ( FormDialog , self ) .__init__ (parent )
409
+ QDialog .__init__ (self , parent )
385
410
386
411
self .apply_callback = apply
387
412
@@ -398,8 +423,14 @@ def __init__(self, data, title="", comment="",
398
423
layout = QVBoxLayout ()
399
424
layout .addWidget (self .formwidget )
400
425
426
+ self .float_fields = []
427
+ self .formwidget .setup ()
428
+
401
429
# Button box
402
- bbox = QDialogButtonBox (QDialogButtonBox .Ok | QDialogButtonBox .Cancel )
430
+ self .bbox = bbox = QDialogButtonBox (QDialogButtonBox .Ok
431
+ | QDialogButtonBox .Cancel )
432
+ self .connect (self .formwidget , SIGNAL ('update_buttons()' ),
433
+ self .update_buttons )
403
434
if self .apply_callback is not None :
404
435
apply_btn = bbox .addButton (QDialogButtonBox .Apply )
405
436
self .connect (apply_btn , SIGNAL ("clicked()" ), self .apply )
@@ -414,6 +445,19 @@ def __init__(self, data, title="", comment="",
414
445
icon = QWidget ().style ().standardIcon (QStyle .SP_MessageBoxQuestion )
415
446
self .setWindowIcon (icon )
416
447
448
+ def register_float_field (self , field ):
449
+ self .float_fields .append (field )
450
+
451
+ def update_buttons (self ):
452
+ valid = True
453
+ for field in self .float_fields :
454
+ if not is_edit_valid (field ):
455
+ valid = False
456
+ for btn_type in (QDialogButtonBox .Ok , QDialogButtonBox .Apply ):
457
+ btn = self .bbox .button (btn_type )
458
+ if btn is not None :
459
+ btn .setEnabled (valid )
460
+
417
461
def accept (self ):
418
462
self .data = self .formwidget .get ()
419
463
QDialog .accept (self )
0 commit comments