[Qt-interest] Widget to use on Model/View
Andre Somers
andre at familiesomers.nl
Thu Aug 20 10:41:31 CEST 2009
Sean Harmer wrote:
> Hi,
>
> On Thursday 20 Aug 2009 06:03:26 João Mesquita wrote:
>
>> Hello guys, this is my first post so I am sorry if there is something
>> obvious I am missing.
>>
>> I am developing an application that has a console like interface and I
>> thought of using QListView to represent this console. Each line on the
>> console would be an item that is then appended to the QListView model. The
>> advantage of using such a widget is that the console log messages can be
>> sorted easily. I could easily make checkboxes to hide certain messages that
>> do not belong to certain log levels or apply Regex or even filters using a
>> custom QSortProxyModel. If anyone is familiar with Wireshark, that is
>> exactly the same behavior I am trying to achieve.
>>
> Sounds fine. You may wish to consider a table view if you have several columns
> of data though.
>
>
>> Problem here is performance. When sorting, not a problem, but when
>> inserting a large number of lines per second, I make the UI unresponsive
>> and even unusable. Should I change the widget, the model or not possible at
>> all?
>>
>> Here is the code I am using (modified batch append code of QListWidget).
>>
>> void ConsoleTabWidget::timerEvent(QTimerEvent *e)
>>
>> {
>>
>> bool scroll = false;
>>
>> if (e->timerId() == scrollTimer->timerId())
>>
>> {
>>
>> if (m_ui->consoleListView->verticalScrollBar()->value() ==
>> m_ui->consoleListView->verticalScrollBar()->maximum())
>>
>> scroll = true;
>>
>> int inserted_items = 0;
>>
>> while( !_list_items.isEmpty() && inserted_items < batch)
>>
>> {
>>
>> sourceModel->appendRow(_list_items.takeFirst());
>>
>> inserted_items++;
>>
>> }
>>
>> if (scroll)
>>
>> m_ui->consoleListView->scrollToBottom();
>>
>> }
>>
>> }
>>
>> Any help would be wonderful!
>>
> I think the problem is that each time you call sourceModel->appendRow() the
> model emits a signal that tells any attached views that the model has changed
> and that they should update. This of course will be quite expensive.
>
> A better way is to give your model a function that takes a list of items to
> append to the model. At the start of this function call
> QAbstractItemModel::beginInsertRows(), then append your data to your model's
> internal data structure, then finally call
> QAbstractItemModel::endInsertRows(). This way you can insert any number of
> rows and only trigger a single update of the attached views. Something like
> this (not tested):
>
> void MyModel::append( const QList<MyItem>& items )
> {
> // Assuming sub-class of QAbstractListModel so no parent index
> // Let the views know we are about to change
> beginInsertRows( QModelIndex(), m_items.size(), m_items.size() + items.size()
> );
>
> // Copy the data
> m_items.append( items );
>
> // Let the views know we are done with the update
> endInsertRows();
> }
>
> Good luck,
>
> Sean
>
> _______________________________________________
> Qt-interest mailing list
> Qt-interest at trolltech.com
> http://lists.trolltech.com/mailman/listinfo/qt-interest
>
>
>
Additionally, you may want to use Seans suggestion above to do a bit of
buffering. That is: only insert the new items if either a certain time
has eleapsed (like .1 second) or a number of items is reached (1000?).
Untill that time, just append the items to an internal list that is not
displayed.
This can dramatically increase performance, as it saves you many, many
redraws.
André
More information about the Qt-interest-old
mailing list