Форум русскоязычного сообщества Ubuntu


Следите за новостями русскоязычного сообщества Ubuntu в Twitter-ленте @ubuntu_ru_loco

Автор Тема: Qt. Дерево иерархии нескольких независимых каталогов  (Прочитано 3323 раз)

0 Пользователей и 1 Гость просматривают эту тему.

Оффлайн Дядюшка Ау

  • Автор темы
  • Участник
  • *
  • Сообщений: 123
  • Дайте две!
    • Просмотр профиля
Есть задача. Отображать на форме дерево каталогов, причем, на верхнем уровне дерева указывается произвольный каталог. Соответственно, для каждой строки верхнего уровня показывается своя иерархия.
Например:
home/user
   home/user/dir1
   home/user/dir2
usr/bin
   usr/bin/dir1
   usr/bin/dir1

Я работаю с объектом QFileSystemModel, содержимое которого показывается в QTreeView. Проблема в том, что TreeView отображает только одну ветку иерархии, которую я указываю, как
Код: ("C++") [Выделить]
ui->treeView->setRootIndex(fs_model->index(dir));
Есть ли простой способ отобразить иерархию, как в примере выше?
Ubuntu 12.04 для поколупацца, Win7 для поработать

Оффлайн CynicRus

  • Любитель
  • *
  • Сообщений: 78
    • Просмотр профиля
Есть мнение, что придется написать собственную модель-посредник.
"Only two things are infinite, the universe and human stupidity... and I'm not sure about the universe."  -- Albert Einstein

Оффлайн Дядюшка Ау

  • Автор темы
  • Участник
  • *
  • Сообщений: 123
  • Дайте две!
    • Просмотр профиля
Да, как вариант. Еще есть мнение, что можно обойтись QTreeWidget (который без модели), а в каждой ветке уже подцепить по модели-наблюдателю. Но вопрос был "есть ли простой способ" :) Извратиться, скорее всего можно, но какой способ извращения наименее извращенный... :-\
Ubuntu 12.04 для поколупацца, Win7 для поработать

Оффлайн CynicRus

  • Любитель
  • *
  • Сообщений: 78
    • Просмотр профиля
Дык использование своей модели - не есть извращение-) Однако - если без извращений, тогда у тебя 2 способа:
1) Писать свою модель
2) Юзать QTreeWdget
"Only two things are infinite, the universe and human stupidity... and I'm not sure about the universe."  -- Albert Einstein

Оффлайн Дядюшка Ау

  • Автор темы
  • Участник
  • *
  • Сообщений: 123
  • Дайте две!
    • Просмотр профиля
Дык использование своей модели - не есть извращение-) Однако - если без извращений, тогда у тебя 2 способа:
1) Писать свою модель

Скорее всего так. Вопрос: Как лучше разрулить индексы в деревьях. Например, моя модель скрывает внутри список из QFileSystemModel. Как лучше организовать индексацию строк, добавленных моей моделью и тех, которые считаны из ФС?
Ubuntu 12.04 для поколупацца, Win7 для поработать

Оффлайн CynicRus

  • Любитель
  • *
  • Сообщений: 78
    • Просмотр профиля
Честно говоря - я слабо понял, что ты задумал. Если ты решил писать свою модель, то наследуешься ты от QAbstractItemModel
. А если ты наследуешься от неё - то зачем QFileSystemModel. А если ты хочешь таки слегонца извратиться...То унаследуйся QFileSystemModel - и там уже определи, как данные сосуществовать будут.

Пользователь решил продолжить мысль 29 Марта 2012, 16:49:24:
http://habrahabr.ru/post/69658/ - авось натолкнет на мысли умные.
« Последнее редактирование: 29 Марта 2012, 16:49:24 от CynicRus »
"Only two things are infinite, the universe and human stupidity... and I'm not sure about the universe."  -- Albert Einstein

Оффлайн Дядюшка Ау

  • Автор темы
  • Участник
  • *
  • Сообщений: 123
  • Дайте две!
    • Просмотр профиля
Честно говоря - я слабо понял, что ты задумал. Если ты решил писать свою модель, то наследуешься ты от QAbstractItemModel
. А если ты наследуешься от неё - то зачем QFileSystemModel. А если ты хочешь таки слегонца извратиться...То унаследуйся QFileSystemModel - и там уже определи, как данные сосуществовать будут.

Ну мне не очень хочется самому писать перебор элементов файловой системы, привязку иконок и т.п. Я думал сделать внутри моей модели обертку для QFileSystemModel. Вопрос встал в реализации QAbstractItemModel::index(). View на форме передает номер строки, а я должен ему выдать QModelIndex(). Не догнал пока, как создать индексы отдельно для моей модели и перенаправления на QFileSystemModel::index().

Т.е. есть 2 вида узлов дерева:
1. - описание корня, начало отдельного дерева каталогов (см. начало темы)
2. - файл из файловой системы

для view все это индексы некоторого дерева, он обращается к ним по номеру строки. Как бы определить - какой индекс вернуть в QMyItemModel::index(). Если номер строки указывает на узел типа 1, то создаем один вид индекса, а если на узел типа 2, то передаем вызов в QFileSystemModel::index().
Ubuntu 12.04 для поколупацца, Win7 для поработать

Оффлайн Tonal

  • Любитель
  • *
  • Сообщений: 82
  • Карма Кагью
    • Просмотр профиля
Самое разумное представляется делать свою модель наследуясь от QAbstractItemModel, в которй для каждого каталога верхнего уровня создавать QFileSystemModel. Как ты и хочешь.

Схема примерно такая: делаем класс для внутреннего использования:
Код: (cpp) [Выделить]
struct FileItemSelector {
  QFileSystemModel model;
  QPersistentModelIndex originIndex;
};
Указатель на экземпляр этого класса в будем хранить в данных индекса.

Далее, в функциях, типа data/rowCount/etc..., которые принимают QModelIndex добываем указатель на связанный экземпляр и вызываем соответствующую функцию модели:
Код: (cpp) [Выделить]
int MyFileModel::rowCount(const QModelIndex& index) const {
  if (!index.isValid())
    return countTopLevelBranches();
  const FileItemSelector* is = reinterpret_cast<FileItemSelector*>(index.internalPointer());
  assert(is);
  return is->model->rowCount(is->originIndex);
}
Так же реализуется и index - там выбор модели происходит по родителю:
Выбрали модель, запросили у неё индекс, создали экземпляр FileItemSelector, создали индекс с указателем на него, запомнили внутреннем кеше.
Кешь можно не чистить вовсе, а можно по таймеру или идлу, только проверяя, что индекс реально не нужен через persistentIndexList. :)

Оффлайн Дядюшка Ау

  • Автор темы
  • Участник
  • *
  • Сообщений: 123
  • Дайте две!
    • Просмотр профиля
Самое разумное представляется делать свою модель наследуясь от QAbstractItemModel, в которй для каждого каталога верхнего уровня создавать QFileSystemModel. Как ты и хочешь.

Спасибо. Можно еще вопрос, не нашел в документации, как работают сами индексы. Вот например, кто решает, что индекс валидный в методе index.isValid()? В примерах моделей, унаследованных от AbstractModel никто ничего с этим методом не делает. Каким образом QModeIndex узнает, что он принадлежит именно нашей модели?
Ubuntu 12.04 для поколупацца, Win7 для поработать

Оффлайн Tonal

  • Любитель
  • *
  • Сообщений: 82
  • Карма Кагью
    • Просмотр профиля
Ну, внутреннего устройства как бы знать и не нужно - всё в документации есть. НО таки исходники доступны и можно посмотреть как что реально происходит в конкретной реализации.
Главное, что нужно понимать: объект QModelIndex создаётся по требованию через QAbstractItemModel::index или QAbstractItemModel::parent, с ним вызываются нужные функции, и он тут же удаляется.
В псевдокоде примерно так:
Код: (cpp) [Выделить]
void SomeModel::inner_function() {
  QModelIndex cur = index(...);
  some_func1(cur, ...);
  some_func2(cur, ...);
  emit some_signal(cur, ...);
}
Т. е. живёт на стеке.
Ну и внутри у его указатель на модель, чтобы спрашивать у ей разные вещи, типа parent/data/child/etc...

Да, посмотри форумы [urlhttp://www.prog.org.ru/index.php]prog.org.ru[/url] и [urlhttp://www.forum.crossplatform.ru/]crossplatform.ru[/url] - они полностью посвящены разработке на Qt. Ну и есть профильный подфорум на rsdn.ru.
Так что имеет смысл там поспрошать - быстрее чем здесь ответы получишь. :)

 

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