I use Qt Model view with QSortFilterProxyModel
QListView with checkbox and name ,only one column
QStandardItemModel setData ,100w row
use QSortFilterProxyModel function setFilterFixedString
and add a function changed all row checkbox checked
like this in my class Inheritance QStandardItemModel
void toggleAllItemsInModel(QStandardItemModel* model, bool checked)
{
for (int i = 0; i < model->rowCount(); ++i) {
QStandardItem* item = model->item(i);
if (item && item->isCheckable()) {
item->setCheckState(checked ? Qt::Checked : Qt::Unchecked);
}
}
my question is this function toggleAllItemsInModel only use 0.1s ,but setFilterFixedString use more than 12s,why this function is so slow and i think Qt model view has been optimized view show, i need optimize,please give some advice.
i use modelItem userole + 1 save hidden mark ,and add function filterAccptsRow,but alse use 12s, set DynamicSortFilter(false), and setFilterRole(Qt::DisplayRole),but no use.
a better function is not use QSortFilterProxyModel and realizing in QStandardItemModel?
this is test code like my code. Only two function selectAll and filterString. use Qt5.15,CentOS Linux 7,release version test
#include <QApplication>
#include <QWidget>
#include <QVBoxLayout>
#include <QListView>
#include <QStandardItemModel>
#include <QSortFilterProxyModel>
#include <QLineEdit>
#include <QPushButton>
#include <QCheckBox>
class CheckableStandardItemModel : public QStandardItemModel {
Q_OBJECT
public:
CheckableStandardItemModel(QObject *parent = nullptr) : QStandardItemModel(parent) {
setColumnCount(1);
}
// select all checkbox
void selectAll(bool select) {
beginResetModel();
for (int row = 0; row < rowCount(); ++row) {
QStandardItem *item = item(row, 0);
if (item) {
item->setCheckState(select ? Qt::Checked : Qt::Unchecked);
}
}
endResetModel();
}
};
class TestWindow : public QWidget {
Q_OBJECT
public:
TestWindow(QWidget *parent = nullptr) : QWidget(parent) {
setupUi();
setupModel();
setupProxyModel();
connectSignals();
}
private:
QListView *listView;
CheckableStandardItemModel *model;
QSortFilterProxyModel *proxyModel;
QLineEdit *filterLineEdit;
QPushButton *filterButton;
QCheckBox *selectAllCheckbox;
void setupUi() {
QVBoxLayout *layout = new QVBoxLayout(this);
listView = new QListView(this);
filterLineEdit = new QLineEdit(this);
filterButton = new QPushButton("Filter", this);
selectAllCheckbox = new QCheckBox("Select All", this);
layout->addWidget(listView);
layout->addWidget(filterLineEdit);
layout->addWidget(filterButton);
layout->addWidget(selectAllCheckbox);
}
void setupModel() {
model = new CheckableStandardItemModel(this);
model->setHorizontalHeaderLabels(QStringList("Name"));
for(int i = 0; i < 1000000; ++i) {
QStandardItem *item = new QStandardItem(QString("Item%1").arg(i));
item->setCheckable(true);
model->appendRow(item);
}
}
void setupProxyModel() {
proxyModel = new QSortFilterProxyModel(this);
proxyModel->setSourceModel(model);
proxyModel->setFilterCaseSensitivity(Qt::CaseInsensitive);
listView->setModel(proxyModel);
}
void connectSignals() {
connect(filterLineEdit, &QLineEdit::textChanged, this, [this](const QString& text) {
//test time here
proxyModel->setFilterFixedString(text);
});
connect(selectAllCheckbox, &QCheckBox::stateChanged, this, [this](int state) {
//test time here
model->selectAll(state == Qt::Checked);
listView->viewport()->update();
});
}
};
int main(int argc, char *argv[]) {
QApplication app(argc, argv);
TestWindow window;
window.show();
return app.exec();
}
beginResetModel()
andendResetModel()
are to be used when the model is actually reset or as an alternative todataChanged()
: since you're using QStandardItemModel, that makes it completely useless, since it will emitdataChanged
anyway when doingsetCheckState()
, unless you block its signals. It should also be unnecessary to update the viewport (if things are done appropriately).