Поиск:

Ответ в темуСоздание новой темы Создание опроса
> [QT]QStandardItem, Qt::UserRole, qRegisterMetaType, создать PropertyEditor 
:(
    Опции темы
SABROG
Дата 10.3.2008, 15:10 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


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, например регистрируется параметр ИМЯ и это выглядит так:

Код

struct sName
{
    QString name;
};
Q_DECLARE_METATYPE(sName)
...
qRegisterMetaType<sName>("sName");


В QStandardItem присваивается таким макаром:

Код

sName name;
name.name = "имя";
rootItem->setChild(0, 1, (new QStandardItem)->setData(QVariant(qVariantFromValue(name)), Qt::UserRole));


При этом name копируется в конструкторе, а оригинал уничтожается. Естественно при таком раскладе повлиять после этого на данные в name не представляется возможным.

В делегате принадлженость данных к конкретному параметру определяется так:

Код

void ttDelegate::setEditorData(QWidget *editor, const QModelIndex &index) const
{
        QVariant originalValue = index.data(Qt::UserRole);
if (originalValue.canConvert<sName>())
        {
            if (QComboBox *combo = qobject_cast<QComboBox *>(editor))
             {
             sName name = originalValue.value<sName>();
             combo->addItem(QLatin1String("Name1"), QVariant(1));
             combo->addItem(QLatin1String("Name2"), QVariant(2));

             int ind = combo->findText(name.name);
                 if (ind) combo->setCurrentIndex(ind);
             }
        }
        else
        {
            QItemDelegate::setEditorData(editor,index);
        }


Я считаю такую систему слишком сложной. Я не хочу, чтобы данные копировались в конструкторе, хочу всегда иметь к ним доступ по указателю и чтобы они в ответ менялись и на контролах. Если и использовать метатипы, то только для хранения ссылок на параметры в структуре mystruct. Уже мозг вскипает, не знаю за что ухватиться. Как вариант думал о QHashе где каждому ключу присваивать ссылку на параметр, а ключи держать в Qt::UserRole.


--------------------
Национальная группа Russian Federation на QtCentre.
PM MAIL   Вверх
JackYF
Дата 10.3.2008, 19:33 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


полуавантюрист
****


Профиль
Группа: Участник
Сообщений: 5814
Регистрация: 28.8.2004
Где: страна тысячи озё р

Репутация: 7
Всего: 162



Гм... посмотри на всякий случай http://www.qt-apps.org/content/show.php/Va...r?content=50717


--------------------
Пожаловаться на меня как модератора можно здесь.
PM MAIL Jabber   Вверх
SABROG
Дата 10.3.2008, 19:38 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Hacker
****


Профиль
Группа: Завсегдатай
Сообщений: 2481
Регистрация: 18.9.2006

Репутация: 81
Всего: 91



Цитата(JackYF @ 10.3.2008,  19:33)
Гм... посмотри на всякий случай http://www.qt-apps.org/content/show.php/Va...r?content=50717

О нем я знаю, оно мне не подходит, пробывал как-то уже.


--------------------
Национальная группа Russian Federation на QtCentre.
PM MAIL   Вверх
Любитель
Дата 11.3.2008, 18:37 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Программист-романтик
****


Профиль
Группа: Комодератор
Сообщений: 3645
Регистрация: 21.5.2005
Где: Воронеж

Репутация: 16
Всего: 92



Цитата(SABROG @  10.3.2008,  15:10 Найти цитируемый пост)
Цель: создать что-то типа Property Editor'a для своей программы (т.е. как в любом IDE).

Взять из Qt Designer-а. Он там отдельным классом, ready to use.

А то, что ты опписал - чо-т слишком сложно. Не осилил smile


--------------------
PM MAIL ICQ Skype   Вверх
SABROG
Дата 11.3.2008, 18:53 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Hacker
****


Профиль
Группа: Завсегдатай
Сообщений: 2481
Регистрация: 18.9.2006

Репутация: 81
Всего: 91



Цитата(Любитель @ 11.3.2008,  18:37)
Цитата(SABROG @  10.3.2008,  15:10 Найти цитируемый пост)
Цель: создать что-то типа Property Editor'a для своей программы (т.е. как в любом IDE).

Взять из Qt Designer-а. Он там отдельным классом, ready to use.

А то, что ты опписал - чо-т слишком сложно. Не осилил smile

То что я написал это похоже на обычный Simple Tree Model Example из Qt. Т.е. похоже придется писать свою собственную модель. Жаль при этом теряются вкусности реализованные в QStandardItemModel.

Попробую объяснить на простом примере. Есть стандартный QLineEdit, чтобы в него впихнуть текст надо вызвать его метод setText(const QString &). Т.е. передаем ссылку. Для теста создал QString через new и сделал указатель глобальным, передал ссылку находящуюся в указателе в setText. Попробывал меняя строку по указателю на QString изменить текст в QLineEdit - ничего не вышло. Из чего можно сделать вывод, что передавая любые данные в Qtшные классы они просто копируются, после чего указатели и объекты можно смело килять. А это для меня не удобно сейчас, т.к. я хочу построить дерево на основе ссылок/указателей, где меняя любой элемент в дереве менялись бы данные в контролах. Я думал про QDataWidgetMapper, но он те же яйца, вид сбоку, т.к. работа идет через модели, а там опять QVariant'ы с их извращенческими типами данных, которые надо конвертить по 100 раз на дню, чтобы прочитать или записать.


--------------------
Национальная группа Russian Federation на QtCentre.
PM MAIL   Вверх
nickless
Дата 11.3.2008, 19:37 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Гентозавр
****


Профиль
Группа: Участник Клуба
Сообщений: 2976
Регистрация: 29.8.2005
Где: Germany

Репутация: 13
Всего: 181



Цитата(SABROG @  11.3.2008,  16:53 Найти цитируемый пост)
я хочу построить дерево на основе ссылок/указателей, где меняя любой элемент в дереве менялись бы данные в контролах

ИМХО даже если это заработает (а если текст в контролле будет изменяться по указателю на него, откуда контролл может знать что данные изменились и надо бы себя перерисовать?), то будет очень много геморроя с отладкой и неожиданными падениями.

Может просто сделать на сигналах/слотах? Т.е. не изобретать велосипед, а сделать нормальный паттерн MVD. В Qt это делать очень удобно, дерево и контроллы это views, модель хранит что надо, при создании контроллов, коннектим их к модели, при изменении данных в модели они автоматически обновятся... красота smile

Добавлено через 2 минуты и 2 секунды
А чтобы меньше конвертировать QVariant-ы можно например просто использовать стандартные Qt-шные типы и стандартные слоты. smile 


--------------------
user posted image

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
PM MAIL   Вверх
SABROG
Дата 11.3.2008, 20:56 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


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 даст мне возможность узнать кто владеет этим параметром, чтобы соотнести изменения в базе данных по ключу родителя. Но это не окончательная мысль, просто как черновик, чтобы понять чего я хочу.


--------------------
Национальная группа Russian Federation на QtCentre.
PM MAIL   Вверх
nickless
Дата 11.3.2008, 22:42 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Гентозавр
****


Профиль
Группа: Участник Клуба
Сообщений: 2976
Регистрация: 29.8.2005
Где: Germany

Репутация: 13
Всего: 181



Цитата(SABROG @  11.3.2008,  18:56 Найти цитируемый пост)
И теперь данные для этих трех таблиц дублируются

Не совсем понял где дублируются, в QStandardItemModel и твоём дереве?

Перечитал еще раз что ты написал, но так и не понял, зачем ты хочешь обойти доступ через модель и брать данные напрямую от дерева? Вот зачем едиторуз знать что у тебя там какое-то дерево, знать ссылки на внутренние данные, знать как их изменять и прочее? Едитор сделал своё дело - передал данные модели, а она пусть с ними сама разбирается...

Вообще как я понял дерево - это просто кэш данных из таблиц, ну так напиши свою модель (или несколько, не знаю как данные сгруппированы), которая кэширует таблицы при доступе (возможно с прослойкой для упрощения самой модели), а наружу ведёт себя как обычная модель и соответственно легко сочетается с Qt-шными *View. Если все действия над данными будут проходить только централизовано через модель, будет проще отследить за изменениями и соответственно обновлять контролы.
Т.е. что-то вроде этого
Код

БД <--> Классы для более осмысленного доступа к БД <--> Кэш данных <--> Модель(и) <--> Всякие View вроде дерева, контроллов итд.
                                                                                  <--> Делегаты


А сейчас как? Есть база данных, контроллы, TreeView  и модель к нему, и все они тесно и хаотично связаны между собой через "дерево/кэш", или я не правильно тебя понял?


--------------------
user posted image

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
PM MAIL   Вверх
SABROG
Дата 11.3.2008, 23:25 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Hacker
****


Профиль
Группа: Завсегдатай
Сообщений: 2481
Регистрация: 18.9.2006

Репутация: 81
Всего: 91



Не хаотично, упорядоченно smile Зарегистрировав свои метатипы в делегате я точно определяю что за параметр кликнулся и создаю под него свой собственный эдитор. Все эти метатипы тупо скопированы моделью куда-то к себе в закрома, поэтому чтобы их изменить или даже прочитать мне приходится пробегаться по всем итемам в QStandardItemModel, чтобы добраться. Изминения в базе данных сейчас вносятся классом делегатом, когда от эдитора ячейки приходит коммит, типа "баста можно закрывать persistentEditor, я все поменял можно меня удалять, а введенные данные пихать в модель и в базу".

Вот так я сейчас получаю корневую структуру выбранного итема:

Код

QStandardItem *root = main->tvtModel->itemFromIndex(main->tvTemplate->currentIndex())->parent();
    sTRoot tRoot = root->data(Qt::UserRole).value<sTRoot>();


main - указатель главной формы (на базе QMainWindow) переданный в класс делегат
tvtModel - глобальный член класса основной формы, указатель на QStandardItemModel для QTreeView
tvTemplate - указатель на сам QTreeView
sTRoot - метатип, структура с данынми

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


--------------------
Национальная группа Russian Federation на QtCentre.
PM MAIL   Вверх
SABROG
Дата 13.3.2008, 13:08 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Hacker
****


Профиль
Группа: Завсегдатай
Сообщений: 2481
Регистрация: 18.9.2006

Репутация: 81
Всего: 91



Объясните мне - нерадивому, почему такое вот прокатывает:

Код

QObject *oo = new QObject;
    QVariant data = qVariantFromValue(oo);


а вот такое уже нет:

Код

    class sabBase
    {
    public:
        virtual ~sabBase(){};
    };
    class A: public sabBase
    {
    public:
        QString name;
    };
A *tst = new A;
QVariant data = qVariantFromValue(tst);

error: no matching function for call to `qVariantFromValue(main(int, char**)::A*&)'

 smile 
-----------------------------------------
Все, разобрался, злая штука получается, главное работает  smile 
Код

    QVariant data = qVariantFromValue((void *)tst);
    sabBase *pvar = (sabBase *) data.value<void *>();


В общем все идет к тому, что мне все-таки удастся запихнуть в QStandardItem указатель на любой класс,  главное, чтобы он был на базе какого-нибудь одного класса. И идентифицировать его через RTTI с обратным преобразованием базового класса к потомку через dynamic_cast. По сути получится аналог метатипов своими руками, только на этот раз хозяином данных будет не модель, а я.  smile 

Это сообщение отредактировал(а) SABROG - 13.3.2008, 13:30


--------------------
Национальная группа Russian Federation на QtCentre.
PM MAIL   Вверх
Любитель
Дата 16.3.2008, 12:19 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Программист-романтик
****


Профиль
Группа: Комодератор
Сообщений: 3645
Регистрация: 21.5.2005
Где: Воронеж

Репутация: 16
Всего: 92



Цитата(SABROG @  11.3.2008,  18:53 Найти цитируемый пост)
Из чего можно сделать вывод, что передавая любые данные в Qtшные классы они просто копируются, после чего указатели и объекты можно смело килять

Само собой. плохо, если было б иначе smile

Цитата(SABROG @  11.3.2008,  18:53 Найти цитируемый пост)
А это для меня не удобно сейчас, т.к. я хочу построить дерево на основе ссылок/указателей, где меняя любой элемент в дереве менялись бы данные в контролах.

Ну дык обычный дата-биндинг, если я правильно понял. С учётом имеющихся в куте вещей использование её моделей (точнее своих, наследованных от кутешных) - идеальное решение. А там уж или классы представлений или названный тобою QDataWidgetMapper.

Цитата(SABROG @  11.3.2008,  18:53 Найти цитируемый пост)
а там опять QVariant'ы с их извращенческими типами данных, которые надо конвертить по 100 раз на дню, чтобы прочитать или записать.

Нормальные там типы smile Регь свои, если не хватает smile

Цитата(SABROG @  11.3.2008,  20:56 Найти цитируемый пост)
Потому я и хочу сделать визуальный контрол зависимый от дерева.

Что не есть гуд... Или фтопку MVC?..

Я не пойму, почему нельзя тупо создать свою модельку (наследовав от чего надо). Зачем столь жёсткое связывнание контрола с данными?



--------------------
PM MAIL ICQ Skype   Вверх
  
Ответ в темуСоздание новой темы Создание опроса
Правила форума "С/С++: Кроссплатформенное программирование, QT/Gtk+/wxWidgets"
JackYF
Любитель
  • В заголовке темы в квадратных скобках обозначьте используемую вами библиотеку, например: [QT],[GTK],[wx].
  • Если вопрос актуален только для некоторой версии библиотеки, либо, если вы пользуетесь не самой последней версией, укажите это. Например: [QT4], [GTK2].
  • Все начинающие изучать Qt - не забудьте зайти сюда.
  • Проставьте несколько ключевых слов темы, чтобы её можно было легче найти.
  • В вопросе укажите полную версию версию библиотеки, а также все дополнительные используемые программные пакеты.
  • Не забывайте пользоваться кнопкой "Код".
  • Телепатов на форуме нет! Задавайте чёткий, конкретный и полный вопрос. Указывайте полностью ошибки компилятора и компоновщика.
  • Новое сообщение должно иметь прямое отношение к тематике этого раздела. Флуд, флейм, оффтопик запрещены.
  • Категорически запрещается обсуждение вареза, "кряков", взлома программ и т.д.

Если Вам понравилась атмосфера форума, заходите к нам чаще! С уважением, JackYF, Любитель.

 
0 Пользователей читают эту тему (0 Гостей и 0 Скрытых Пользователей)
0 Пользователей:
« Предыдущая тема | С/С++: Кроссплатформенное программирование, Qt/Gtk+/wxWidgets | Следующая тема »


 




[ Время генерации скрипта: 0.1127 ]   [ Использовано запросов: 22 ]   [ GZIP включён ]


Реклама на сайте     Информационное спонсорство

 
По вопросам размещения рекламы пишите на vladimir(sobaka)vingrad.ru
Отказ от ответственности     Powered by Invision Power Board(R) 1.3 © 2003  IPS, Inc.