diff options
author | Ali Kianian <ali.kianian@qt.io> | 2024-02-12 12:26:17 +0200 |
---|---|---|
committer | Ali Kianian <ali.kianian@qt.io> | 2024-02-12 12:37:14 +0000 |
commit | 1f9e41ac9ab56a5c5abb5d0c241b4131f11d570a (patch) | |
tree | a9fe805ba1f60ad8944a0dec17ef76c8e30c38fd | |
parent | dccd828f1fd47afcece1166e9532e73354e09f4c (diff) |
QmlDesigner: Keep the order of columns for imported jsons
Fixes: QDS-11670
Change-Id: Ia068bbb864065b648cffcab2c3477d3cec7f25f8
Reviewed-by: Mahmoud Badri <mahmoud.badri@qt.io>
Reviewed-by: Miikka Heikkinen <miikka.heikkinen@qt.io>
Reviewed-by: Qt CI Patch Build Bot <ci_patchbuild_bot@qt.io>
3 files changed, 77 insertions, 9 deletions
diff --git a/src/plugins/qmldesigner/components/collectioneditor/collectiondetails.cpp b/src/plugins/qmldesigner/components/collectioneditor/collectiondetails.cpp index 4acd2f601a..e8e8e18dc0 100644 --- a/src/plugins/qmldesigner/components/collectioneditor/collectiondetails.cpp +++ b/src/plugins/qmldesigner/components/collectioneditor/collectiondetails.cpp @@ -6,6 +6,9 @@ #include "collectioneditorutils.h" #include <utils/span.h> +#include <qmljs/parser/qmljsast_p.h> +#include <qmljs/parser/qmljsastvisitor_p.h> +#include <qmljs/qmljsdocument.h> #include <qqml.h> #include <QJsonArray> @@ -261,6 +264,47 @@ inline static bool isEmptyJsonValue(const QJsonValue &value) return value.isNull() || value.isUndefined() || (value.isString() && value.toString().isEmpty()); } +class PropertyOrderFinder : public QmlJS::AST::Visitor +{ +public: + static QStringList parse(const QString &jsonContent) + { + PropertyOrderFinder finder; + QmlJS::Document::MutablePtr jsonDoc = QmlJS::Document::create(Utils::FilePath::fromString( + "<expression>"), + QmlJS::Dialect::Json); + + jsonDoc->setSource(jsonContent); + jsonDoc->parseJavaScript(); + + if (!jsonDoc->isParsedCorrectly()) + return {}; + + jsonDoc->ast()->accept(&finder); + return finder.m_orderedList; + } + +protected: + bool visit(QmlJS::AST::PatternProperty *patternProperty) override + { + const QString propertyName = patternProperty->name->asString(); + if (!m_propertySet.contains(propertyName)) { + m_propertySet.insert(propertyName); + m_orderedList.append(propertyName); + } + return true; + } + + void throwRecursionDepthError() override + { + qWarning() << Q_FUNC_INFO << __LINE__ << "Recursion depth error"; + }; + +private: + QSet<QString> m_propertySet; + QStringList m_orderedList; +}; + QString CollectionParseError::errorString() const { switch (errorNo) { @@ -690,7 +734,7 @@ CollectionDetails CollectionDetails::fromImportedCsv(const QByteArray &document) return fromImportedJson(importedArray); } -CollectionDetails CollectionDetails::fromImportedJson(const QJsonDocument &document) +CollectionDetails CollectionDetails::fromImportedJson(const QByteArray &json, QJsonParseError *error) { QJsonArray importedCollection; auto refineJsonArray = [](const QJsonArray &array) -> QJsonArray { @@ -710,6 +754,14 @@ CollectionDetails CollectionDetails::fromImportedJson(const QJsonDocument &docum return resultArray; }; + QJsonParseError parseError; + QJsonDocument document = QJsonDocument::fromJson(json, &parseError); + if (error) + *error = parseError; + + if (parseError.error != QJsonParseError::NoError) + return CollectionDetails{}; + if (document.isArray()) { importedCollection = refineJsonArray(document.array()); } else if (document.isObject()) { @@ -738,7 +790,7 @@ CollectionDetails CollectionDetails::fromImportedJson(const QJsonDocument &docum } } - return fromImportedJson(importedCollection); + return fromImportedJson(importedCollection, PropertyOrderFinder::parse(QLatin1String(json))); } CollectionDetails CollectionDetails::fromLocalJson(const QJsonDocument &document, @@ -803,9 +855,24 @@ void CollectionDetails::insertRecords(const QJsonArray &record, int idx, int cou d->dataRecords.insert(idx, count, localRecord); } -CollectionDetails CollectionDetails::fromImportedJson(const QJsonArray &importedArray) +CollectionDetails CollectionDetails::fromImportedJson(const QJsonArray &importedArray, + const QStringList &propertyPriority) { - const QList<CollectionProperty> columnData = getColumnsFromImportedJsonArray(importedArray); + QList<CollectionProperty> columnData = getColumnsFromImportedJsonArray(importedArray); + if (!propertyPriority.isEmpty()) { + QMap<QString, int> priorityMap; + for (const QString &propertyName : propertyPriority) { + if (!priorityMap.contains(propertyName)) + priorityMap.insert(propertyName, priorityMap.size()); + } + const int lowestPriority = priorityMap.size(); + + Utils::sort(columnData, [&](const CollectionProperty &a, const CollectionProperty &b) { + return priorityMap.value(a.name, lowestPriority) + < priorityMap.value(b.name, lowestPriority); + }); + } + QList<QJsonArray> localJsonArray; for (const QJsonValue &importedRowValue : importedArray) { QJsonObject importedRowObject = importedRowValue.toObject(); diff --git a/src/plugins/qmldesigner/components/collectioneditor/collectiondetails.h b/src/plugins/qmldesigner/components/collectioneditor/collectiondetails.h index 2ccc69e447..95528413f6 100644 --- a/src/plugins/qmldesigner/components/collectioneditor/collectiondetails.h +++ b/src/plugins/qmldesigner/components/collectioneditor/collectiondetails.h @@ -9,6 +9,7 @@ QT_BEGIN_NAMESPACE class QJsonObject; +struct QJsonParseError; class QVariant; QT_END_NAMESPACE @@ -125,7 +126,8 @@ public: static void registerDeclarativeType(); static CollectionDetails fromImportedCsv(const QByteArray &document); - static CollectionDetails fromImportedJson(const QJsonDocument &document); + static CollectionDetails fromImportedJson(const QByteArray &json, + QJsonParseError *error = nullptr); static CollectionDetails fromLocalJson(const QJsonDocument &document, const QString &collectionName, CollectionParseError *error = nullptr); @@ -136,7 +138,8 @@ private: void markChanged(); void insertRecords(const QJsonArray &record, int idx = -1, int count = 1); - static CollectionDetails fromImportedJson(const QJsonArray &importedArray); + static CollectionDetails fromImportedJson(const QJsonArray &importedArray, + const QStringList &propertyPriority = {}); static CollectionDetails fromLocalCollection(const QJsonObject &localCollection, CollectionParseError *error = nullptr); diff --git a/src/plugins/qmldesigner/components/collectioneditor/collectionwidget.cpp b/src/plugins/qmldesigner/components/collectioneditor/collectionwidget.cpp index efffa2c2e9..24fb745ab7 100644 --- a/src/plugins/qmldesigner/components/collectioneditor/collectionwidget.cpp +++ b/src/plugins/qmldesigner/components/collectioneditor/collectionwidget.cpp @@ -306,13 +306,11 @@ bool CollectionWidget::importFile(const QString &collectionName, const QUrl &url return false; QJsonParseError parseError; - QJsonDocument document = QJsonDocument::fromJson(fileContent, &parseError); + loadedCollection = CollectionDetails::fromImportedJson(fileContent, &parseError); if (parseError.error != QJsonParseError::NoError) { warn(tr("Json file Import error"), tr("Cannot parse json content\n%1").arg(parseError.errorString())); } - - loadedCollection = CollectionDetails::fromImportedJson(document); } else if (fileInfo.suffix() == "csv") { if (!loadUrlContent()) return false; |