forked from qt-creator/qt-creator
AssetExport: Add typeId and typeName to component instances
typdId is required to identify the instance's component while generating PSDs Task-number: QDS-2811 Change-Id: I61e0fe977e252c9c2aaeacd425b057c92a7c5b49 Reviewed-by: Leena Miettinen <riitta-leena.miettinen@qt.io> Reviewed-by: Thomas Hartmann <thomas.hartmann@qt.io>
This commit is contained in:
@@ -28,6 +28,7 @@
|
|||||||
#include "exportnotification.h"
|
#include "exportnotification.h"
|
||||||
|
|
||||||
#include "designdocument.h"
|
#include "designdocument.h"
|
||||||
|
#include "nodemetainfo.h"
|
||||||
#include "qmldesignerplugin.h"
|
#include "qmldesignerplugin.h"
|
||||||
#include "rewriterview.h"
|
#include "rewriterview.h"
|
||||||
#include "qmlitemnode.h"
|
#include "qmlitemnode.h"
|
||||||
@@ -43,6 +44,7 @@
|
|||||||
#include <QJsonArray>
|
#include <QJsonArray>
|
||||||
#include <QJsonDocument>
|
#include <QJsonDocument>
|
||||||
#include <QLoggingCategory>
|
#include <QLoggingCategory>
|
||||||
|
#include <QPlainTextEdit>
|
||||||
#include <QWaitCondition>
|
#include <QWaitCondition>
|
||||||
|
|
||||||
#include <random>
|
#include <random>
|
||||||
@@ -130,13 +132,27 @@ void AssetExporter::exportQml(const Utils::FilePaths &qmlFiles, const Utils::Fil
|
|||||||
m_exportFiles = qmlFiles;
|
m_exportFiles = qmlFiles;
|
||||||
m_totalFileCount = m_exportFiles.count();
|
m_totalFileCount = m_exportFiles.count();
|
||||||
m_components.clear();
|
m_components.clear();
|
||||||
|
m_componentUuidCache.clear();
|
||||||
m_exportPath = exportPath;
|
m_exportPath = exportPath;
|
||||||
m_currentState.change(ParsingState::Parsing);
|
m_currentState.change(ParsingState::Parsing);
|
||||||
triggerLoadNextFile();
|
|
||||||
if (exportAssets)
|
if (exportAssets)
|
||||||
m_assetDumper = make_unique<AssetDumper>();
|
m_assetDumper = make_unique<AssetDumper>();
|
||||||
else
|
else
|
||||||
m_assetDumper.reset();
|
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()
|
void AssetExporter::cancel()
|
||||||
@@ -253,6 +269,68 @@ Utils::FilePath AssetExporter::componentExportDir(const Component *component) co
|
|||||||
return m_exportPath.pathAppended(component->name());
|
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 AssetExporter::generateUuid(const ModelNode &node)
|
||||||
{
|
{
|
||||||
QByteArray uuid;
|
QByteArray uuid;
|
||||||
@@ -263,6 +341,20 @@ QByteArray AssetExporter::generateUuid(const ModelNode &node)
|
|||||||
return uuid;
|
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()
|
void AssetExporter::triggerLoadNextFile()
|
||||||
{
|
{
|
||||||
QTimer::singleShot(0, this, &AssetExporter::loadNextFile);
|
QTimer::singleShot(0, this, &AssetExporter::loadNextFile);
|
||||||
|
@@ -76,6 +76,7 @@ public:
|
|||||||
const QString &suffix = {}) const;
|
const QString &suffix = {}) const;
|
||||||
void exportAsset(const QPixmap &asset, const Utils::FilePath &path);
|
void exportAsset(const QPixmap &asset, const Utils::FilePath &path);
|
||||||
QByteArray generateUuid(const ModelNode &node);
|
QByteArray generateUuid(const ModelNode &node);
|
||||||
|
QString componentUuid(const ModelNode &instance) const;
|
||||||
|
|
||||||
signals:
|
signals:
|
||||||
void stateChanged(ParsingState);
|
void stateChanged(ParsingState);
|
||||||
@@ -93,6 +94,10 @@ private:
|
|||||||
void onQmlFileLoaded();
|
void onQmlFileLoaded();
|
||||||
Utils::FilePath componentExportDir(const Component *component) const;
|
Utils::FilePath componentExportDir(const Component *component) const;
|
||||||
|
|
||||||
|
void beginExport();
|
||||||
|
void preprocessQmlFile(const Utils::FilePath &path);
|
||||||
|
bool assignUuids(const ModelNode &root);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
mutable class State {
|
mutable class State {
|
||||||
public:
|
public:
|
||||||
@@ -109,6 +114,7 @@ private:
|
|||||||
Utils::FilePath m_exportPath;
|
Utils::FilePath m_exportPath;
|
||||||
bool m_perComponentExport = false;
|
bool m_perComponentExport = false;
|
||||||
std::vector<std::unique_ptr<Component>> m_components;
|
std::vector<std::unique_ptr<Component>> m_components;
|
||||||
|
QHash<QString, QString> m_componentUuidCache;
|
||||||
QSet<QByteArray> m_usedHashes;
|
QSet<QByteArray> m_usedHashes;
|
||||||
QHash<QString, QPixmap> m_assets;
|
QHash<QString, QPixmap> m_assets;
|
||||||
std::unique_ptr<AssetDumper> m_assetDumper;
|
std::unique_ptr<AssetDumper> m_assetDumper;
|
||||||
|
@@ -67,7 +67,8 @@ const char ReferenceAssetTag[] = "referenceAsset";
|
|||||||
const char AssetPathTag[] = "assetPath";
|
const char AssetPathTag[] = "assetPath";
|
||||||
const char AssetBoundsTag[] = "assetBounds";
|
const char AssetBoundsTag[] = "assetBounds";
|
||||||
const char OpacityTag[] = "opacity";
|
const char OpacityTag[] = "opacity";
|
||||||
const char TypeNameTag[] = "qmlType";
|
const char TypeNameTag[] = "typeName";
|
||||||
|
const char TypeIdTag[] = "typeId";
|
||||||
|
|
||||||
const char TextDetailsTag[] = "textDetails";
|
const char TextDetailsTag[] = "textDetails";
|
||||||
const char FontFamilyTag[] = "fontFamily";
|
const char FontFamilyTag[] = "fontFamily";
|
||||||
|
@@ -130,12 +130,6 @@ QJsonObject Component::nodeToJson(const ModelNode &node)
|
|||||||
|
|
||||||
std::unique_ptr<ModelNodeParser> parser(createNodeParser(node));
|
std::unique_ptr<ModelNodeParser> parser(createNodeParser(node));
|
||||||
if (parser) {
|
if (parser) {
|
||||||
if (parser->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 = parser->json(*this);
|
jsonObject = parser->json(*this);
|
||||||
} else {
|
} else {
|
||||||
ExportNotification::addError(tr("Error exporting node %1. Cannot parse type %2.")
|
ExportNotification::addError(tr("Error exporting node %1. Cannot parse type %2.")
|
||||||
|
@@ -25,6 +25,8 @@
|
|||||||
|
|
||||||
#include "modelitemnodeparser.h"
|
#include "modelitemnodeparser.h"
|
||||||
#include "assetexportpluginconstants.h"
|
#include "assetexportpluginconstants.h"
|
||||||
|
#include "assetexporter.h"
|
||||||
|
#include "componentexporter.h"
|
||||||
|
|
||||||
#include "qmlitemnode.h"
|
#include "qmlitemnode.h"
|
||||||
|
|
||||||
@@ -83,6 +85,10 @@ QJsonObject QmlDesigner::ItemNodeParser::json(QmlDesigner::Component &component)
|
|||||||
metadata.insert(ExportTypeTag, ExportTypeChild);
|
metadata.insert(ExportTypeTag, ExportTypeChild);
|
||||||
metadata.insert(TypeNameTag, QString::fromLatin1(m_node.type()));
|
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);
|
jsonObject.insert(MetadataTag, metadata);
|
||||||
return jsonObject;
|
return jsonObject;
|
||||||
}
|
}
|
||||||
|
Reference in New Issue
Block a user