c++ - 如何为 QML 创建通用 ListModel

标签 c++ qt templates qml

我的应用程序由许多列表组成,我通过使用 QAbstractListModel 派生模型类在 QML-ListViews 中显示这些列表。它总是相同的,只是 Item-Type 有所不同。这就是为什么我想知道如何为这种方法构建类模板。

最佳答案

我发现,不可能在类模板中使用 Q_OBJECT-Macro。这就是为什么我的 GenericListModel 由两部分组成。

<强>1。通用列表模型数据

第一部分是模型本身,它派生自 QAbstractListModel 并实现基本函数 data()、rowCount() 和 roleNames()。

<强>2。通用列表模型

第二部分是类模板,用作包装器以提供类似于 QListView 的功能。

如果您有任何建议或问题,请告诉我。改进这个解决方案真是太好了。

我在这里上传了完整的源代码: https://github.com/sebabebibobu/QGenericListModel/

<强>1。通用列表模型数据

QVariant GenericListModelData::data(const QModelIndex &index, int role) const
{
    QObject *item = m_itemList.at(index.row());
    return item->property(item->metaObject()->property(role).name());
}

/*
 * Returns the number of items attached to the list.
 */
int GenericListModelData::rowCount(const QModelIndex &parent) const
{
    Q_UNUSED(parent)
    return m_itemList.size();
}

/*
 * Generates a hash out of QMetaObject property-index and property-name.
 */
QHash<int, QByteArray> GenericListModelData::roleNames() const
{
    QHash<int, QByteArray> roles;

    if (!m_itemList.isEmpty()) {
        for(int i = 0; i < m_itemList.at(0)->metaObject()->propertyCount(); i++) {
            roles[i] = m_itemList.at(0)->metaObject()->property(i).name();
        }
    }

    return roles;
}

/*
 * Append Item to List.
 */
void GenericListModelData::appendItem(QObject *item)
{
    /* map the notify()-signal-index with the property-index when the first item get's inserted */
    if (m_itemList.isEmpty()) {
        for(int i = 0; i < item->metaObject()->propertyCount(); i++) {
            m_propertySignalIndexHash.insert(item->metaObject()->property(i).notifySignalIndex(), i);
        }
    }

    /* connect each notify()-signals to the onDataChanged()-slot which call's the dataChanged()-signal */
    for(int i = 0; i < item->metaObject()->propertyCount(); i++) {
        connect(item, "2" + item->metaObject()->property(i).notifySignal().methodSignature(), this, SLOT(onDataChanged()));
    }

    /* finally append the item the list */
    beginInsertRows(QModelIndex(), rowCount(), rowCount());
    m_itemList.append(item);
    endInsertRows();
}

/*
 * Helper-Slot that emit's the dataChanged()-signal of QAbstractListModel.
 */
void GenericListModelData::onDataChanged()
{
    QModelIndex index = createIndex(m_itemList.indexOf(sender()),0);

    QVector<int> roles;
    roles.append(m_propertySignalIndexHash.value(senderSignalIndex()));
    emit dataChanged(index, index, roles);
}

<强>2。通用列表模型

template <typename T>
class GenericListModel : public GenericListModelData
{
public:
    explicit GenericListModel(QObject *parent) : GenericListModelData(parent) {

    }

    void append(T *item) {
        appendItem(item);
    }

    T *at(int i) {
        return qobject_cast<T *>(m_itemList.at(i));
    }
};

更新2016年5月1日

GrecKo 在评论中发帖说,像我这样的项目已经存在。这就是为什么我也决定在这里分享这个项目的链接:

http://gitlab.unique-conception.org/qt-qml-tricks/qt-qml-models

关于c++ - 如何为 QML 创建通用 ListModel,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/36948212/

相关文章:

c++ - tcp 套接字,无法绑定(bind)到端口 - 正在使用

c++ - 是否有接受 unicode 的 C/C++ system() 函数?

python - TortoiseHG 图标丢失(Ubuntu Linux 16)

c++ - GCC 向依赖默认构造函数的模板化类中的静态数据成员给出 "undefined reference"错误

templates - KnockoutJS - 嵌套模板中的可观察对象

c++ - 从 boost::regex 获取子表达式(匹配前)

c++ - 快速将双指针数组转换为单指针,可能可以是连续的

c++ - 水平线的类型是什么?

qt - 当对象在外部发生变化时更新 QListView

c++ - 使用依赖于类型的模板名称的声明