2

我有一个自定义代理模型,当将新列/行添加到其源模型时,它偶尔会自行检修。从文档看来,在此类操作的开始和结束时调用QAbstractItemModel::beginResetModel()QAbstractItemModel::endResetModel()是正确的方法。不幸的是,我的检修功能有几个可能的退出点,我只知道我会忘记endResetModel在每个退出点调用,因为它变得更加复杂。

因此,我想创建一个简单的 RAII 类,它将调用beginResetModel构造然后调用endResetModel破坏,如下所示:

class ModelResetter
{
public:
    ModelResetter(QAbstractItemModel* model) : m_model(model)
    {
        m_model->beginResetModel();
    }
    ~ModelResetter()
    {
        m_model->endResetModel();
    }

private:
    QAbstractItemModel* m_model;
};

问题在于,beginResetModel()两者endResetModel()protectedQAbstractItemModel. 在我的继承模型中声明ModelResetter为 a似乎没有帮助,因为我正在尝试与基类交互。friend class

我不想为我实现的每个模型都做一个自定义实现,那么我可以用模板来做这个吗?我对模板语法还不是很熟悉。

编辑 1:(我删除了编辑 2 中的示例模板代码以避免混淆)

如果我能以某种方式将模板限制为只允许继承的类型,那就太好了QAbstractItemModel,但我在标准 C++ 中看不到任何允许这样做的东西。我不会使用 Boost。

编辑 2:我想我并不清楚我的要求。他们来了:

  • 对一般情况的基类进行操作
  • 在调试模式下强制QAbstractItemModel继承要求,而在发布模式下没有惩罚
  • 使用简单,几乎没有开销
  • 不需要修改基类或新函数
4

2 回答 2

1

您可以让继承的模型公开方法,这些方法只会分别调用 beginResetModel() 和 endResetModel(),然后让 ModelResetter 调用这些方法。

于 2013-03-08T14:55:08.647 回答
0

我不想回答我自己的问题,但几天后我整理了一个基于模板的解决方案,可以满足我的所有要求。是的,我的第一个从头开始的模板类。这是实现:

//modelresetter.h
#include <QAbstractItemModel>

/* you must declare this class as a friend to your model
 * to give it access to protected members as follows:
 * template <class Model> friend class ModelResetter;
 */
template<class Model>
class ModelResetter
{
public:
    ModelResetter(Model* model) : m_model(model)
    {
        Q_ASSERT_X(qobject_cast<QAbstractItemModel*>(model) != 0, __FUNCTION__,
                   "templated object does not inherit QAbstractItemModel");
        m_model->beginResetModel();
    }
    ~ModelResetter()
    {
        m_model->endResetModel();
    }

private:
    Model* m_model;
};

和用法:

//mymodel.cpp
bool MyModel::overhaul()
{
    ModelResetter<MyModel> resetter(this); resetter;  //prevent compiler warning

    //do stuff
    if(somethingswrong)
        return false; //model will finish reset at every exit point

    //do more stuff
    return true; //model also completes reset on success
}

谢谢你的帮助!

于 2013-03-08T19:23:49.850 回答