[Qt-interest] Widget to use on Model/View

Sean Harmer sean.harmer at maps-technology.com
Thu Aug 20 10:17:05 CEST 2009


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




More information about the Qt-interest-old mailing list