Sort QAbstractListModel derived model by role in QML ListView

I created a model based on QAbstractListModel based on a basic QHash. Since I need to use the model in QML, I cannot use the sort function. In QT, widgets and views are integrated.

I tried using QSortFilterProxyModel, but it does not work with my model. Getting the model to work properly in QML was not tedious enough, and now I'm fixated on sorting.

Any suggestions are welcome.

Here is the source of the model:

typedef QHash<QString, uint> Data; class NewModel : public QAbstractListModel { Q_OBJECT Q_PROPERTY(int count READ count NOTIFY countChanged) public: NewModel(QObject * parent = 0) : QAbstractListModel(parent) {} enum Roles {WordRole = Qt::UserRole, CountRole}; QHash<int, QByteArray> roleNames() const { QHash<int, QByteArray> roles; roles[WordRole] = "word"; roles[CountRole] = "count"; return roles; } QVariant data(const QModelIndex &index, int role = Qt::DisplayRole) const { if (index.row() < 0 || index.row() >= m_data.size()) return QVariant(); Data::const_iterator iter = m_data.constBegin() + index.row(); switch (role) { case WordRole: return iter.key(); case CountRole: return iter.value(); } return QVariant(); } int rowCount(const QModelIndex &parent) const { Q_UNUSED(parent) return m_data.size(); } int count() const { return m_data.size(); } public slots: void append(const QString &word) { bool alreadyThere = m_data.contains(word); if (alreadyThere) m_data[word]++; else m_data.insert(word, 1); Data::const_iterator iter = m_data.find(word); uint position = delta(iter); if (alreadyThere) { QModelIndex index = createIndex(position, 0); emit dataChanged(index, index); } else { beginInsertRows(QModelIndex(), position, position); endInsertRows(); emit countChanged(); } } void prepend(const QString &word) { if (m_data.contains(word)) m_data[word]++; else m_data.insert(word, 1); } signals: void countChanged(); private: uint delta(Data::const_iterator i) { uint d = 0; while (i != m_data.constBegin()) { ++d; --i; } return d; } Data m_data; }; 

Here is the "trying" to sort it:

 NewModel model; QAbstractItemModel * pm = qobject_cast<QAbstractItemModel *>(&model); QSortFilterProxyModel proxy; proxy.setSourceModel(pm); proxy.setSortRole(NewModel::WordRole); proxy.setDynamicSortFilter(true); 

Alas, the proxy works as a model, but does not sort the entries.

+6
source share
3 answers

If you enable QSortFilterProxyModel :: setDynamicSortFilter (true), you need to call the QSortFilterProxyModel :: sort (...) function once so that the proxy knows which way to sort.

At the same time, whenever the model is updated, the proxy will sort everything again automatically.

 proxy.setDynamicSortFilter(true); proxy.sort(0); 
+6
source

First of all, there is no need for qobject_cast<QAbstractItemModel *> downcasting - NewModel is a derived class of QAbstractItemModel , and the principle of polymorphism says that you can use the subclass wherever the parent class is applicable.

Secondly, your prepend method does not use beginInsertRows and endInsertRows . This is a violation of the MVC API. You will get data corruption in connected views and proxy models if you use it this way.

Thirdly, you did not mention whether you really use your proxy model as a model for the connected view :).

Finally, you use QHash as a backup storage for your data using QHash::iterator to insert. This is a promising solution, but one that simply cannot work - inserting or deleting can cause the hash table to grow / contract, which means changing all the data that you publish using your index indexes. It just won't work. Do not use QHash if you need a stable order. The complexity O(n) your delta method should be interpreted as a warning; this is the wrong approach.

+1
source

Take a look at https://github.com/oKcerG/SortFilterProxyModel . This project provides QSortFilterProxyModel functionality for QML. I used it in different projects and it worked. However, if you want to implement your own solution, this is something to get your ideas.

0
source

Source: https://habr.com/ru/post/943644/


All Articles