diff --git a/src/gtk/dataview.cpp b/src/gtk/dataview.cpp index 935f9ef11c..81de210a39 100644 --- a/src/gtk/dataview.cpp +++ b/src/gtk/dataview.cpp @@ -244,6 +244,13 @@ public: bool IsSorted() const { return m_sort_column >= 0; } + // Freezing sort temporarily disables sorting when inserting the items into + // the tree as an optimization when inserting many items. Sort must be + // thawed, by calling FreezeSort(false), before inserting the last item to + // ensure that the items still end up in the right order. + void FreezeSort(bool freeze) { m_sort_frozen = freeze; } + bool IsSortFrozen() const { return m_sort_frozen; } + // Should we be sorted either because we have a configured sort column or // because we have a default sort order? bool ShouldBeSorted() const @@ -286,6 +293,7 @@ private: GtkSortType m_sort_order; wxDataViewColumn *m_dataview_sort_column; int m_sort_column; + bool m_sort_frozen; GtkTargetEntry m_dragSourceTargetEntry; wxCharBuffer m_dragSourceTargetEntryTarget; @@ -352,7 +360,7 @@ public: m_children.Add( id ); - if (m_internal->ShouldBeSorted()) + if ( !m_internal->IsSortFrozen() && m_internal->ShouldBeSorted() ) { gs_internal = m_internal; m_children.Sort( &wxGtkTreeModelChildCmp ); @@ -399,7 +407,7 @@ public: { m_children.Insert( id, pos ); - if (m_internal->ShouldBeSorted()) + if ( !m_internal->IsSortFrozen() && m_internal->ShouldBeSorted() ) { gs_internal = m_internal; m_children.Sort( &wxGtkTreeModelChildCmp ); @@ -451,6 +459,8 @@ public: wxDataViewItem &GetItem() { return m_item; } wxDataViewCtrlInternal *GetInternal() { return m_internal; } + void FreezeSort(bool freeze) { m_internal->FreezeSort(freeze); } + void Resort(); private: @@ -3624,6 +3634,7 @@ wxDataViewCtrlInternal::wxDataViewCtrlInternal( wxDataViewCtrl *owner, wxDataVie m_root = NULL; m_sort_order = GTK_SORT_ASCENDING; m_sort_column = -1; + m_sort_frozen = false; m_dataview_sort_column = NULL; m_dragDataObject = NULL; @@ -3719,11 +3730,21 @@ void wxDataViewCtrlInternal::BuildBranch( wxGtkTreeModelNode *node ) wxDataViewItemArray children; unsigned int count = m_wx_model->GetChildren( node->GetItem(), children ); + // Avoid sorting children multiple times when inserting many nodes, + // this results in O(N^2*log(N)) complexity. + if ( count > 1 ) + node->FreezeSort(true); + unsigned int pos; for (pos = 0; pos < count; pos++) { wxDataViewItem child = children[pos]; + // Rr-enable sorting before inserting the last child if we had + // disabled it above. + if ( pos == count - 1 && pos != 0 ) + node->FreezeSort(false); + if (m_wx_model->IsContainer( child )) node->AddNode( new wxGtkTreeModelNode( node, child, this ) ); else