Merge remote-tracking branch 'origin/4.14'

Conflicts:
	src/plugins/mcusupport/mcusupportoptions.cpp
	src/plugins/qmldesigner/assetexporterplugin/componentexporter.cpp

Change-Id: I337d1b86f54ad4433a3ed0d73e2011654ef6b950
This commit is contained in:
Eike Ziller
2021-02-02 12:20:00 +01:00
17 changed files with 339 additions and 63 deletions

View File

@@ -650,10 +650,13 @@ static void setKitEnvironment(Kit *k, const McuTarget *mcuTarget,
processPackage(package);
processPackage(qtForMCUsSdkPackage);
const QString path = QLatin1String(HostOsInfo::isWindowsHost() ? "Path" : "PATH");
pathAdditions.append("${" + path + "}");
pathAdditions.append(QDir::toNativeSeparators(Core::ICore::libexecPath() + "/clang/bin"));
changes.append({path, pathAdditions.join(HostOsInfo::pathListSeparator())});
// Clang not needed in version 1.7+
if (mcuTarget->qulVersion() < QVersionNumber{1,7}) {
const QString path = QLatin1String(HostOsInfo::isWindowsHost() ? "Path" : "PATH");
pathAdditions.append("${" + path + "}");
pathAdditions.append(QDir::toNativeSeparators(Core::ICore::libexecPath() + "/clang/bin"));
changes.append({path, pathAdditions.join(HostOsInfo::pathListSeparator())});
}
if (kitNeedsQtVersion())
changes.append({QLatin1String("LD_LIBRARY_PATH"), "%{Qt:QT_INSTALL_LIBS}"});

View File

@@ -28,6 +28,7 @@
#include "exportnotification.h"
#include "designdocument.h"
#include "nodemetainfo.h"
#include "qmldesignerplugin.h"
#include "rewriterview.h"
#include "qmlitemnode.h"
@@ -43,6 +44,7 @@
#include <QJsonArray>
#include <QJsonDocument>
#include <QLoggingCategory>
#include <QPlainTextEdit>
#include <QWaitCondition>
#include <random>
@@ -130,13 +132,27 @@ void AssetExporter::exportQml(const Utils::FilePaths &qmlFiles, const Utils::Fil
m_exportFiles = qmlFiles;
m_totalFileCount = m_exportFiles.count();
m_components.clear();
m_componentUuidCache.clear();
m_exportPath = exportPath;
m_currentState.change(ParsingState::Parsing);
triggerLoadNextFile();
if (exportAssets)
m_assetDumper = make_unique<AssetDumper>();
else
m_assetDumper.reset();
QTimer::singleShot(0, this, &AssetExporter::beginExport);
}
void AssetExporter::beginExport()
{
for (const Utils::FilePath &p : m_exportFiles) {
if (m_cancelled)
break;
preprocessQmlFile(p);
}
if (!m_cancelled)
triggerLoadNextFile();
}
void AssetExporter::cancel()
@@ -253,6 +269,68 @@ Utils::FilePath AssetExporter::componentExportDir(const Component *component) co
return m_exportPath.pathAppended(component->name());
}
void AssetExporter::preprocessQmlFile(const Utils::FilePath &path)
{
// Load the QML file and assign UUIDs to items having none.
// Meanwhile cache the Component UUIDs as well
std::unique_ptr<Model> model(Model::create("Item", 2, 7));
Utils::FileReader reader;
if (!reader.fetch(path.toString())) {
ExportNotification::addError(tr("Cannot preprocess file: %1. Error %2")
.arg(path.toString()).arg(reader.errorString()));
return;
}
QPlainTextEdit textEdit;
textEdit.setPlainText(QString::fromUtf8(reader.data()));
NotIndentingTextEditModifier *modifier = new NotIndentingTextEditModifier(&textEdit);
modifier->setParent(model.get());
RewriterView *rewriterView = new RewriterView(QmlDesigner::RewriterView::Validate, model.get());
rewriterView->setCheckSemanticErrors(false);
rewriterView->setTextModifier(modifier);
model->attachView(rewriterView);
rewriterView->restoreAuxiliaryData();
ModelNode rootNode = rewriterView->rootModelNode();
if (!rootNode.isValid()) {
ExportNotification::addError(tr("Cannot preprocess file: %1").arg(path.toString()));
return;
}
if (assignUuids(rootNode)) {
// Some UUIDs were assigned. Rewrite the file.
rewriterView->writeAuxiliaryData();
const QByteArray data = textEdit.toPlainText().toUtf8();
Utils::FileSaver saver(path.toString(), QIODevice::Text);
saver.write(data);
if (!saver.finalize()) {
ExportNotification::addError(tr("Cannot update %1.\n%2")
.arg(path.toString()).arg(saver.errorString()));
return;
}
}
// Cache component UUID
const QString uuid = rootNode.auxiliaryData(Constants::UuidAuxTag).toString();
m_componentUuidCache[path.toString()] = uuid;
}
bool AssetExporter::assignUuids(const ModelNode &root)
{
// Assign an UUID to the node without one.
// Return true if an assignment takes place.
bool changed = false;
for (const ModelNode &node : root.allSubModelNodesAndThisNode()) {
const QString uuid = node.auxiliaryData(Constants::UuidAuxTag).toString();
if (uuid.isEmpty()) {
// Assign an unique identifier to the node.
QByteArray uuid = generateUuid(node);
node.setAuxiliaryData(Constants::UuidAuxTag, QString::fromLatin1(uuid));
changed = true;
}
}
return changed;
}
QByteArray AssetExporter::generateUuid(const ModelNode &node)
{
QByteArray uuid;
@@ -263,6 +341,20 @@ QByteArray AssetExporter::generateUuid(const ModelNode &node)
return uuid;
}
QString AssetExporter::componentUuid(const ModelNode &instance) const
{
// Returns the UUID of the component's root node
// Empty string is returned if the node is not an instance of a component within
// the project.
NodeMetaInfo metaInfo = instance.metaInfo();
if (!metaInfo.isValid())
return {};
const QString path = metaInfo.componentFileName();
if (m_componentUuidCache.contains(path))
return m_componentUuidCache[path];
return {};
}
void AssetExporter::triggerLoadNextFile()
{
QTimer::singleShot(0, this, &AssetExporter::loadNextFile);

View File

@@ -76,6 +76,7 @@ public:
const QString &suffix = {}) const;
void exportAsset(const QPixmap &asset, const Utils::FilePath &path);
QByteArray generateUuid(const ModelNode &node);
QString componentUuid(const ModelNode &instance) const;
signals:
void stateChanged(ParsingState);
@@ -93,6 +94,10 @@ private:
void onQmlFileLoaded();
Utils::FilePath componentExportDir(const Component *component) const;
void beginExport();
void preprocessQmlFile(const Utils::FilePath &path);
bool assignUuids(const ModelNode &root);
private:
mutable class State {
public:
@@ -109,6 +114,7 @@ private:
Utils::FilePath m_exportPath;
bool m_perComponentExport = false;
std::vector<std::unique_ptr<Component>> m_components;
QHash<QString, QString> m_componentUuidCache;
QSet<QByteArray> m_usedHashes;
QHash<QString, QPixmap> m_assets;
std::unique_ptr<AssetDumper> m_assetDumper;

View File

@@ -67,7 +67,8 @@ const char ReferenceAssetTag[] = "referenceAsset";
const char AssetPathTag[] = "assetPath";
const char AssetBoundsTag[] = "assetBounds";
const char OpacityTag[] = "opacity";
const char TypeNameTag[] = "qmlType";
const char TypeNameTag[] = "typeName";
const char TypeIdTag[] = "typeId";
const char TextDetailsTag[] = "textDetails";
const char FontFamilyTag[] = "fontFamily";

View File

@@ -130,12 +130,6 @@ QJsonObject Component::nodeToJson(const ModelNode &node)
std::unique_ptr<NodeDumper> dumper(createNodeDumper(node));
if (dumper) {
if (dumper->uuid().isEmpty()) {
// Assign an unique identifier to the node.
QByteArray uuid = m_exporter.generateUuid(node);
node.setAuxiliaryData(Constants::UuidAuxTag, QString::fromLatin1(uuid));
node.model()->rewriterView()->writeAuxiliaryData();
}
jsonObject = dumper->json(*this);
} else {
ExportNotification::addError(tr("Error exporting node %1. Cannot parse type %2.")

View File

@@ -25,6 +25,8 @@
#include "itemnodedumper.h"
#include "assetexportpluginconstants.h"
#include "assetexporter.h"
#include "componentexporter.h"
#include "qmlitemnode.h"
@@ -83,6 +85,10 @@ QJsonObject QmlDesigner::ItemNodeDumper::json(QmlDesigner::Component &component)
metadata.insert(ExportTypeTag, ExportTypeChild);
metadata.insert(TypeNameTag, QString::fromLatin1(m_node.type()));
QString typeId = component.exporter().componentUuid(m_node);
if (!typeId.isEmpty())
metadata.insert(TypeIdTag, typeId);
jsonObject.insert(MetadataTag, metadata);
return jsonObject;
}

View File

@@ -60,6 +60,7 @@ AnnotationCommentTab::AnnotationCommentTab(QWidget *parent)
ui->titleEdit->setModel(new QStringListModel{QStringList{"Description",
"Display Condition",
"helper lines",
"position marker",
"highlight",
"project author",
"project confirmed",

View File

@@ -220,8 +220,8 @@ ModelNode TransitionEditorView::addNewTransition()
for (const QmlPropertyChanges & change : state.propertyChanges()) {
QStringList locList;
const ModelNode target = change.target();
const QString targetId = target.id();
if (target.isValid() && target.hasMetaInfo()) {
const QString targetId = target.id();
for (const VariantProperty &property : change.modelNode().variantProperties()) {
TypeName typeName = target.metaInfo().propertyTypeName(property.name());