Don't send events when changing model in wxGTK wxDataViewCtrl

Sending events from e.g. AssociateModel(NULL) made the GTK version
inconsistent with the other ones, neither of which sent any events in
this case, and could result in a lot of grief in the user code if it
didn't expect the event handler to be called at this moment (e.g. during
the destruction).

Make wxGTK compatible with the other ports and safer by always disabling
the selection changed events before calling gtk_tree_view_set_model().

Note that it's still incompatible with the other ports because they also
preserve the selection even after the change of model, but wxGTK loses
it. Ideally this would be fixed too, but for now live with this as the
lesser evil.
This commit is contained in:
Vadim Zeitlin
2019-09-12 23:36:20 +02:00
parent 063b6edf68
commit 54a8d1d8f3

View File

@@ -250,6 +250,11 @@ public:
}
// Associate our model with the tree view or disassociate it from it
// without generating any selection changed events, unlike
// gtk_tree_view_set_model() that this function wraps.
void UseModel(bool use);
// accessors
wxDataViewModel* GetDataViewModel() { return m_wx_model; }
const wxDataViewModel* GetDataViewModel() const { return m_wx_model; }
@@ -1865,20 +1870,16 @@ bool wxGtkDataViewModelNotifier::ValueChanged( const wxDataViewItem &item, unsig
bool wxGtkDataViewModelNotifier::BeforeReset()
{
GtkWidget *treeview = m_internal->GetOwner()->GtkGetTreeView();
gtk_tree_view_set_model( GTK_TREE_VIEW(treeview), NULL );
m_internal->UseModel(false);
return true;
}
bool wxGtkDataViewModelNotifier::AfterReset()
{
GtkWidget *treeview = m_internal->GetOwner()->GtkGetTreeView();
GtkWxTreeModel *wxgtk_model = m_internal->GetGtkModel();
m_internal->Cleared();
gtk_tree_view_set_model( GTK_TREE_VIEW(treeview), GTK_TREE_MODEL(wxgtk_model) );
m_internal->UseModel(true);
return true;
}
@@ -3551,7 +3552,7 @@ wxDataViewCtrlInternal::wxDataViewCtrlInternal( wxDataViewCtrl *owner, wxDataVie
if (!m_wx_model->IsVirtualListModel())
InitTree();
gtk_tree_view_set_model( GTK_TREE_VIEW(m_owner->GtkGetTreeView()), GTK_TREE_MODEL(m_gtk_model) );
UseModel(true);
}
wxDataViewCtrlInternal::~wxDataViewCtrlInternal()
@@ -3559,7 +3560,7 @@ wxDataViewCtrlInternal::~wxDataViewCtrlInternal()
m_wx_model->RemoveNotifier( m_notifier );
// remove the model from the GtkTreeView before it gets destroyed
gtk_tree_view_set_model( GTK_TREE_VIEW( m_owner->GtkGetTreeView() ), NULL );
UseModel(false);
g_object_unref( m_gtk_model );
@@ -3568,6 +3569,18 @@ wxDataViewCtrlInternal::~wxDataViewCtrlInternal()
delete m_dropDataObject;
}
void wxDataViewCtrlInternal::UseModel(bool use)
{
// Avoid any selection changed events from gtk_tree_view_set_model() call
// below as they don't happen under the other platforms and can be
// unexpected with the possibly fatal consequences for the user-defined
// event handler.
wxDataViewCtrl::SelectionEventsSuppressor noSelection(m_owner);
gtk_tree_view_set_model( GTK_TREE_VIEW(m_owner->GtkGetTreeView()),
use ? GTK_TREE_MODEL(m_gtk_model) : NULL );
}
void wxDataViewCtrlInternal::ScheduleRefresh()
{
m_dirty = true;