Изменение и удаление значений из глубоко вложенного QVariant - PullRequest
0 голосов
/ 12 декабря 2018

Я использую QVariant для управления настройками проекта нашего собственного приложения.

Для этого я использую вложенную QVariantMap рекурсивную таблицу, содержащую QVariantMap s, и оставляет фактические данныезначения.

Теперь я обнаружил, что довольно сложно устанавливать и удалять узлы из этой древовидной структуры.Особенно, если вложение достигает определенной глубины.

Часть проблемы заключается в том, что value<T> возвращает копию вместо ссылки.(Мне интересно, почему в Qt отсутствует эта функция ??)

#include <QVariantMap>
#include <QDebug>

int main(int argc, char** args) {
    QVariantMap map = { {"A", QVariantMap{ {"B",5.} }} };
    {
        // Change value
        auto nested = map["A"].value<QVariantMap>();
        nested["B"] = 6;
        map["A"] = nested;
        qDebug() << map;
        // What it should be
        // map["A"]["B"] = 5;
    }
    {
        // Remove value
        auto nested = map["A"].value<QVariantMap>();
        nested.remove("B");
        map["A"] = nested;
        qDebug() << map;
        // What it should be
        // map["A"].remove("B");
    }
}

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

1 Ответ

0 голосов
/ 12 декабря 2018

Подумав, я пришел к мысли использовать путь к желаемому значению.Этот путь должен быть уникальным.

Следующий код рекурсивно находит значение и удаляет его.Изменение значения должно быть очень похожим.Я не уверен, если есть более легкий подход.

bool remove(QVariantMap& map, const QString& path, QString sep = ".") {
    auto elems = path.split(sep);
    if (elems.size() > 1) {
        if (!map.contains(elems.first())) return false;
        auto tmp = elems;
        tmp.pop_front();
        auto childMap = map[elems.first()].value<QVariantMap>();
        bool ret = remove(childMap, tmp.join("."));
        if (!ret) return false;
        map[elems.first()] = childMap;
        return true;
    }
    else if (elems.size() == 1) {
        return map.remove(elems[0]) >= 1;
    }
    else {
        return false;
    }
}

Примечание

Это решение не следует использовать, если данных много, так как копирование карт происходит довольно часто.

...