forked from qt-creator/qt-creator
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>
This commit is contained in:
@@ -6,6 +6,9 @@
|
|||||||
#include "collectioneditorutils.h"
|
#include "collectioneditorutils.h"
|
||||||
|
|
||||||
#include <utils/span.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 <qqml.h>
|
||||||
|
|
||||||
#include <QJsonArray>
|
#include <QJsonArray>
|
||||||
@@ -261,6 +264,47 @@ inline static bool isEmptyJsonValue(const QJsonValue &value)
|
|||||||
return value.isNull() || value.isUndefined() || (value.isString() && value.toString().isEmpty());
|
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
|
QString CollectionParseError::errorString() const
|
||||||
{
|
{
|
||||||
switch (errorNo) {
|
switch (errorNo) {
|
||||||
@@ -690,7 +734,7 @@ CollectionDetails CollectionDetails::fromImportedCsv(const QByteArray &document)
|
|||||||
return fromImportedJson(importedArray);
|
return fromImportedJson(importedArray);
|
||||||
}
|
}
|
||||||
|
|
||||||
CollectionDetails CollectionDetails::fromImportedJson(const QJsonDocument &document)
|
CollectionDetails CollectionDetails::fromImportedJson(const QByteArray &json, QJsonParseError *error)
|
||||||
{
|
{
|
||||||
QJsonArray importedCollection;
|
QJsonArray importedCollection;
|
||||||
auto refineJsonArray = [](const QJsonArray &array) -> QJsonArray {
|
auto refineJsonArray = [](const QJsonArray &array) -> QJsonArray {
|
||||||
@@ -710,6 +754,14 @@ CollectionDetails CollectionDetails::fromImportedJson(const QJsonDocument &docum
|
|||||||
return resultArray;
|
return resultArray;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
QJsonParseError parseError;
|
||||||
|
QJsonDocument document = QJsonDocument::fromJson(json, &parseError);
|
||||||
|
if (error)
|
||||||
|
*error = parseError;
|
||||||
|
|
||||||
|
if (parseError.error != QJsonParseError::NoError)
|
||||||
|
return CollectionDetails{};
|
||||||
|
|
||||||
if (document.isArray()) {
|
if (document.isArray()) {
|
||||||
importedCollection = refineJsonArray(document.array());
|
importedCollection = refineJsonArray(document.array());
|
||||||
} else if (document.isObject()) {
|
} 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,
|
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);
|
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;
|
QList<QJsonArray> localJsonArray;
|
||||||
for (const QJsonValue &importedRowValue : importedArray) {
|
for (const QJsonValue &importedRowValue : importedArray) {
|
||||||
QJsonObject importedRowObject = importedRowValue.toObject();
|
QJsonObject importedRowObject = importedRowValue.toObject();
|
||||||
|
@@ -9,6 +9,7 @@
|
|||||||
|
|
||||||
QT_BEGIN_NAMESPACE
|
QT_BEGIN_NAMESPACE
|
||||||
class QJsonObject;
|
class QJsonObject;
|
||||||
|
struct QJsonParseError;
|
||||||
class QVariant;
|
class QVariant;
|
||||||
QT_END_NAMESPACE
|
QT_END_NAMESPACE
|
||||||
|
|
||||||
@@ -125,7 +126,8 @@ public:
|
|||||||
static void registerDeclarativeType();
|
static void registerDeclarativeType();
|
||||||
|
|
||||||
static CollectionDetails fromImportedCsv(const QByteArray &document);
|
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,
|
static CollectionDetails fromLocalJson(const QJsonDocument &document,
|
||||||
const QString &collectionName,
|
const QString &collectionName,
|
||||||
CollectionParseError *error = nullptr);
|
CollectionParseError *error = nullptr);
|
||||||
@@ -136,7 +138,8 @@ private:
|
|||||||
void markChanged();
|
void markChanged();
|
||||||
void insertRecords(const QJsonArray &record, int idx = -1, int count = 1);
|
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,
|
static CollectionDetails fromLocalCollection(const QJsonObject &localCollection,
|
||||||
CollectionParseError *error = nullptr);
|
CollectionParseError *error = nullptr);
|
||||||
|
|
||||||
|
@@ -306,13 +306,11 @@ bool CollectionWidget::importFile(const QString &collectionName, const QUrl &url
|
|||||||
return false;
|
return false;
|
||||||
|
|
||||||
QJsonParseError parseError;
|
QJsonParseError parseError;
|
||||||
QJsonDocument document = QJsonDocument::fromJson(fileContent, &parseError);
|
loadedCollection = CollectionDetails::fromImportedJson(fileContent, &parseError);
|
||||||
if (parseError.error != QJsonParseError::NoError) {
|
if (parseError.error != QJsonParseError::NoError) {
|
||||||
warn(tr("Json file Import error"),
|
warn(tr("Json file Import error"),
|
||||||
tr("Cannot parse json content\n%1").arg(parseError.errorString()));
|
tr("Cannot parse json content\n%1").arg(parseError.errorString()));
|
||||||
}
|
}
|
||||||
|
|
||||||
loadedCollection = CollectionDetails::fromImportedJson(document);
|
|
||||||
} else if (fileInfo.suffix() == "csv") {
|
} else if (fileInfo.suffix() == "csv") {
|
||||||
if (!loadUrlContent())
|
if (!loadUrlContent())
|
||||||
return false;
|
return false;
|
||||||
|
Reference in New Issue
Block a user