2013-04-25 11 views
6

QAbstractListModelから派生したモデルを基礎QHashに基づいて作成しました。 QMLでモデルを使用する必要があるため、ソート機能Qtウィジェットとビューを統合することはできません。QAbstractListModelから派生したモデルをQMLのロールでソートSort List

私はQSortFilterProxyModelを使用しようとしましたが、私のモデルでは動作しません。モデルをQMLで正常に動作させるのは面倒ではなかったので、今はソートに取り組んでいます。

ご迷惑をおかけして申し訳ございません。ここで

は、モデルの源である:ここで

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; 
}; 

はそれをソートする「しよう」です:

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

ああ、プロキシがモデルとして動作しますが、それはエントリをソートしません。 。すべての

答えて

1

まず、qobject_cast<QAbstractItemModel *>ダウンキャストのための必要はありません - NewModelQAbstractItemModelの派生クラスであり、多型の原理は、親クラスが適用される場所がどこでもサブクラスを使用することができると述べています。

第2に、prependメソッドはbeginInsertRowsendInsertRowsを使用しません。これはMVC APIの違反です。このように使用すると、接続ビューとプロキシモデルでデータが破損することになります。

第3に、実際にプロキシモデルを添付ビューのモデルとして使用しているかどうかについては言及していません。

最後に、QHashをデータのバッキングストアとして使用しています(挿入の場合はQHash::iterator)。それは面白い解決策ですが、ちょうどうまくいかないものがあります。挿入または削除すると、ハッシュテーブルが拡大/縮小する可能性があります。これは、モデルインデックスを使用して公開するすべてのデータを変更することを意味します。これはうまくいかないでしょう。安定した注文が必要な場合はQHashを使用しないでください。あなたのdeltaメソッドの複雑さは警告として解釈する必要があります。これは間違ったアプローチです。

+0

'prepend()'は、モデルを使用しないときにモデルを生成するために使用されますが、それを賢明に使用することに問題はありません。私は検索のためにQHashを使う必要があります。私はすでにストレージのハッシュを使ってデータを別のモデルに転送していますが、元のデータをハッシュから再利用する方法を探しています。モデルは正常に動作するように見えますが、私の問題はソートだけです。 – dtech

+1

コードの上でModelTestを実行しようとすると、驚くかもしれません。 –

+0

これは厳密に指定されたコンテキストで使用され、API全体の一部として完璧であるという考えははるかに排除されており、特に必要な機能のみを目的としています。たぶん、ソートプロキシではうまくいかないのかもしれません。 N1の要件である最速のルックアップのために最適化された基底のコンテナを維持しながら、在庫をモデルで処理するよりも、独自のソートプロキシラッパーを行う方が簡単です。 – dtech

6

QSortFilterProxyModel :: setDynamicSortFilter(true)を有効にする場合は、QSortFilterProxyModel :: sort(...)関数を1回呼び出して、プロキシにどのようにソートするかを知らせる必要があります。

これで、モデルが更新されるたびにプロキシは自動的にすべてを並べ替えます。

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

これは、ありがとう! – Sharm

関連する問題