2012-01-17 5 views
4

私のアプリケーションは、 QAbstractListModelオブジェクトを継承する型のオブジェクトをいくつか格納しています。QAbstractListModelとQListアダプタ

一般的なアドオンをモデルに簡単な std::vector<T>またはQList<T>を包むとき、これは、重複コードのかなり多くを生成し、 を削除し、複数選択機能。

は道QAbstractListModelが使用されることになっているか(少なくともQtのの一部である コンテナ用)重複コードを削除することができ、いくつかのアダプタクラスが されていること?ですか

例:モデルにvector<ObjectA>vector<ObjectB>をラップしたいと思います。 insertRowsdeleteRowscolumnCountなどのコードは常に同じになります。私はこれを(tupledataで動作する小さなメタプログラミングで)統合したいと考えています。

+0

あなたは 'QAbstractListModel'または' QAbstractItemModel'を意味しましたか? – Karlson

+0

@ Karlson確かに、ModelViewフレームワークの類似の名前の多数が混乱しました。私はフレームワークのメインタグのようにタグ 'abstractitemmodel'タグを残します。 – pmr

+0

がそれを手に入れました。私の答えは以下の通りです。 – Karlson

答えて

6

QtのC++(SIGNALS、SLOTSなど)への拡張がテンプレートでうまく動作しないため、これを2つの別々のクラスで行う必要があります。これの根拠と回避策は次の場所にあります。http://doc.qt.digia.com/qq/qq15-academic.html

解決策の概要を示します。 (これは、我々は我々のアプリケーションで使用しているコードに基づいており、それが正常に動作しています。)

Qtのものテンプレートのものを行い

class FooListModelQt : public QAbstractTableModel { 
    Q_OBJECT 

public: 
    // Non-template methods, signals, slots, etc. can be used here. For example... 
    QSet<int> SelectedRows() const; 
    // ... etc. ... 

signals: 
    void SelectionChanged(); 
    // ... etc. ... 

protected: 
    explicit FooListModelQt(QObject *parent = NULL); 
    virtual ~FooListModelQt() = 0; 
    // ... etc. ... 

}; 

2.抽象クラスを行います1.要約リストクラス

template <typename T> 
class FooListModel : public FooListModelQt { 
public: 
    const T* at(int index) const { return items_.at(index); } 
    int count() const { return items_.count(); } 
    void Append(T *item); 
    // ... etc. ... 

protected: 
    explicit FooListModel(QObject *parent = NULL); 
    virtual ~FooListModel(); 

private: 
    QList<T*> items_; 
}; 

3.実際のリストクラス

class BarListModel : public FooListModel<Bar> { 
    Q_OBJECT 

public: 
    explicit BarListModel(QObject *parent = NULL); 
    int columnCount(const QModelIndex &parent) const; 
    QVariant data(const QModelIndex &index, int role) const; 
    // ... etc. ... 
}; 
+0

それで 'Q_OBJECT'マクロをスキップすると、' moc'は常にクラスを無視してテンプレートビジネスについて教えてくれますか? (OT、この記事はちょっとした謝辞を書いたものであり、コア言語の機能を取り除く理由はありません。特に、制約を課していない信号やスロットの実装に直面しています)。 – pmr

+0

それは私の前提です。 Q_OBJECT(シグナル、スロット、翻訳など)が必要なものを使用していない場合は、OKにしてください。 –

+0

私はちょうどそれを数時間失ってしまったので、最終的なモデルオブジェクトをQML/Declarative GUIに公開しようとしているので、特定のモデルの正確なクラスにQ_OBJECTが付いていることを確認してください。それ自体はそれでマークされなければなりません、それはベースから「継承」されません。 Daveの例のBarListModelを参照してください。 Q_OBJECTが繰り返されています。また、qmlRegisterTypeも必要です。つまり、最終クラスはテンプレートではなく、BarListModelのようなプレーンなクラスでなければなりません。 – quetzalcoatl

1

通常、QAbstractItemModelから継承する独自のモデルを実装し、data()などのプレゼンテーション関数の独自の実装を提供して、モデルに与えたデータ格納コンテナを処理します。

あなたはQList<T>std::vector<T>を使用するためのコードの重複を持っている場合、私はどちらか実行して、他の1つに変換することをお勧め:

QList<T> list = QList::fromVector(QVector::fromStdVector(vector)); 

または他の方法。

std::vector<T> vector = qlist.toVector().toStdVector(); 

私は後者を行いますが、どちらかを選択できます。

パス1:次のように

objectAobjectBを実装します。あなたが取ることができるアクションの2つのパスですが、あなたの追加のコメントに基づいて

class objectA : baseObject 

class objectB : baseObject 

ここで、baseObjectは:

struct baseObject 
{ 
    virtual std::string toString() = 0; 
}; 

おそらく文字列に変換する方が簡単でしょう。

パス2は、基本的にデータストレージコンテナとしてstd::vector<boost::any>()を使用してモデル内に含まれます。この方法で、QAbstractListModelのサブクラス化する単一のモデルを実装できます。

data()ビューの要素に表示される関数はQVariantを返す必要があり、限られているため、データ格納コンテナを使用してデータの表示を制限することができます。あなたがそれを作ることができるところで。

+0

重要な点は、ボイラープレートを実装する基本クラスがテンプレートでなければならないということです。私は自分の問題をよりよく反映するために少し質問を洗練した。 – pmr

関連する問題