On 16.04.2012 14:27, Koen Deforche wrote:
> Hey Stefan,
>
> Op 10 april 2012 16:47 heeft Stefan Ruppert<[email protected]>  het
> volgende geschreven:
>> Hi all,
>>
>> I managed to use the WTreeView to load thousands and more tree items
>> from our database. It works fine, but sometimes when I select a new tree
>> which will remove the complete old large tree within the WTreeView it
>> crashes or asserts.
>>
>> Currently I got the following assert(). I'm using the latest Wt 3.2.1
>> release.
>>
>> myarmbrowser.wt: /home/ruppert/work/wt/wt-3.2.1/src/Wt/WTreeView.C:1899:
>> void Wt::WTreeView::modelRowsInserted(const Wt::WModelIndex&, int, int):
>> Assertion `n' failed.
>> Abgebrochen (Speicherabzug geschrieben)
>>
>> I have a complete call stack, it seems to crash within endInsertRows()
>> signal processing. For small trees (less than 1000 items) I never
>> noticed a crash.
>>
>> Maybe I'll try to limit the tree, but whats the number of items which
>> can be handled correctly?
>
> Obviously, any number should be handled correctly (limited by a CSS
> limitation w.r.t. maximum height of a widget, actually).
>
> The assertion suggests a genuine bug -- could you suggest how we can
> reproduce it here, preferably with a test case ?
>
> Regards,
> koen

Hi Koen,

today I had some time to debug the crashes with large tree views. In 
fact I think I have found a serious bug within WStandardItem class.

Currently I'm using a WStandardItemModel which is populated with a huge 
tree. The I use a WSortFilterProxyModel model to support filtering and 
sorting on that tree. Now whenever a new tree is loaded the old tree is 
removed be calling removeRows() on the source model. This will result in 
calling WStandardItem::removeRows() method. And here is a bug during 
removing rows in conjunction with a WSortFilterProxyModel:

void WStandardItem::removeRows(int row, int count)
{
   if (model_)
     model_->beginRemoveRows(index(), row, row + count - 1);

   for (int i = 0; i < columnCount(); ++i) {
     Column& c = (*columns_)[i];

     for (int j = 0; j < count; ++j)
       delete c[row + j];

     c.erase(c.begin() + row, c.begin() + row + count);
   }

   renumberRows(row);

   if (model_)
     model_->endRemoveRows();
}

Here all removed items are deleted before the endRemoveRows() signal is 
emitted. But within the endRemoveRows() signal the WSortFilterProxyModel 
removes its source WModelIndex instance which in turn will use the 
deleted WStandardItem instances!!!

Here is a change which works for me:

void WStandardItem::removeRows(int row, int count)
{
   if (model_)
     model_->beginRemoveRows(index(), row, row + count - 1);

   Column eraseColumns;
   for (int i = 0; i < columnCount(); ++i) {
     Column& c = (*columns_)[i];

     for (int j = 0; j < count; ++j)
       eraseColumns.push_back(c[row + j]);

     c.erase(c.begin() + row, c.begin() + row + count);
   }

   renumberRows(row);

   if (model_)
     model_->endRemoveRows();

   for (int i = 0; i < eraseColumns.size(); ++i)
      delete eraseColumns[i];
}


Regards,
Stefan

------------------------------------------------------------------------------
Live Security Virtual Conference
Exclusive live event will cover all the ways today's security and 
threat landscape has changed and how IT managers can respond. Discussions 
will include endpoint security, mobile security and the latest in malware 
threats. http://www.accelacomm.com/jaw/sfrnl04242012/114/50122263/
_______________________________________________
witty-interest mailing list
[email protected]
https://lists.sourceforge.net/lists/listinfo/witty-interest

Reply via email to