![]() |
|
![]() ![]() ![]() |
|
SABROG |
|
||||||
![]() Hacker ![]() ![]() ![]() ![]() Профиль Группа: Завсегдатай Сообщений: 2481 Регистрация: 18.9.2006 Репутация: 81 Всего: 91 |
Цель: создать что-то типа Property Editor'a для своей программы (т.е. как в любом IDE).
Условия: использовать QTreeView и делегаты. Для каждого свойства в ячейке создавать editor, будь то QLineEdit, QPushButton, QDoubleSpinBox и т.д. и т.п. Многие параметры пересекаются по типам данных, но параметры должны быть уникальными, чтобы я мог точно определить в какую ячейку базы данных его записывать. Далее есть структура вида: struct mystruct { type1 par1; type2 par2; type3 par3; type3 par4; type4 par5; } Типы (typeN) могут быть любыми, QString, QSqlDatabase, свои указатели, ссылки, что угодно. По сути mystruct - вид singleton'a, создается один раз в конструкторе головного окна, указатель на него доступен из любой точки основного класса. Хочу чтобы все это работало так: я считываю из базы данных нужные поля с параметрами и присваиваю значения par1...parN. Потом заполняю QStandardItemModel для QTreeView. При клике мышкой на любую ячейку создается Editor на основе присвоенного параметра (типо-независимо, но параметро зависимо), я меняю что-то в этом Editore, срабатывает метод делегата для коммита изминений, в методе я опять же определяю какому параметру принадлежит index и делаю Update в базе данных нужного столбца. Далее я хочу, чтобы всё содержимое/данные в QStandardItemModel были привязаны к данным в структуре mystruct, таким образом, чтобы при изминении через Editor ячейки, я мог потом получить новые значения по ссылки типа mystruct->par3, и в обратку, если я меняю параметр mystruct->par5, то при создании Editor'a в ячейке было это новое значение. Например par1 имеет тип QString и относится к Qt::DisplayRole, а par2 по сути является данными для Qt::UserRole. Т.е. одна ячейка и 2 параметра в ней, один отвечает за надпись в ячейки, другой за реальное содержимое, будь то ключ или указатель на что-то. Сейчас вся эта система работает на основе qRegisterMetaType, например регистрируется параметр ИМЯ и это выглядит так:
В QStandardItem присваивается таким макаром:
При этом name копируется в конструкторе, а оригинал уничтожается. Естественно при таком раскладе повлиять после этого на данные в name не представляется возможным. В делегате принадлженость данных к конкретному параметру определяется так:
Я считаю такую систему слишком сложной. Я не хочу, чтобы данные копировались в конструкторе, хочу всегда иметь к ним доступ по указателю и чтобы они в ответ менялись и на контролах. Если и использовать метатипы, то только для хранения ссылок на параметры в структуре mystruct. Уже мозг вскипает, не знаю за что ухватиться. Как вариант думал о QHashе где каждому ключу присваивать ссылку на параметр, а ключи держать в Qt::UserRole. |
||||||
|
|||||||
JackYF |
|
|||
![]() полуавантюрист ![]() ![]() ![]() ![]() Профиль Группа: Участник Сообщений: 5814 Регистрация: 28.8.2004 Где: страна тысячи озё р Репутация: 7 Всего: 162 |
Гм... посмотри на всякий случай http://www.qt-apps.org/content/show.php/Va...r?content=50717
|
|||
|
||||
SABROG |
|
|||
![]() Hacker ![]() ![]() ![]() ![]() Профиль Группа: Завсегдатай Сообщений: 2481 Регистрация: 18.9.2006 Репутация: 81 Всего: 91 |
О нем я знаю, оно мне не подходит, пробывал как-то уже. |
|||
|
||||
Любитель |
|
|||
Программист-романтик ![]() ![]() ![]() ![]() Профиль Группа: Комодератор Сообщений: 3645 Регистрация: 21.5.2005 Где: Воронеж Репутация: 16 Всего: 92 |
||||
|
||||
SABROG |
|
|||
![]() Hacker ![]() ![]() ![]() ![]() Профиль Группа: Завсегдатай Сообщений: 2481 Регистрация: 18.9.2006 Репутация: 81 Всего: 91 |
То что я написал это похоже на обычный Simple Tree Model Example из Qt. Т.е. похоже придется писать свою собственную модель. Жаль при этом теряются вкусности реализованные в QStandardItemModel. Попробую объяснить на простом примере. Есть стандартный QLineEdit, чтобы в него впихнуть текст надо вызвать его метод setText(const QString &). Т.е. передаем ссылку. Для теста создал QString через new и сделал указатель глобальным, передал ссылку находящуюся в указателе в setText. Попробывал меняя строку по указателю на QString изменить текст в QLineEdit - ничего не вышло. Из чего можно сделать вывод, что передавая любые данные в Qtшные классы они просто копируются, после чего указатели и объекты можно смело килять. А это для меня не удобно сейчас, т.к. я хочу построить дерево на основе ссылок/указателей, где меняя любой элемент в дереве менялись бы данные в контролах. Я думал про QDataWidgetMapper, но он те же яйца, вид сбоку, т.к. работа идет через модели, а там опять QVariant'ы с их извращенческими типами данных, которые надо конвертить по 100 раз на дню, чтобы прочитать или записать. |
|||
|
||||
nickless |
|
|||
![]() Гентозавр ![]() ![]() ![]() ![]() Профиль Группа: Участник Клуба Сообщений: 2976 Регистрация: 29.8.2005 Где: Germany Репутация: 13 Всего: 181 |
ИМХО даже если это заработает (а если текст в контролле будет изменяться по указателю на него, откуда контролл может знать что данные изменились и надо бы себя перерисовать?), то будет очень много геморроя с отладкой и неожиданными падениями. Может просто сделать на сигналах/слотах? Т.е. не изобретать велосипед, а сделать нормальный паттерн MVD. В Qt это делать очень удобно, дерево и контроллы это views, модель хранит что надо, при создании контроллов, коннектим их к модели, при изменении данных в модели они автоматически обновятся... красота ![]() Добавлено через 2 минуты и 2 секунды А чтобы меньше конвертировать QVariant-ы можно например просто использовать стандартные Qt-шные типы и стандартные слоты. ![]() -------------------- ![]() Real men don't use backups, they post their stuff on a public ftp server and let the rest of the world make copies - Linus Torvalds |
|||
|
||||
SABROG |
|
|||
![]() Hacker ![]() ![]() ![]() ![]() Профиль Группа: Завсегдатай Сообщений: 2481 Регистрация: 18.9.2006 Репутация: 81 Всего: 91 |
У меня сейчас как-раз все на модели и сделано. Но сейчас ситуация встала ребром, если раньше я довольствовался тем, что считываю данные из 3х таблиц и заполняю QStandardItemModel. То теперь я считываю уже не 3 связанных таблицы, а 20. Сделано, чтобы программа шустрее работала, по сути кеширование в памяти, около 15 мегабайт данных. Таким образом все 20 реляционных таблиц были связаны указателями и построилось дерево, по которому я могу бегать без PRIMARY KEY'сов. В это дерево попали и те 3 таблицы для которых строилась QStandardItemModel. И теперь данные для этих трех таблиц дублируются. Потому я и хочу сделать визуальный контрол зависимый от дерева.
Сейчас у меня в голове крутится такая мысль: - добавляю к каждому элементу дерева параметр parent, чтобы обеспечить обратное сканирование - определяю enum с типами параметров, например enum {par1, par2, par3} (это только для тех 3х таблиц) - в QStandardItem data (Qt::UserRole) пихаю QPair<unsinged char, void *>, где uchar это тип параметра из enum'a, а указатель указывает на элемент дерева. Таким образом в коде, где надо создавать editor и т.п. я смогу по типу параметра (enum'у) определить какой из параметров редактируется и какой тип структуры предполагается, а по указателю смогу достучаться до данных находящихся не в модели, а в дереве. При редактировании данных в editor'e изминенные данные перенести по указателю в нужное место дерева. А параметр parent даст мне возможность узнать кто владеет этим параметром, чтобы соотнести изменения в базе данных по ключу родителя. Но это не окончательная мысль, просто как черновик, чтобы понять чего я хочу. |
|||
|
||||
nickless |
|
|||
![]() Гентозавр ![]() ![]() ![]() ![]() Профиль Группа: Участник Клуба Сообщений: 2976 Регистрация: 29.8.2005 Где: Germany Репутация: 13 Всего: 181 |
Не совсем понял где дублируются, в QStandardItemModel и твоём дереве? Перечитал еще раз что ты написал, но так и не понял, зачем ты хочешь обойти доступ через модель и брать данные напрямую от дерева? Вот зачем едиторуз знать что у тебя там какое-то дерево, знать ссылки на внутренние данные, знать как их изменять и прочее? Едитор сделал своё дело - передал данные модели, а она пусть с ними сама разбирается... Вообще как я понял дерево - это просто кэш данных из таблиц, ну так напиши свою модель (или несколько, не знаю как данные сгруппированы), которая кэширует таблицы при доступе (возможно с прослойкой для упрощения самой модели), а наружу ведёт себя как обычная модель и соответственно легко сочетается с Qt-шными *View. Если все действия над данными будут проходить только централизовано через модель, будет проще отследить за изменениями и соответственно обновлять контролы. Т.е. что-то вроде этого
А сейчас как? Есть база данных, контроллы, TreeView и модель к нему, и все они тесно и хаотично связаны между собой через "дерево/кэш", или я не правильно тебя понял? -------------------- ![]() Real men don't use backups, they post their stuff on a public ftp server and let the rest of the world make copies - Linus Torvalds |
|||
|
||||
SABROG |
|
|||
![]() Hacker ![]() ![]() ![]() ![]() Профиль Группа: Завсегдатай Сообщений: 2481 Регистрация: 18.9.2006 Репутация: 81 Всего: 91 |
Не хаотично, упорядоченно
![]() Вот так я сейчас получаю корневую структуру выбранного итема:
main - указатель главной формы (на базе QMainWindow) переданный в класс делегат tvtModel - глобальный член класса основной формы, указатель на QStandardItemModel для QTreeView tvTemplate - указатель на сам QTreeView sTRoot - метатип, структура с данынми Это часть кода хоть и принадлежит классу делегату, но в этот метод не передается QIndexModel, т.к. по сути вместо эдитора для одной из ячеек создается обычный QPushButton где триггер коннектится к этому слоту. |
|||
|
||||
SABROG |
|
||||||
![]() Hacker ![]() ![]() ![]() ![]() Профиль Группа: Завсегдатай Сообщений: 2481 Регистрация: 18.9.2006 Репутация: 81 Всего: 91 |
Объясните мне - нерадивому, почему такое вот прокатывает:
а вот такое уже нет:
error: no matching function for call to `qVariantFromValue(main(int, char**)::A*&)' ![]() ----------------------------------------- Все, разобрался, злая штука получается, главное работает ![]()
В общем все идет к тому, что мне все-таки удастся запихнуть в QStandardItem указатель на любой класс, главное, чтобы он был на базе какого-нибудь одного класса. И идентифицировать его через RTTI с обратным преобразованием базового класса к потомку через dynamic_cast. По сути получится аналог метатипов своими руками, только на этот раз хозяином данных будет не модель, а я. ![]() Это сообщение отредактировал(а) SABROG - 13.3.2008, 13:30 |
||||||
|
|||||||
Любитель |
|
||||||
Программист-романтик ![]() ![]() ![]() ![]() Профиль Группа: Комодератор Сообщений: 3645 Регистрация: 21.5.2005 Где: Воронеж Репутация: 16 Всего: 92 |
Само собой. плохо, если было б иначе ![]()
Ну дык обычный дата-биндинг, если я правильно понял. С учётом имеющихся в куте вещей использование её моделей (точнее своих, наследованных от кутешных) - идеальное решение. А там уж или классы представлений или названный тобою QDataWidgetMapper.
Нормальные там типы ![]() ![]() Что не есть гуд... Или фтопку MVC?.. Я не пойму, почему нельзя тупо создать свою модельку (наследовав от чего надо). Зачем столь жёсткое связывнание контрола с данными? |
||||||
|
|||||||
![]() ![]() ![]() |
Правила форума "С/С++: Кроссплатформенное программирование, QT/Gtk+/wxWidgets" | |
|
Если Вам понравилась атмосфера форума, заходите к нам чаще! С уважением, JackYF, Любитель. |
1 Пользователей читают эту тему (1 Гостей и 0 Скрытых Пользователей) | |
0 Пользователей: | |
« Предыдущая тема | С/С++: Кроссплатформенное программирование, Qt/Gtk+/wxWidgets | Следующая тема » |
|
По вопросам размещения рекламы пишите на vladimir(sobaka)vingrad.ru
Отказ от ответственности Powered by Invision Power Board(R) 1.3 © 2003 IPS, Inc. |