Ho creato un modello derivato QAbstractListModel basato su un QHash sottostante. Poiché ho bisogno di utilizzare il modello in QML, non posso utilizzare la funzionalità di ordinamento che i widget e le viste di Qt hanno integrato.Ordinare un modello derivato QAbstractListModel in base al ruolo in QML ListView
Ho provato a utilizzare un QSortFilterProxyModel ma non sembra funzionare con il mio modello. Fare in modo che il modello funzioni correttamente in QML non è stato abbastanza noioso, e ora sono bloccato sull'ordinamento.
Qualsiasi suggerimento è gradito.
Qui è la fonte del modello:
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;
};
qui è "cercando" di risolverlo:
NewModel model;
QAbstractItemModel * pm = qobject_cast<QAbstractItemModel *>(&model);
QSortFilterProxyModel proxy;
proxy.setSourceModel(pm);
proxy.setSortRole(NewModel::WordRole);
proxy.setDynamicSortFilter(true);
Ahimè, il proxy funziona come un modello, ma non ordinare le voci .
'prepend()' viene utilizzato per popolare il modello quando non viene utilizzato, non ci sono problemi con l'utilizzo corretto. Ho bisogno di usare QHash per la ricerca, l'ho già fatto usando l'hash per lo storage e poi trasferendo i dati su un altro modello, ma sto cercando modi per riutilizzare i dati originali dall'hash. Il modello così com'è sembra funzionare bene, il mio problema riguarda solo l'ordinamento. – dtech
Prova ad eseguire ModelTest sopra al tuo codice, potresti essere piuttosto sorpreso. –
Viene utilizzato in un contesto strettamente specificato, il pensiero che sia perfetto come parte dell'intera API è molto lontano, mirano solo alla funzionalità di cui ho bisogno in particolare. Forse è per questo che non funziona con il proxy di ordinamento. Sarà più facile fare il mio wrapper proxy di ordinamento piuttosto che far funzionare il magazzino con il modello, mantenendo il contenitore sottostante ottimizzato per la ricerca più veloce, che è il requisito N1. – dtech