2012-01-17 35 views
4

我的應用程序存儲一些從 QAbstractListModel對象繼承的類型的對象。QAbstractListModel和QList適配器

這種包裝簡單 std::vector<T>QList<T>到模型與一般加時, 刪除和多選功能,產生了相當多的重複的代碼。

是這樣的方式QAbstractListModel應該被使用或者是有一些 適配器類,可以消除重複的代碼(至少對於 容器是Qt的一部分)?

例如:我想將vector<ObjectA>vector<ObjectB>換成模型。代碼insertRowsdeleteRows,columnCount等總是會是相同的,我想鞏固(與一個小的元編程,甚至可以與tupledata工作)。

+0

你的意思是'QAbstractListModel'還是'QAbstractItemModel'? – Karlson 2012-01-17 14:37:54

+0

@Karlson事實上,ModelView框架中的衆多相似名稱讓我感到困惑。我將離開標籤'abstractitemmodel'標籤,因爲它似乎是框架的主要標籤。 – pmr 2012-01-17 14:42:16

+0

明白了。我的答案在下面。 – Karlson 2012-01-17 14:47:29

回答

6

你必須在兩個獨立的類中這樣做,因爲Qt對C++的擴展(SIGNALS,SLOTS等)不能很好地與模板配合使用。理由和解決方法可以在這裏找到:http://doc.qt.digia.com/qq/qq15-academic.html

下面是一個解決方案的大綱。 (這是基於代碼我們使用我們的應用程序和工作正常。)

1.摘要列表的類,它的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.抽象類,做模板的東西

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

(三)實際列表類

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 2012-01-17 16:22:19

+0

這是我的假設,是的。如果你沒有使用任何需要Q_OBJECT(信號,插槽,翻譯等)的東西,那麼你應該沒問題。 – 2012-01-17 16:35:30

+0

我剛剛失去了幾個小時,所以建議的意思:它將把最終模型對象展示給QML /聲明性GUI,確保具體模型的確切類用Q_OBJECT標記。它本身必須用它來標記,它不是從基地「繼承」的。請參閱Dave示例中的BarListModel?有Q_OBJECT重複。另外,qmlRegisterType也是需要的。這意味着您的最終類不能是模板,它必須是普通類,如BarListModel。 – quetzalcoatl 2012-09-21 23:36:13

1

通常我會直接實現自己的模型,從QAbstractItemModel繼承,並提供我自己的演示函數的實現,如data()來處理我給模型的數據存儲容器。

如果你有使用QList<T>std::vector<T>那麼我會建議做任何一個轉換到另一個代碼重複:

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

或其他方式。

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

我會做後者,但你可以選擇。

根據您的補充意見有動作的2路可以走:

路徑1:

實施objectAobjectB如下:

class objectA : baseObject 

class objectB : baseObject 

其中baseObject是:

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

可能更容易轉換爲字符串,然後是其他任何東西。

Path 2基本上涉及使用std::vector<boost::any>()作爲數據存儲容器的模型,這種方式可以實現單個模型子類QAbstractListModel

你必須考慮的事情,如果你的數據存儲容器,你可能會共同的數據表示,你是有限的,你可以做,因爲data()函數,將使您的觀點元素必須返回QVariant,它是有限的你可以從中構建它。

+0

關鍵是實現鍋爐板的基類必須是模板。爲了更好地反映我的問題,我稍微磨光了一下我的問題。 – pmr 2012-01-17 15:22:01