I have a qt-application with QListView
, a custom model and a class inherited from QStyledItemDelegate
to show custom items. Unfortunately it takes to long (5 seconds) when I add approximately 6000 items. Do you have a hint/solution for my problem?
Below you see my implementation:
The Model:
class AddressItemData : public QObject {
Q_OBJECT
public:
AddressItemData (QObject * parent = 0) : QObject(parent) {}
QString address;
QString name;
bool inserted;
};
class AddressModel : public QAbstractListModel
{
Q_OBJECT
public:
AddressModel (QObject *parent = 0);
int rowCount(const QModelIndex &parent = QModelIndex()) const {
return addressItems.count();
}
QVariant data(const QModelIndex &index, int role = Qt::DisplayRole) const {
if (!index.isValid())
return QVariant();
if (index.row() >= addressItems.size() || index.row() < 0)
return QVariant();
if (Qt::DisplayRole == role) {
return QVariant::fromValue<AddressItemData*>(addressItems.at(index.row()));
}
return QVariant();
}
void addAddressItem(AddressItemData* addressItem){
beginInsertRows(QModelIndex(), rowCount(), rowCount());
addressItems.append(addressItem);
endInsertRows();
}
void addAddressItems(QList<AddressItemData*> addressItems){
beginInsertRows(QModelIndex(), rowCount(), rowCount() + addressItems.size() - 1);
this->addressItems.append(addressItems);
endInsertRows();
}
void removeAddressItem(AddressItemData* addressItem);
void deleteAllAddressItems(void){
beginRemoveRows(QModelIndex(), rowCount(), rowCount());
for (int i = 0; i < addressItems.size(); ++i) {
delete addressItems.at(i);
}
addressItems.clear();
endRemoveRows();
}
private:
QList<AddressItemData*> addressItems;
};
For the model I created a custom add and delete method, which will be called from the delegate.
The ItemViewDelegate:
class AddressViewDelegate : public QStyledItemDelegate
{
Q_OBJECT
public:
AddressViewDelegate (QWidget *parent = 0) : QStyledItemDelegate(parent) {}
void paint(QPainter *painter, const QStyleOptionViewItem &option,
const QModelIndex &index) const {
if(!index.isValid())
return;
painter->save();
QStyleOptionViewItemV4 opt = option;
if (option.state & QStyle::State_Selected)
painter->fillRect(option.rect, option.palette.highlight());
QRect addressRect = opt.rect;
AddressItemData* d = index.data().value<AddressItemData*>();
painter->setPen(Qt::black);
painter->drawText(QRect(addressRect.left(), addressRect.top(), addressRect.width(), addressRect.height()/2),
opt.displayAlignment, d->address);
}
QSize sizeHint(const QStyleOptionViewItem &option,
const QModelIndex &index) const {
if(!index.isValid())
return QSize();
QSize result = QStyledItemDelegate::sizeHint(option, index);
result.setHeight(result.height()*2);
return result;
}
};
For test purposes, the application displays only the address. I want to show also the other information next to address in one line. Later I also want to add signal/slot-behavior for each row, but that's still a long way off.
The main:
AddressModel* model = new AddressModel;
AddressViewDelegate* viewDelegate = new AddressViewDelegate;
ui->listView->setItemDelegate(viewDelegate);
ui->listView->setModel(model);
ui->listView->setUniformItemSizes(true);
ui->listView->setLayoutMode(QListView::Batched);
QList<AddressItemData *> addressItems;
... for loop to add AddressItemData:
AddressItemData* data = new AddressItemData;
data->address = anotherTable.at(index);
addressItems.append(data);
// ...
model->addAddressItems(addressItems);
In the main
, I call addAddressItems
but also with the single-call-variant it is slow. I hope my code is clear enough and I can help others as well.
Do you have an idea, why the adding-procedure is so slow?