Fix crash when deleting all wxTreeListCtrl items with wxGTK3
GTK+ 3 (but not the generic version nor even GTK+ 2, apparently) sends "selection changed" event from gtk_tree_model_row_deleted() when deleting the currently selected row, which resulted in sending of wxEVT_TREELIST_SELECTION_CHANGED events with invalid wxTreeListItem, containing a dangling pointer, and a crash in the treelist sample when trying to dump it. Avoid this by clearing the model (and hence generating these events) first and deleting the items only afterwards. Also add a trivial unit test for wxTreeListCtrl::DeleteAllItems(), which doesn't even allow to reproduce this bug, but is still probably better to have than not to. Closes #18045.
This commit is contained in:
@@ -572,12 +572,16 @@ void wxTreeListModel::DeleteItem(Node* item)
|
|||||||
|
|
||||||
void wxTreeListModel::DeleteAllItems()
|
void wxTreeListModel::DeleteAllItems()
|
||||||
{
|
{
|
||||||
|
// Note that this must be called before actually deleting the items as
|
||||||
|
// clearing GTK+ wxDataViewCtrl results in SELECTION_CHANGED events being
|
||||||
|
// sent and these events contain pointers to the model items, so they must
|
||||||
|
// still be valid.
|
||||||
|
Cleared();
|
||||||
|
|
||||||
while ( m_root->GetChild() )
|
while ( m_root->GetChild() )
|
||||||
{
|
{
|
||||||
m_root->DeleteChild();
|
m_root->DeleteChild();
|
||||||
}
|
}
|
||||||
|
|
||||||
Cleared();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
const wxString& wxTreeListModel::GetItemText(Node* item, unsigned col) const
|
const wxString& wxTreeListModel::GetItemText(Node* item, unsigned col) const
|
||||||
|
@@ -39,6 +39,7 @@ private:
|
|||||||
CPPUNIT_TEST( Traversal );
|
CPPUNIT_TEST( Traversal );
|
||||||
CPPUNIT_TEST( ItemText );
|
CPPUNIT_TEST( ItemText );
|
||||||
CPPUNIT_TEST( ItemCheck );
|
CPPUNIT_TEST( ItemCheck );
|
||||||
|
CPPUNIT_TEST( DeleteAll );
|
||||||
CPPUNIT_TEST_SUITE_END();
|
CPPUNIT_TEST_SUITE_END();
|
||||||
|
|
||||||
// Create the control with the given style.
|
// Create the control with the given style.
|
||||||
@@ -55,6 +56,7 @@ private:
|
|||||||
void Traversal();
|
void Traversal();
|
||||||
void ItemText();
|
void ItemText();
|
||||||
void ItemCheck();
|
void ItemCheck();
|
||||||
|
void DeleteAll();
|
||||||
|
|
||||||
|
|
||||||
// The control itself.
|
// The control itself.
|
||||||
@@ -231,4 +233,11 @@ void TreeListCtrlTestCase::ItemCheck()
|
|||||||
m_treelist->GetCheckedState(m_code) );
|
m_treelist->GetCheckedState(m_code) );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void TreeListCtrlTestCase::DeleteAll()
|
||||||
|
{
|
||||||
|
m_treelist->DeleteAllItems();
|
||||||
|
|
||||||
|
CHECK( !m_treelist->GetFirstChild(m_treelist->GetRootItem()).IsOk() );
|
||||||
|
}
|
||||||
|
|
||||||
#endif // wxUSE_TREELISTCTRL
|
#endif // wxUSE_TREELISTCTRL
|
||||||
|
Reference in New Issue
Block a user