PascalVKooten
PascalVKooten

Reputation: 21433

Displaying big data using Qt Table View

I am not sure how to go about this big data problem. Instead of using a Table Widget, it is suggested to use a Table View for big data for speed. The data will be at most 200000 rows by 300 columns of strings. Also, it might have gaps in the structure. For the View, it is needed to define a Model. I was not able to do this yet and I wonder the following:

Will it really be faster to use a View if the user only wants replace some values in a column, and inspect the data? Is a QList a smart choice given speed needs, or are there better options? And how to implement this as a Model?

Upvotes: 1

Views: 3048

Answers (1)

Werner Erasmus
Werner Erasmus

Reputation: 4076

A QTableWidget uses its own Model as backend (container for its data). One can't (or it is not intented that one should) customize a QTableWidget's model. Each cell in a QTableWidget is represented by a QTableWidgetItem. They are written to solve general problems and are not that fast.

When one decides to use a QTableView with it's own model deriving from QAbstractTableModel as backend, one can speed things up allot. I've found that one of the things that took the most processing time was the size calculation of rows. I overloaded sizeHintForRow in my table like this:

int MyTable::sizeHintForRow ( int row ) const
{
  //All rows have the same height in MyTable, hence we use the height of the
  // first row for performance reasons.
  if( cachedRowSizeHint_ == -1 )
  {
    cachedRowSizeHint_ =
        model()->headerData( 0, Qt::Vertical, Qt::SizeHintRole ).toSize().height();
  }
  return cachedRowSizeHint_;
}

Implementing a simple table model is quite easy (Qt Help files are adequate...). One can start by providing the data for the minimum roles (Edit and Display). TableModel data can always be modified by using QIdentityProxyModels where necessary. If your models don't work, post your code. Remember to not return invalid data for roles e.g:

QVariant IO_PluginMngr::data(const QModelIndex & index, int role) const
{
  if( index.isValid() )
  {
    if( role == Qt::DisplayRole)
    {
      return sequence_[index.row()][index.column()];
    }
  }
  return QVariant();
}

Returning for example erroneous data for especially SizeHintRole will cause havoc in the views.

I've noticed that one should, when implementing models, be diligent in calling begin/endInsertRows when appropriate, otherwise persistent model indexes don't work.

We've written more complicated tables where the data is modified in threads in the background, and swapped out prior to updating the table. One of the areas in which one could have speed improvement, is to never order the data in your model, but rather use an ordered reference sequence that references the real (unordered) data. We have tables that have about a thousand rows and 50 columns that get updated once a second (with many views), and the processor our processor is sitting a about 20%, but the greatest speed improvement was the caching of the sizeHint.

Upvotes: 3

Related Questions