Russian Qt Forum
Ноябрь 26, 2024, 05:19 *
Добро пожаловать, Гость. Пожалуйста, войдите или зарегистрируйтесь.
Вам не пришло письмо с кодом активации?

Войти
 
  Начало   Форум  WIKI (Вики)FAQ Помощь Поиск Войти Регистрация  

Страниц: [1]   Вниз
  Печать  
Автор Тема: как удобно работать с адресами в виде дерева  (Прочитано 6408 раз)
unkier
Гость
« : Март 11, 2010, 17:10 »

имеем таблицу с адресами

id город улица дом квартира

надо представить в дереве вида

город1
 ->улица0
 ->улица1
   ->дом1
     ->кв1
 ->улица2

 ->улица2
город 2

читаю пример Simple Tree Model Example но пока чёто глухо.
как это запихать вроде понятно.
наверно с помощью qsqlquery вытащить все города, потом для каждого города вытащить все улицы, потом для каждой улицы вытащить все дома, потом для каждого дома вытащить все квартиры. при этом каждый раз создавая TreeItem и соблюдая кто чей наследник.

но есть неясности. если данные в моей таблице меняются, как и кто это отслеживает ?
как понять на какой узел дерева тыкнул юзер ? как можно как то прикрепить свои данные к TreeItem (он же вообще не от кого не наследуется) и как до него добраться когда юзер его выделил ?
Записан
unkier
Гость
« Ответ #1 : Март 11, 2010, 17:27 »

или проще просто с TreeWidget напрямую без моделей и видов ?

и еще вопрос вдогонку. можно ли с одной таблицей работать из нескольких мест ? то есть создать к примеру sqlquery для своих нужд притом что с этой же таблицей через QSqlTableModel из другой формы работают.
?
« Последнее редактирование: Март 11, 2010, 18:25 от unkier » Записан
asvil
Гость
« Ответ #2 : Март 11, 2010, 18:44 »

необходим crosstab, pivot table или сводная таблица для sql запроса:
select страна, город, улица from страны join города on страны.ид = города.страна_ид join улицы on улицы.город_ид = города.ид
я лично по запросам crosstab, pivot table увидеть в инете реализацию на qt не смог.
вообще для этого случая нужна упрощенная сводная таблица, без сводимых значений. Так или иначе цепляю свою реализацию. Работает в proxy стиле.
Записан
Zmeishe
Гость
« Ответ #3 : Март 11, 2010, 19:17 »

Адресный реестр, в общем случае, это не дерево.
Всё зависит от задачи.

Деревом можно оформить справочник населённых пунктов, если нет необходимости хранить историю смены подчинённости. Например, Сокольский район Ивановской губернии был переведён в состав Нижегородской губернии, причём, совсем недавно в 90-е годы.

Населённые пункты и улицы могут менять названия. Историю смены названий в дерево не засунешь, а вот поиск провести обязан. Т.к. пользователь не обязан знать какое название было вчера, а какое стало сегодня.
С домами тоже непросто. Есть угловые дома и многих бесит адрес ул. Ванеева 17/47
47 это что? Корпус?
У такого дома должен быть двойной адрес ул.Ванеева 17 / ул. Генкиной 47
В дерево не засунешь, а поиском найти обязан по любому адресу.
Сначала определись с архитектурой базы данных, потом ГУЙ рисуй.

Записан
unkier
Гость
« Ответ #4 : Март 11, 2010, 20:45 »

необходим crosstab, pivot table или сводная таблица для sql запроса:
select страна, город, улица from страны join города on страны.ид = города.страна_ид join улицы on улицы.город_ид = города.ид
а QSqlRelationalTableModel этих проблем не решает ?
я по началу хотел сделать всё по человечески с несколькими таблицами и связями. но от этого усложнения вапще непонятно как это делать.

а по поводу архитектуры. это не я так придумал. всё еще будет переделываться много раз.
Записан
npkitsul
Гость
« Ответ #5 : Март 11, 2010, 22:10 »

 Непонимающий

1. База данных SQL доступная например через класс SQLRelationaTableModel самое всеобъемлеющее решение.

2. А самая компактная структура данных для самых быстрых алгоритмов будет:
Дерево для стран, областей, городов, улиц, домов, корпусов, строений.

Физический дом будет представлен листком одного из домов, корпусов, строений, т.е.
if ((p->ChildrenStart == 0) && (p->ChildrenEnd == 0))
{
      это физический дом.
}
 
Указатели на детей естественно в "indexed array", что бы поиск дома 342 был мгновенен:
house[342].

Указатели на страны, области, города, и улицы отсортированы в алфавитном порядке. Для быстрого поиска.

А для быстрого поиска по имени улицы, можно прикрепить глобальную hash table для ссылок на все улицы.



Населённые пункты и улицы могут менять названия. Историю смены названий в дерево не засунешь, а вот поиск провести обязан. Т.к. пользователь не обязан знать какое название было вчера, а какое стало сегодня.
Так вот в глобальную hash table и засунуть можно весь List исторических имён.

С домами тоже непросто. Есть угловые дома и многих бесит адрес ул. Ванеева 17/47
47 это что? Корпус?
У такого дома должен быть двойной адрес ул.Ванеева 17 / ул. Генкиной 47
Так можно сделать у дома double list синонимов, и внести их тоже в hash table.

Как оно? Это перфексионизм?

 Строит глазки
Записан
break
Гипер активный житель
*****
Offline Offline

Сообщений: 846


Просмотр профиля
« Ответ #6 : Март 12, 2010, 01:07 »

А если так:

Города
Почтовые адреса
Дома
Квартиры

Все разные таблицы со своими ID

а потом делаем многие ко многим

ID города, ID Почтового адреса, ID Дома, ID Квартиры

так получится и двойные адреса разрулить и доп. информацию по каждому объекту хранить - планы, схемы домов, планировки квартир, и т.д. и поиск организовать

и написав Хранимую процедуру или Вьев (что предпочтительнее - зависит от БД)  можно вывести в одной таблице (хотя дома с двойными адресами лучше обработать в этой процедуре чтобы вывелись одной строкой)

также через ID можно организовать отдельную таблицу с деревом

Записан
mcrads
Гость
« Ответ #7 : Март 12, 2010, 21:33 »

А если так?
class City: public QObject
{
    QList<Street> streetList;
    ...
}

class Street: public QObject
{
    QList<House> houseList;
......
}

и т.д.? и использовать метаобъектную информацию. например objectName(), setObjectName(), findChildren(), parent()
я таким способом реализовывал виртуальную файловую систему классами VSystem, VDir, VFile. в принципе шустренько и поиск работает удобно =)

PS Ну и естественно правильно определять родителей! тогда все будет очень просто и иерархично =)
Записан
viktor.kz
Гость
« Ответ #8 : Март 15, 2010, 10:43 »

А если так (способ корявый, но работает):
2 таблицы.
Таблица типов адресов. name_ab - сокращение.
Код
SQL
CREATE TABLE address_type
   (id      number(10,0) NOT NULL,
    name    varchar2(250) NOT NULL,
    name_ab varchar2(250))
/

Для примера заполняем.
INSERT INTO ADDRESS_TYPE VALUES (null,'Город','г.');
INSERT INTO ADDRESS_TYPE VALUES (null,'Район','р-он.');
INSERT INTO ADDRESS_TYPE VALUES (null,'Проспект','пр.');
INSERT INTO ADDRESS_TYPE VALUES (null,'Микрорайон','мкр.');
INSERT INTO ADDRESS_TYPE VALUES (null,'Квартал','кв-л.');
INSERT INTO ADDRESS_TYPE VALUES (null,'Улица','ул.');
INSERT INTO ADDRESS_TYPE VALUES (null,'Дом','д.');
INSERT INTO ADDRESS_TYPE VALUES (null,'Участок','уч.');
INSERT INTO ADDRESS_TYPE VALUES (null,'Переулок','пер.');
INSERT INTO ADDRESS_TYPE VALUES (null,'Учетный квартал','уч. кв-л.');

Таблица адресов:
Код
SQL
CREATE TABLE address
  (id           number(10,0) NOT NULL,
   address_type number(10,0) NOT NULL,
   parent       number(10,0) NOT NULL,
   name         varchar2(250) NOT NULL)
/
 
parent - ID родителя. Если 0 (NULL, если not null убрать), то нет родителя (самый верхний элемент).

Вначале заполняешь города, затем улицы, дома, квартиры.
Потом делаешь всё в QTreeWidget.
Делаешь что-то типа
void BuildTree(QTreeWidgetItem *twiItem, int iParent)
twiItem - родитель в QTreeWidget. iParent - ID родителя в базе.
При старте делаешь:
BuildTree(treeWidget->invisibleRootItem(), 0);
Прогружается список верхних итемов. Когда прогружаешь, проверяешь есть ли у него дети. Если есть то добавляешь какой нибудь пустой элемент чтобы он |+| добавил.
Затем на событие void on_treeWidget_itemExpanded(QTreeWidgetItem* twiItem) вызываешь BuildTree.
Соотвественно итемы подгружаются по нажатию на |+|. Не забываешь удалять пустой итем.

Чтобы получить полный адрес в цикле пробегаешься по таблицу ADDRESS. Читаешь сокращения из ADDRESS_TYPE.
И в итоге получается: "г. Караганда ул. Киевская 121 кв. 39"

По тупому, но работает...
Записан
mcrads
Гость
« Ответ #9 : Март 15, 2010, 22:50 »

жестоко... Sql для такой простенькой задачи - все равно что белазом дрова на дачу привозить блин... нужно сервер, нужно клиент, очень и очень много мороки...
Записан
break
Гипер активный житель
*****
Offline Offline

Сообщений: 846


Просмотр профиля
« Ответ #10 : Март 16, 2010, 00:48 »

Цитировать
жестоко... Sql для такой простенькой задачи - все равно что белазом дрова на дачу привозить блин... нужно сервер, нужно клиент, очень и очень много мороки...

При чем тут SQL - разложить данные по таблицам и составить соответствующие таблицы со связями один-ко-многим, многие-ко-многим это проблема? По мне так наследование QObject для своих классов "улица", "город" является БЕЛАЗОМ.

Задачка типовая для реляционных БД. Ключ решения - сами данные не должны лежать ни в каком дереве. Данные это ДАННЫЕ. Просто списки "Почтовых адресов", "Городов", "Стран" имеющие уникальные ID (для упрощения БД - ID могут быть сквозными по Базе), а связи устанавливаются в отдельных таблицах "Адресный рубрикатор-дерево", "Адреса-список для поиска" и т.д.
Записан
mcrads
Гость
« Ответ #11 : Март 16, 2010, 22:23 »

но ведь спрашивалась обработка в виде дерева? один из выходов - QAbstractItemModel + QTreeView. второй - структуризация классами.ну тут решать тому кто спрашивал.. вариантов то много... ИМХО, таблицы выйдут немного сложнее для реализации. ИМХО и только ИМХО.
Записан
break
Гипер активный житель
*****
Offline Offline

Сообщений: 846


Просмотр профиля
« Ответ #12 : Март 17, 2010, 12:05 »

Цитировать
таблицы выйдут немного сложнее для реализации
возможно но мне показалось что речь шла о данных которые надо где-то хранить - а если так то в случае с классами вы будете их сериализовать / десириализовать при загрузке - сохранении - Это проще?

Цитировать
но ведь спрашивалась обработка в виде дерева?
Да правильно  и я предложил таблицы, предполагая что все помнят про стандартный подход создания дерева через таблицу


ROW_ID   !   OBJECT_ID   ! PARENT__ROW_ID

PARENT_ROW_ID ссылается на ROW_ID как вторичный ключ
OBJECT_ID ссылается на ID объекта в таблице объектов, потом пишется рекурсивная хранимая процедура которая может выбрать все дерева начиная с ID ветки. С ее помощью строится модель.
« Последнее редактирование: Март 17, 2010, 12:08 от break » Записан
Страниц: [1]   Вверх
  Печать  
 
Перейти в:  


Страница сгенерирована за 0.066 секунд. Запросов: 23.