Как зарегистрировать QMap внутри QList в качестве метатипа в QtScript?

Я смотрю на передачу объекта QList<QMap<QString, QString>> из моего кода Qt в файл JavaScript и задаюсь вопросом, как правильно обрабатывать часть кода qScriptRegisterMetaType.

В настоящее время я рассматриваю возможность использования в моем методе преобразования значений Script частей метода регистрации QList и метода регистрации QMap.

Код, на который я ссылаюсь, можно найти здесь для QList и здесь для QMap.

В частности, при преобразовании QList<QMap<QString, QString>> в QScriptValue я хочу использовать этот фрагмент для обработки части QMap:

QScriptValue obj = engine->newObject();
StringMap::const_iterator it(map.begin());
for (; it != map.end(); ++it)
{
    obj.setProperty(it.key(), qScriptValueFromValue(engine,it.value()));
}
return obj;

Используя это, я хочу затем запустить преобразование QMap, устанавливая каждое свойство для QList и возвращая полученное значение QScriptValue.

QScriptValue ScriptListtoScriptValue(QScriptEngine* engine, const ListMap& list)
{
    QScriptValue obj = engine->newArray(list.size());
    for ( int i = 0; i < list.size(); i++ ) {
        obj.setProperty(i, engine->newQObject(list[i]));
    }

    return obj;
}

Могу ли я вызвать функцию, которая запускает преобразование QMap внутри преобразования QList, и установить свойство таким образом? Мне интересно, если я что-то упустил или Qt не будет доволен этим и не передаст данные должным образом в JavaScript.

Что касается причины, по которой я это делаю: я хочу отправить структуру в JavaScript, чтобы QMap содержал пару ключ/значение для нескольких имен столбцов и значений в виде отдельной записи. Затем QList будет списком этих записей. Если у меня есть недостатки в моем подходе и есть лучший способ отправить такую ​​информацию из Qt в JavaScript, я был бы очень признателен за конструктивную критику.


person Sasha Demyanik    schedule 27.03.2018    source источник


Ответы (1)


Мне удалось найти решение, которое работает для всех, кто хочет попробовать это в будущем. Я объединил эти два метода так, как я предложил.

В заголовочном файле я создал класс ScriptList, который является QList< QMap<QString, QString> > и должен был включать пробел между угловыми скобками, иначе он будет интерпретирован как >>. Кроме того, я создал класс StringMap, который обрабатывал QMap<QString, QString>.

class StringMap : public QMap<QString, QString> {};

class ScriptList : public QList< QMap<QString, QString> > {};
QScriptValue ScriptListToScriptValue(QScriptEngine* engine, const ScriptList& list);
void ScriptListFromScriptValue(const QScriptValue &obj, ScriptList& list);
QScriptValue MapToScriptValue(QScriptEngine* engine, const QMap<QString, QString>& map);
void MapFromScriptValue(const QScriptValue &obj, QMap<QString, QString>& map);

Затем я сделал все необходимые объявления и регистрацию:

Q_DECLARE_METATYPE(ScriptList)
Q_DECLARE_METATYPE(StringMap)

qRegisterMetaType<ScriptList>("QList< QMap<QString,QString> >");

qScriptRegisterMetaType(m_engine, ScriptListToScriptValue, ScriptListFromScriptValue);

Друг друга эти строки находятся в разных частях кода.

Затем идут функции, необходимые для создания QMap в QList.

QScriptValue ScriptListToScriptValue(QScriptEngine* engine, const ScriptList& list)
{
    QScriptValue obj = engine->newArray(list.size());
    for ( int i = 0; i < list.size(); i++ ) {
        obj.setProperty(i, MapToScriptValue(engine, list[i]));
    }

    return obj;
}

void ScriptListFromScriptValue(const QScriptValue &obj, ScriptList& list)
{
    list.clear();
    QScriptValueIterator itr(obj);
    while ( itr.hasNext() ) {
        itr.next();
        if ( itr.flags() & QScriptValue::SkipInEnumeration)
            continue;
        QMap<QString, QString> map;
        MapFromScriptValue(itr.value(), map);
        list.append(map);
    }

}

QScriptValue MapToScriptValue(QScriptEngine *engine, const QMap<QString, QString>& map)
{
    QScriptValue obj = engine->newObject();
    StringMap::const_iterator it(map.begin());
    for (; it != map.end(); ++it)
    {
        obj.setProperty(it.key(), qScriptValueFromValue(engine,it.value()));
    }
    return obj;
}


void MapFromScriptValue(const QScriptValue &obj, QMap<QString, QString>& map)
{
    QScriptValueIterator itr(obj);
    while(itr.hasNext())
    {
        itr.next();
        map.operator [](itr.name().toUtf8()) = qscriptvalue_cast<ScriptMap::mapped_type>(itr.value());
    }
}

Надеюсь, это поможет любому в подобной ситуации.

person Sasha Demyanik    schedule 28.03.2018