Russian Qt Forum

Qt => Model-View (MV) => Тема начата: Igors от Октябрь 11, 2018, 07:29



Название: Старая таблица
Отправлено: Igors от Октябрь 11, 2018, 07:29
Добрый день

Переделываю большое дерево написанную не мной и еще до того как родилось Qt. После долгого лазания по коду выяснил такие моменты.
 
1) Для каждой строки каждой колонки (т.е. для каждой ячейки) хранится контейнер таких данных (псевдокод)
Цитировать
struct Field  {
  FieldType m_type;     // тип поля (напр иконка, текст, стрелка expand/collapse и.т.п)

  Node * m_object;      // объект
  int m_dataPart;         // что показывается в данной строке напр  Object->Position
  int m_dataSubPart;   //  напр  Object->Position->x
  intptr_t m_Aux;       //   доп данные (что угодно в зависимости от типа поля и др)
};
Ну и рисование ячейки сводится к пробежке по контейнеру таких эл-тов. Напр в первой колонке разные строки имеют от 0 до 4 чекбоксов

2) Хранятся только видимые строки. Если юзер нажал expand, то новые строки вставляются (этому посвящено довольно много кода) и удаляются при сollapse. Основания для этого имеются. Число объектов (корни дерева) может быть 50-100K и более, а один объект "полностью expanded" - примерно 100 строк.
 
Насколько верны эти старые решения в свете MV(C) и всего такого? Стоит ли их сносить и делать "правельно"?  :)

Спасибо


Название: Re: Старая таблица
Отправлено: qate от Октябрь 11, 2018, 10:19
> Напр в первой колонке разные строки имеют от 0 до 4 чекбоксов

Казнить, нельзя помиловать.
Неужели таким удобно пользоваться ?

> Число объектов (корни дерева) может быть 50-100K и более ...

Может все переписать в новый более удобный и упрощенный вариант ?


Название: Re: Старая таблица
Отправлено: Igors от Октябрь 11, 2018, 13:10
> Напр в первой колонке разные строки имеют от 0 до 4 чекбоксов

Казнить, нельзя помиловать.
Неужели таким удобно пользоваться ?
Да, вполне удобно

Может все переписать в новый более удобный и упрощенный вариант ?
Ну так это собсно и есть тема для обсуждения, предлагайте как


Название: Re: Старая таблица
Отправлено: qate от Октябрь 11, 2018, 13:21
сложно предлагать не понимая  что делает программа )
по мне так это ад адовый с комбобоксами и деревом на 100К объектов - человек это не осиливает


Название: Re: Старая таблица
Отправлено: ViTech от Октябрь 11, 2018, 13:39
сложно предлагать не понимая  что делает программа )

Цитировать
Приходит ветеринар к терапевту.
Терапевт:
- На что жалуетесь?
Ветеринар:
- Нет, ну так каждый может!


Название: Re: Старая таблица
Отправлено: Racheengel от Октябрь 11, 2018, 15:16
может хотя бы скриншотом поделитесь для начала...?


Название: Re: Старая таблица
Отправлено: Igors от Октябрь 12, 2018, 10:11
может хотя бы скриншотом поделитесь для начала...?
Не имею права, да и незачем провоцировать следующую порцию ненужных вопросов и недоумения. Деревьев не видели, что ли? :) См хотя бы диалог "выбор файла" в любом ОС. Любое дерево в принципе такое же - иерархическая структура, есть "листья", "ветки", которые могут быть expanded/collapsed. Да, другое содержимое полей/ячеек, и что, разве кто-то просил вникать в то что делает каждая бубочка? Это только напрасно утомляет обсуждающих но не дает никакого прогресса. 

Ладно, попробуем так. Вот все любят повторять фразы типа "модель хранит, вьюха отображает" :) Но где взять эту самую "модель"? Конечно "что отображать" известно, это объекты сцены (Node *) которые сами тоже деревья. Но моделью они сами по себе быть не могут, хотя бы потому что организованы в виде списка. А нужен контейнер прямого доступа чтобы иметь возможность обращаться к строке/ячейке по индексам. Поэтому так или иначе нужно заводить контейнер/вектор эл-тов типа "Line" (строка) которые хранят указатели на данные-первоисточники (Node).

Верно ли я понимаю этот момент?


Название: Re: Старая таблица
Отправлено: qate от Октябрь 12, 2018, 15:56
> Но где взять эту самую "модель"?

написать самому
в примерах есть http://doc.qt.io/qt-5/qtwidgets-draganddrop-puzzle-example.html, где на модели это и написано


Название: Re: Старая таблица
Отправлено: ViTech от Октябрь 13, 2018, 14:07
Ладно, попробуем так. Вот все любят повторять фразы типа "модель хранит, вьюха отображает" :) Но где взять эту самую "модель"? Конечно "что отображать" известно, это объекты сцены (Node *) которые сами тоже деревья. Но моделью они сами по себе быть не могут, хотя бы потому что организованы в виде списка. А нужен контейнер прямого доступа чтобы иметь возможность обращаться к строке/ячейке по индексам. Поэтому так или иначе нужно заводить контейнер/вектор эл-тов типа "Line" (строка) которые хранят указатели на данные-первоисточники (Node).

Верно ли я понимаю этот момент?

Можно и так понимать, но это не единственный вариант. QAbstractItemModel может выступать посредником между внешними данными и View, и не иметь своей внутренней структуры данных, ссылающейся на внешние. Моделью может служить исходное дерево объектов сцены, в QModelIndex::internalPointer() можно записывать указатели на внешние Node. Далее возникают вопросы, как реагировать и синхронизироваться с внешним деревом, если оно изменяется вне QAbstractItemModel-View. Но такие же вопросы возникают и с вариантами со своей внутренней структурой в QAbstractItemModel.


Название: Re: Старая таблица
Отправлено: Igors от Октябрь 13, 2018, 14:48
> Но где взять эту самую "модель"?

написать самому
в примерах есть http://doc.qt.io/qt-5/qtwidgets-draganddrop-puzzle-example.html, где на модели это и написано
Пример помню, но не вижу никакой его связи с моделью дерева

Можно и так понимать, но это не единственный вариант. QAbstractItemModel может выступать посредником между внешними данными и View, и не иметь своей внутренней структуры данных, ссылающейся на внешние. Моделью может служить исходное дерево объектов сцены, в QModelIndex::internalPointer() можно записывать указатели на внешние Node.
Ну хорошо, исходные данные напр QLinkedList<Node>, Не вижу как соорудить модель без промежуточного контейнера прямого доступа (напр вектор). Ну разве что использовать std::distance и std::advance для списка - но это просто неграмотно.

Следующая позиция.
Код:
struct Field  {
..
  Node * m_object;      // объект
  int m_dataPart;         // что показывается в данной строке напр  Object->Position
  int m_dataSubPart;   //  напр  Object->Position.x
...
};
Члены "локаторы" m_dataPart и m_dataSubPart выглядят обязательными. Можно их упаковать в один или наоборот, расширить, но это непринципиально.  В самом деле, как дать строке понять что она отображает напр  Object->Position.x?  Ведь объекта "x" нет, это просто поле структуры/класса. Значит надо задавать явно. Правда это ведет к морю констант/enum'ов, но ничего лучшего не видно. Или я под впечатлением работающего кода? (так часто бывает)


Название: Re: Старая таблица
Отправлено: ViTech от Октябрь 13, 2018, 15:54
Ну хорошо, исходные данные напр QLinkedList<Node>, Не вижу как соорудить модель без промежуточного контейнера прямого доступа (напр вектор). Ну разве что использовать std::distance и std::advance для списка - но это просто неграмотно.

Тут вечный компромисс: память vs скорость.

Следующая позиция.
Код:
struct Field  {
..
  Node * m_object;      // объект
  int m_dataPart;         // что показывается в данной строке напр  Object->Position
  int m_dataSubPart;   //  напр  Object->Position.x
...
};
Члены "локаторы" m_dataPart и m_dataSubPart выглядят обязательными. Можно их упаковать в один или наоборот, расширить, но это непринципиально.  В самом деле, как дать строке понять что она отображает напр  Object->Position.x?  Ведь объекта "x" нет, это просто поле структуры/класса. Значит надо задавать явно. Правда это ведет к морю констант/enum'ов, но ничего лучшего не видно. Или я под впечатлением работающего кода? (так часто бывает)

Это уже особенности конкретного дерева. Если без дополнительных "локаторов" данные не отобразить, значит надо создавать промежуточную структуру. Если её целиком накладно содержать, значит надо мутить её по частям. В общем, слишком много всяких "если". И вряд ли найдется одно универсальное решение, которое будет одинаково эффективно для всех возможных комбинаций "если".

У меня для QAbstractItemModel почти всегда какой-нибудь enum да есть. Обычно для колонок. По колонке можно определить, какое свойство объекта отображать.


Название: Re: Старая таблица
Отправлено: Igors от Октябрь 14, 2018, 08:01
Это уже особенности конкретного дерева. Если без дополнительных "локаторов" данные не отобразить, значит надо создавать промежуточную структуру. Если её целиком накладно содержать, значит надо мутить её по частям. В общем, слишком много всяких "если". И вряд ли найдется одно универсальное решение, которое будет одинаково эффективно для всех возможных комбинаций "если".
Ну если "так много возможных решений", то можно увидеть хотя бы одно?  :) Напр вот случай "проще уже некуда"
Код:
struct Node {
...
  QVector3D m_position;
...
};
"Position" - строка с "раскладушкой", когда случился expand появляются строки c именами x, y, z и значениями в др колонке. Что за такая промежуточная структура? Как ее мутить? Поясните. Пусть решение будет ограниченным, не идеальным и.т.п. - я понимаю


Название: Re: Старая таблица
Отправлено: ViTech от Октябрь 14, 2018, 12:53
Ну если "так много возможных решений", то можно увидеть хотя бы одно?  :) Напр вот случай "проще уже некуда"
Код:
struct Node {
...
  QVector3D m_position;
...
};
"Position" - строка с "раскладушкой", когда случился expand появляются строки c именами x, y, z и значениями в др колонке. Что за такая промежуточная структура? Как ее мутить? Поясните. Пусть решение будет ограниченным, не идеальным и.т.п. - я понимаю

Если исходные данные напрямую не отображаются в требуемое дерево, значит нужно использовать промежуточное представление. struct Field похоже и была таким вариантом промежуточного представления. Только что потом делалось с этими m_dataPart/m_dataSubPart, свитчами разгребалось? Как-то не очень вариант... Можно попробовать отобразить исходное дерево Node в дерево TreeItem (примерно как здесь (http://doc.qt.io/qt-5/qtwidgets-itemviews-editabletreemodel-example.html)). В базовом классе TreeItem методы data()/setData() сделать виртуальными, а в потомках хранить связь с Node и обращаться к его данным. Недавно что-то подобное обсуждали (http://www.prog.org.ru/topic_32206_0.html).


Название: Re: Старая таблица
Отправлено: Igors от Октябрь 16, 2018, 11:35
Можно попробовать отобразить исходное дерево Node в дерево TreeItem (примерно как здесь (http://doc.qt.io/qt-5/qtwidgets-itemviews-editabletreemodel-example.html)).
Ну это просто модель "для UI", никаких связок с "реальными данными" нет

В базовом классе TreeItem методы data()/setData() сделать виртуальными, а в потомках хранить связь с Node и обращаться к его данным.
Это дерево - практически единственное где возможен хороший объем данных. А всякой мелочевки полно, причем дерево часто вырождается в ListBpx (нет чайлдва). Там сделал классы - наследники QTreeWidget и QTreeWidgetItem, к нему прицепил указатель на реальные данные. Редактирование "от айтема" - без проблем, хватает индекса колонки, а если данные обновились "извне" - да просто перезалил всю модель. 

Конечно так можно сделать и здесь (правда вопрос навигации/локаторов остается открытым), но тогда что я имею с Qt? Ну скроллы и раскладушки автоматом, это не так уж много для данного дерева. Зато насует данных по самые "не балуйся", и хз - может и тормоза пойдут. И что тогда? "Назад к велику" или как?