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

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

Страниц: [1]   Вниз
  Печать  
Автор Тема: [РЕШЕНО] QTreeView с загрузкой данных при разворачи  (Прочитано 5512 раз)
mugabe
Гость
« : Июнь 03, 2009, 09:49 »

Задача:
Есть огромная древовидная структура данных, загружаемая с удаленного сервера. Сразу грузить всю структуру - долго, да и не нужно.
Нужно что бы сначала загружался первый уровень, а при разворачивании загружались только вложенные элементы.

Пытался реализовать такое на базе примера Simple Tree Model.
Пока что ничего не вышло.

Сначала пробовал загружать данные при первом обращении к TreeItem::data(...), child(...), childCount(...) и т.д.
И в принципе даже работало, но возникала проблема во время отрисовке, когда вызывался один из вышеперечисленных методов, пока предыдущий вызов еще не успел завершить свою работу. Тут жабу подкинул класс-обертка для QHttp, позволяющая делать синхронные запросы - он вызывает QEventLoop::exec() до тех пор пока не получит ответ, что позволяет выполнить paintEvent() до того, как данные получены Грустный

Это подтолкнуло поступить более правильно (на мой взгляд):
1. При разворачивании элемента он разворачивается, но показывает только один элемент с текстом "Загрузка...". При этом действия пользователя не блокируются и он может делать что-то еще, пока грузятся данные.
2. Когда данные будут загружены, этот элемент удаляется и добавляются настоящие элементы.

Но с реализацией этого возникли трудоности. Возможно, из за недостаточного понимания Qt-шной модели MVC, в частности индексов.

Сейчас у меня происходит следующее:
1. При первом вызове TreeItem::data(...), child(...), childCount(...) возвращается один элемент с надписью "Загрузка...".
2. В это время через обычный QHttp делается ассинхронный запрос к серверу. Сигнал QHttp::finished(...) привязывается к слоту моей модели requestFinished(...).

3. При завершении запроса срабатывает слот requestFinished(...), анализируются данные пришедшие от сервера и корректируются данные в необходимом TreeItem.

И вот тут у меня загвоздка, как после этого дать понять TreeView, что модель обновилась? На сколько я понимаю нужно вызвать QAbstractItemModel::insertRow(int row, const QModelIndex &parent).
Но как получить индекс QModelIndex &parent, если у меня есть только ссылка на TreeItem этого parent-а?
« Последнее редактирование: Июнь 04, 2009, 07:01 от mugabe » Записан
EhTemka
Гость
« Ответ #1 : Июнь 03, 2009, 14:49 »

TreeItem - это QTreeWidgetItem? Если да , то есть функция

Код
C++ (Qt)
QModelIndex QTreeWidget::indexFromItem ( QTreeWidgetItem * item, int column = 0 ) const   [protected]
Записан
mugabe
Гость
« Ответ #2 : Июнь 04, 2009, 04:16 »

TreeItem - это QTreeWidgetItem?
Нет, это класс из Simple Tree Model.
Я работаю с QTreeView, а не QTreeWidget.
Записан
drsm
Гость
« Ответ #3 : Июнь 04, 2009, 05:33 »

я тупо храню QHash<RequestId, QModelIndex>,
а вызывать при вставке нужно не insertRow, а begin/endInsertRows().
Записан
mugabe
Гость
« Ответ #4 : Июнь 04, 2009, 06:19 »

я тупо храню QHash<RequestId, QModelIndex>,
а вызывать при вставке нужно не insertRow, а begin/endInsertRows().

Ну до вызова insertRow еще не дошло, т.к. индекс я не получил, так что пока не суть Улыбающийся
Я так понимаю, что QModelIndex можно хранить и в самом элементе, но если честно, плохо понимаю что происходит в QAbstractItemModel::index(...)

Вот кусок из Simple Tree Model:
Код
C++ (Qt)
QModelIndex TreeModel::index(int row, int column, const QModelIndex &parent)
            const
{
    if (!hasIndex(row, column, parent))
        return QModelIndex();
 
    TreeItem *parentItem;
 
    if (!parent.isValid())
        parentItem = rootItem;
    else
        parentItem = static_cast<TreeItem*>(parent.internalPointer());
 
    TreeItem *childItem = parentItem->child(row);
    if (childItem)
        return createIndex(row, column, childItem);
    else
        return QModelIndex();
}

Что здесь нужно сделать, что бы хранить этот индекс в элементе?

Код
C++ (Qt)
QModelIndex TreeModel::index(int row, int column, const QModelIndex &parent)
            const
{
    if (!hasIndex(row, column, parent))
        return QModelIndex();
 
    TreeItem *parentItem;
 
    if (!parent.isValid())
        parentItem = rootItem;
    else
        parentItem = static_cast<TreeItem*>(parent.internalPointer());
 
    TreeItem *childItem = parentItem->child(row);
    if (childItem) {
        // comment here
        childItem->setIndex(   createIndex(row, column, childItem)   );
        return childItem->index();
    }
    else
        return QModelIndex();
}
 
QModelIndex  TreeItem::index() const {
 return m_index;
}
void TreeItem::setIndex(const QModelIndex &index) {
 m_index = index;
}
 

комменты на русском как-то странно обрабатываются, на месте "comment here" хотел написать:
         // тут что-то вроде такого... сохраняем индекс в итеме и возвращаем его...
         // и может надо работать с указателями на индекс воизбежание копирования?


Так правильно?
« Последнее редактирование: Июнь 04, 2009, 06:23 от mugabe » Записан
Tonal
Гость
« Ответ #5 : Июнь 04, 2009, 06:38 »

Посмотри в сторону canFetchMore и fetchMore.
Записан
mugabe
Гость
« Ответ #6 : Июнь 04, 2009, 06:48 »

Смотрел - он не совсем подходит для такой задачи.
Да и проблемы у него те же.



В общем попробовал сделать так, как предположил выше - работает! Улыбающийся
Записан
Страниц: [1]   Вверх
  Печать  
 
Перейти в:  


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