From: Vadim Zeitlin Date: Tue, 26 Apr 2011 22:57:01 +0000 (+0000) Subject: Fix assert when destroying wxDataViewCtrl being edited in wxGTK. X-Git-Url: https://git.saurik.com/wxWidgets.git/commitdiff_plain/b2fd3bea361eefa072f4d62e2502dd018ef68b83 Fix assert when destroying wxDataViewCtrl being edited in wxGTK. If wxDataViewCtrl was destroyed while showing a generic editor, an assert occurred in wxWindowBase dtor as the event handler pushed on it by the editor. Fix this by calling CancelEditing() when the control is destroyed and also fix the crash in CancelEditing() in wxGTK due to recursive calls to FinishEditing(). Closes #12683. git-svn-id: https://svn.wxwidgets.org/svn/wx/wxWidgets/trunk@67612 c3d73ce0-8a6f-49c7-b76d-6d57e0e08775 --- diff --git a/include/wx/gtk/dataview.h b/include/wx/gtk/dataview.h index 9ff89012ec..03bcbdf1c3 100644 --- a/include/wx/gtk/dataview.h +++ b/include/wx/gtk/dataview.h @@ -192,6 +192,12 @@ private: virtual wxDataViewItem DoGetCurrentItem() const; virtual void DoSetCurrentItem(const wxDataViewItem& item); + // Return wxDataViewColumn matching the given GtkTreeViewColumn. + // + // If the input argument is NULL, return NULL too. Otherwise we must find + // the matching column and assert if we didn't. + wxDataViewColumn* FromGTKColumn(GtkTreeViewColumn *gtk_col) const; + friend class wxDataViewCtrlDCImpl; friend class wxDataViewColumn; friend class wxDataViewCtrlInternal; diff --git a/src/common/datavcmn.cpp b/src/common/datavcmn.cpp index fa3d3563d5..8e2469c228 100644 --- a/src/common/datavcmn.cpp +++ b/src/common/datavcmn.cpp @@ -728,12 +728,15 @@ bool wxDataViewRendererBase::StartEditing( const wxDataViewItem &item, wxRect la void wxDataViewRendererBase::DestroyEditControl() { + // Remove our event handler first to prevent it from (recursively) calling + // us again as it would do via a call to FinishEditing() when the editor + // loses focus when we hide it below. + wxEvtHandler * const handler = m_editorCtrl->PopEventHandler(); + // Hide the control immediately but don't delete it yet as there could be // some pending messages for it. m_editorCtrl->Hide(); - wxEvtHandler * const handler = m_editorCtrl->PopEventHandler(); - wxPendingDelete.Append(handler); wxPendingDelete.Append(m_editorCtrl); } @@ -743,8 +746,6 @@ void wxDataViewRendererBase::CancelEditing() if (!m_editorCtrl) return; - GetOwner()->GetOwner()->GetMainWindow()->SetFocus(); - DestroyEditControl(); } diff --git a/src/gtk/dataview.cpp b/src/gtk/dataview.cpp index 6201a6c42d..249abb706d 100644 --- a/src/gtk/dataview.cpp +++ b/src/gtk/dataview.cpp @@ -4447,6 +4447,22 @@ IMPLEMENT_DYNAMIC_CLASS(wxDataViewCtrl, wxDataViewCtrlBase) wxDataViewCtrl::~wxDataViewCtrl() { + // Stop editing before destroying the control to remove any event handlers + // which are added when editing started: if we didn't do this, the base + // class dtor would assert as it checks for any leftover handlers. + if ( m_treeview ) + { + GtkTreeViewColumn *col; + gtk_tree_view_get_cursor(GTK_TREE_VIEW(m_treeview), NULL, &col); + + wxDataViewColumn * const wxcol = FromGTKColumn(col); + if ( wxcol ) + { + // This won't do anything if we're not editing it + wxcol->GetRenderer()->CancelEditing(); + } + } + m_cols.Clear(); delete m_internal; @@ -4689,10 +4705,9 @@ unsigned int wxDataViewCtrl::GetColumnCount() const return m_cols.GetCount(); } -wxDataViewColumn* wxDataViewCtrl::GetColumn( unsigned int pos ) const +wxDataViewColumn* wxDataViewCtrl::FromGTKColumn(GtkTreeViewColumn *gtk_col) const { - GtkTreeViewColumn *gtk_col = gtk_tree_view_get_column( GTK_TREE_VIEW(m_treeview), pos ); - if (!gtk_col) + if ( !gtk_col ) return NULL; wxDataViewColumnList::const_iterator iter; @@ -4705,9 +4720,18 @@ wxDataViewColumn* wxDataViewCtrl::GetColumn( unsigned int pos ) const } } + wxFAIL_MSG( "No matching column?" ); + return NULL; } +wxDataViewColumn* wxDataViewCtrl::GetColumn( unsigned int pos ) const +{ + GtkTreeViewColumn *gtk_col = gtk_tree_view_get_column( GTK_TREE_VIEW(m_treeview), pos ); + + return FromGTKColumn(gtk_col); +} + bool wxDataViewCtrl::DeleteColumn( wxDataViewColumn *column ) { gtk_tree_view_remove_column( GTK_TREE_VIEW(m_treeview),