Название: Предметная голосовая беседа по Model-View для OpenSrc проекта по Skype/SIP/Viber Отправлено: xintrea от Май 26, 2015, 17:02 Все, я дошел до предела.
Не могу осилить очередную ступеньку в доработке проекта MyTetra (http://webhamster.ru/site/page/index/articles/projectcode/105). Релиза небыло уже 4 года. Я застрял, и дальше двигаться не могу. Проблема в том, что мне не с кем посоветоваться. В моем окружении нет ни одного программиста, который бы писал на C++ и тем более знал Qt4/5. Черт возьми, да в моем окружении вообще нет ни одного программиста! Я живу в полной профессиональной изоляции. Сейчас мне нужно переделать в MyTetra пару моделей и вид так, чтобы вид смог показывать сортированные данные. Я собрался это делать через proxy модель. Этот вопрос я уже поднимал здесь (https://www.linux.org.ru/forum/development/11599166) и здесь (https://toster.ru/q/216166?e=1961590#answer_item_582306) и здесь (http://www.prog.org.ru/topic_28883_0.html). Но если использовать proxy модель, то нужно, чтобы source модель была чистая, с реализациями только стандартных методов QAbstractTableModel. Но из-за этого полностью ломается вся концепция моделей. В моем понимании модель - это такой класс, который позволяет сделать с данными все что ты хочешь, используя удобный для конкретных данных интерфейс. Хочешь удалить данные по списку индексов - пожалуйста! Хочешь добавить сразу несколько строк с данными в любое место? На тебе метод. Хочешь по номеру строки или по QModelIndex получить всю строку - да не вопрос. Но в Qt получается, что в модели можно только читать/менять данные в ячейках (data/setData), добавлять/удалять строчки и столбцы (insertRows/removeRows) и... все! Конечно, этими базовыми методами можно полностью управлять данными, но тогда всю логику по работе с данными придется реализовывать в виде, который использует такую примитивную модель. Но это же неправильно. Вид должен давать модели простые и емкие команды управления данными, а уж модель сама с ними разбираться. И к тому же, с моделью может взаимодействовать не только вид, но и например объект буфера обмена, со своими требованиями и закидонами. В общем, имеем взаимоисключающие параграфы. Я уже понял, что обсуждением в текстовом виде (переписка) много чего не решишь. Текст - это медленно, и то что можно сказать за минуту, пишется за десять. Мне нужно пообщаться со знающим человеком голосом. Исходники: https://github.com/xintrea/mytetra_dev Лютое бесцельное безумие начиная с коммита 4f9d3ce. Прошу отписаться на емайл xintrea[сцобакка]gmail.com или в асю 115519OOO (заменить три буквы О на нули) идейных товарищей, которые готовы пообщаться по вышеприведенным вопросам голосом. Напишите в письме время, когда вы готовы поговорить (на рабочей неделе могу только вечером, после 18:00 по Москве, в выходные - по договоренности), напишите предпочитаемые средства связи. Для оперативной координации звонка по Skype/SIP/Viber не помешал бы номер мобильного телефона. PS: Что я штудировал, но просветление не пришло: 1. Официальная документация 2. Qt4: Программирование моделей и представлений. Подробное объяснение на русском языке. http://webhamster.ru/mytetrashare/index/mtb0/1392580691nchkxju7yz 3. Программирование моделей в Qt - рекомендации по использованию, неочевидные моменты http://webhamster.ru/mytetrashare/index/mtb0/14259955927q5bhzmfbg 4. Беседы о Qt: Парадигма Model-View http://webhamster.ru/mytetrashare/index/mtb0/14064861764k4dumxivg 5. Модели-Посредники в Qt http://webhamster.ru/mytetrashare/index/mtb0/1432497788j6rq3ufits Название: Re: Предметная голосовая беседа по Model-View для OpenSrc проекта по Skype/SIP/Viber Отправлено: Old от Май 26, 2015, 20:35 К сожалению, у меня сейчас нет возможности поговорит голосом, поэтому напишу свои мысли.
Но в Qt получается, что в модели можно только читать/менять данные в ячейках (data/setData), добавлять/удалять строчки и столбцы (insertRows/removeRows) и... все! Нет, это совсем не так.Вы можете написать любые свои методы, которые будут добавлять одну или несколько строк/столбцов, менять целые строки или области в таблице, удалять хоть строки, хоть столбцы. Главное, что бы модель при таких операциях, правильно информировало вид о том, как изменилась модель, что бы правильно это визуализировать. Для этого есть специальные сигналы, которые отсылаются с помощью специальных методов: beginXXX(), endXXX(). Т.е. делайте любые свои методы со сложной удобной вам обработкой данных, главное правильно информируйте вид. Название: Re: Предметная голосовая беседа по Model-View для OpenSrc проекта по Skype/SIP/Viber Отправлено: vbv от Май 27, 2015, 08:11 Как по мне - то через прокси менять данные в исходной модели не имеет смысла.
Это как в серверах баз данных менять данные через представления (view). Для серверов баз данных справедливы следующие утверждения: 1. Обновляемыми являются только простые представления. 2. Для сложных представлений создаются методы/правила для обновления/вставки/удаления. А при некоторых представлениях исходных данных некоторые функции вообще невозможно выполнить корректно. Таким образом если мы хотим, что бы proxyModel работала с нашей моделью и выполняла наши задачи нужно создавать потомок, например от QAbstractProxyModel или от его потомка и обучить его работать с нашей моделью исходных данных. Это мое мнение, не претендующее на идеальное решение. Сам занимаюсь программированием связанным с базами данных и функционал сортировки/отбора у меня реализованы на сервере (переформируется запрос) и моя модель данных отдает данные элементу отображения уже в том виде в котором надо и элемент отображения, например QTableView показывает его уже в том виде в котором мне нужно. И, да QTableView у меня тоже, уже обучен специальными методами которыми она манипулирует моей моделью без посредников. Название: Re: Предметная голосовая беседа по Model-View для OpenSrc проекта по Skype/SIP/Viber Отправлено: xintrea от Май 27, 2015, 09:32 К сожалению, у меня сейчас нет возможности поговорит голосом, поэтому напишу свои мысли. Мы договорились с одним товарищем из Барнаула пообщаться в воскресенье 31.05.2015. Он очень горит желанием сделать конференцию на гуглоплюсе. Начнем в 9:00 (потому что в Барнауле будет уже обед). Если все получится, можно поучаствовать или просто посмотреть трансляцию. Но мне нужны контакты с вами, если решите - пишите на емайл. Цитировать Но в Qt получается, что в модели можно только читать/менять данные в ячейках (data/setData), добавлять/удалять строчки и столбцы (insertRows/removeRows) и... все! Нет, это совсем не так.Вы можете написать любые свои методы, которые будут добавлять одну или несколько строк/столбцов, менять целые строки или области в таблице, удалять хоть строки, хоть столбцы. Главное, что бы модель при таких операциях, правильно информировало вид о том, как изменилась модель, что бы правильно это визуализировать. Для этого есть специальные сигналы, которые отсылаются с помощью специальных методов: beginXXX(), endXXX(). Т.е. делайте любые свои методы со сложной удобной вам обработкой данных, главное правильно информируйте вид. А теперь пойдем дальше. Нам нужно у вида подменить нашу удобную модель на прокси-модель. Мы создаем прокси-модель, устанавливаем ей соурс-модель через setSourceModel(), устанавливаем эту прокси-модель в вид. И тут обнаруживаем, что прокси-модель не умеет вызывать наши нестандартные методы. Вот в этом у меня и проблема. Ранее вид работал с моделью, используя нестандартные методы. После внедрения прокси-модели, он уже этого сделать не может. Как выходить из положения? Работать одновременно с двумя моделями? Сделать одну для вида, а вторую для удобной работы? А как их синхронизировать? В каких случаях использовать какую? Я уже подозреваю, что в концепции модель-вид, принятой в Qt, не хватает контроллера. Но использование самописного класса контроллера в Qt неоднозначно. Потому что в классическом варианте пользователь взаимодействет с контроллером, а контроллер уже сам дергает модели и выдает пользователю нужные виды. А в Qt пользователь взаимодействует с видом. А куда же пристыковать контроллер? Непонятно. Получается, что вид в Qt выполняет функции контроллера. В общем, встает вопрос архитектуры приложения, который я сам все никак не могу решить. Название: Re: Предметная голосовая беседа по Model-View для OpenSrc проекта по Skype/SIP/Viber Отправлено: xintrea от Май 27, 2015, 09:45 Таким образом если мы хотим, что бы proxyModel работала с нашей моделью и выполняла наши задачи нужно создавать потомок, например от QAbstractProxyModel или от его потомка и обучить его работать с нашей моделью исходных данных. Я пробовал сделать класс proxy-модели через множественное наследование - унаследовался от QSortFilterProxyModel и от моей модели (имеющей в качестве родителя QAbstractTableModel). Это нужно было для того, чтобы у proxy-модели работали нестандартные методы. Но так как моя модель имеет родителя QAbstractTableModel, а тот в свою очередь унаследован от QAbstractItemMode, и QSortFilterProxyModel унаследован от QAbstractProxyModel и следовательно от QAbstractItemMode, то скомпилять такое не смог, ибо непонятно, что делать с одинаковыми стандартными методами. Название: Re: Предметная голосовая беседа по Model-View для OpenSrc проекта по Skype/SIP/Viber Отправлено: Old от Май 27, 2015, 09:50 И тут обнаруживаем, что прокси-модель не умеет вызывать наши нестандартные методы. А для чего ей это уметь?Вы можете вызывать методы рабочей модели, они будут отсылать сигналы, прокси-модель их обрабатывает (так же как view) и будет отсылать аналогичные сигналы дальше для view. Для чего view учить работе с нестандартными методами ваших моделей? View должен только отображать данные, управлять ими должны другие объекты. Название: Re: Предметная голосовая беседа по Model-View для OpenSrc проекта по Skype/SIP/Viber Отправлено: xintrea от Май 27, 2015, 09:56 Для чего view учить работе с нестандартными методами ваших моделей? View должен только отображать данные, управлять ими должны другие объекты. Я не против, об этом я и написал: Цитировать Я уже подозреваю, что в концепции модель-вид, принятой в Qt, не хватает контроллера. Но использование самописного класса контроллера в Qt неоднозначно. Потому что в классическом варианте пользователь взаимодействет с контроллером, а контроллер уже сам дергает модели и выдает пользователю нужные виды. А в Qt пользователь взаимодействует с видом. А куда же пристыковать контроллер? Непонятно. Получается, что вид в Qt выполняет функции контроллера. В общем, встает вопрос архитектуры приложения, который я сам все никак не могу решить. Проблема то в том, что в Qt вид является по-сути контроллером. И как разделить функции вида и контроллера при такой архитектуре - мне непонятно. Название: Re: Предметная голосовая беседа по Model-View для OpenSrc проекта по Skype/SIP/Viber Отправлено: Old от Май 27, 2015, 10:02 Проблема то в том, что в Qt вид является по-сути контроллером. И как разделить функции вида и контроллера при такой архитектуре - мне непонятно. Вовсе нет, вид в Qt, через стандартный интерфейс модели, может немного ей управлять, например, менять сортировку. Но это все настраиваемое поведение и вы всегда можете его переназначить на удобное вам.А дальше вам ничто не мешает создавать свои контроллеры, которые и будут управлять моделями. Название: Re: Предметная голосовая беседа по Model-View для OpenSrc проекта по Skype/SIP/Viber Отправлено: GreatSnake от Май 27, 2015, 10:37 Если proxy модель хочется использовать только для сортировки, то лучше сразу забыть про это.
Ибо больше проблем, чем бонусов. Название: Re: Предметная голосовая беседа по Model-View для OpenSrc проекта по Skype/SIP/Viber Отправлено: xintrea от Май 27, 2015, 11:51 Проблема то в том, что в Qt вид является по-сути контроллером. И как разделить функции вида и контроллера при такой архитектуре - мне непонятно. Вовсе нет, вид в Qt, через стандартный интерфейс модели, может немного ей управлять, например, менять сортировку. Но это все настраиваемое поведение и вы всегда можете его переназначить на удобное вам.А дальше вам ничто не мешает создавать свои контроллеры, которые и будут управлять моделями. В том то и дело, что контроллер создать не проблема. Проблема в том, что в Qt вид взаимодействует с пользователем, и по-сути является контроллером в классической парадигме MVC. Смотрим на рисунок из википедии: (https://upload.wikimedia.org/wikipedia/commons/thumb/f/fd/MVC-Process.png/240px-MVC-Process.png) Видим, что стрелочки от пользователя к виду нет (но есть стрелочка от вида к пользователю). То есть, пользователь не может взаимодействовать с видом, он вид только видит. И по классической парадигме MVC пользователь должен оказывать влиение только на контроллер. А в Qt пользователь взаимодействует с видом. Кликает на элементы, и действия пользователя обрабатывает вид. И это рвет все шаблоны. С этим я и не могу разобраться. Точнее, кое-как разобрался - у меня код контроллера скапливается в виде. Но это же неправильно. Название: Re: Предметная голосовая беседа по Model-View для OpenSrc проекта по Skype/SIP/Viber Отправлено: vbv от Май 27, 2015, 12:18 Я пробовал сделать класс proxy-модели через множественное наследование - унаследовался от QSortFilterProxyModel и от моей модели (имеющей в качестве родителя QAbstractTableModel). Это нужно было для того, чтобы у proxy-модели работали нестандартные методы. Но так как моя модель имеет родителя QAbstractTableModel, а тот в свою очередь унаследован от QAbstractItemMode, и QSortFilterProxyModel унаследован от QAbstractProxyModel и следовательно от QAbstractItemMode, то скомпилять такое не смог, ибо непонятно, что делать с одинаковыми стандартными методами. Сие работать не будет, хотя компильнуть можно! А давайте поставим вопрос по другому: 1. Чего мы хотим от proxyModel? 2. Чего, нестандартного, умеет recordModel? Название: Re: Предметная голосовая беседа по Model-View для OpenSrc проекта по Skype/SIP/Viber Отправлено: Old от Май 27, 2015, 14:20 А в Qt пользователь взаимодействует с видом. Кликает на элементы, и действия пользователя обрабатывает вид. И это рвет все шаблоны. С этим я и не могу разобраться. Точнее, кое-как разобрался - у меня код контроллера скапливается в виде. Но это же неправильно. Конечно не правильно.Пользователь кликает на элементы, вид или QItemSelectionModel посылает сигнал об этих событиях, эти сигналы должен получать и обрабатывать не вид, а тот самый объект контроллера. Название: Re: Предметная голосовая беседа по Model-View для OpenSrc проекта по Skype/SIP/Viber Отправлено: kandrey от Май 28, 2015, 23:33 Знакомые терзания. При всей внешней красоте идеи прокси моделей - их отладка невыносима, особенно корректный маппинг индексов.
Цитировать После внедрения прокси-модели, он уже этого сделать не может. Как выходить из положения? - думаю, надо проксировать все нестандартные методыЦитировать Если proxy модель хочется использовать только для сортировки, то лучше сразу забыть про это. - пришел к такому же выводу. Если честно - я забил на прокси модели, по крайней мере для своих моделей, скорей всего не хватает квалификации для построения таких компонентов. Другое дело, если исходную модель нельзя править - тогда, наверное, другого выхода нет как писать прокси.Ибо больше проблем, чем бонусов Название: Re: Предметная голосовая беседа по Model-View для OpenSrc проекта по Skype/SIP/Viber Отправлено: Akon от Май 29, 2015, 16:58 Цитировать А теперь пойдем дальше. Нам нужно у вида подменить нашу удобную модель на прокси-модель. Мы создаем прокси-модель, устанавливаем ей соурс-модель через setSourceModel(), устанавливаем эту прокси-модель в вид. И тут обнаруживаем, что прокси-модель не умеет вызывать наши нестандартные методы. Родственная душа :)Попробую формализовать задачу, дабы иметь четкое понимание и не распыляться на ненужное. Итак, имеется исходная модель, в которой есть "нестандартный" метод x(). Код: class Model : public QAbstaractItemModel Некий виджет, отображающий данные из модели, принимает на вход (в качестве параметра конструктора) исходную модель и использует "нестандартный" метод x(): Код: class ModelWidget : public QWidget Теперь мы хотим, например, отсортировать или отфильтровать данные с помощью прокси-модели (в общем случае с помощью цепочки прокси-моделей). Но возникает проблема: если подавать прокси-модель по месту исходной модели, то первая не иммет "нестандартного" метода x(). Для решения проблемы я рассматривал 3 варианта: 1. Интерфейс. Все "нестандартного" методы группируются в интерфейс (или интерфейсы). В этом случае наши классы приобретают следующий вид: Код: class Xable Я не остановился на данном варианте, ввиду большого синтаксического оверхеда и создания дополнительного интерфейса. 2. "Раскрутка" прокси-модели до исходной модели. В этом варианте на вход виджета подается QAbstractItemModel. Это, как и в предыдущем случае, может быть либо исходная модель, либо прокси. Код: class ModelWidget : public QWidget Код: /// \file Этот вариант в итоге я и использовал. 3. Выделить аспект проксирования в модели в миксин. Миксин (mix-in) это шаблонный класс, в котором параметр шаблона фигурирует в списке базовых классов. Применительно к прокси-модели это выглядело бы след. образом: Код: template <class BaseT> Код: Model model; // source model with x() "non-standard" function Напросившийся вывод: проблемы нет, если относиться к исходным моделям как к сущностям, обеспечивающим исключительно поддержку видам, т.е. если оставайться в рамках QAbstractItemModel без использования "нестандартных" методов. Все "нестандартные" методы присутствуют в другом соответствующем классе. Модель не предоставляет транзитивную ссылку на этот класс (иначе, уже появляется "нестандартный" метод). Как модель, так и этот класс подаются на вход виджета: Код: class ModelWidget : public QWidget Название: Re: Предметная голосовая беседа по Model-View для OpenSrc проекта по Skype/SIP/Viber Отправлено: Igors от Май 31, 2015, 16:57 Напросившийся вывод: проблемы нет, если относиться к исходным моделям как к сущностям, обеспечивающим исключительно поддержку видам, т.е. если оставайться в рамках QAbstractItemModel без использования "нестандартных" методов. Все "нестандартные" методы присутствуют в другом соответствующем классе. Модель не предоставляет транзитивную ссылку на этот класс (иначе, уже появляется "нестандартный" метод). Как модель, так и этот класс подаются на вход виджета: Ой как "подвели бвзу" :) А может сказать прямо, типа "ото приводите указатель на свой класс" - по существу это все.Со всем этим я знаком весьма поверхностно (не работаю с СУБД - и слава богу). Делал несколько таблиц и один листбокс (правда навороченный). Ну открыл букварь, прочитал, сделал, никаких трудностей не испытал. Вся работа была в стиле (как рисовать хитрый листбокс, где там "раскладушка", давить мышу и.т.п.). К Qt претензий никаких, наоборот. В общем я уже успел забыть все что делал (легко пришло - легко ушло, нормально). В памяти осталась одна деталь, о ней подробнее Почитав букварь я не особо терзался "отсутствием контроллера" (пробой в идеологии?), но быстро понял - общая конструкция (QAbstracItemModel) позволяет делать все, а конкретная реализация (в QTreeWidget для моего листбокса) - "жирная", по существу - для лохов. Прикинул сколько айтемов может иметь мой листбокс. Обычно юзер пополняет литстбоксы сам - практически это до 10 айтемов. Правда есть 2-3 случая (из примерно 50) когда это не так - могут быть тысячи. Но здравый смысл быстро победил - и я задействовал жирную реализацию для лохов. И все бы хорошо если бы не одно "но" Меня вполне устраивает QTreeWidget (и его модель), но вот QTreeWidgetItem у меня свой (перекрыт) - и в нем масса нестандартных методов "x"(y, z) - а вот достучаться к ним напрямую из моего листбокса я не могу, ведь он оперирует с QTreeWidgetItem. Ну пришлось приводить (что в общем не есть хорошо/чисто), и лучше сразу сделать это приведение методом моего класса листбокс. Размышляя об этом я так и не нашел лучшего решения - возможно это принципиальное ограничение наследования. А в общем всегда приятно видеть увлеченных, неравнодушных людей, тему прочитал с удовольствием, жаль что мало таких. Спасибо |