19
19
EXPAND_ICON = ':/qtutils/fugue/toggle-small-expand'
20
20
CONTRACT_ICON = ':/qtutils/fugue/toggle-small'
21
21
22
+ _ENABLE_LAYOUT_EVENT_TYPE = QEvent .User
23
+
22
24
class ToolPaletteGroup (QVBoxLayout ):
23
25
24
26
def __init__ (self ,* args ,** kwargs ):
@@ -265,6 +267,10 @@ def __init__(self,parent,name,*args,**kwargs):
265
267
self ._column_count = 0
266
268
self ._row_count = 0
267
269
270
+ # Variable for controlling whether or not self._layout_widgets() is
271
+ # called in self.resizeEvent().
272
+ self ._layout_widgets_during_resizeEvent = True
273
+
268
274
def addWidget (self ,widget ,force_relayout = True ):
269
275
# Append to end of tool pallete
270
276
#widget.clicked.connect(embed)
@@ -385,6 +391,18 @@ def minimumSizeHint(self):
385
391
height = self .minimumSize ().height ()
386
392
return QSize (width , height )
387
393
394
+ def event (self , event ):
395
+ # Handle the custom event for reenabling the call to
396
+ # self._layout_widgets() during self.resizeEvent().
397
+ if (event .type () == _ENABLE_LAYOUT_EVENT_TYPE ):
398
+ self ._layout_widgets_during_resizeEvent = True
399
+ # Return True so that this event isn't sent along to other event
400
+ # handlers as well.
401
+ return True
402
+
403
+ # Handle all other events in the usual way.
404
+ return super ().event (event )
405
+
388
406
def resizeEvent (self , event ):
389
407
# overwrite the resize event!
390
408
# print '--------- %s'%self._name
@@ -396,13 +414,39 @@ def resizeEvent(self, event):
396
414
# print self.minimumSize()
397
415
# print self.sizeHint()
398
416
# print self.minimumSizeHint()
399
- #pass resize event on to qwidget
400
- # call layout()
401
- QWidget .resizeEvent (self , event )
402
- size = event .size ()
403
- if size .width () == self .size ().width () and size .height () == self .size ().height ():
404
- # print 'relaying out widgets'
405
- self ._layout_widgets ()
417
+ # This method can end up undergoing infinite recursion for some window
418
+ # layouts, see
419
+ # https://github.com/labscript-suite/labscript-utils/issues/27. It seems
420
+ # that sometimes self._layout_widgets() increases the number of columns,
421
+ # which then triggers a resizeEvent, which then calls
422
+ # self._layout_widgets() which then decreases the number of columns to
423
+ # its previous value, which triggers a resizeEvent, and so on. That loop
424
+ # may occur e.g. if increasing/decreasing the number of columns
425
+ # add/removes a scrollbar, which then changes the number of widgets that
426
+ # can fit in a row. Keeping track of the recursion depth isn't trivial
427
+ # because _layout_widgets() doesn't directly call itself; it just causes
428
+ # more resizing events to be added to the event queue. To work around
429
+ # that, this method will mark that future calls to this method shouldn't
430
+ # call _layout_widgets() but will also add an event to the event queue
431
+ # to reenable calling _layout_widgets() again once all of the resize
432
+ # events caused by this call to it have been processed.
433
+
434
+ try :
435
+ #pass resize event on to qwidget
436
+ QWidget .resizeEvent (self , event )
437
+ size = event .size ()
438
+ if size .width () == self .size ().width () and size .height () == self .size ().height ():
439
+ if self ._layout_widgets_during_resizeEvent :
440
+ # Avoid calling this again until all the resize events that
441
+ # will be put in the queue by self._layout_widgets() have
442
+ # run.
443
+ self ._layout_widgets_during_resizeEvent = False
444
+ self ._layout_widgets ()
445
+ finally :
446
+ # Add event to end of the event queue to allow _layout_widgets() in
447
+ # future calls. This event shouldn't be handled until the resize
448
+ # events generated during _layout_widgets() have run.
449
+ QCoreApplication .instance ().postEvent (self , QEvent (_ENABLE_LAYOUT_EVENT_TYPE ))
406
450
407
451
408
452
# A simple test!
0 commit comments