Tue 01 Jan 2013 08:20:34 PM UTC, original submission:
When moving layer via shift+mouse button, sometime "AttributeError: 'NoneType' object has no attribute 'model'" error can happen if move didn't finish in time and was scheduled for later.
To reproduce:
Preparation:
1) start mypaint
2) in preferences assign "Move Layer" to <Shift>Button3 (shift-right mouse button)
3) zoom out (zoom ~18% will suffice at my machine)
4) select big brush (e.g deevad/fill radius 6)
5) paint all over the screen. (e.g. paint giant diagonal line from top left to bottom right cornor)
Bug reproduction:
6) Press Shift
7) Click RMB to initiate moving
Next steps must be done quickly
8) move layer. Stop moving.
9) release shift key
10) release RMB
There will be error box (attach#1)
What's going on:
If movement takes too long, mypaint schedules moving to be done later. Sometimes this 'later' comes so much later, that some variables are already cleared and can't be used.
What's happening in the code:
in SpringLoadedModeMixin around gui/canvasevent.py:913
key_release_cb pops mode, around canvaseven:767 pop calls old_mode.leave(), which calls InteractionMode.leave() that clears doc at line canvasevent.py:180 [ok, that's confusing, I'll add stacktrace to the attach #2]
BUT. LayerMoveMode might be not finished with doc yet:
around canvasevent.py:1438 it calls gobject.idle_add(self._finalize_move_idler), so after a while GTK decides to finalize movement.
BUT. At that point LayerMoveMode.doc is already cleared thanks to key_release_cb/pop/leave
So basically
Attach#1: picture
Attach#2: contains two callstacks: first was gained by adding _setattr to LayerMoveMode and printing when doc changes to None
second by adding traceback.print_stack() into _finalize. As you can see _finalize_move_idler got called after
Interesting thing to note:
finalizer calls _drag_cleanup, which calls doc.modes.pop. But key_release_cb also calls doc.modes.pop(well, right now it's not a problem, since _finalizer displays error)
Workaround:
adding ignore_modifier=True to LayerMoveMode.__init__ seems to work
(see https://gitorious.org/~zrzz/mypaint/librarian-mypaint/commit/a59a5b7766c02e834c0af699830d3bdfa3cbfa2a )
but I have no idea what problems it might cause
|