我如何保持我的QAbstractTableModel与我的数据存储同步

How do I keep my QAbstractTableModel in sync with my data store?

本文关键字:我的 数据 存储 同步 QAbstractTableModel 何保持      更新时间:2023-10-16

在我的应用程序中,我有一个类来保存项目列表:

class Database : public QObject
{
    Q_OBJECT
public:
    Database(QObject *parent, const QString &name);
    const Entry& item(int idx) const { Q_ASSERT(idx < itemCount()); return _items.at(idx); }
    const QString& name() const { return _name; }
    int itemCount() const { return _items.size(); }
    bool addItem(const Entry &item);
    bool addItems(const Database *source, const QList<int> &idxs);
    bool updateItem(int idx, const Entry &updated);
    void removeItem(int idx);
    void removeItems(const QList<int> &idxs);
private:
    QList<Entry> _items;
signals:
    void itemsRemoved(int start, int count);
    void itemsAdded(int count);
    void itemChanged(int index);
    void countUpdate();
};

项操作函数(add、update、remove)在完成操作(添加、更改、删除项)时发出相应的信号。我有这样的数据库的列表和一个QTableView显示他们的内容。我还有一个定制的对象,qabstracttablemodel派生的模型类,它可以在需要时指向(并显示)不同的数据库:

class DatabaseModel : public QAbstractTableModel
{
    Q_OBJECT
public:
    DatabaseModel(QObject *parent = 0);
    int rowCount(const QModelIndex &parent = QModelIndex()) const { return _data->itemCount(); }
    int columnCount(const QModelIndex &parent = QModelIndex()) const { return 5; };
    QVariant data(const QModelIndex &index, int role = Qt::DisplayRole) const = 0;
    void setDatabase(const Database *data);
    {
        beginResetModel();
        _data = data;
        endResetModel();
    }
protected:
    const Database *_data;
};

我有一个问题,使模型反映其当前数据库的变化。在此之前,我通过每次数据库中的某些更改(由从数据库到DatabaseModel的信号触发)发出模型重置来实现它的工作,但我认为这有点过头了。现在我不知道如何正确连接数据库和模型。

将Database信号连接到模型并使模型发出datachchanged()不起作用,因为Database中的项数(因此模型的行数)正在变化。在QAbstractTableModel中有称为rowsInserted()和rowsRemoved()的信号,但是文档说它们不能在自定义类中使用。有一些虚函数要重新实现,叫做removeRows()和insertRows(),但是文档说我必须在它们里面调用begin(Remove|Insert)Rows()和end(Remove|Insert)Rows(),这会导致两个问题:

    Rows()需要一个QModelIndex '父'参数,我不知道该使用什么
    EDIT:实际上这并不重要,现在我正在传递QModelIndex()。QAbstractTreeModel使用它来标识树中的父节点,对于表模型显然不是必需的。
  1. 文档说这些函数需要在更改底层数据存储
  2. 之前调用

如何使模型与数据库保持同步?谢谢!

我想我明白你的问题了。一方面,你正在做正确的事情,并试图保持数据与模型分离,另一方面,你的数据不知道模型本身。

在更改数据之前调用begin…Rows(),然后调用end…Rows()是有原因的。即QPersistentModelIndex。通常情况下,您不应该对QModelIndex对象进行保存,但是持久化索引应该被保存和保留。模型必须保证其有效性。看看begin…Rows()方法的代码,它主要是关于那些持久索引的。

你有几个选择。
a)如果你确信你不会使用持久索引,你可以在你的模型中实现一个私有槽,它可以从你的数据源中侦听一种更新信号。这个槽只调用begin…Rows()和end…Rows(),中间没有任何内容。它不"干净",但它会工作。

b)您可以在数据源中实现更多信号,一个信号表示数据更改的开始(例如删除或添加一行),另一个信号表示所述操作的结束。当然,这会大大增加代码的大小。

c)你可以把你的DataBase类在模型中作为朋友,并调用begin…结束……方法,但是DataBase必须知道模型。

d)你可以重新考虑这个概念。据我所知,您正在使用DataBase类作为模型的数据存储和代码其他部分的接口,对吗?使用自定义项和操作模型本身的方法不是更容易吗,从而避免了麻烦?我已经做了我的公平分享,所以我可以给你的代码,如果需要的话。

希望这对你有帮助。
最好的祝福