From 861313f0e97347deed5026d0dd97e88b63c73688 Mon Sep 17 00:00:00 2001 From: Ilya Sinitsyn Date: Tue, 22 Mar 2022 04:46:09 +0700 Subject: [PATCH 1/3] Handle the nodes duplication error in the DVC test --- tests/controls/dataviewctrltest.cpp | 255 +++++++++++++++++++++++----- 1 file changed, 208 insertions(+), 47 deletions(-) diff --git a/tests/controls/dataviewctrltest.cpp b/tests/controls/dataviewctrltest.cpp index 2a41f826b7..e1775a0046 100644 --- a/tests/controls/dataviewctrltest.cpp +++ b/tests/controls/dataviewctrltest.cpp @@ -102,6 +102,10 @@ public: // |-- wxTEST_ITEM_CHILD // | // |-- wxTEST_ITEM_GRANDCHILD + // | | + // | |-- wxTEST_ITEM_LEAF + // | | + // | |-- wxTEST_ITEM_LEAF_HIDDEN // | // |-- wxTEST_ITEM_GRANDCHILD_HIDDEN // @@ -111,15 +115,19 @@ public: wxTEST_ITEM_ROOT, wxTEST_ITEM_CHILD, wxTEST_ITEM_GRANDCHILD, - wxTEST_ITEM_GRANDCHILD_HIDDEN, + wxTEST_ITEM_LEAF, + wxTEST_ITEM_LEAF_HIDDEN, + wxTEST_ITEM_GRANDCHILD_HIDDEN }; DataViewCtrlTestModel() : m_root(wxTEST_ITEM_ROOT), m_child(wxTEST_ITEM_CHILD), m_grandChild(wxTEST_ITEM_GRANDCHILD), - m_grandChildHidden(wxTEST_ITEM_GRANDCHILD_HIDDEN), - m_secondGrandchildVisible(false) + m_leaf(wxTEST_ITEM_LEAF), + m_leafHidden(wxTEST_ITEM_LEAF_HIDDEN), + m_grandchildHidden(wxTEST_ITEM_GRANDCHILD_HIDDEN), + m_allItemsVisible(false) { } @@ -139,8 +147,14 @@ public: case wxTEST_ITEM_GRANDCHILD: return wxDataViewItem(const_cast(&m_grandChild)); + case wxTEST_ITEM_LEAF: + return wxDataViewItem(const_cast(&m_leaf)); + + case wxTEST_ITEM_LEAF_HIDDEN: + return wxDataViewItem(const_cast(&m_leafHidden)); + case wxTEST_ITEM_GRANDCHILD_HIDDEN: - return wxDataViewItem(const_cast(&m_grandChildHidden)); + return wxDataViewItem(const_cast(&m_grandchildHidden)); } return wxDataViewItem(); } @@ -177,6 +191,14 @@ public: variant = "grand child"; break; + case wxTEST_ITEM_LEAF: + variant = "leaf"; + break; + + case wxTEST_ITEM_LEAF_HIDDEN: + variant = "initially hidden leaf"; + break; + case wxTEST_ITEM_GRANDCHILD_HIDDEN: variant = "initially hidden"; break; @@ -213,6 +235,10 @@ public: case wxTEST_ITEM_GRANDCHILD: case wxTEST_ITEM_GRANDCHILD_HIDDEN: return GetDataViewItem(m_child); + + case wxTEST_ITEM_LEAF: + case wxTEST_ITEM_LEAF_HIDDEN: + return GetDataViewItem(m_grandChild); } return wxDataViewItem(); } @@ -224,9 +250,11 @@ public: case wxTEST_ITEM_NULL: case wxTEST_ITEM_ROOT: case wxTEST_ITEM_CHILD: + case wxTEST_ITEM_GRANDCHILD: return true; - case wxTEST_ITEM_GRANDCHILD: + case wxTEST_ITEM_LEAF: + case wxTEST_ITEM_LEAF_HIDDEN: case wxTEST_ITEM_GRANDCHILD_HIDDEN: return false; } @@ -249,15 +277,27 @@ public: case wxTEST_ITEM_CHILD: children.push_back(GetDataViewItem(m_grandChild)); - if ( m_secondGrandchildVisible ) + if ( m_allItemsVisible ) { - children.push_back(GetDataViewItem(m_grandChildHidden)); + children.push_back(GetDataViewItem(m_grandchildHidden)); return 2; } return 1; case wxTEST_ITEM_GRANDCHILD: + children.push_back(GetDataViewItem(m_leaf)); + + if ( m_allItemsVisible ) + { + children.push_back(GetDataViewItem(m_leafHidden)); + return 2; + } + + return 1; + + case wxTEST_ITEM_LEAF: + case wxTEST_ITEM_LEAF_HIDDEN: case wxTEST_ITEM_GRANDCHILD_HIDDEN: FAIL( "The item is not a container" ); return 0; @@ -265,10 +305,34 @@ public: return 0; } - void ShowSecondGrandChild() + enum wxItemsOrder { - m_secondGrandchildVisible = true; - ItemAdded(GetDataViewItem(m_child), GetDataViewItem(m_grandChildHidden)); + wxORDER_LEAF_THEN_GRANCHILD, + wxORDER_GRANCHILD_THEN_LEAF + }; + + void ShowChildren(wxItemsOrder order) + { + m_allItemsVisible = true; + switch ( order ) + { + case wxORDER_LEAF_THEN_GRANCHILD: + ItemAdded(GetDataViewItem(m_grandChild), GetDataViewItem(m_leafHidden)); + ItemAdded(GetDataViewItem(m_child), GetDataViewItem(m_grandchildHidden)); + break; + + case wxORDER_GRANCHILD_THEN_LEAF: + ItemAdded(GetDataViewItem(m_child), GetDataViewItem(m_grandchildHidden)); + ItemAdded(GetDataViewItem(m_grandChild), GetDataViewItem(m_leafHidden)); + break; + } + } + + void HideChildren() + { + m_allItemsVisible = false; + ItemDeleted(GetDataViewItem(m_grandChild), GetDataViewItem(m_leafHidden)); + ItemDeleted(GetDataViewItem(m_child), GetDataViewItem(m_grandchildHidden)); } private: @@ -282,10 +346,12 @@ private: wxTestItem m_root; wxTestItem m_child; wxTestItem m_grandChild; - wxTestItem m_grandChildHidden; + wxTestItem m_leaf; + wxTestItem m_leafHidden; + wxTestItem m_grandchildHidden; // Whether wxTEST_ITEM_GRANDCHILD_HIDDEN item should be visible or not. - bool m_secondGrandchildVisible; + bool m_allItemsVisible; }; @@ -296,6 +362,51 @@ public: ~DataViewCtrlWithCustomModelTestCase(); protected: + enum wxItemExistence + { + wxITEM_APPEAR, + wxITEM_DISAPPEAR + }; + + void UpdateAndWaitForItem(const wxDataViewItem& item, wxItemExistence existence) + { + m_dvc->Refresh(); + m_dvc->Update(); + +#ifdef __WXGTK__ + // Unfortunately it's not enough to call wxYield() once, so wait up to + // 0.5 sec. + wxStopWatch sw; + while ( true ) + { + wxYield(); + + const bool isItemRectEmpty = m_dvc->GetItemRect(item).IsEmpty(); + switch ( existence ) + { + case wxITEM_APPEAR: + if ( !isItemRectEmpty ) + return; + break; + + case wxITEM_DISAPPEAR: + if ( isItemRectEmpty ) + return; + break; + } + + if ( sw.Time() > 500 ) + { + WARN("Timed out waiting for wxDataViewCtrl"); + break; + } + } +#else // !__WXGTK__ + wxUnusedVar(item); + wxUnusedVar(existence); +#endif // __WXGTK__ + } + // The dataview control. wxDataViewCtrl *m_dvc; @@ -303,7 +414,12 @@ protected: DataViewCtrlTestModel *m_model; // Its items. - wxDataViewItem m_root, m_child, m_grandchild, m_grandchildHidden; + wxDataViewItem m_root, + m_child, + m_grandchild, + m_leaf, + m_leafHidden, + m_grandchildHidden; wxDECLARE_NO_COPY_CLASS(DataViewCtrlWithCustomModelTestCase); }; @@ -384,6 +500,10 @@ DataViewCtrlWithCustomModelTestCase::DataViewCtrlWithCustomModelTestCase() m_child = m_model->GetDataViewItem(DataViewCtrlTestModel::wxTEST_ITEM_CHILD); m_grandchild = m_model->GetDataViewItem(DataViewCtrlTestModel::wxTEST_ITEM_GRANDCHILD); + m_leaf = + m_model->GetDataViewItem(DataViewCtrlTestModel::wxTEST_ITEM_LEAF); + m_leafHidden = + m_model->GetDataViewItem(DataViewCtrlTestModel::wxTEST_ITEM_LEAF_HIDDEN); m_grandchildHidden = m_model->GetDataViewItem(DataViewCtrlTestModel::wxTEST_ITEM_GRANDCHILD_HIDDEN); @@ -566,53 +686,94 @@ TEST_CASE_METHOD(DataViewCtrlWithCustomModelTestCase, wxYield(); #endif // __WXGTK__ - SECTION( "Was Expanded" ) + // Unfortunately we can't combine test options with SECTION() so use + // the additional enum variable. + enum { - CHECK( m_dvc->GetItemRect(m_grandchild).IsEmpty() ); - CHECK( m_dvc->GetItemRect(m_grandchildHidden).IsEmpty() ); + wxOPTIONS_EXPAND_ADD_LEAF_THEN_GRANCHILD, + wxOPTIONS_DONT_EXPAND_ADD_LEAF_THEN_GRANCHILD, + wxOPTIONS_EXPAND_ADD_GRANCHILD_THEN_LEAF, + wxOPTIONS_DONT_EXPAND_ADD_GRANCHILD_THEN_LEAF + } options; - m_dvc->Expand(m_child); - -#ifdef __WXGTK__ - wxYield(); -#endif // __WXGTK__ - - CHECK( !m_dvc->GetItemRect(m_grandchild).IsEmpty() ); - CHECK( m_dvc->GetItemRect(m_grandchildHidden).IsEmpty() ); - - m_dvc->Collapse(m_child); + SECTION( "Was Expanded, Add The Leaf Then The Grandchild" ) + { + options = wxOPTIONS_EXPAND_ADD_LEAF_THEN_GRANCHILD; } - SECTION( "Was Not Expanded" ) + SECTION( "Was Not Expanded, Add The Leaf Then The Grandchild" ) { - // Do nothing. + options = wxOPTIONS_DONT_EXPAND_ADD_LEAF_THEN_GRANCHILD; + } + + SECTION( "Was Expanded, Add The Grandchild Then The Leaf" ) + { + options = wxOPTIONS_EXPAND_ADD_GRANCHILD_THEN_LEAF; + } + + SECTION( "Was Not Expanded, Add The Grandchild Then The Leaf" ) + { + options = wxOPTIONS_DONT_EXPAND_ADD_GRANCHILD_THEN_LEAF; + } + + switch ( options ) + { + case wxOPTIONS_EXPAND_ADD_LEAF_THEN_GRANCHILD: + case wxOPTIONS_EXPAND_ADD_GRANCHILD_THEN_LEAF: + CHECK( m_dvc->GetItemRect(m_grandchild).IsEmpty() ); + CHECK( m_dvc->GetItemRect(m_leafHidden).IsEmpty() ); + CHECK( m_dvc->GetItemRect(m_grandchildHidden).IsEmpty() ); + + m_dvc->Expand(m_child); + m_dvc->Expand(m_grandchild); + UpdateAndWaitForItem(m_grandchild, wxITEM_APPEAR); + + CHECK( !m_dvc->GetItemRect(m_grandchild).IsEmpty() ); + CHECK( !m_dvc->GetItemRect(m_leaf).IsEmpty() ); + CHECK( m_dvc->GetItemRect(m_leafHidden).IsEmpty() ); + CHECK( m_dvc->GetItemRect(m_grandchildHidden).IsEmpty() ); + + m_dvc->Collapse(m_grandchild); + m_dvc->Collapse(m_child); + break; + + case wxOPTIONS_DONT_EXPAND_ADD_LEAF_THEN_GRANCHILD: + case wxOPTIONS_DONT_EXPAND_ADD_GRANCHILD_THEN_LEAF: + // Do nothing. + break; } // Check wxDataViewModel::ItemAdded(). - m_model->ShowSecondGrandChild(); + switch ( options ) + { + case wxOPTIONS_EXPAND_ADD_LEAF_THEN_GRANCHILD: + case wxOPTIONS_DONT_EXPAND_ADD_LEAF_THEN_GRANCHILD: + m_model->ShowChildren(DataViewCtrlTestModel::wxORDER_LEAF_THEN_GRANCHILD); + break; + + case wxOPTIONS_EXPAND_ADD_GRANCHILD_THEN_LEAF: + case wxOPTIONS_DONT_EXPAND_ADD_GRANCHILD_THEN_LEAF: + m_model->ShowChildren(DataViewCtrlTestModel::wxORDER_GRANCHILD_THEN_LEAF); + break; + } m_dvc->Expand(m_child); - m_dvc->Refresh(); - m_dvc->Update(); + m_dvc->Expand(m_grandchild); + UpdateAndWaitForItem(m_leaf, wxITEM_APPEAR); + CHECK( m_dvc->IsExpanded(m_child) ); - -#ifdef __WXGTK__ - // Unfortunately it's not enough to call wxYield() once, so wait up to - // 0.5 sec. - wxStopWatch sw; - while ( m_dvc->GetItemRect(m_grandchild).IsEmpty() ) - { - if ( sw.Time() > 500 ) - { - WARN("Timed out waiting for wxDataViewCtrl"); - break; - } - wxYield(); - } -#endif // __WXGTK__ - + CHECK( m_dvc->IsExpanded(m_grandchild) ); CHECK( !m_dvc->GetItemRect(m_grandchild).IsEmpty() ); + CHECK( !m_dvc->GetItemRect(m_leaf).IsEmpty() ); + CHECK( !m_dvc->GetItemRect(m_leafHidden).IsEmpty() ); CHECK( !m_dvc->GetItemRect(m_grandchildHidden).IsEmpty() ); + + m_model->HideChildren(); + UpdateAndWaitForItem(m_leafHidden, wxITEM_DISAPPEAR); + + CHECK( m_dvc->GetItemRect(m_leafHidden).IsEmpty() ); + // Check that the problem with nodes duplication in ItemAdded() fixed. + CHECK( m_dvc->GetItemRect(m_grandchildHidden).IsEmpty() ); } TEST_CASE_METHOD(SingleSelectDataViewCtrlTestCase, From 7966eaf268c26a1e4d868024abdfb0f1273c63e0 Mon Sep 17 00:00:00 2001 From: Ilya Sinitsyn Date: Wed, 23 Mar 2022 23:12:56 +0700 Subject: [PATCH 2/3] Fix nodes duplication in the generic DVC implementation Don't create a subtree in `FindNode()` and just return as the subtree will be realized when a parent node will be expanded. --- src/generic/datavgen.cpp | 61 +++++++++++++++++++++++++++++++--------- 1 file changed, 47 insertions(+), 14 deletions(-) diff --git a/src/generic/datavgen.cpp b/src/generic/datavgen.cpp index 55f6cdce77..dee692434e 100644 --- a/src/generic/datavgen.cpp +++ b/src/generic/datavgen.cpp @@ -959,7 +959,13 @@ private: // Return false only if the event was vetoed by its handler. bool SendExpanderEvent(wxEventType type, const wxDataViewItem& item); - wxDataViewTreeNode * FindNode( const wxDataViewItem & item ); + struct FindNodeResult + { + wxDataViewTreeNode * m_node; + bool m_subtreeRealized; + }; + + FindNodeResult FindNode( const wxDataViewItem & item ); wxDataViewColumn *FindColumnForEditing(const wxDataViewItem& item, wxDataViewCellMode mode) const; @@ -3089,8 +3095,15 @@ bool wxDataViewMainWindow::ItemAdded(const wxDataViewItem & parent, const wxData // specific position (row) is unclear, so clear whole height cache ClearRowHeightCache(); - wxDataViewTreeNode *parentNode = FindNode(parent); + const FindNodeResult findResult = FindNode(parent); + wxDataViewTreeNode *parentNode = findResult.m_node; + // If one of parents is not realized yet (has children but was never + // expanded). Return as nodes will be initialized in Expand(). + if ( !findResult.m_subtreeRealized ) + return true; + + // The parent node was not found. if ( !parentNode ) return false; @@ -3197,7 +3210,13 @@ bool wxDataViewMainWindow::ItemDeleted(const wxDataViewItem& parent, } else // general case { - wxDataViewTreeNode *parentNode = FindNode(parent); + const FindNodeResult findResult = FindNode(parent); + wxDataViewTreeNode *parentNode = findResult.m_node; + + // One of parents of the parent node has children but was never + // expanded, so the tree was not built and we have nothing to delete. + if ( !findResult.m_subtreeRealized ) + return true; // Notice that it is possible that the item being deleted is not in the // tree at all, for example we could be deleting a never shown (because @@ -3316,7 +3335,10 @@ bool wxDataViewMainWindow::DoItemChanged(const wxDataViewItem & item, int view_c // column but also falls back to other values for comparison. To ensure // consistency it is better to treat a value change as if it was an item // change. - wxDataViewTreeNode* const node = FindNode(item); + const FindNodeResult findResult = FindNode(item); + wxDataViewTreeNode* const node = findResult.m_node; + if ( !findResult.m_subtreeRealized ) + return true; wxCHECK_MSG( node, false, "invalid item" ); node->PutInSortOrder(this); } @@ -4084,14 +4106,22 @@ void wxDataViewMainWindow::Collapse(unsigned int row) } } -wxDataViewTreeNode * wxDataViewMainWindow::FindNode( const wxDataViewItem & item ) +wxDataViewMainWindow::FindNodeResult +wxDataViewMainWindow::FindNode( const wxDataViewItem & item ) { + FindNodeResult result; + result.m_node = NULL; + result.m_subtreeRealized = true; + const wxDataViewModel * model = GetModel(); if( model == NULL ) - return NULL; + return result; if (!item.IsOk()) - return m_root; + { + result.m_node = m_root; + return result; + } // Compose the parent-chain for the item we are looking for wxVector parentChain; @@ -4112,9 +4142,9 @@ wxDataViewTreeNode * wxDataViewMainWindow::FindNode( const wxDataViewItem & item if( node->GetChildNodes().empty() ) { // Even though the item is a container, it doesn't have any - // child nodes in the control's representation yet. We have - // to realize its subtree now. - ::BuildTreeHelper(this, model, node->GetItem(), node); + // child nodes in the control's representation yet. + result.m_subtreeRealized = false; + return result; } const wxDataViewTreeNodes& nodes = node->GetChildNodes(); @@ -4126,7 +4156,10 @@ wxDataViewTreeNode * wxDataViewMainWindow::FindNode( const wxDataViewItem & item if (currentNode->GetItem() == parentChain[iter]) { if (currentNode->GetItem() == item) - return currentNode; + { + result.m_node = currentNode; + return result; + } node = currentNode; found = true; @@ -4134,15 +4167,15 @@ wxDataViewTreeNode * wxDataViewMainWindow::FindNode( const wxDataViewItem & item } } if (!found) - return NULL; + return result; } else - return NULL; + return result; if ( !iter ) break; } - return NULL; + return result; } void wxDataViewMainWindow::HitTest( const wxPoint & point, wxDataViewItem & item, From 946ad457e994506f0b25691511539d9a3540261c Mon Sep 17 00:00:00 2001 From: Ilya Sinitsyn Date: Wed, 23 Mar 2022 12:49:24 -0700 Subject: [PATCH 3/3] Fix items adding to a collapsed node of DVC under GTK Note that `wxDataViewCtrlInternal_FindNode()` was removed to access protected `wxDataViewCtrlInternal::BuildBranch()`. --- src/gtk/dataview.cpp | 75 ++++++++++++++++++++++++++------------------ 1 file changed, 45 insertions(+), 30 deletions(-) diff --git a/src/gtk/dataview.cpp b/src/gtk/dataview.cpp index 68fbad271a..cb80d76648 100644 --- a/src/gtk/dataview.cpp +++ b/src/gtk/dataview.cpp @@ -275,11 +275,22 @@ public: void OnInternalIdle(); + enum wxFindNodeMode + { + // return NULL from FindNode() of a subtree was not realized + wxFIND_NODE_RETURN_IF_SUBTREE_NOT_REALIZED, + + // call BuildBranch() from FindNode() to realize a subtree + wxFIND_NODE_BUILD_SUBTREE, + }; + protected: void InitTree(); void ScheduleRefresh(); - wxGtkTreeModelNode *FindNode( const wxDataViewItem &item ); + wxGtkTreeModelNode *FindNode( const wxDataViewItem &item, + wxFindNodeMode mode = + wxFIND_NODE_RETURN_IF_SUBTREE_NOT_REALIZED ); wxGtkTreeModelNode *FindNode( GtkTreeIter *iter ); wxGtkTreeModelNode *FindParentNode( const wxDataViewItem &item ); wxGtkTreeModelNode *FindParentNode( GtkTreeIter *iter ); @@ -3959,7 +3970,7 @@ bool wxDataViewCtrlInternal::ItemAdded( const wxDataViewItem &parent, const wxDa { if (!m_wx_model->IsVirtualListModel()) { - wxGtkTreeModelNode *parent_node = FindNode( parent ); + wxGtkTreeModelNode *parent_node = FindNode( parent, wxFIND_NODE_BUILD_SUBTREE ); wxCHECK_MSG(parent_node, false, "Did you forget a call to ItemAdded()? The parent node is unknown to the wxGtkTreeModel"); @@ -3973,6 +3984,17 @@ bool wxDataViewCtrlInternal::ItemAdded( const wxDataViewItem &parent, const wxDa const wxGtkTreeModelChildren& nodeSiblings = parent_node->GetChildren(); const int nodeSiblingsSize = nodeSiblings.size(); + if ( nodeSiblingsSize == 0 ) + { + BuildBranch( parent_node ); + return true; + } + else + { + if ( parent_node->FindChildByItem(item) != wxNOT_FOUND ) + return true; + } + int nodePos = 0; if ( posInModel == modelSiblingsSize - 1 ) @@ -4398,10 +4420,13 @@ int wxDataViewCtrlInternal::GetIndexOf( const wxDataViewItem &parent, const wxDa } -static wxGtkTreeModelNode* -wxDataViewCtrlInternal_FindNode( wxDataViewModel * model, wxGtkTreeModelNode *treeNode, const wxDataViewItem &item ) +wxGtkTreeModelNode *wxDataViewCtrlInternal::FindNode( const wxDataViewItem &item, + wxFindNodeMode mode ) { - if( model == NULL ) + if ( !item.IsOk() ) + return m_root; + + if( m_wx_model == NULL ) return NULL; ItemList list; @@ -4412,14 +4437,25 @@ wxDataViewCtrlInternal_FindNode( wxDataViewModel * model, wxGtkTreeModelNode *tr { wxDataViewItem * pItem = new wxDataViewItem( it ); list.Insert( pItem ); - it = model->GetParent( it ); + it = m_wx_model->GetParent( it ); } - wxGtkTreeModelNode * node = treeNode; + wxGtkTreeModelNode * node = m_root; for( ItemList::compatibility_iterator n = list.GetFirst(); n; n = n->GetNext() ) { if( node && node->GetNodes().GetCount() != 0 ) { + switch ( mode ) + { + case wxFIND_NODE_RETURN_IF_SUBTREE_NOT_REALIZED: + // Do nothing and a subtree will not built. + break; + + case wxFIND_NODE_BUILD_SUBTREE: + BuildBranch( node ); + break; + } + int len = node->GetNodes().GetCount(); wxGtkTreeModelNodes &nodes = node->GetNodes(); int j = 0; @@ -4450,10 +4486,9 @@ wxGtkTreeModelNode *wxDataViewCtrlInternal::FindNode( GtkTreeIter *iter ) return m_root; wxDataViewItem item( (void*) iter->user_data ); - if (!item.IsOk()) - return m_root; - wxGtkTreeModelNode *result = wxDataViewCtrlInternal_FindNode( m_wx_model, m_root, item ); + const wxFindNodeMode mode = wxFIND_NODE_RETURN_IF_SUBTREE_NOT_REALIZED; + wxGtkTreeModelNode *result = FindNode( item, mode ); /* if (!result) @@ -4468,26 +4503,6 @@ wxGtkTreeModelNode *wxDataViewCtrlInternal::FindNode( GtkTreeIter *iter ) return result; } -wxGtkTreeModelNode *wxDataViewCtrlInternal::FindNode( const wxDataViewItem &item ) -{ - if (!item.IsOk()) - return m_root; - - wxGtkTreeModelNode *result = wxDataViewCtrlInternal_FindNode( m_wx_model, m_root, item ); - -/* - if (!result) - { - wxLogDebug( "Not found %p", item.GetID() ); - char *crash = NULL; - *crash = 0; - } - // TODO: remove this code -*/ - - return result; -} - static wxGtkTreeModelNode* wxDataViewCtrlInternal_FindParentNode( wxDataViewModel * model, wxGtkTreeModelNode *treeNode, const wxDataViewItem &item ) {