From 0078cf01cc3eff08c801040f62cee1925d39b59e Mon Sep 17 00:00:00 2001 From: Luca Bacci <luca.bacci982@gmail.com> Date: Wed, 5 Sep 2018 15:07:25 +0200 Subject: [PATCH 17/26] port-to-gtk3: Block Gtk::TreeSelection changed handler on tree model clear (#7) Now GParted compiles with Gtkmm3, but we get a failed assertion doing the following: * Select a device with more than 1 partition * Select a partition * Activate 'Refresh Devices' (or do any operation that causes it, like mount/unmount etc.) This is the failed assertion: ** ERROR:Win_GParted.cc:1152:void GParted::Win_GParted::set_valid_operations(): assertion failed: (valid_display_partition_ptr( selected_partition_ptr )) Aborted (core dumped) Where is the problem? Win_GParted::Refresh_Visual() calls TreeView_Detail::load_partitions() to clear and refill the treeview. The problem is in GParted::TreeView_Detail::load_partitions() at TreeView_Detail.cc:91: treestore_detail->clear(); This activates TreeView_Detail::on_selection_changed() which in turn activates Win_GParted::on_partition_selected() passing an old, stale pointer as an argument. This triggers the failed assertion. Why does this happen with Gtk3 and not with Gtk2? First a bit of background of GtkTreeView: What happens to the selection in a GtkTreeView when the selected row is removed? With Gtk2 the selection simply becomes empty, so nothing is selected afterwards. With Gtk3 this was changed [1] and selection moves to an adjacent row. gtk_tree_store_clear() removes rows one by one. While removing rows the selection changed signal is emitted. With Gtk2 it is emitted only one time, to indicate that selection has become empty. With Gtk3 it is instead emitted several times, each time indicating that selection has moved to the adjacent row. The handler TreeView_Detail::on_selection_changed() only takes action when the selection is not empty. So with Gtk3 it really takes action and activates Win_GParted::on_partition_selected() with a pointer to old data. What's the purpose of TreeView_Detail::on_selection_changed()? Its task is to update the selection in the drawing area above the TreeViewDetail, the DrawingAreaVisualDisk, so that the selected partition stays in sync on the two widgets. Fix by blocking the signal handler during the treeview clear. Reference: [1] Commit - treeview: Handle the case where the cursor row gets deleted https://gitlab.gnome.org/GNOME/gtk/commit/1a2932ba2915c34171581a85afba39311e9c3ac6 Closes #7 - Port to Gtk3 --- src/TreeView_Detail.cc | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/TreeView_Detail.cc b/src/TreeView_Detail.cc index 2e105b03..dcf02ac9 100644 --- a/src/TreeView_Detail.cc +++ b/src/TreeView_Detail.cc @@ -88,7 +88,9 @@ void TreeView_Detail::load_partitions( const PartitionVector & partitions ) bool show_mountpoints = false; bool show_labels = false; + block = true; treestore_detail ->clear() ; + block = false; load_partitions( partitions, show_names, show_mountpoints, show_labels ); -- 2.21.0