Skip to content

Commit e74472c

Browse files
Merge pull request #76 from zakv/fix-27
Work around infinite recursion in ToolPalette.resizeEvent()
2 parents f0999f5 + c543328 commit e74472c

File tree

1 file changed

+51
-16
lines changed

1 file changed

+51
-16
lines changed

labscript_utils/qtwidgets/toolpalette.py

Lines changed: 51 additions & 16 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,24 +391,53 @@ 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!
390-
# print '--------- %s'%self._name
391-
# print self._widget_list[0].size()
392-
# print self._widget_list[0].sizeHint()
393-
# print self._widget_list[0].minimumSizeHint()
394-
# print self._layout.rowMinimumHeight(0)
395-
# print self.size()
396-
# print self.minimumSize()
397-
# print self.sizeHint()
398-
# 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()
408+
# This method can end up undergoing infinite recursion for some window
409+
# layouts, see
410+
# https://github.com/labscript-suite/labscript-utils/issues/27. It seems
411+
# that sometimes self._layout_widgets() increases the number of columns,
412+
# which then triggers a resizeEvent, which then calls
413+
# self._layout_widgets() which then decreases the number of columns to
414+
# its previous value, which triggers a resizeEvent, and so on. That loop
415+
# may occur e.g. if increasing/decreasing the number of columns
416+
# add/removes a scrollbar, which then changes the number of widgets that
417+
# can fit in a row. Keeping track of the recursion depth isn't trivial
418+
# because _layout_widgets() doesn't directly call itself; it just causes
419+
# more resizing events to be added to the event queue. To work around
420+
# that, this method will mark that future calls to this method shouldn't
421+
# call _layout_widgets() but will also add an event to the event queue
422+
# to reenable calling _layout_widgets() again once all of the resize
423+
# events caused by this call to it have been processed.
424+
425+
try:
426+
#pass resize event on to qwidget
427+
QWidget.resizeEvent(self, event)
428+
size = event.size()
429+
if size.width() == self.size().width() and size.height() == self.size().height():
430+
if self._layout_widgets_during_resizeEvent:
431+
# Avoid calling this again until all the resize events that
432+
# will be put in the queue by self._layout_widgets() have
433+
# run.
434+
self._layout_widgets_during_resizeEvent = False
435+
self._layout_widgets()
436+
finally:
437+
# Add event to end of the event queue to allow _layout_widgets() in
438+
# future calls. This event shouldn't be handled until the resize
439+
# events generated during _layout_widgets() have run.
440+
QCoreApplication.instance().postEvent(self, QEvent(_ENABLE_LAYOUT_EVENT_TYPE))
406441

407442

408443
# A simple test!

0 commit comments

Comments
 (0)