diff --git a/src/gtk/dataview.cpp b/src/gtk/dataview.cpp index 3ca8b55e60..ee482cd68c 100644 --- a/src/gtk/dataview.cpp +++ b/src/gtk/dataview.cpp @@ -680,7 +680,13 @@ wxgtk_tree_model_init(GTypeInstance* instance, void*) { GtkWxTreeModel* tree_model = GTK_WX_TREE_MODEL(instance); tree_model->internal = NULL; - tree_model->stamp = g_random_int(); + + // 0 is handled specially in wxGtkTreeCellDataFunc, so don't use it as the + // stamp. + do + { + tree_model->stamp = g_random_int(); + } while ( tree_model->stamp == 0 ); } } // extern "C" @@ -746,9 +752,18 @@ static GtkTreePath * wxgtk_tree_model_get_path (GtkTreeModel *tree_model, GtkTreeIter *iter) { - GtkWxTreeModel *wxtree_model = (GtkWxTreeModel *) tree_model; - g_return_val_if_fail (GTK_IS_WX_TREE_MODEL (wxtree_model), NULL); - g_return_val_if_fail (iter->stamp == GTK_WX_TREE_MODEL (wxtree_model)->stamp, NULL); + g_return_val_if_fail (GTK_IS_WX_TREE_MODEL (tree_model), NULL); + + GtkWxTreeModel *wxtree_model = GTK_WX_TREE_MODEL (tree_model); + if ( wxtree_model->stamp == 0 ) + { + // The model is temporarily invalid and can't be used, see Cleared(), + // but we need to return some valid path from here -- just return an + // empty one. + return gtk_tree_path_new(); + } + + g_return_val_if_fail (iter->stamp == wxtree_model->stamp, NULL); return wxtree_model->internal->get_path( iter ); } @@ -1891,12 +1906,25 @@ bool wxGtkDataViewModelNotifier::Cleared() GtkTreePath *path = gtk_tree_path_new_first(); // points to root + // It is important to avoid selection changed events being generated from + // here as they would reference the already deleted model items, which + // would result in crashes in any code attempting to handle these events. + wxDataViewCtrl::SelectionEventsSuppressor noSelection(m_internal->GetOwner()); + + // We also need to prevent wxGtkTreeCellDataFunc from using the model items + // not existing any longer, so change the model stamp to indicate that it + // temporarily can't be used. + const gint stampOrig = wxgtk_model->stamp; + wxgtk_model->stamp = 0; + int i; for (i = 0; i < count; i++) gtk_tree_model_row_deleted( GTK_TREE_MODEL(wxgtk_model), path ); gtk_tree_path_free( path ); + wxgtk_model->stamp = stampOrig; + m_internal->Cleared(); return true; @@ -3059,6 +3087,13 @@ static void wxGtkTreeCellDataFunc( GtkTreeViewColumn *WXUNUSED(column), g_return_if_fail (GTK_IS_WX_TREE_MODEL (model)); GtkWxTreeModel *tree_model = (GtkWxTreeModel *) model; + if ( !tree_model->stamp ) + { + // The model is temporarily invalid and can't be used, see the code in + // wxGtkDataViewModelNotifier::Cleared(). + return; + } + wxDataViewRenderer *cell = (wxDataViewRenderer*) data; wxDataViewItem item( (void*) iter->user_data );