Qml listview добавляет новую строку к субвектору в модели - PullRequest
0 голосов
/ 21 мая 2019

У меня есть определенная структура, определенная в C ++, которая содержит несколько переменных, среди которых есть переменная QList. Теперь я могу динамически добавлять новую структуру в Qml listview, но мой вопрос таков: я также хочу добавить новый элемент в QList внутри структуры, я могу сделать это в фоновом режиме, но не могу обновить viewview.

Я думаю, что ошибка появляется в функции connect () в C ++. Как я понимаю, для добавления новой строки необходимо вызвать beginInsertRows () и endInsertRows (), но должны ли отправитель и получатель быть одинаковыми в этих двух сценариях?

Итак, у меня есть следующая структура в C ++ вместе с некоторыми сигналами и функциями, используемыми для вставки новых строк.

"todolist.h":

struct ToDoItem
{
    bool done;
    QString description;
    QList<int> list;

    ToDoItem(){
        done = false;
        description = "text";
        QList<int> mylist;
        mylist.append(1);
        list = mylist;
    }
};
signals:
    void preItemAppended();
    void postItemAppended();

    void preListAppended();
    void postListAppended();

public slots:
    void appendItem();
    void appendList();

void ToDoList::appendItem()
{
    emit preItemAppended();

    mItems.append(ToDoItem());
    emit postItemAppended();
}

void ToDoList::appendList()
{
    emit preListAppended();

    mItems[0].list.append(1);

    emit postListAppended();
}

"todomodel.h"

void ToDoModel::setList(ToDoList *list)
{
    beginResetModel();

    if (mList)
        mList->disconnect(this);

    mList = list;

    if (mList) {
        connect(mList, &ToDoList::preItemAppended, this, [=]() {
            const int index = mList->items().size();
            beginInsertRows(QModelIndex(), index, index);
        });
        connect(mList, &ToDoList::postItemAppended, this, [=]() {
            endInsertRows();
        });

        connect(mList, &ToDoList::preListAppended, this, [=]() {
            const int index = mList->lists().size();
            beginInsertRows(QModelIndex(), index, index);
        });
        connect(mList, &ToDoList::postListAppended, this, [=]() {
            endInsertRows();
        });
    }

    endResetModel();
}

Хорошо работают первые две функции соединения, которые используются для вставки нового элемента, но вторые две функции соединения не работают.

1 Ответ

0 голосов
/ 21 мая 2019

Не рекомендуется подключать сигналы к beginInsertRows и endInsertRows. Вы должны абстрагироваться от этого и, скорее, подключиться к add или remove методам. Предположим, у вас есть класс модели, который реализует QAbstractListModel:

class MyListModel : public QAbstractListModel {

  Q_OBJECT
  Q_PROPERTY(int size READ size NOTIFY sizeChanged)

  public:
  explicit myListModel(QObject *parent = nullptr);
  ~myListModel() override;

  int rowCount(const QModelIndex &p) const override;
  QVariant data(const QModelIndex &index, int role) const override;
  QHash<int, QByteArray> roleNames() const override;
  int size() const;

  public slots:
  void add(QObject *o);
  QObject *remove(int i);
  signals:
  void sizeChanged();

 private:
  QList<QObject *> m_data;

};

Реализация add и remove будет выглядеть следующим образом:

void MyListModel::add(QObject* o) {
    int i = m_data.size();
    beginInsertRows(QModelIndex(), i, i);
    m_data.append(o);
    o->setParent(this);
    sizeChanged();
    endInsertRows();
}


QObject * MyListModel::take(int i) {
    if ((i > -1) && (i < m_data.size())) {
        beginRemoveRows(QModelIndex(), i, i);
        QObject * o = m_data.takeAt(i);
        o->setParent(nullptr);
        sizeChanged();
        endRemoveRows();
        return o;
    }
    return nullptr;
}

В этом случае вы можете вызвать add для вновь добавленных элементов, или, если вы заново заполняете свой список, вы можете очистить его и перебрать список и добавить их 1 на 1.

ДОБАВЛЕНИЕ ПРИМЕРНОГО ОБЪЕКТА:

class ToDoItem : public QObject {
  Q_OBJECT
  Q_PROPERTY(bool done READ done WRITE setDone NOTIFY doneChanged)

  public:
    explicit ToDoItem(QObject* parent = nullptr);
    ~ToDoItem() override;

    bool done() const { return m_done_; }
    void setDone(bool done) { m_done_ = done; emit doneChanged(done); }

  signals:
    void doneChanged(bool);

  private:
    bool m_done_;
};
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...