file-browser: remove dummy child last
Previously, when the virtual root that has any number of non-dummy
children is removed from under gedit, depending on the order of calls
to on_directory_monitor_event()
, a segmentation fault could occur in GTK.
The reason for this is helpfully noted by GTK:
(gedit:71019): Gtk-CRITICAL **: 19:33:58.168: ../gtk/gtk/gtktreeview.c:6711 (validate_visible_area): assertion `has_next' failed.
There is a disparity between the internal view of the GtkTreeView,
and the GtkTreeModel. This generally means that the model has changed
without letting the view know. Any display from now on is likely to
be incorrect.
Due to this disparity gedit_file_browser_store_get_value()
cannot
succeed at a later point, effectively returning an invalid GValue to
GTK, causing the crash in the end.
That disparity is caused by the fact that when a non-dummy node
is removed, then model_check_dummy()
is called on its parent
(if there is one). Now, when model_remove_node_children()
is
removing the children of the virtual root, its first child
will be a dummy node, and that is removed without a problem.
However, the removal of the second child (the first non-dummy one)
will result in a call to model_check_dummy()
, which will create
a new dummy node because the "original" dummy node has just
been removed in the previous iteration. In the last iteration
the model_check_dummy()
call will see that there are no other
children of the parent, and hence will insert the dummy node
into the GtkTreeModel. And this extra insertion causes the
disparity between GTK's and gedit's state.
Fix that by removing dummy child last. By not removing the dummy
child first, it is guaranteed that model_check_dummy()
will
not create a new dummy node - although it will still insert it
into the GtkTreeModel when removing the last non-dummy, but that
is not an issue since the model_remove_node()
takes care of
removing the dummy node from the model shortly. It also guarantees
that all children of a node will be removed after a call to
model_remove_node_children()
, and this makes it possible
to simplify model_clear()
as it no longer needs to concern
itself with the leftover dummy node.
(Hopefully) fixes #356 (closed)