Название: QAbstractTableModel и два представления: нужен совет... Отправлено: Cyrax от Январь 02, 2008, 21:46 Вопрос следующий: каким образом модель данных (наследник QAbstractTableModel) может определить, какое из представлений вызывает её методы (в частности, data() и setData()) для случая, когда эта модель связана с двумя представлениями ?
Ситуация следующая. Имеется два представления: табличное (с двууровневыми заголовками) и древовидное (QTreeView). Табличное представление содержит значения некоторых параметров, имена которых указаны в горизонтальном заголовке. При наведении мышки на имя какого-либо параметра в горизонтальном заголовке всплывает подсказка с дополнительной информацией об этом параметре. Древовидное представление содержит подробную информацию об этих заголовках (дерево параметров): имя параметра/подпараметра (содержащееся также в табличном представлении в горизонтальном заголовке) + ещё несколько характеристик параметра (часть из которых указывается во всплывающей подсказке горизонтального хидера табличного представления). Таким образом, почти вся информация, отображаемая древовидным представлением, отображается в табличном представлении. В то же время табличное представление отображает информацию, отсутствующую в древовидном представлении (значения параметров), и наоборот, древовидное представление содержит информацию, отсутствующую в табличном (некоторые характеристики параметров). Оптимальный способ организации данных - создание общей модели данных (наследника QAbstractTableModel) для обоих представлений, каждое из которых будет работать с соответствующими методами этой модели. Задача заключается в определении моделью данных, какое из представлений вызвало её метод, поскольку для одного и того же индекса QModelIndex табличное и древовидное представления будут запрашивать/изменять разные данные. Другой способ - создание для каждого представления своей модели данных (табличная и древовидная). Но при этом будет происходить дублирование данных, в связи с чем придётся синхронизировать эти модели. Но это уже отказ от архитектуры "модель-представление" (проще взять QTableWidget и QStandartItemModel + их синхронизация)... Как лучше это всё организовать ? Название: Re: QAbstractTableModel и два представления: нужен совет... Отправлено: Racheengel от Январь 02, 2008, 23:54 Я бы предложил один из 2 вариантов:
1. Модель насделуется от QAbstractTreeItemModel и содержит общие данные. 2. Общие данные содержатся в отдельном классе. Далее, создается один класс-модель для таблицы (с данными, уникальными для таблицы), и второй класс-дерево (с данными, уникальными для дерева). Оба этих класса содержат также указатели на класс с общими данными. Название: Re: QAbstractTableModel и два представления: нужен совет... Отправлено: Cyrax от Январь 03, 2008, 09:35 Цитировать 1. Модель насделуется от QAbstractTreeItemModel и содержит общие данные. Наверное, имеешь ввиду QAbstractItemModel ? (иерархическая структура)Как в этом случае определить, какое из представлений запрашивает данные ? Получили, например, некоторый индекс. Для этого индекса древовидному представлению нужно вернуть одни данные, табличному - другие... И почему именно QAbstractItemModel, а не QAbstractTableModel ? В любом случае модель данных должна будет хранить 2 структуры данных: табличную (например, двумерный массив) и древовидную - для хранения информации об иерархии и характеристиках параметров. При этом для табличного представления будет нужна информация как из табличной структуры данных, так и из древовидной, для древовидного представления - только из древовидной структуры данных. Цитировать 2. Общие данные содержатся в отдельном классе. Далее, создается один класс-модель для таблицы (с данными, уникальными для таблицы), и второй класс-дерево (с данными, уникальными для дерева). Оба этих класса содержат также указатели на класс с общими данными. Тогда можно всю информацию вынести в отдельный класс и создать 2 модели (без данных) - служащие только для обеспечения соответствующего интерфейса и использующие этот класс.А вообще, хотелось бы иметь одну общую модель данных (например, наследник QAbstractTableModel). Только вот модель всё-таки оказывается привязанной к структуре представления (для некоторого индекса табличному представлению нужно вернуть одни данные, древовидному - другие)... Название: Re: QAbstractTableModel и два представления: нужен совет... Отправлено: vaprele07 от Январь 03, 2008, 10:30 Делается одна модель данный, работающая непосредственно с бд (множества А+Б) и 2 прокси модели (QAbstractProxyModel), реализующие нужные тебе представления. В таком случае тебе не придётся придумывать всяких костылей синхронизации данных.
Название: Re: QAbstractTableModel и два представления: нужен совет... Отправлено: Cyrax от Январь 03, 2008, 11:25 Цитировать Делается одна модель данный, работающая непосредственно с бд (множества А+Б) и 2 прокси модели (QAbstractProxyModel), реализующие нужные тебе представления. В таком случае тебе не придётся придумывать всяких костылей синхронизации данных. Что значит "реализующие нужные тебе представления" ? Одна прокси-модель работает с табличным представлением, другая - с древовидным ? Т.е. задача прокси заключается в конвертировании индексов таким образом, чтобы их допустимые множества для обоих представлений не пересекались ? Тогда компоненты многих индексов потеряют физический смысл. Скажем, для табличного представления смысл сохранится (строка, столбец), а для древовидного - исказится.Для древовидного представления тоже можно сохранить физический смысл компонентов индекса, если, например, для древовидного представления в прокси будем менять знак строки и столбца на отрицательный... Название: Re: QAbstractTableModel и два представления: нужен совет... Отправлено: Racheengel от Январь 03, 2008, 11:31 Именно так, две модели - одно для дерева, второе для таблицы (мой вариант 2 - та же идея). Обе модели берут реальные данные из третьей и конвертируют индексы так, как нужно представлениям.
Название: Re: QAbstractTableModel и два представления: нужен совет... Отправлено: Cyrax от Январь 03, 2008, 11:46 vaprele07
А ещё лучше рассмотреть конкретный пример. Горизонтальный заголовок таблицы содержит имена параметров. Вертикальный - номера значений параметров. Т.е., если в таблице 50 строк, то для каждого параметра будет 50 значений. Древовидное представление содержит иерархию параметров (имена которых указаны в горизонтальном заголовке табличного представления) с их характеристиками/описанием. Пусть M - главная модель с данными, работающая с БД. V_tree - древовидное представление V_table - табличное представление P_tree - прокси-модель, работающая с древовидным представлением P_table - прокси-модель, работающая с табличным представлением Скажем, табличное представление V_table запросило у своей модели (у прокси-модели P_tree) данные по индексу (0, 0, null) для роли DisplayRole. Т.е. данные для своей ячейки в первом столбце первого ряда (это первое значение первого параметра X). Затем древовидное представление V_tree запросило данные у своей прокси-модели P_tree по индексу (0, 0, null) для роли DisplayRole. Т.е. данные для своего первого столбца первого ряда (это имя первого параметра X). Какие значения индексов должны передать прокси-модели P_table и P_tree главной модели M ? (учитываем, что модель M должна получать разные индексы для разных данных) Название: Re: QAbstractTableModel и два представления: нужен совет... Отправлено: Cyrax от Январь 03, 2008, 11:50 Цитировать Именно так, две модели - одно для дерева, второе для таблицы (мой вариант 2 - та же идея). Обе модели берут реальные данные из третьей и конвертируют индексы так, как нужно представлениям. А что лучше взять - 2 модели, конвертирующие индексы, или 2 прокси, конвертирующих индексы ?Racheengel , предлагаю рассмотреть конкретный пример из моего предыдущего поста касательно конвертирования индексов ? Название: Re: QAbstractTableModel и два представления: нужен совет... Отправлено: Racheengel от Январь 03, 2008, 14:55 А что лучше взять - 2 модели, конвертирующие индексы, или 2 прокси, конвертирующих индексы ? В данном случае это одно и тоже. Прокси - это модель, которая не содержит реальных данных.Что касается индексов, надо сначала ответить на вопрос: как представлены данные в модели М? Совсем необязательно, что они будут вообще основаны на индексах. Индекс всего лишь указывает на то, какие данные реально нужны. Для P_table по индексу (0, 0, null) нужно будет вернуть значение 0 параметра 0 из модели М, а для P_tree - имя параметра 0 из модели М. Название: Re: QAbstractTableModel и два представления: нужен совет... Отправлено: Cyrax от Январь 03, 2008, 15:20 Цитировать Что касается индексов, надо сначала ответить на вопрос: как представлены данные в модели М? 2 структуры данных: таблица (двумерный массив) и дерево параметров (списки + указатели, либо двумерный массив). Вся информация, необходимая для формирования этих двух структур данных, извлекается из БД в конструкторе модели M (вопросы синхронизации данных модели M с данными в БД пока не рассматривает - это отдельный вопрос).А вот здесь желателен пример, какие индексы могут формировать прокси-модели P_tree и P_table из получаемого индекса (0, 0, null) с учётом указанных структур данных модели M. Цитировать Совсем необязательно, что они будут вообще основаны на индексах. Индекс всего лишь указывает на то, какие данные реально нужны. Для P_table по индексу (0, 0, null) нужно будет вернуть значение 0 параметра 0 из модели М, а для P_tree - имя параметра 0 из модели М. Да, данные в модели M не обязательно должны быть основаны на индексах, но иначе как по индексам модель M не сможт определить, какие данные запрашивают представления V_tree и V_table. Т.е. в любом случае данные модели M придётся привязывать к индексам.Название: Re: QAbstractTableModel и два представления: нужен совет... Отправлено: Racheengel от Январь 03, 2008, 15:35 Нет, я имею в виду, что индексы нужны для доступа представлений к прокси-моделям. А уже прокси-модели будут извлекать реальные данные из М в зависимости от того, какой был запрошен индекс, и передавать представлению в виде QVariant.
Название: Re: QAbstractTableModel и два представления: нужен совет... Отправлено: Cyrax от Январь 03, 2008, 16:15 Цитировать А уже прокси-модели будут извлекать реальные данные из М в зависимости от того, какой Т.е. предлагаешь изменить (расширить) стандартный Qt-интерфейс для "общения" модели M с M_tree и M_table ?был запрошен индекс Потому что если оставить тот же интерфейс (data, setData и др.), то придётся модель M привязывать к индексам... Название: Re: QAbstractTableModel и два представления: нужен совет... Отправлено: ритт от Январь 03, 2008, 16:41 извините, конечно, что вмешиваюсь...
"расширять интерфейс" не нужно. нужно почитать/перечитать документацию по модель-вью и по прокси-моделям в частности. доступ к данным во ВСЕХ моделях кутэ осуществляется через некий индекс и категоризацию через роли. в худшем случае (в зависимости от конкретной задачи) придётся написать наследника прокси-модели и перегрузить некоторые методы, чтобы заточить под конкретные нужды. Название: Re: QAbstractTableModel и два представления: нужен совет... Отправлено: Cyrax от Январь 03, 2008, 17:06 Цитировать доступ к данным во ВСЕХ моделях кутэ осуществляется через некий индекс и категоризацию Поконкретнее, пожалуйста. Ближе к моей "задаче".через роли. в худшем случае (в зависимости от конкретной задачи) придётся написать наследника прокси-модели и перегрузить некоторые методы, чтобы заточить под конкретные нужды. Предлагаешь обходиться дополнительными пользовательскими ролями ? (схема "одна общая модель + 2 представления + дополнительные роли") ? Название: Re: QAbstractTableModel и два представления: нужен совет... Отправлено: ритт от Январь 03, 2008, 20:48 да
Название: Re: QAbstractTableModel и два представления: нужен совет... Отправлено: ритт от Январь 03, 2008, 20:50 схема "одна общая модель + 1-2 прокси-модели + 2 представления + дополнительные роли
Название: Re: QAbstractTableModel и два представления: нужен совет... Отправлено: Cyrax от Январь 03, 2008, 21:48 Цитировать 1-2 прокси-модели 1 прокси-модель, я так понимаю, - когда общая модель данных M заточена под одно из представлений (например, наследник QAbstractTableModel, работающий с представлением напрямую, не нуждается в прокси P_table) ?(в данном случае понадобится одна прокси-модель P_tree для работы с представлением V_tree) Таким образом, пусть модель M будет заточена под табличное представление V_table. Т.е. V_table пусть будет основным представлением, V_tree - дополнительным, нуждающимся в прокси-модели P_tree: - одна общая модель M, - одна прокси-модель P_tree для работы общей модели M с представлением V_tree, - 2 представления V_table и V_tree. Общая модель M работает с основным представлением V_table напрямую, с дополнительным V_tree - через прокси P_tree. Тогда: 1. При запросе/установке данных представлением V_table общая модель M работает с обычными индексами (индекс таблицы), соответствующими ячейкам таблицы и со стандартными ролями Qt. 2. При запросе/установке данных представлением V_tree прокси-модель P_tree индекс (индекс дерева) оставляет неизменным, а роль изменяет на одну из пользовательских (дополнительных) ролей. Так ? Название: Re: QAbstractTableModel и два представления: нужен совет... Отправлено: ритт от Январь 03, 2008, 22:06 неверно, начиная с понимания, что модели заточены под вьюхи
Название: Re: QAbstractTableModel и два представления: нужен совет... Отправлено: Tonal от Январь 03, 2008, 22:09 Я бы сделал так:
Реализовал слой логики, которая ничего о Qt может и не знать. В этом слое есть твой хитрый контейнер, у которого есть методы для доступа как к таблице (имя атрибута, номер строки) и как к дереву (родитель, итератор по детям)... Далее в логике представления рисуем модели, которые не имеют своих данных, а лишь обращаются к соответствующим методам доступа логики. Название: Re: QAbstractTableModel и два представления: нужен совет... Отправлено: Cyrax от Январь 03, 2008, 23:06 Цитировать неверно, начиная с понимания, что модели заточены под вьюхи Именно. Тогда как архитектура/концепция "модель-представление" подразумевает абстракцию данных от представления...xep, касательно моего предыдущего поста - такую реализацию ты имелл вииду или нет ? Или не думал над конкретикой/деталями ? Цитировать Я бы сделал так: Все предлагаемые варианты крутятся вокруг одной схемы: "объект с общими данными + 2 представления + 2 промежуточных объекта".Реализовал слой логики, которая ничего о Qt может и не знать. В этом слое есть твой хитрый контейнер, у которого есть методы для доступа как к таблице (имя атрибута, номер строки) и как к дереву (родитель, итератор по детям)... Далее в логике представления рисуем модели, которые не имеют своих данных, а лишь обращаются к соответствующим методам доступа логики. Т.е. имеются следующие варианты: 1. общая модель M + 1 или 2 прокси-модели P_tree и P_table + 2 представления 2. общая модель M + 2 модели M_tree и M_table + 2 представления 3. класс с общими данными + 2 модели M_tree и M_table + 2 представления Пока предлагаются "голые" варианты. А хотелось бы услышать преимущества и особенности предлагаемых вариантов... 3-й вариант мне пока больше нравится... Название: Re: QAbstractTableModel и два представления: нужен совет... Отправлено: Racheengel от Январь 03, 2008, 23:36 Под вьюхи заточены прокси-модели, а не модель М. Модель М вообще не должна знать, как должны отображаться данные - она просто их содержит. А вот уже прокси-модели выгребают из М то, что надо показать во вьюхе.
Варианты 1 и 3 в принципе идентичны, если считать модель М этим самым классом с общими данными (он может быть вообще не Qt-моделью). Лично я бы так и делал - класс с данными и две прокси. Название: Re: QAbstractTableModel и два представления: нужен совет... Отправлено: ритт от Январь 04, 2008, 00:49 нет, не такую...
модель, две прокси-модели, две вьюхи примера ради: одна прокся оперирует данными роли ДисплэйРоле, другая прокся - данными роли ЭдитРоле. соответственно, каждый индекс будет возвращать на ДисплэйРоле, например, название значения, а на ЭдитРоле - само значение...или наоборот...или же вообще провести свои роли. в таком случае та же таблмодель тебе даст массив не двумерный, а размерностью [столбцов * строк * кол-во уникальных ролей] плюсы: модели срать с прибором на то, кто её пользует, в частности, её же можно использовать в связке с любыми кутэшными вьюхами; не надо "расширять интерфейс"; перестраивать индексы придётся только при скрытии строк/столбцов (прокси-модели это умеют и без тебя) в идеале можно обойтись только наследованием модели эМ, а проксям тупо указать роль, с которой забирать дату по сырцо-индексам из минусов: если в дереве действительно древовидное отображение (больше 1-2 дочерних нод), таблмодель в качестве модели эМ плохо подходит, т.к. будет ассертить на валидные парентИндексы из перечисленных у тебя выше трёх вариантов второй - вообще непотреб. выбирать надо из первого и третьего - всё зависит от структуры/сложности исходных данных Название: Re: QAbstractTableModel и два представления: нужен совет... Отправлено: Tonal от Январь 04, 2008, 09:43 2 Cyrax Насколько я понимаю, мой вариант это №3 по твоей классификации.
Мы успешно его применяем. Главное достоинство подхода - разделение обязанностей. Если по пунктам, то примерно так: 1) Класс логики содержит только логику, без ненужных ему привязок к GUI да и вообще к Qt. Соответственно тестировать, да и вообще использовать его можно совершенно отдельно от остального приложения (у нас, например, такие классы используются в разных конверторах) 2) Классы Qt моделей довольно просты и содержат только логику конвертации и стандартное представление дерева или таблицы соответственно, ошибок в них меньше, а писать проще. Название: Re: QAbstractTableModel и два представления: нужен совет... Отправлено: Cyrax от Январь 04, 2008, 09:47 Блин, ну чё за язык: "срать с прибором", "забирать дату по сырцо-индексам".
Что такое "срать" ? Что такое "прибор" ? Что такое "сырцо-индекс" ? Ничего не понятно... Цитировать примера ради: одна прокся оперирует данными роли ДисплэйРоле, другая прокся - данными Что значит "оперирует данными роли..." ? Каждый из прокси передаёт/получает данные только для одной какой-то роли, а передачу/приём данных для других ролей игнорирует ?роли ЭдитРоле. соответственно, каждый индекс будет возвращать на ДисплэйРоле, например, название значения, а на ЭдитРоле - само значение...или наоборот Цитировать или же вообще провести свои роли. в таком случае та же таблмодель тебе даст массив не двумерный, а размерностью [столбцов * строк * кол-во уникальных ролей] xep, у меня имена параметров указаны в горизонтальном заголовке таблицы. В первой строке таблицы указаны первые значения для всех параметров, во второй - вторые и т.д. В каждой ячейке расположено n-е значение (n-строка) некоторого параметра. Посему дополнительные роли для ячеек мне не нужны и двумерного массива будет достаточно.Да и вообще задача заключается в том, что для одного и того же индекса и для одной и той же роли должны возвращаться/передаваться разные данные для табличного представления и древовидного представления. Я не понимаю твою мысль. Если к стандартным ролям DisplayRole, EditRole, ToolTipRole и т.д., соответствующих табличному представлению, ввести дополнительные роли TreeDisplayRole, TreeEditRole, TreeToolTipRole и т.д. для древовидного представления, то никаких промежуточных моделей или прокси-моделей не понадобится - общая модель M при получении запроса будет исходить из ролей: если роли DisplayRole, EditRole, ToolTipRole и т.д., то возвращаем данные для табличного представления, если TreeDisplayRole, TreeEditRole, TreeToolTipRole и т.д., - для древовидного. Да и вообще, такая схема ролей - чушь какая-то. Цитировать плюсы: модели срать с прибором на то, кто её пользует, в частности, её же можно использовать в связке с любыми кутэшными вьюхами; не надо "расширять интерфейс"; перестраивать индексы придётся только при скрытии строк/столбцов (прокси-модели это умеют и без тебя) Т.е. ставку в отношении плюсов делаешь на функциональность прокси-моделей. Но у меня по-любому перед представлениями будут стоять прокси-модели для фильтрации и сортировки данных. В случае чего, можно будет "перестраивать индексы придётся ... при скрытии строк/столбцов" этими прокси-моделями. А запихивать их функциональность по сортировке/фильтрации в прокси-модели P_table и P_tree, работающих с общей моделью M - не совсем правильно (т.е. разделение по функциональности в силу сильного различия их функций).Цитировать в идеале можно обойтись только наследованием модели эМ, а проксям тупо указать роль, с которой забирать дату по сырцо-индексам Что значит "тупо указать роль, с которой забирать дату по сырцо-индексам" ?Цитировать из минусов: если в дереве действительно древовидное отображение (больше 1-2 дочерних нод), таблмодель в качестве модели эМ плохо подходит, т.к. будет ассертить на валидные парентИндексы Не понял мысль. Мне по-любому придётся создавать две структуры данных: для таблицы (например, массив) и для дерева. При этом если общая модель будет основана на таблице или дереве, то по-любому придётся анализировать индексы и роли и по ним определять, от кого пришёл запрос - от таблицы или от дерева.Таким образом, пока не указано ни одно серьёзное преимущество в пользу прокси-моделей P_tree и P_table по отношению к обычным моделям M_tree и M_table. Кроме того, что в прокси-моделях по-любому придётся реализовывать чистые виртуальные методы (не зависимо от необходимости этих методов), "заточку" этих прокси-моделей под дерево и под таблицу придётся реализовывать самому, поскольку QAbstractProxyModel наследуется от QAbstractItemModel, тогда как QAbstractTableModel уже имеет такую "заточку" под таблицу (ну а для дерева - также QAbstractItemModel)... Пока только минусы... Название: Re: QAbstractTableModel и два представления: нужен совет... Отправлено: Cyrax от Январь 04, 2008, 09:57 Tonal, твой вариант пока лидирует.
Поскольку везкие аргументы в пользу прокси пока отсутствуют, то представляется такая схема: - общий класс с данными, работающий с БД и содержащий в себе 2 структуры данных: табличную (для хранения значений параметров, отображаемых табличным представлением) и древовидную (для хранения иерархии, имён и характеристик параметров, отображаемых в древовидном представлении) - две модели M_table (наследник QAbstractTableModel) и M_tree (наследник QAbstractItemModel) - две прокси-модели P_tree и P_table, сортирующие и фильтрующие данные - два представления V_tree и V_table Собственно, отличная реализация принципа "разделения обязанностей"... Название: Re: QAbstractTableModel и два представления: нужен совет... Отправлено: Tonal от Январь 04, 2008, 10:09 Общий класс у нас обычно строиться таким образом:
Хеш объектов по id-у (у каждого объекта есть своё уникальный id) + несколько дополнительных структур (индексов) для быстрой индексации по выбранным атрибутам, или навигации по дереву подчинённости (если есть). Каждый такой индекс содержит указатели на объекты из основного хеша. |