I customized my data model AnnotationListModel inherited from QStringListModel.
The purpose of AnnotationListModel class, is to add checkboxes for data items and achieve exclusion between data items.
Now, I create three QListView and AnnotationListModel objects in a QDialog. The data item in the model is added as a checkbox, and is exclusive.
I can check the checkbox in QListView, but the checked status can't display quickly.
How can I enable QListView to flush quickly?
class AnnotationListModel :public QStringListModel
{
Q_OBJECT
public:
AnnotationListModel(AnnotationType annType, const QStringList& stringList, QObject* parent = nullptr);
~AnnotationListModel() {};
protected:
Qt::ItemFlags flags(const QModelIndex& index) const override;
QVariant data(const QModelIndex& index, int role = Qt::DisplayRole) const override;
bool setData(const QModelIndex& index, const QVariant& value, int role = Qt::EditRole) override;
signals:
void sendAnnotation(const AnnotationType& annoType, const QString& annotation);
private:
AnnotationType m_annoType;
QStringList m_stringList;
QMap<QString, bool> m_stringList_map; //<annotationName,checked>
};
AnnotationListModel::AnnotationListModel(AnnotationType annType, const QStringList& stringList, QObject* parent)
:QStringListModel(parent), m_stringList(stringList), m_annoType(annType)
{
setStringList(m_stringList);
for (auto& value : m_stringList)
{
m_stringList_map[value] = false;
}
}
Qt::ItemFlags AnnotationListModel::flags(const QModelIndex& index) const
{
if (!index.isValid())
{
return Qt::ItemIsEnabled;
}
return Qt::ItemIsUserCheckable | QStringListModel::flags(index);
}
QVariant AnnotationListModel::data(const QModelIndex& index, int role) const
{
if (!index.isValid())
{
return QVariant();
}
if (role == Qt::CheckStateRole)
{
if (m_stringList_map[m_stringList.at(index.row())] == true)
{
return Qt::Checked;
}
else
{
return Qt::Unchecked;
}
}
else if (role == Qt::DisplayRole)
{
return m_stringList.at(index.row());
}
return QStringListModel::data(index, role);
}
bool AnnotationListModel::setData(const QModelIndex& index, const QVariant& value, int role)
{
if (!index.isValid())
{
return false;
}
if (role == Qt::CheckStateRole)
{
if (value == Qt::Checked)
{
for (int i{ 0 }; i < m_stringList.size(); ++i)
{
if (i != index.row())
{
m_stringList_map[m_stringList.at(i)] = false;
}
else
{
m_stringList_map[m_stringList.at(i)] = true;
sendAnnotation(m_annoType, m_stringList.at(i));
}
}
}
else if (value == Qt::Unchecked)
{
m_stringList_map[m_stringList.at(index.row())] = false;
}
}
return QStringListModel::setData(index, value, role);
}
Create three AnnotationListModel objects:
switch (itr_kind.key())
{
case AnnotationType::CounCode:
m_counCodeModel = new AnnotationListModel(AnnotationType::CounCode, l_annoStrList);
m_uiDialog->listView_country->setModel(m_counCodeModel);
connect(m_counCodeModel, &AnnotationListModel::sendAnnotation, this, &AnnotationDialog::sendAnnotation);
break;
case AnnotationType::DriSide:
m_driSideModel = new AnnotationListModel(AnnotationType::DriSide, l_annoStrList);
m_uiDialog->listView_driving->setModel(m_driSideModel);
connect(m_driSideModel, &AnnotationListModel::sendAnnotation, this, &AnnotationDialog::sendAnnotation);
break;
case AnnotationType::RoadType:
m_roadTypeModel = new AnnotationListModel(AnnotationType::RoadType, l_annoStrList);
m_uiDialog->listView_road->setModel(m_roadTypeModel);
connect(m_roadTypeModel, &AnnotationListModel::sendAnnotation, this, &AnnotationDialog::sendAnnotation);
}
The Dialog is opened through mainwindow.

IMO, you have made 4 mistakes but the important ones are the first 2:
QStringListModelin your case) is with a proxy model (a subclass ofQAbstractProxyModel). It works just as well but is easier to implement and way more flexible since it can be used with any model type.QMap<...>container for that.I believe this is where most of the computation time was being wasted in your code, especially when testing the dialog in debug mode (containers have many, many checks that are done only in debug, making them way slower to use than in release).
At least, it was right not to save the checked index as a
QModelIndex.dataChangedsignals from yoursetDatamethod.false/truefrom yoursetDatamethod. To be precise, a boolean is indeed returned but only byQStringListModel::setData(...), which is not what you want to do.The below
AnnotationProxyModelimplements exclusive checkboxes for any model you want to implement. It derivesQIdentityProxyModeland remember the checked index thanks to aQPersistentModelIndex(which unlikeQModelIndexis OK to save).I let you check if you really need to keep the
Q_OBJECTmacro and your signal(s) in the below definition and if yes, add them back yourself.Like any other proxy model, it is used by calling
setSourceModel(...)with yourQStringListModel, i.e. in that fashion: