crossplatform.ru

Здравствуйте, гость ( Вход | Регистрация )

2 страниц V   1 2 >  
Ответить в данную темуНачать новую тему
> Поиск и выбор узла в QTreeView
JohnZ
  опции профиля:
сообщение 3.8.2014, 22:28
Сообщение #1


Участник
**

Группа: Участник
Сообщений: 139
Регистрация: 19.7.2014
Пользователь №: 4190

Спасибо сказали: 10 раз(а)




Репутация:   0  


Прошу сильно не пинать, может уже и избитый вопрос, но я в форуме не нашёл.
Если есть тема с решением, прошу ткнуть в ссыль ...
В общем траблема в выборе узла в QTreeView, из примера simpledommodel.
Добавил я в узел свой уникальный ключ Id, по которому ведётся поиск.

DomItem *DomItem::findIDD(int fIdd )
{
    int i, nCnt;
    DomItem *childItem;

    if (fIdd == Idd)    return this;

    nCnt = domNode.childNodes().count();
    for (i = 0;i < nCnt;i++)
    {
        if (childItem = child(i)->findIDD(fIdd ))
            return  childItem;
    }
    return 0;
}

//////////////////////////////////////////////////////////////////////////////////////////////////////

Это из View

        qDebug() << fitem->row();
        QModelIndex index = model->index(fitem->row(), 0, QModelIndex());
        scrollTo(index, EnsureVisible);

//////////////////////////////////////////////////////////////////////////////////////////////////////

Узел находит, а вот выбрать я его не могу, т.к. row() найденного узла при свёрнутом дереве всегда 1,
вне зависимости где этот узел находится :blink: Ведь дерево из DomItem в момент поиска уже построено !?
Подскажите плз, как в QTreeView выбор установить на найденный узел ?
Узлов 3-6 тыс. и искать вручную сложновато ...
Перейти в начало страницы
 
Быстрая цитата+Цитировать сообщение
lanz
  опции профиля:
сообщение 5.8.2014, 20:38
Сообщение #2


Старейший участник
****

Группа: Участник
Сообщений: 690
Регистрация: 28.12.2012
Пользователь №: 3660

Спасибо сказали: 113 раз(а)




Репутация:   8  


В TreeModel важно правильно указать родителя, если найденный узел ниже по уровню вложенности чем корневой. QModelIndex() означает рута как родителя.
Вот здесь подробнее:
http://qt-project.org/doc/qt-4.8/model-vie...arents-of-items
Перейти в начало страницы
 
Быстрая цитата+Цитировать сообщение
JohnZ
  опции профиля:
сообщение 5.8.2014, 23:29
Сообщение #3


Участник
**

Группа: Участник
Сообщений: 139
Регистрация: 19.7.2014
Пользователь №: 4190

Спасибо сказали: 10 раз(а)




Репутация:   0  


Цитата(lanz @ 5.8.2014, 20:38) *
В TreeModel важно правильно указать родителя, если найденный узел ниже по уровню вложенности чем корневой. QModelIndex() означает рута как родителя.
Вот здесь подробнее:
http://qt-project.org/doc/qt-4.8/model-vie...arents-of-items


Читал я это, и даже на русском, а не на пендосском ...
Каждый индекс имеет свой уникальный ключ, кроме row & col, IMHO которого должно быть достаточно
для прямого доступа к узлу внутри представления ?!
Задавал я и парента и про-парента, не позиционирует никак, только иногда курсор скачет на рута.
Вот кусок кода, который выводит мне весь путь к узлу, а затем я вручную к нему добираюсь ... :(

    do {
            if (fitem)
                qDebug() << fitem->node().nodeName()
                               << fitem->node().toElement().attribute("name")
                               << " IDD = " << fitem->Idd  << "\n";
            else
                 qDebug() << "End !";

            fitem = fitem->parent();
            if (fitem->Idc < 3) break; // ROOT

    } while(fitem);


Иначе пока никак :(
Перейти в начало страницы
 
Быстрая цитата+Цитировать сообщение
lanz
  опции профиля:
сообщение 6.8.2014, 18:12
Сообщение #4


Старейший участник
****

Группа: Участник
Сообщений: 690
Регистрация: 28.12.2012
Пользователь №: 3660

Спасибо сказали: 113 раз(а)




Репутация:   8  


Если ваша модель возвращает этот id для какой нибудь роли, то можно получить готовый индекс через match:
http://qt-project.org/doc/qt-5/qabstractitemmodel.html#match

Если получится, выложите минимальный пример, попробую посмотреть что там не так.
Перейти в начало страницы
 
Быстрая цитата+Цитировать сообщение
JohnZ
  опции профиля:
сообщение 10.8.2014, 22:13
Сообщение #5


Участник
**

Группа: Участник
Сообщений: 139
Регистрация: 19.7.2014
Пользователь №: 4190

Спасибо сказали: 10 раз(а)




Репутация:   0  


Цитата(lanz @ 6.8.2014, 18:12) *
Если ваша модель возвращает этот id для какой нибудь роли, то можно получить готовый индекс через match:
http://qt-project.org/doc/qt-5/qabstractitemmodel.html#match

Если получится, выложите минимальный пример, попробую посмотреть что там не так.


Видимо я не точно выразился, либо меня не так поняли ...

Вот ф-я поиска по IDD которая выводит путь к узлу. Исполнителя я привёл в первом посту.
У меня не отрабатывает то, что между коментариями !

Например вызов QComboBox.setCurrentIndex ( 7 ) установит выбор на 7-ю строку,
и покажет его. Мне нужно аналогично для QTreeView !!!

//  Это переработанный  simpledommodel

class MdiChild : public QTreeView
{
    Q_OBJECT
.....................

}


void MdiChild::findIDD()
{
    QModelIndex index = selectedIndexes().first();  
    DomItem *item = static_cast<DomItem*>(index.internalPointer());

    int tfIdd = QInputDialog::getInt(this, tr("Find Idd Object"), tr("Idd: "));

    DomItem *fitem = item->findIDD(tfIdd);

///////////////////////////////////////////////////////////////////////////////////////////////

    QModelIndex index = model->index(fitem->row(), 0, QModelIndex());
     scrollTo(index, EnsureVisible);

///////////////////////////////////////////////////////////////////////////////////////////////

    if (fitem)
    {

    do {
                qDebug() << fitem->node().nodeName()
                         << fitem->node().toElement().attribute(getTagByClass(201))
                         << " IDC = " << fitem->Idc
                         << " IDD = " << fitem->Idd;

            fitem = fitem->parent();
            if (fitem->Idc < 3) break;

        } while(fitem);
     }
}


Заранее благодарен за помощь !

Цитата(lanz @ 6.8.2014, 18:12) *
Если ваша модель возвращает этот id для какой нибудь роли, то можно получить готовый индекс через match:
http://qt-project.org/doc/qt-5/qabstractitemmodel.html#match

Если получится, выложите минимальный пример, попробую посмотреть что там не так.


Видимо я не точно выразился, либо меня не так поняли ...

Вот ф-я поиска по IDD которая выводит путь к узлу. Исполнителя я привёл в первом посту.
У меня не отрабатывает то, что между коментариями !

Например вызов QComboBox.setCurrentIndex ( 7 ) установит выбор на 7-ю строку,
и покажет его. Мне нужно аналогично для QTreeView !!!

//  Это переработанный  simpledommodel

class MdiChild : public QTreeView
{
    Q_OBJECT
.....................

}

void MdiChild::findIDD()
{
    QModelIndex index = selectedIndexes().first();  
    DomItem *item = static_cast<DomItem*>(index.internalPointer());

    int tfIdd = QInputDialog::getInt(this, tr("Find Idd Object"), tr("Idd: "));

    DomItem *fitem = item->findIDD(tfIdd);

/////////////////////////////////////////////////////////////////////////////////////////////

    QModelIndex index = model->index(fitem->row(), 0, QModelIndex());
     scrollTo(index, EnsureVisible);

/////////////////////////////////////////////////////////////////////////////////////////////

    if (fitem)
    {
             do {
              qDebug() << fitem->node().nodeName()
                         << fitem->node().toElement().attribute("name")
                     << " IDC = " << fitem->Idc
                     << " IDD = " << fitem->Idd;

              fitem = fitem->parent();
              if (fitem->Idc < 3) break;  // Root

        } while(fitem);
     }
}


Заранее благодарен за помощь !

Перейти в начало страницы
 
Быстрая цитата+Цитировать сообщение
lanz
  опции профиля:
сообщение 12.8.2014, 19:53
Сообщение #6


Старейший участник
****

Группа: Участник
Сообщений: 690
Регистрация: 28.12.2012
Пользователь №: 3660

Спасибо сказали: 113 раз(а)




Репутация:   8  


Имеете ввиду:
treeView->selectionModel()->select(index) ?
http://qt-project.org/doc/qt-4.8/qitemsele...del.html#select
Перейти в начало страницы
 
Быстрая цитата+Цитировать сообщение
JohnZ
  опции профиля:
сообщение 13.8.2014, 13:25
Сообщение #7


Участник
**

Группа: Участник
Сообщений: 139
Регистрация: 19.7.2014
Пользователь №: 4190

Спасибо сказали: 10 раз(а)




Репутация:   0  


Спасибо за ответ. lanz извиняюсь что морочу вам ... :rolleyes: , но не "догоняю" :(
Idd я вижу только когда дерево развёрнуто, как на снимке.
Поиск мне возвращает указатель на узел DomItem * (из примера QT, как писалось выше)

Видимо индекс найденного узла получаю НЕ правильный, поэтому и не позиционирует ?

QModelIndex index = model->index(fitem->row(), 0, QModelIndex());

// fitem->row() почему-то ВСЕГДА 1 :blink: Фактически вернулись к 1-й месаге темы :(

Тогда вопрос, - как его (QModelIndex) получить, правильный, имея указатель
на найденный объект DomItem * ???

Из объекта вообще возможно получить его индекс в модели ?

///////////////////////////////////////////////////////////////////////////////////////

QModelIndex DomModel::index(int row, int column, const QModelIndex &parent) const
{
    if (!hasIndex(row, column, parent))
        return QModelIndex();

    DomItem *parentItem;

    if (!parent.isValid())
        parentItem = rootItem;
    else
        parentItem = static_cast<DomItem*>(parent.internalPointer());

    DomItem *childItem = parentItem->child(row);
    if (childItem)
        return createIndex(row, column, childItem);
    else
        return QModelIndex();
}


Видимо можно было-бы пере-делать поиск основываясь на получении
индекса из кода выше, начиная всегда от корня (хотя нужно ниже !)
но какие параметры row & column задавать, согласно снимка ?
Опять-же, когда дерево не развёрнуто, row в узле всегда == 1 !?

Сообщение отредактировал JohnZ - 13.8.2014, 14:18
Эскизы прикрепленных изображений
Прикрепленное изображение
 
Перейти в начало страницы
 
Быстрая цитата+Цитировать сообщение
lanz
  опции профиля:
сообщение 14.8.2014, 23:09
Сообщение #8


Старейший участник
****

Группа: Участник
Сообщений: 690
Регистрация: 28.12.2012
Пользователь №: 3660

Спасибо сказали: 113 раз(а)




Репутация:   8  


Не стоит искать элементы так. Воспользуйтесь интерфейсом модели.
Прикрепил пример проекта. Исправьте если что не так в нем, будем над ним работать.
Не очень удобно пытаться составить в голове куски кода.

Сообщение отредактировал lanz - 14.8.2014, 23:10
Прикрепленные файлы
Прикрепленный файл  scratch1.zip ( 3.31 килобайт ) Кол-во скачиваний: 248
 
Перейти в начало страницы
 
Быстрая цитата+Цитировать сообщение
JohnZ
  опции профиля:
сообщение 16.8.2014, 0:49
Сообщение #9


Участник
**

Группа: Участник
Сообщений: 139
Регистрация: 19.7.2014
Пользователь №: 4190

Спасибо сказали: 10 раз(а)




Репутация:   0  


lanz - БлагоДарю ! Это действительно то, что мне нужно в проект.
Описание ф-ции match(...) для меня было не совсем понятным, (из-за индекса) поэтому "слепил" свой вариант
поиска Idd. Конечно-же "малость" придётся переделать то что уже есть, т.к. "структуры" различны (sdi<-->mdi) ...
В связИ с этим, есть несколько вопросов.
При добавлении и удалении строк у меня просто вставляется/удаляется узел в/из QDomDocument,
например для справочника
    if ((item->Idc == 100))  // New Catalogue
    {
        newobj = model->insertCatalogue(&item->node().toElement(),  text );
        collapse ( index );
        expand (  index ); // <-- ес-сно parent
        return(newobj);
    }

Я понимаю что это не совсем корректно (т.е. без beginInsert и т.д...) но пока работает, и обновляет :)

Как для Вашей модели должны выглядеть insertRows(...) и removeRows(...) для корректной работы view-а ?

Нужны-ли будут в класе Element Вашей модели

bool removeChildren(int position, int count)
bool insertChildren(int position, int count, int columns)

для поддержания механизма вставки / удаления строк ? (как в QT-шном примере)
Если да, то как должны выглядеть ?

Ещё раз спасибо за пример !

Удачи !

Сообщение отредактировал JohnZ - 16.8.2014, 11:09
Перейти в начало страницы
 
Быстрая цитата+Цитировать сообщение
lanz
  опции профиля:
сообщение 17.8.2014, 10:55
Сообщение #10


Старейший участник
****

Группа: Участник
Сообщений: 690
Регистрация: 28.12.2012
Пользователь №: 3660

Спасибо сказали: 113 раз(а)




Репутация:   8  


Обычно я не пользуюсь insert/removeRows. Как написано в документации:
Цитата
If you implement your own model, you can reimplement this function if you want to support insertions. Alternatively, you can provide your own API for altering the data. In either case, you will need to call beginInsertRows() and endInsertRows() to notify other components that the model has changed.


begin/endInsertRows нужно просто вызвать, это не так сложно :lol:
void MyModel::insertElement(const QModelIndex &parent, int id)
{
    Element * pEl = this->mRoot;
    if( parent.isValid() ) pEl = (Element*)parent.internalPointer();

    this->beginInsertRows( parent, pEl->children().size(), pEl->children().size() );
    Element * el = new Element( pEl );
    el->id = id;
    this->endInsertRows();
}


Если вы хотите использовать интерфейс insert/removeRows вместо своего, тогда да, вам понадобятся методы insert/removeChildren.
Перейти в начало страницы
 
Быстрая цитата+Цитировать сообщение

2 страниц V   1 2 >
Быстрый ответОтветить в данную темуНачать новую тему
Теги
Нет тегов для показа


1 чел. читают эту тему (гостей: 1, скрытых пользователей: 0)
Пользователей: 0




RSS Текстовая версия Сейчас: 25.4.2024, 9:03