Skip to content

Commit d9eb80f

Browse files
committed
Fixed #27; worked around bug where ToolPalette.resizeEvent() could trigger itself in an infinite resursion loop.
1 parent f0999f5 commit d9eb80f

File tree

1 file changed

+51
-7
lines changed

1 file changed

+51
-7
lines changed

labscript_utils/qtwidgets/toolpalette.py

Lines changed: 51 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,8 @@
1919
EXPAND_ICON = ':/qtutils/fugue/toggle-small-expand'
2020
CONTRACT_ICON = ':/qtutils/fugue/toggle-small'
2121

22+
_ENABLE_LAYOUT_EVENT_TYPE = QEvent.User
23+
2224
class 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

Comments
 (0)