Извлечение всех данных из определенного столбца во вложенной модели QStandardItemModel

У меня есть QStandardItemModel, который я прохожу через представление, чтобы отобразить его внутри QTreeView. Моя модель содержит 2 столбца, работающих как пары ключей и значений. Первый столбец содержит шаблон исправления ключей, а второй столбец содержит соответствующие им значения. Мое дерево примеров выглядит примерно так:

Item | Attributes
Name   Tomato
 |-Type Fruit
 |-Color Red
Name ...
 |-Type ...

Как я уже сказал, мой шаблон в первом столбце остается прежним, но значения во втором столбце вводятся пользователем.

Что я хочу:

Я хочу пройти (рекурсивно) через модель, захватив все значения из столбца Attributes и записать их в файл

Что я уже сделал:

void Writer::writeToYaml(const std::shared_ptr<QStandardItemModel>& model, 
                               const QString& filePath)                 
{

    for(int r = 0; r < model->rowCount(); ++r)
    {
        QModelIndex index = model->index(r, 1);
        QVariant data = model->data(index);
        qDebug() << data;

        if(model->hasChildren(index))
        {
            writeToYaml(model, filePath);
        }
    }
}

Когда я запускаю свой код, qDebug() все время выводит только Tomato. Я считаю, что сам цикл заканчивается в корневом узле, в результате чего получается только первое значение. Можно ли рекурсивно извлечь все элементы из определенного столбца во вложенной модели?


person MarKS    schedule 16.03.2018    source источник


Ответы (1)


Я пишу это из головы, так что вам, возможно, придется немного подправить, но это должно сработать. Вам необходимо обратиться к элементам более низкого уровня с родительскими индексами.

Но я не уверен, что ваша модель верна, потому что предоставленный вами код не должен печатать «помидор», а должен создавать бесконечный цикл, потому что, как только вы рекурсивно вызываете writeToYaml, вы снова перебираете элементы верхнего уровня. Это означает, что model->hasChildren(index), скорее всего, никогда не будет истинным в вашем случае...

void Writer::writeToYaml(const std::shared_ptr<QAbstractItemModel>& model, const QString& filePath)                 
{

    std::stack<QModelIndex> indices;

    for (int = model->rowCount() - 1; r >= 0; --r) // iterate from last to first as you put items on a stack
    {
        indices.push(model->index(r, 1));
    }

    while (!indices.empty())
    {
        auto index = indices.top();
        indices.pop();

        QVariant data = model->data(index);
        qDebug() << data;

        if (model->hasChildren(index))
        {
            for (int r = model->rowCount(index) -1 ; r >= 0; --r)
//                                       ^^^^^ note this, this iterates over all children of item on given index
            {
                indices.push(model->index(r, 1, index));
//                                              ^^^^^ this is the parent index that identifies the item in tree hierarchy
            }
        }
    }
}
person Jaa-c    schedule 16.03.2018
comment
Ты прав! Вызов writeToYaml должен создавать бесконечный цикл всякий раз, когда он истинен. Но индекс, который я получаю, относится ко второму столбцу, у которого нет детей. Я использовал его, чтобы показать, можно ли рекурсивно захватывать элементы. Позвольте мне попробовать ваш код. - person MarKS; 16.03.2018
comment
спасибо за подход! Я исправил некоторые опечатки и изменил краткую логику в вашем коде, чтобы также получить значения для родительских узлов. Я считаю, что это можно сделать намного чище, но пока это работает для меня. Причем порядок извлечения в моем случае не важен. Поскольку вы придумали этот подход, я отмечу его как ответ. - person MarKS; 16.03.2018