1919EXPAND_ICON = ':/qtutils/fugue/toggle-small-expand'
2020CONTRACT_ICON = ':/qtutils/fugue/toggle-small'
2121
22+ _ENABLE_LAYOUT_EVENT_TYPE = QEvent .User
23+
2224class ToolPaletteGroup (QVBoxLayout ):
2325
2426 def __init__ (self ,* args ,** kwargs ):
@@ -265,6 +267,10 @@ def __init__(self,parent,name,*args,**kwargs):
265267 self ._column_count = 0
266268 self ._row_count = 0
267269
270+ # Variable for controlling whether or not self._layout_widgets() is
271+ # called in self.resizeEvent().
272+ self ._layout_widgets_during_resizeEvent = True
273+
268274 def addWidget (self ,widget ,force_relayout = True ):
269275 # Append to end of tool pallete
270276 #widget.clicked.connect(embed)
@@ -385,6 +391,18 @@ def minimumSizeHint(self):
385391 height = self .minimumSize ().height ()
386392 return QSize (width , height )
387393
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+
388406 def resizeEvent (self , event ):
389407 # overwrite the resize event!
390408 # print '--------- %s'%self._name
@@ -396,13 +414,39 @@ def resizeEvent(self, event):
396414 # print self.minimumSize()
397415 # print self.sizeHint()
398416 # 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 ))
406450
407451
408452# A simple test!
0 commit comments