Skip to content

Commit

Permalink
Merge pull request #2963 from ales-erjavec/fixes/widgetsscheme-force-…
Browse files Browse the repository at this point in the history
…delete

[FIX] WidgetManager: Schedule delayed deletion for managed OWWidgets
  • Loading branch information
lanzagar authored Mar 30, 2018
2 parents 17c385f + 8dfd877 commit b1972e5
Showing 1 changed file with 27 additions and 13 deletions.
40 changes: 27 additions & 13 deletions Orange/canvas/scheme/widgetsscheme.py
Original file line number Diff line number Diff line change
Expand Up @@ -136,6 +136,10 @@ class ProcessingState(enum.IntEnum):

InputUpdate, BlockingUpdate, ProcessingUpdate, Initializing = ProcessingState

#: State mask for widgets that cannot be deleted immediately
#: (see __try_delete)
_DelayDeleteMask = InputUpdate | BlockingUpdate

#: Widget initialization states
Delayed = namedtuple(
"Delayed", ["node"])
Expand Down Expand Up @@ -183,9 +187,6 @@ def __init__(self, parent=None):
# immediately
self.__delay_delete = set()

#: Deleted/removed during creation/initialization.
self.__delete_after_create = []

#: processing state flags for all widgets (including the ones
#: in __delay_delete).
#: Note: widgets which have not yet been created do not have an entry
Expand Down Expand Up @@ -386,16 +387,17 @@ def _delete_widget(self, widget):
Delete the OWBaseWidget instance.
"""
widget.close()

# Save settings to user global settings.
widget.saveSettings()

# Notify the widget it will be deleted.
widget.onDeleteWidget()

if self.__widget_processing_state[widget] != 0:
state = self.__widget_processing_state[widget]
if state & WidgetManager._DelayDeleteMask:
# If the widget is in an update loop and/or blocking we
# delay the scheduled deletion until the widget is done.
log.debug("Widget %s removed but still in state :%s. "
"Deferring deletion.", widget, state)
self.__delay_delete.add(widget)
else:
widget.deleteLater()
Expand Down Expand Up @@ -581,6 +583,7 @@ def eventFilter(self, receiver, event):
widget.close()
widget.saveSettings()
widget.onDeleteWidget()
widget.deleteLater()

event.accept()
return True
Expand Down Expand Up @@ -638,16 +641,21 @@ def __on_processing_state_changed(self, state):
A widget processing state has changed (progressBarInit/Finished)
"""
widget = self.sender()
try:
node = self.node_for_widget(widget)
except KeyError:
return

if state:
self.__widget_processing_state[widget] |= self.ProcessingUpdate
else:
self.__widget_processing_state[widget] &= ~self.ProcessingUpdate
self.__update_node_processing_state(node)

# propagate the change to the workflow model.
try:
# we can still track widget state after it was removed from the
# workflow model (`__delay_delete`)
node = self.node_for_widget(widget)
except KeyError:
pass
else:
self.__update_node_processing_state(node)

def __on_processing_started(self, node):
"""
Expand Down Expand Up @@ -705,10 +713,16 @@ def __update_node_processing_state(self, node):
node.set_processing_state(1 if state else 0)

def __try_delete(self, widget):
if self.__widget_processing_state[widget] == 0:
if not (self.__widget_processing_state[widget]
& WidgetManager._DelayDeleteMask):
log.debug("Delayed delete for widget %s", widget)
self.__delay_delete.remove(widget)
widget.deleteLater()
del self.__widget_processing_state[widget]
widget.blockingStateChanged.disconnect(
self.__on_blocking_state_changed)
widget.processingStateChanged.disconnect(
self.__on_processing_state_changed)
widget.deleteLater()

def __on_env_changed(self, key, newvalue, oldvalue):
# Notify widgets of a runtime environment change
Expand Down

0 comments on commit b1972e5

Please sign in to comment.