4

私のアプリには、アイテムのリストを保持するためのクラスがあります。

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();
};

アイテム操作関数 (追加、更新、削除) は、完了時に対応するシグナルを発行します (アイテムの追加、変更、削除)。そのようなデータベースのリストと、その内容を表示するための QTableView があります。また、カスタムの QAbstractTableModel 派生モデル クラスのオブジェクトが 1 つあります。これは、必要に応じて別のデータベースを指す (および表示する) ようにすることができます。

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 へのシグナルによってトリガーされて) モデルのリセットを発行することで動作させていましたが、それはやり過ぎだと判断しました。データベースとモデルを正しく接続する方法がわかりません。

データベース シグナルをモデルに接続し、モデルが dataChanged() を発行するようにしても、データベース内のアイテム数 (したがってモデルの行) が変化するため、機能しません。QAbstractTableModel には rowsInserted() および rowsRemoved() と呼ばれるシグナルがありますが、カスタム クラスでは使用できないとドキュメントに記載されています。removeRows() および insertRows() と呼ばれる再実装する仮想関数がありますが、ドキュメントでは、それらの内部で begin(Remove|Insert)Rows() および end(Remove|Insert)Rows() を呼び出す必要があると書かれており、2 つの問題が発生します。 :


  1. begin...Rows() にはQModelIndex 'parent' パラメータが必要ですが、何を使用すればよいかわかりません 。これは QAbstractTreeModel によってツリー内の親ノードを識別するために使用され、明らかにテーブル モデルには必要ありません。
  2. ドキュメントには、基礎となるデータストアを変更するにこれらの関数を呼び出す必要があると書かれています

モデルをデータベースと同期させるにはどうすればよいですか? ありがとう!

4

1 に答える 1

8

私はあなたの問題を見ていると思います。一方では、正しいことを行い、データをモデルから分離しようとしていますが、他方では、データはモデル自体を認識していません。

データを変更する前に begin...Rows() を呼び出し、後で end...Rows() を呼び出す必要があるのには理由があります。つまり、QPersistentModelIndex. 通常、オブジェクトをホートすることは想定されていませんQModelIndexが、永続的なインデックスは保存して保持する必要があります。モデルはその有効性を保証する必要があります。これらの begin...Rows() メソッドのコードを見ると、主にこれらの永続インデックスに関するものです。

いくつかの選択肢があります。
a) 永続的なインデックスを使用しないことが確実な場合は、モデルにプライベート スロットを実装して、データ ソースからの一種の更新信号をリッスンすることができます。このスロットは、begin...Rows() と end...Rows() を間に何も入れずに呼び出すだけです。「きれい」ではありませんが、うまくいきます。

b) データ ソースにさらに多くのシグナルを実装できます。1 つはデータ変更の開始 (たとえば、行の削除または追加) を通知し、もう 1 つはその操作の終了を通知します。もちろん、それはコードのサイズを大幅に増加させます。

c)DataBaseクラスをモデルのフレンドにして、データソース内から begin... end... メソッドを呼び出すことができますが、その場合DataBaseはモデルを認識している必要があります。

d) 概念を再考することができます。私が把握できることから、DataBaseクラスをモデルのデータ ストレージとして、およびコードの他の部分のインターフェイスとして使用していますね。モデル自体で動作するメソッドでカスタム アイテムを使用して、問題を回避する方が簡単ではないでしょうか? 必要に応じてコードを提供できるように、それらのかなりの部分を実行しました。

うまくいけば、それは役に立ちます。
よろしくお願いします

于 2011-05-03T17:27:25.280 に答える