PDA

View Full Version : QTableView performance



hml
15th March 2010, 19:28
Hello,

I have this abstract table model


class log_q_item_model : public QAbstractTableModel {
Q_OBJECT
public:
log_q_item_model(const log_ptr& log) /// log_ptr is boost:;shared_ptr< std::vector< std::pair<date, double> > >
: log_(log)
{}

int rowCount(const QModelIndex&) const
{
return log_->size();
}
int columnCount(const QModelIndex&) const
{
return 2;
}
QVariant data(const QModelIndex& index, int role) const
{
if (index.isValid() && index.row()>=0 && static_cast<size_t>(index.row())<log_->size() && role==Qt::DisplayRole) {
const logentry_t& e = (*log_)[index.row()];

return (index.column()==0)?
QString(boost::gregorian::to_simple_string(e.first ).c_str()):
QString::number(e.second,'f',2);
}

return QVariant();
}

QVariant headerData(int section, Qt::Orientation orientation, int role) const
{
if (role != Qt::DisplayRole)
return QVariant();

if (orientation == Qt::Horizontal) {
switch (section) {
case 0:
return tr("Date");

case 1:
return tr("Logname");

default:
return QVariant();
}
}

return QVariant();
}
private:
const log_ptr log_;
};


that use with a QTableView to display about 10 000 entries.

It is a bit slow to display? I know because I filled up the log vector before without displaying it and the GUI was faster.
I would appreciate any hints as to where to optimize this class?

Regards,

prof.ebral
15th March 2010, 19:37
Could you thread it in blocks of 1,000? Or thread the load time so that the table fills as new entries pass the thread .. kinda like when you load a new large music library.

I have not used a Table in Qt yet.

wysota
15th March 2010, 22:10
I know because I filled up the log vector before without displaying it and the GUI was faster.
What do you mean by "before" and "faster"? What was faster than what?

hml
16th March 2010, 16:37
Initially, after calculating the log vector, I plotted its elements on a 2D plot with qwtplot library.
That was fast.
I then added the QTableView and display it in a grid layout alongside the plot.
Now the window takes much longer to show (3seconds)

The vector is calculated once and the only difference with before is the addition of the QTableView.
I deduce that my AbstractTableModel must be wrongly implemented,

rds,

wysota
16th March 2010, 16:44
How do you add elements to the table? Can we see the code?

hml
16th March 2010, 16:58
I don't understand.
I only create a new instance of


class log_q_table_view : public QTableView {
public:
log_q_table_view(const log_ptr& log, QWidget* parent =0)
{
setEditTriggers(QAbstractItemView::NoEditTriggers) ;
setModel(new log_q_item_model(log));
verticalHeader()->setResizeMode(QHeaderView::ResizeToContents);
horizontalHeader()->setResizeMode(QHeaderView::ResizeToContents);
}
};


In the GUI, I create a new instance of log_q_table_view, and then add it to the grid layout for display.

The vector pointed to by the log shared pointer has existed for a long time at that stage,

Was this what you meant?

Thank you!

wysota
16th March 2010, 17:06
Bah... sorry, I meant to ask how do you add elements to the table model. Sorry for not being clear. I see you are passing a copy of the data to the table. This is completely unnecessary (http://blog.wysota.eu.org/index.php/2007/12/17/itemviews-data-redundancy/) but I don't think this will slow down your app so much. I'd say the problem is caused by the calculations you are doing in data(). It would be wise to get rid of them and then run your application under a profiler to find the bottle neck - right now we're just shooting blind.

hml
16th March 2010, 17:14
all right i will profile the GUI.
There are over 10000 entries. so data() would be called at least that many times.

In data(), I have to check that the QModelIndex is valid and that the row is valid and that the role is DisplayRole, don't I?



I see you are passing a copy of the data to the table. This is completely unnecessary


I am copying a log_ptr. But that is just a boost::shared_ptr and does not involve deep copying of the whole vector, it's just a pointer.
And the model just interprets my internal data structure to return QVariants, I follow what you say in the blog I think,

thanks,