QAbstractItemModel: Why emitting dataChanged and insert rows signals when inserting numerous items into model so slow?

StackOverflow https://stackoverflow.com/questions/9210684

Вопрос

Hi to all Qt Model/view programming gurus here in Stackoverflow. The project I am working on requires me to define a QAbstractItemModel-derived model for XML data. I had previously asked a question here when I ran into a problem during implementation of this model: QSortFilterProxyModel crashes when deleting a row from the source model via the source model function

The model is currently doing its job pretty well in the application except for some performance issues which I do not know how to solve. One of the functions in this application is to add Frame element xml nodes by setting the Max Num and Rand numbers. Each Frame element will have both Num and Rand numbers running from 0 to MaxNum - 1 and 0 to MaxRand-1 respectively. Furthermore I will need to add a child Parameter element for Rand=0 th and Rand=MaxRand-1 th element each. An abbreviated illustration is as follows:

For Max Num=100, Max Rand=50

<Frame Num="0" Rand="0">
  <Parameter Value="false"/>
 </Frame>
 <Frame Num="0" Rand="1"/>
 <Frame Num="0" Rand="2"/>
 ...
 <Frame Num="0" Rand="48"/>
 <Frame Num="0" Rand="49">
  <Parameter Value="true"/>
 </Frame>
 <Frame Num="1" Rand="0">
  <Parameter Value="false"/>
 </Frame>
 <Frame Num="1" Rand="1"/>
 <Frame Num="1" Rand="2"/>
 ...
 <Frame Num="1" Rand="48"/>
 <Frame Num="1" Rand="49">
  <Parameter Value="true"/>
 </Frame> 
...
<Frame Num="99" Rand="0">
  <Parameter Value="false"/>
 </Frame>
 <Frame Num="99" Rand="1"/>
 <Frame Num="99" Rand="2"/>
 ...
 <Frame Num="99" Rand="48"/>
 <Frame Num="99" Rand="49">
  <Parameter Value="true"/>
 </Frame>

The application works fine when both MaxNum and MaxRand are small i.e. total number of Frame elements around 50. However, when the element count goes beyond 500 or so, the adding of Frame elements via QAbstractItemModel functions becomes painfully and exponentially slow. The GUI freezes for a long period of time, to the point where I gave up waiting most of the time.

MAJOR UPDATE:

I have found out what is causing the slowdown when inserting a large number of, say 1000 items into my model. I was calling both insertRow(row, parent) and setData() once per item inserted, which turns out to be very expensive due to the signals emitted inside these functions.

I have modified the code to insertRows(row, 1000, parent) instead and defined a new silentSetData() that does not emit a dataChanged(currIndex, currIndex). I have also included a new public function called notifyDataChanges(startRow, endRow, parentIndex) which in turns emit the dataChanged signal once for the given range of data. All is fine but now the caller class will need to explicitly call notifyDataChanges after the whole set of data is inserted.

Now I am wondering why is emitting dataChanged signals so expensive? Has anyone tried other means to overcome this problem when inserting/changing large number of items in the model at once?

Это было полезно?

Решение

Another way to do that is to explicitly reset the model data structures. For example in one of my models the data is represented with a QStringList. I have implemented a function that resets the data in the model. For example:

void MyModel:setNewData(const QStringList newList) {

  beginResetModel();

  m_dataList = newList;

  endResetModel();
}

I would imagine this approach is also applicable in your case.

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top