LINUX.ORG.RU

Qt, модель и вставка данных

 ,


0

2

Что-то никак не вкурю. Вот, допустим, есть какой-ниудь список объектов. Данные отображаются в таблице. К таблице подключена модель, которая из списка по номеру строки вытягивает объект и по номеру столбца вытягивает информацию из полученного объекта. Теперь где-нибудь глубоко внутри программы в список добавляется еще один объект. В доке написано:

[protected] void QAbstractItemModel::beginInsertRows(const QModelIndex &parent, int first, int last) Begins a row insertion operation. When reimplementing insertRows() in a subclass, you must call this function before inserting data into the model's underlying data store.

т.е. перед добавлением объекта в список нужно было вызвать beginInsertRows(), а по окончании endInsertRows(). Как в этом случае обновить вьюху, чтобы появилась новая строка?


Ответ на: комментарий от RazrFalcon

правильно это как? Создал объект, заполнил данными, вставил в список. Откуда вьюха узнает, что данные добавились?

Crow
() автор топика
Ответ на: комментарий от Crow

Модель сообщит в endInsertRows().

Неправильно, это типо в центр данные вставить, а не в конец. Тогда ничего не произойдёт.

RazrFalcon ★★★★★
()
Ответ на: комментарий от RazrFalcon

а если список сортированный, при вставке автоматом происходит вставка в позицию согласно условию сортировки?

Crow
() автор топика
Ответ на: комментарий от Crow

Где отсортированный? В прокси-модели или в самом контейнере абстрактной модели?

PS: контейнер обычно qvector или qlist.

RazrFalcon ★★★★★
()
Ответ на: комментарий от Athor

Ок, завожу сигнал, после вставки в список делаю emit objectInserted(obj);. У модели есть соответствующий слот. Что в нем должно быть написано? как писал выше в доке:

you must call this function before inserting data into the model's underlying data store

.

Crow
() автор топика
Ответ на: комментарий от RazrFalcon

Сам список с объектами сортированный, не важно qvector/qlist или кастомный контейнер. При вставке объекты будут вставляться не обязательно в конец. Модель держит ссылку на этот список и из него зачитывает данные

Crow
() автор топика
Ответ на: комментарий от Crow

И как оно тогда работает? Я могу ошибаться, но QAbstractItemModel работает только с последовательными данными. Если вам нужна сортировка - используйте прокси модель.

RazrFalcon ★★★★★
()
Ответ на: комментарий от RazrFalcon

И как оно тогда работает? Я могу ошибаться, но QAbstractItemModel работает только с последовательными данными. Если вам нужна сортировка - используйте прокси модель.

сортировка мне не нужна, мне нужно что-бы в таблице данные отображались согласно тому порядку, в котором они идут в списке объектов, в который можно вставить в любую позицию элемент в другом месте программы, которое совершенно не знает ни о каких моделях.

держать ссылку - не значит владеть, не? Владеть в моем понимании - создавать/удалять объект.

допустип объект с данными вида:

class MyObject {
public:
    MyObject(QString strFirst, QString strSecond);
    QString first();
    QString second();
}

лежат они в каком-нибудь списке
QList<MyObject *> lst;

сам список пусть лежит где-нибудь в каком-нибудь другом объекте, не важно. Важно что не в модели.

создаю свою модель со ссылкой на этот список
MyObjectListModel model = new MyObjectListModel(lst, ...)
в модели, естественно, методы получения данных переопределены таки образом, что получают из списка объект и из него получают необходимые строки для отображения.

теперь в каком-нибудь совершенно далеком от этой модели месте в коде вставляем в список новый элемент.
lst.insert(lst.size() / 2, new MyObject("half first", "half second");

вот как модель должна узнать, что данные изменились?

Crow
() автор топика
Ответ на: комментарий от Crow

я пошлю сигнал, мол объект вставлен. Модель на него отреагирует, но что делать-то? Согласно доке нужно было облажить вставку beginInsertRows()/endInsertRows()

Crow
() автор топика

Должно быть что-то типа такого

bool MyModel::insertObject(int row, MyObject *obj)
{
  beginInsertRows(QModelIndex(), row, row);
  m_list.insert(row, obj);
  endInsertRows();
}

Torvus
()
Ответ на: комментарий от Torvus

получается добавление объекта должно работать только через модель и никак иначе? что-то очень сомнительное решение

Crow
() автор топика
Ответ на: комментарий от Crow

получается добавление объекта должно работать только через модель и никак иначе? что-то очень сомнительное решение

сомнительное решение - это то, что ты предлагаешь. данными должна заведовать модель и больше никто

Torvus
()
Ответ на: комментарий от Torvus

т.е. если я захочу некоторые данные из какого-нибудь списка вывести в табличку/список, то у меня нифига не получится, потому что изначально никому не нужно было выводить эту инфу в гуй, а, соответственно, никаких моделей там нет. Так?

Crow
() автор топика
Ответ на: комментарий от Crow

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

void MyModel::reset(const QList<MyObject*> &list)
{
  beginResetModel();
  m_list = list;
  endResetModel();
}
ну а вообще, почитай про MVC в Qt и не только. в интернете полно информации

Torvus
()
Последнее исправление: Torvus (всего исправлений: 1)
Ответ на: комментарий от Torvus

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

Crow
() автор топика
Ответ на: комментарий от Crow

Но, кажется, reset модели затратное занятие.

Затратнее reset только sort, но об это стоит задумываться только на больших объемах данных

Torvus
()
Ответ на: комментарий от Crow

Модель — это окно в данные, а где их хранить неважно. Важно чтобы при вызове rowCount(), data(), etc возвращались целостные данные согластно индексу в модели. То-есть спонтанно обновить список без дёргания сигналов модели заведомо приведёт к рассинхронизации модели и её представления. Если редактируется порядок элементов или дерево родителей, то необходимо уведомить об этом представление заранее (begin), иначе сломаются персистентные индексы (QPersistentModelIndex), при завершении редактирования (end) модель сама отправит сигнал и представление обновится.

Dendy ★★★★★
()
Ответ на: комментарий от Crow

что-то очень сомнительное решение

Напишите свой view, который будет отображать то, что вам нужно.

RazrFalcon ★★★★★
()
Вы не можете добавлять комментарии в эту тему. Тема перемещена в архив.