Russian Qt Forum

Qt => Базы данных => Тема начата: crocus от Май 27, 2008, 05:25



Название: QTreeView и база данных
Отправлено: crocus от Май 27, 2008, 05:25
Перечитал все, что в гугеле нарыл, них..ра не врублюсь!
Обычная табличка -- ID, parent_ID, level, нужно представить данные в виде дерева.
Не догоняю главного -- что нужно скормить QStandartItemModel (каким должен быть запрос), чтобы начать строить tree.


Название: Re: QTreeView и база данных
Отправлено: lit-uriy от Май 27, 2008, 08:28
Если у тебя Представление должно отображать данные из БД то QStandartItemModel не лучший выбор, лучше взять QSqlQueryModel, но по умолчанию она только для чтения, если еще и писать в БД нужно, то прийдется от нее наследника сделать.


Название: Re: QTreeView и база данных
Отправлено: ритт от Май 27, 2008, 08:44
Код:
	QString sSql = QString("SELECT id, name FROM elements WHERE parent_id IS NULL OR parent_id=0 ORDER BY name ASC");
QSqlQuery parentsQuery;
if(!parentsQuery.exec(sSql))
return;

while(parentsQuery.next())
{
int parentId = parentsQuery.value(0).toInt();
QString parentName = parentsQuery.value(1).toString();

QTreeWidgetItem* parentItem = new QTreeWidgetItem(someTreeWidget, QStringList(parentName));
parentItem->setData(0, Qt::UserRole + 1, parentId);
someTreeWidget->addTopLevelItem(parentItem); // вероятно, можно удалить, т.к. в теории QTreeWidgetItem(someTreeWidget, ...) сделает ноду топовой
{
sSql = QString("SELECT id, name FROM elements WHERE parent_id=%1 ORDER BY name ASC").arg(parentId);
QSqlQuery childrenQuery;
if(childrenQuery.exec(sSql))
{
while(childrenQuery.next())
{
int childId = childrenQuery.value(0).toInt();
QString childName = childrenQuery.value(1).toString();

QTreeWidgetItem* childItem = new QTreeWidgetItem(parentItem, QStringList(childName));
childItem->setData(0, Qt::UserRole + 1, childId);
}
}
}
}
т.к. данных у тебя предполагается много, лучше запросы заменить на кверимодель

это, соответственно, для таблички вида
Цитировать
CREATE TABLE  `elements` (
  `id` int(11) NOT NULL auto_increment,
  `parent_id` int(11) NOT NULL default '0',
  `name` varchar(255) NOT NULL,
  PRIMARY KEY  (`ID`),
  KEY `ix_element_1` (`parent_id`),
);

но я ещё раз советую разбить таблицу на две: ид=>данные и ид=>родитель...а код выше использовать как базовый пример для построения сложной модели )


Название: Re: QTreeView и база данных
Отправлено: Alex03 от Май 27, 2008, 11:18
..........
но я ещё раз советую разбить таблицу на две: ид=>данные и ид=>родитель...а код выше использовать как базовый пример для построения сложной модели )
Константин в посте crocus-а не было ни слова про мастер-деталь (или 2-х уровневость). А в дереве может быть много уровней - табличек не напасёшься...
Кстати в Вашем примере запросы по всей видимости выполняются в разных транзакциях, что не есть гут.

crocus. Если данных не много и надо их все выгрести на клиента, то можно одним циклом на подобие того что привёл Константин.


Название: Re: QTreeView и база данных
Отправлено: pastor от Май 27, 2008, 12:16
Подобные темы уже были. Юзаем поиск.

http://prog.org.ru/forum/index.php/topic,4659.0.html


Название: Re: QTreeView и база данных
Отправлено: ритт от Май 27, 2008, 12:40
> в посте crocus-а не было ни слова про 2-х уровневость...
Алекс03, я знаю о чём говорю


Название: Re: QTreeView и база данных
Отправлено: ритт от Май 27, 2008, 12:44
> А в дереве может быть много уровней - табличек не напасёшься...
хватит двух


Название: Re: QTreeView и база данных
Отправлено: Alex03 от Май 27, 2008, 14:04
> А в дереве может быть много уровней - табличек не напасёшься...
хватит двух
С тем же успехом можно сказать что хватит одной таблицы. :)


Название: Re: QTreeView и база данных
Отправлено: crocus от Май 27, 2008, 16:01
Всем спасибо, разбираюсь..
Поиск рулит. Видимо глаз замылился.


Название: Re: QTreeView и база данных
Отправлено: Вячеслав от Май 27, 2008, 18:04
но я ещё раз советую разбить таблицу на две: ид=>данные и ид=>родитель...а код выше использовать как базовый пример для построения сложной модели )

а можно pro-аргументы за такое чудо ?
contra - 1) лишние индексы (и pk и fk)
2) лишние join'ы при выборке данных
3) в некоторых случаях много _мелких_ записей может серьезно замедлить сервер (mysql и fb меньше  слоник)
Ы ?


Название: Re: QTreeView и база данных
Отправлено: ритт от Май 27, 2008, 21:28
> mysql и fb меньше  слоник
ну ты и выражаешься :) поди-разбери теперь что это должно означать

крокусу нужна категоризация элементов с родительско-дочерней зависимостью
сейчас у него всё в одной таблице и строки при необходимости дублируются, если родителей/детей больше одного


Название: Re: QTreeView и база данных
Отправлено: White Owl от Май 27, 2008, 23:11
крокусу нужна категоризация элементов с родительско-дочерней зависимостью
сейчас у него всё в одной таблице и строки при необходимости дублируются, если родителей/детей больше одного
А он вообще-то не говорил что родителей может быть больше одного. Для дерева с одним родителем вполне хватает одной таблицы, для множественных родителей - двух таблиц. Количество детей всегда подразумевается больше одного.


Название: Re: QTreeView и база данных
Отправлено: Sergeich от Май 28, 2008, 01:25
 Если родителей может быть больше одного, то это уже не дерево, а граф  ;D И как его отображать вообще хер поймешь :D


Название: Re: QTreeView и база данных
Отправлено: Вячеслав от Май 28, 2008, 07:59
> mysql и fb меньше  слоник
ну ты и выражаешься :) поди-разбери теперь что это должно означать

крокусу нужна категоризация элементов с родительско-дочерней зависимостью
сейчас у него всё в одной таблице и строки при необходимости дублируются, если родителей/детей больше одного
Попиши акты после разборок со смежниками на тему кто дурак и что теперь делать - еще не так будешь выражаться ;)
Имелось ввиду (сам наблюдал) что птиц (и intrbase) и mySql при 17-18млн очень мелких записей - (там было 3 поля дата,код датчика,значение) начинали дико тормозимть при выборке по дате.... Для птица это в теории можно было бы объясниить сборкой мусора - но  mySql не версионник , так-что непонятно .... да, птиц был 2.0x какой-то 2.1 тогда еще небыло .... народ попытался уползти на слонника(postgress) но там грабли начались с 50млн с падением в кору(вроде уже пофикисли ,но опять-таки щаз не смотрели ж) Теперь маленькая версия этой проги живет на Линтере\Sybase ASA большая  на "кластерном дятле" (Оракле)......
А для дерева (не графа) для баз этож вроде классика id,parent_id,(данные )+ => строим отношение один-ко многим (один родитель много детей) ......


Название: Re: QTreeView и база данных
Отправлено: Tonal от Июнь 05, 2008, 22:08
2 Вячеслав
Можешь привести структуру таблички, пример данных и тормозящие запросы для птица?
Или ссылку на обсуждение этого момента?
Можно в личку, чтоб не захламлять форум.


Название: Re: QTreeView и база данных
Отправлено: crocus от Июнь 12, 2008, 12:06
Чтобы не создавать новую ветку по TreeView.
Вопрос в следующем: если в treeview выставить QAbstractItemView::SelectionMode в MultiSelection, получаем как на скрине ниже
мне кажется что было бы логично при селекте какого-либо дочернего итема, с родительского итема селект автоматически снимался - например в данном случае, если мы будем осуществлять запрос к БД, то получим не только искомое (дочернюю ветвь- Фолиант5), а полностью, включая родительскую ветвь - Фолиант. Конечно, можно руками деселектить родителя, но полагаю для рядового пользователя это будет непосильной задачей :). К тому же при doubleclick по итему (чтобы раскрыть ветвь) происходит и выделение итема. Есть конечно вариант перехвата QEvent::MouseButtonDblClick и блокировки селекта, но это как-то не на поверхности.
В общем сталкивался ли кто с подобным  вопросом и существуют ли простые методы решения.


Название: Re: QTreeView и база данных
Отправлено: Sergey B. от Июнь 13, 2008, 09:58
Вот так работает...
Название столбцов и таблиц - изменены, но структура сохранена!


Код:
void MyDialog::BuildTree(){

QSqlQuery cities, districts;
bool ok=cities.exec("SELECT cityname FROM cities ORDER BY cityname;");
if (!ok) {
QMessageBox::warning(this, tr("SuperProga"), cities.lastError().text());
return;
}

model=new QStandardItemModel(this);
QStandardItem *parentItem = model->invisibleRootItem();

while(cities.next()){
QStandardItem *item = new QStandardItem(QString("%0").arg(cities.value(0).toString()));
parentItem->appendRow(item);
   
  districts.prepare("SELECT disname FROM districts WHERE CityID=(SELECT ID FROM cities WHERE cityname LIKE :city) ORDER BY disname;");
  districts.bindValue(":city", cities.value(0).toString());
  bool disok=districts.exec();
  if (!disok) {
  QMessageBox::warning(this, tr("SuperProga "), districts.lastError().text());
return;
}
  while(districts.next()){
QStandardItem *itemchild = new QStandardItem(QString("%0").arg(districts.value(0).toString()));
item->appendRow(itemchild);

  }
 


}
model->setHeaderData(0, Qt::Horizontal, tr("Cities"));
treeView->setModel(model);
treeView->setAlternatingRowColors(true);
treeView->setEditTriggers(QAbstractItemView::NoEditTriggers);
}

Это для двух уровневой структуры. Если надо больше, то после:
Код:
parentItem->appendRow(item);

пишешь:
Код:
parentItem = item;
и т.д.
В Assistant посмотри по QStandardItemModel, там всё хорошо расписано.


Название: Re: QTreeView и база данных
Отправлено: crocus от Июнь 13, 2008, 10:07
Да, отлично, я на основе http://vitaljkapblog.livejournal.com/65648.html (http://vitaljkapblog.livejournal.com/65648.html) , нечто похожее сделал.


Название: Re: QTreeView и база данных
Отправлено: crocus от Июнь 18, 2008, 03:42
Вопрос о выделении слишком прост?, слишком сложен? или никому не нужен?, в принципе решение найдено и работает, но хотелось бы увидеть полет мысли участников форума.


Название: Re: QTreeView и база данных
Отправлено: kolob от Июль 29, 2011, 16:14
Не хотелось плодить тем двойником. Поэтому вопрос: кто как создает иерархическую модель?
Т.е. есть таблица БД элементарного вида id, parent_id, value. Нужно отобразить иерархию в TreeView.
В голове возникают различные мысли. Вот такие:
1. Выгружать все в контейнер вида QMap <int, QMap<int, QString>> и дальнейшими манипуляциями создавать модель типа QStandardItemModel.
2. Частично 1-й вариант, только создать класс унаследованный от QStandardItemModel и скормить ему данный контейнер.
3. Создать рекурсивную функцию.
4. Создавать каждый элемент по порядку из результата запроса.
Ну вот как то так. Не ругайте сильно, если где то я не понятно выразился. Это только мысли. И на Qt4 делаю только первый проект. Поэтому теорию по модель - представление познал только недавно.