QT6 源(124)QModelRoleData 与 QModelRoleDataSpan :模型视图架构里的模型里的项 item 里可以存储多个角色的数据。以及角色数据数组,及其源码。

(1)给出本 QModelRoleData 类的源码

/*
The QModelRoleData class holds a role and the data associated to that role.

QModelRoleData对象存储一个项目角色的任意整数),以及与该角色关联的数据。
(这是来自Qt::ltemDataRole枚举的值,或者是一个自定义角色.
QModelRoleData objects store an item role
(which is a value from the Qt::ItemDataRole enumeration,
or an arbitrary integer for a custom role)
as well as the data associated with that role.

QModelRoleData 对象通常由视图或代理创建,并设置他们要为其获取数据的角色。
然后将该对象传递给模型(参见QAbstractltemModel::multiData()).
这些模型填充与存储的角色相对应的数据。最后,视图可视化从模型中检索到的数据。
A QModelRoleData object is typically created by views or delegates,
setting which role they want to fetch the data for.
The object is then passed to models (see QAbstractItemModel::multiData()),
which populate the data corresponding to the role stored.
Finally, the view visualizes the data retrieved from the model.

*/

class QModelRoleData
{
    int       m_role;
    QVariant  m_data;

public:
    //Constructs a QModelRoleData object for the given role.
    explicit QModelRoleData(int role) noexcept : m_role(role) {} //有参构造函数
    
    //Returns the role held by this object.
    constexpr       int        role() const noexcept { return m_role; }
    constexpr       QVariant & data()       noexcept { return m_data; }
    //Returns the data held by this object as a modifiable reference.
    constexpr const QVariant & data() const noexcept { return m_data; }
    //Returns the data held by this object.
    
    template <typename T>
    constexpr
    void setData(T && value)
        noexcept(noexcept(m_data.setValue(std::forward<T>(value))))
    { m_data.setValue(std::forward<T>(value)); }
    //Sets the data held by this object to value.
    //value must be of a datatype which can be stored in a QVariant.
    
    //Clears the data held by this object.
    //Note that the role is unchanged; only the data is cleared.
    void clearData() noexcept { m_data.clear(); }
}; //完结 class QModelRoleData
Q_DECLARE_TYPEINFO(QModelRoleData, Q_RELOCATABLE_TYPE); //本类型的存储特征:可重定位。

(2)给出 QModelRoleDataSpan 的源码

/*
The QModelRoleDataSpan class provides a span over QModelRoleData objects.

QModelRoleDataSpan 是对数组中 QModelRoleData 对象的抽象。
A QModelRoleDataSpan is used as an abstraction over an array of QModelRoleData objects.

Like a view, QModelRoleDataSpan provides a small object (pointer and size) that
    can be passed to functions that need to examine the contents of the array.
A QModelRoleDataSpan can be constructed from any array-like sequence (plain arrays,
    QVector, std::vector, QVarLengthArray, and so on).
Moreover, it does not own the sequence, which must therefore be kept alive longer than
    any QModelRoleDataSpan objects referencing it.
就像视图一样,QModelRoleDataSpan提供一个小对象(指针和大小),可以传递给需要检查数组内容的函数。
QModelRoleDataSpan 可以从任何类似数组的序列构建(如普通数组、QVector、std:vector、QVarLengthArray.
等此外,它不拥有该序列,因此必须确保该序列的生命周期长于任何引用它的QModelRoleDataSpan对象。

与视图不同,QModelRoleDataSpan 是一个跨度,因此允许对底层元素进行修改。
Unlike a view, QModelRoleDataSpan is a span,
    so it allows for modifications to the underlying elements.

QModelRoleDataSpan的主要用途是使模型能够在一次调用中返回对应不同角色的数据。
QModelRoleDataSpan's main use case is making it possible for a model to return the
    data corresponding to different roles in one call.

为了从模型中提取一个元素,视图(通过其委托)通常会根据需要多次调用`data()方法,以获取同一索引处的多个角色!
In order to draw one element from a model,
a view (through its delegates) will generally request multiple roles for the
    same index by calling data() as many times as needed:

     QVariant text = model->data(index, Qt::DisplayRole);
     QVariant decoration = model->data(index, Qt::DecorationRole);
     QVariant checkState = model->data(index, Qt::CheckStateRole);
     // etc.

QModelRoleDataSpan允许视图使用一个函数调用请求相同的数据。
实现这一点的方法是,让视图准备一个合适的 QModelRoleData 对象数组,每个对象都初始化为应被获取的角色。
然后将该数组封装在 QModelRoleDataSpan 对象中,接着传递给模型的multiData()函数。
QModelRoleDataSpan allows a view to request the same data using just one function call.
This is achieved by having the view prepare a suitable array of QModelRoleData objects,
each initialized with the role that should be fetched.
The array is then wrapped in a QModelRoleDataSpan object,
which is then passed to a model's multiData() function.
使用 QModelRoleDataSpan 的举例如下:

     std::array<QModelRoleData, 3> roleData = { {
         QModelRoleData(Qt::DisplayRole   ),
         QModelRoleData(Qt::DecorationRole),
         QModelRoleData(Qt::CheckStateRole)
     } };

     // Usually, this is not necessary: A QModelRoleDataSpan
     // will be built automatically for you when passing an array-like
     // container to multiData().
     QModelRoleDataSpan span(roleData);

     model->multiData(index, span);

     // Use roleData[0].data(), roleData[1].data(), etc.

建议将 QModelRoleData 对象的数组(可能还包括相应的跨度)存储起来,并在后续对模型的调用中重复使用。
这样可减少与创建和返回 QVariant 对象相关的内存分配。
Views are encouraged to store the array of QModelRoleData objects
(and, possibly, the corresponding span) and re-use it in subsequent calls to the model.
This allows to reduce the memory allocations related with creating and
    returning QVariant objects.

最后,给定一个QModelRoleDataSpan对象,模型的职责是填充与span中每个角色对应的数据。
具体如何实现取决于具体的模型类。
以下是一个可能的实现概述,它遍历整个span,并对每个元素调用setData()函数:
Finally, given a QModelRoleDataSpan object,
the model's responsibility is to fill in the data corresponding to each role in the span.
How this is done depends on the concrete model class.
Here's a sketch of a possible implementation that iterates over the span and
    uses setData() on each element:

    void MyModel::multiData(const QModelIndex & index,
                            QModelRoleDataSpan roleDataSpan) const
    {
        for (QModelRoleData & roleData : roleDataSpan)
        {
            int role = roleData.role();

            // ... obtain the data for index and role ...

            roleData.setData(result);
        }
    }


*/

class QModelRoleDataSpan //看着好像是在堆区存储了 len 个 QModelRoleData 类型的数据
{                        //看着是封装于构成了 m_modelRoleData 数组。
    QModelRoleData * m_modelRoleData = nullptr;
    qsizetype        m_len           = 0;

    template <typename T>
    using if_compatible_container = std::enable_if_t<
        QtPrivate::IsContainerCompatibleWithModelRoleDataSpan<T>::value, bool>;

public:
    //Constructs an empty QModelRoleDataSpan.
    //Its data() will be set to nullptr, and its length to zero.
    constexpr QModelRoleDataSpan() noexcept {} //无参构造函数

    //Constructs an QModelRoleDataSpan spanning over modelRoleData,
    //  seen as a 1-element array.
    constexpr QModelRoleDataSpan(QModelRoleData & modelRoleData) noexcept //有参构造函数
        : m_modelRoleData(&modelRoleData),  m_len(1)   {}

    //Constructs an QModelRoleDataSpan spanning over the array,
    //  beginning at modelRoleData and with length len.
    //Note: The array must be kept alive as long as this object has not been destructed.
    constexpr QModelRoleDataSpan(QModelRoleData * modelRoleData, qsizetype len)
        : m_modelRoleData(modelRoleData),   m_len(len) {}                 //有参构造函数

    template <typename Container, if_compatible_container<Container> = true>//有参构造函数
    constexpr QModelRoleDataSpan(Container & c)
        noexcept(noexcept(std::data(c)) && noexcept(std::size(c)))
        : m_modelRoleData(std::data(c)),    m_len(qsizetype(std::size(c))) {}

    //Returns the length of the span represented by this object.
    constexpr qsizetype size  () const noexcept { return m_len; }
    constexpr qsizetype length() const noexcept { return m_len; }

    //Returns a pointer to the beginning of the span represented by this object.
    constexpr QModelRoleData * data () const noexcept { return m_modelRoleData; }
    constexpr QModelRoleData * begin() const noexcept { return m_modelRoleData; }

    constexpr QModelRoleData * end  () const noexcept { return m_modelRoleData + m_len; }
    //Returns a pointer to the imaginary element one past the
    //      end of the span represented by this object.
    //指向 QModelRoleData 数组里的最后一个元素的后面的虚拟元素的地址。

    constexpr QModelRoleData & operator[](qsizetype index) const
    { return m_modelRoleData[index]; }

    //返回 QModelRoleData 数组里第一个对应形参角色的数据
    constexpr QVariant * dataForRole(int role) const
    {
                auto  result = begin();
        const   auto  e      = end  ();

        for (; result != e; ++result)
            if (result->role() == role)   break;


        return Q_ASSERT(result != end()), &result->data();
    }
    //Returns the data associated with the
    //  first QModelRoleData in the span that has its role equal to role.
    //If such a QModelRoleData object does not exist, the behavior is undefined.
    //Note: Avoid calling this function from the model's side,
    //as a model cannot possibly know in advance which roles are in a
    //  given QModelRoleDataSpan.
    //This function is instead suitable for views and delegates,
    //  which have control over the roles in the span.

}; //完结 class QModelRoleDataSpan
Q_DECLARE_TYPEINFO(QModelRoleDataSpan, Q_RELOCATABLE_TYPE); //指出本类的存储方式

(3)应用举例如下

 QVariant text = model->data(index, Qt::DisplayRole);
 QVariant decoration = model->data(index, Qt::DecorationRole);
 QVariant checkState = model->data(index, Qt::CheckStateRole);
 // etc.

//********************以及************************************

 std::array<QModelRoleData, 3> roleData = { {
     QModelRoleData(Qt::DisplayRole),
     QModelRoleData(Qt::DecorationRole),
     QModelRoleData(Qt::CheckStateRole)
 } };

 // Usually, this is not necessary: A QModelRoleDataSpan
 // will be built automatically for you when passing an array-like
 // container to multiData().
 QModelRoleDataSpan span(roleData);

 model->multiData(index, span);

 // Use roleData[0].data(), roleData[1].data(), etc.


(4)给出本类的继承关系图

在这里插入图片描述

(5)

谢谢

评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

zhangzhangkeji

谢谢支持

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值