覆盖 QAbstractItemModel::index 并访问 std::map

Posted

技术标签:

【中文标题】覆盖 QAbstractItemModel::index 并访问 std::map【英文标题】:Overriding QAbstractItemModel::index and accessing std::map 【发布时间】:2011-05-08 09:29:25 【问题描述】:

在我的程序中,我想将视图/模型模式与 view = QListView 和我自己的模型(我从 QAbstractListModel 子类化)一起使用。我的数据类看起来像

class Avtomat

...
 map<QString, State *> states;
...
;

在我的模型类中

class AvtomatModel : public QAbstractListModel

    ...
    Avtomat a;
    ...
;

我正在尝试重载 QAbstractItemView::index 函数,以便能够提供用于编辑数据映射的界面。 由于索引函数采用 int row 参数,我通过提供以下内容解决了该问题

State* Avtomat::pStateFromIndex(int index) const

    map<QString, State *>::const_iterator i;
    int count = 0;
    for (i = states.begin(); i != states.end() && count != index; ++i)
        ++count;
    return (*i).second;

所以在我的索引函数中我确实喜欢这样

return createIndex(row, column, a.pStateFromIndex(row));

但这看起来很丑,因为我有 O(n)。你能帮我设计一个更好的方法来使用 int index 访问我的地图吗?

【问题讨论】:

【参考方案1】:

这是一个基本的数据建模问题。您需要检索数据的主要方式是什么?按键还是按索引?

如果您只通过索引(包括在模型中)访问它,那么您只是使用了不合适的数据结构,应该切换到其他东西,比如列表。

如果您也确实需要按键查询,那么您有多种选择。如果效率不是一个巨大的驱动因素,那么你已经在做的事情没有错,尤其是在数据集很小的情况下。或者,您还可以维护与基础数据的键和索引映射。这是一个简单而有效的解决方案,但它意味着您必须承担管理两者之间一致性的责任,并且如果您的数据集很大,那么内存开销可能会很大。或者,您可以使用直接通过键和索引提供访问的数据结构。最终,这取决于您的具体情况和您正在使用的数据域。

文档中有一个很好的 Qt 容器类(以及 std 容器)summary。 algorithmic complexity 部分可能对您来说特别有趣。

【讨论】:

【参考方案2】:

另一种选择是使用向量将数据保存在键值对中。然后可以通过索引或键访问向量。 这样做的缺点是插入向量相对于 std::map 的开销很大。

typedef std::pair<QString, State*> StateP;
typedef std::vector<StateP> States;
States states;

然后根据比较第一个元素的谓词保持向量的排序顺序。您可以通过 O(1) 中的索引或 O(log n) 中的键来查找项目。

struct StatePCompare 
    bool operator()(StateP const& lhs, StateP const& rhs) const 
        return (lhs.first < rhs.first);
    
;

void Avtomat::insert(QString key, State* state) 

    States::iterator i = std::lower_bound(states.begin(), states.end(), StatePCompare());
    if ((i != states.end() && (i->first == key)) 
        // key already exists, set the element
        i->second = state;
    
    else 
        states.insert(i, state);
    


State* Avtomat::find(QString key) 

    States::iterator i = std::lower_bound(states.begin(), states.end(), StatePCompare());
    if ((i != states.end() && (i->first == key)) 
        return i->second;
    
    return NULL;

【讨论】:

以上是关于覆盖 QAbstractItemModel::index 并访问 std::map的主要内容,如果未能解决你的问题,请参考以下文章

白盒测试法:逻辑覆盖与路径覆盖

代码覆盖率VS测试覆盖率

覆盖率啥意思

软件测试 白盒测试 语句覆盖 判定覆盖

07-白盒测试方法-逻辑覆盖法

代码覆盖率是个啥概念?