forked from qt-creator/qt-creator
AssetExport: Enable generating multiple metadata files
Task-number: QDS-3357
Change-Id: Icc591d61d149ff92b6c415434e2a7574103802ae
Reviewed-by: Thomas Hartmann <thomas.hartmann@qt.io>
Reviewed-by: Leena Miettinen <riitta-leena.miettinen@qt.io>
(cherry picked from commit f1268a9f86
)
This commit is contained in:
@@ -96,6 +96,11 @@ AssetExportDialog::AssetExportDialog(const Utils::FilePath &exportPath,
|
|||||||
m_exportAssetsCheck->setChecked(true);
|
m_exportAssetsCheck->setChecked(true);
|
||||||
optionsLayout->addWidget(m_exportAssetsCheck);
|
optionsLayout->addWidget(m_exportAssetsCheck);
|
||||||
|
|
||||||
|
m_perComponentExportCheck = new QCheckBox(tr("Export components separately"), this);
|
||||||
|
m_perComponentExportCheck->setChecked(false);
|
||||||
|
optionsLayout->addWidget(m_perComponentExportCheck);
|
||||||
|
optionsLayout->addStretch();
|
||||||
|
|
||||||
m_ui->buttonBox->button(QDialogButtonBox::Cancel)->setEnabled(false);
|
m_ui->buttonBox->button(QDialogButtonBox::Cancel)->setEnabled(false);
|
||||||
|
|
||||||
m_ui->stackedWidget->addWidget(m_filesView);
|
m_ui->stackedWidget->addWidget(m_filesView);
|
||||||
@@ -149,7 +154,8 @@ void AssetExportDialog::onExport()
|
|||||||
m_exportLogs->clear();
|
m_exportLogs->clear();
|
||||||
|
|
||||||
m_assetExporter.exportQml(m_filePathModel.files(), m_ui->exportPath->fileName(),
|
m_assetExporter.exportQml(m_filePathModel.files(), m_ui->exportPath->fileName(),
|
||||||
m_exportAssetsCheck->isChecked());
|
m_exportAssetsCheck->isChecked(),
|
||||||
|
m_perComponentExportCheck->isChecked());
|
||||||
}
|
}
|
||||||
|
|
||||||
void AssetExportDialog::onExportStateChanged(AssetExporter::ParsingState newState)
|
void AssetExportDialog::onExportStateChanged(AssetExporter::ParsingState newState)
|
||||||
|
@@ -74,6 +74,7 @@ private:
|
|||||||
std::unique_ptr<Ui::AssetExportDialog> m_ui;
|
std::unique_ptr<Ui::AssetExportDialog> m_ui;
|
||||||
QPushButton *m_exportBtn = nullptr;
|
QPushButton *m_exportBtn = nullptr;
|
||||||
QCheckBox *m_exportAssetsCheck = nullptr;
|
QCheckBox *m_exportAssetsCheck = nullptr;
|
||||||
|
QCheckBox *m_perComponentExportCheck = nullptr;
|
||||||
QListView *m_filesView = nullptr;
|
QListView *m_filesView = nullptr;
|
||||||
QPlainTextEdit *m_exportLogs = nullptr;
|
QPlainTextEdit *m_exportLogs = nullptr;
|
||||||
Utils::OutputFormatter *m_outputFormatter = nullptr;
|
Utils::OutputFormatter *m_outputFormatter = nullptr;
|
||||||
|
@@ -115,15 +115,20 @@ AssetExporter::~AssetExporter()
|
|||||||
}
|
}
|
||||||
|
|
||||||
void AssetExporter::exportQml(const Utils::FilePaths &qmlFiles, const Utils::FilePath &exportPath,
|
void AssetExporter::exportQml(const Utils::FilePaths &qmlFiles, const Utils::FilePath &exportPath,
|
||||||
bool exportAssets)
|
bool exportAssets, bool perComponentExport)
|
||||||
{
|
{
|
||||||
ExportNotification::addInfo(tr("Exporting metadata at %1. Export assets: ")
|
m_perComponentExport = perComponentExport;
|
||||||
|
ExportNotification::addInfo(tr("Export root directory: %1.\nExporting assets: %2")
|
||||||
.arg(exportPath.toUserOutput())
|
.arg(exportPath.toUserOutput())
|
||||||
.arg(exportAssets? tr("Yes") : tr("No")));
|
.arg(exportAssets? tr("Yes") : tr("No")));
|
||||||
|
|
||||||
|
if (m_perComponentExport)
|
||||||
|
ExportNotification::addInfo(tr("Each component is exported separately"));
|
||||||
|
|
||||||
notifyProgress(0.0);
|
notifyProgress(0.0);
|
||||||
m_exportFiles = qmlFiles;
|
m_exportFiles = qmlFiles;
|
||||||
m_totalFileCount = m_exportFiles.count();
|
m_totalFileCount = m_exportFiles.count();
|
||||||
m_components = QJsonArray();
|
m_components.clear();
|
||||||
m_exportPath = exportPath;
|
m_exportPath = exportPath;
|
||||||
m_currentState.change(ParsingState::Parsing);
|
m_currentState.change(ParsingState::Parsing);
|
||||||
triggerLoadNextFile();
|
triggerLoadNextFile();
|
||||||
@@ -149,22 +154,26 @@ bool AssetExporter::isBusy() const
|
|||||||
m_currentState == AssetExporter::ParsingState::WritingJson;
|
m_currentState == AssetExporter::ParsingState::WritingJson;
|
||||||
}
|
}
|
||||||
|
|
||||||
Utils::FilePath AssetExporter::exportAsset(const QmlObjectNode &node, const QString &uuid)
|
Utils::FilePath AssetExporter::exportAsset(const QmlObjectNode &node, const Component *component,
|
||||||
|
const QString &uuid)
|
||||||
{
|
{
|
||||||
if (m_cancelled)
|
if (m_cancelled)
|
||||||
return {};
|
return {};
|
||||||
Utils::FilePath assetPath = m_exportPath.pathAppended(QString("assets/%1.png").arg(uuid));
|
const Utils::FilePath assetExportDir = m_perComponentExport ? componentExportDir(component) :
|
||||||
|
m_exportPath;
|
||||||
|
const QString fileName = uuid + ".png";
|
||||||
|
const Utils::FilePath assetPath = assetExportDir.pathAppended("assets").pathAppended(fileName);
|
||||||
if (m_assetDumper)
|
if (m_assetDumper)
|
||||||
m_assetDumper->dumpAsset(node.toQmlItemNode().instanceRenderPixmap(), assetPath);
|
m_assetDumper->dumpAsset(node.toQmlItemNode().instanceRenderPixmap(), assetPath);
|
||||||
|
|
||||||
return assetPath;
|
return assetPath;
|
||||||
}
|
}
|
||||||
|
|
||||||
void AssetExporter::exportComponent(const ModelNode &rootNode)
|
void AssetExporter::exportComponent(const ModelNode &rootNode)
|
||||||
{
|
{
|
||||||
qCDebug(loggerInfo) << "Exporting component" << rootNode.id();
|
qCDebug(loggerInfo) << "Exporting component" << rootNode.id();
|
||||||
Component exporter(*this, rootNode);
|
m_components.push_back(make_unique<Component>(*this, rootNode));
|
||||||
exporter.exportComponent();
|
m_components.back()->exportComponent();
|
||||||
m_components.append(exporter.json());
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void AssetExporter::notifyLoadError(AssetExporterView::LoadState state)
|
void AssetExporter::notifyLoadError(AssetExporterView::LoadState state)
|
||||||
@@ -212,6 +221,11 @@ void AssetExporter::onQmlFileLoaded()
|
|||||||
triggerLoadNextFile();
|
triggerLoadNextFile();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Utils::FilePath AssetExporter::componentExportDir(const Component *component) const
|
||||||
|
{
|
||||||
|
return m_exportPath.pathAppended(component->name());
|
||||||
|
}
|
||||||
|
|
||||||
QByteArray AssetExporter::generateUuid(const ModelNode &node)
|
QByteArray AssetExporter::generateUuid(const ModelNode &node)
|
||||||
{
|
{
|
||||||
QByteArray uuid;
|
QByteArray uuid;
|
||||||
@@ -252,26 +266,48 @@ void AssetExporter::writeMetadata() const
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
auto const startupProject = ProjectExplorer::SessionManager::startupProject();
|
|
||||||
QTC_ASSERT(startupProject, return);
|
auto writeFile = [](const Utils::FilePath &path, const QJsonArray &artboards) {
|
||||||
const QString projectName = startupProject->displayName();
|
if (!makeParentPath(path)) {
|
||||||
Utils::FilePath metadataPath = m_exportPath.pathAppended(projectName + ".metadata");
|
ExportNotification::addError(tr("Writing metadata failed. Cannot create file %1").
|
||||||
ExportNotification::addInfo(tr("Writing metadata to file %1.").
|
arg(path.toString()));
|
||||||
arg(metadataPath.toUserOutput()));
|
return;
|
||||||
makeParentPath(metadataPath);
|
}
|
||||||
m_currentState.change(ParsingState::WritingJson);
|
|
||||||
|
ExportNotification::addInfo(tr("Writing metadata to file %1.").arg(path.toUserOutput()));
|
||||||
|
|
||||||
QJsonObject jsonRoot; // TODO: Write plugin info to root
|
QJsonObject jsonRoot; // TODO: Write plugin info to root
|
||||||
jsonRoot.insert("artboards", m_components);
|
jsonRoot.insert("artboards", artboards);
|
||||||
QJsonDocument doc(jsonRoot);
|
QJsonDocument doc(jsonRoot);
|
||||||
if (doc.isNull() || doc.isEmpty()) {
|
if (doc.isNull() || doc.isEmpty()) {
|
||||||
ExportNotification::addError(tr("Empty JSON document."));
|
ExportNotification::addError(tr("Empty JSON document."));
|
||||||
} else {
|
return;
|
||||||
Utils::FileSaver saver(metadataPath.toString(), QIODevice::Text);
|
}
|
||||||
|
|
||||||
|
Utils::FileSaver saver(path.toString(), QIODevice::Text);
|
||||||
saver.write(doc.toJson(QJsonDocument::Indented));
|
saver.write(doc.toJson(QJsonDocument::Indented));
|
||||||
if (!saver.finalize()) {
|
if (!saver.finalize()) {
|
||||||
ExportNotification::addError(tr("Writing metadata failed. %1").
|
ExportNotification::addError(tr("Writing metadata failed. %1").
|
||||||
arg(saver.errorString()));
|
arg(saver.errorString()));
|
||||||
}
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
m_currentState.change(ParsingState::WritingJson);
|
||||||
|
|
||||||
|
auto const startupProject = ProjectExplorer::SessionManager::startupProject();
|
||||||
|
QTC_ASSERT(startupProject, return);
|
||||||
|
const QString projectName = startupProject->displayName();
|
||||||
|
|
||||||
|
if (m_perComponentExport) {
|
||||||
|
for (auto &component : m_components) {
|
||||||
|
const Utils::FilePath path = componentExportDir(component.get());
|
||||||
|
writeFile(path.pathAppended(component->name() + ".metadata"), {component->json()});
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
QJsonArray artboards;
|
||||||
|
std::transform(m_components.cbegin(), m_components.cend(), back_inserter(artboards),
|
||||||
|
[](const unique_ptr<Component> &c) {return c->json(); });
|
||||||
|
writeFile(m_exportPath.pathAppended(projectName + ".metadata"), artboards);
|
||||||
}
|
}
|
||||||
notifyProgress(1.0);
|
notifyProgress(1.0);
|
||||||
ExportNotification::addInfo(tr("Export finished."));
|
ExportNotification::addInfo(tr("Export finished."));
|
||||||
|
@@ -43,6 +43,7 @@ class Project;
|
|||||||
|
|
||||||
namespace QmlDesigner {
|
namespace QmlDesigner {
|
||||||
class AssetDumper;
|
class AssetDumper;
|
||||||
|
class Component;
|
||||||
|
|
||||||
class AssetExporter : public QObject
|
class AssetExporter : public QObject
|
||||||
{
|
{
|
||||||
@@ -65,12 +66,13 @@ public:
|
|||||||
~AssetExporter();
|
~AssetExporter();
|
||||||
|
|
||||||
void exportQml(const Utils::FilePaths &qmlFiles, const Utils::FilePath &exportPath,
|
void exportQml(const Utils::FilePaths &qmlFiles, const Utils::FilePath &exportPath,
|
||||||
bool exportAssets = false);
|
bool exportAssets, bool perComponentExport);
|
||||||
|
|
||||||
void cancel();
|
void cancel();
|
||||||
bool isBusy() const;
|
bool isBusy() const;
|
||||||
|
|
||||||
Utils::FilePath exportAsset(const QmlObjectNode& node, const QString &uuid);
|
Utils::FilePath exportAsset(const QmlObjectNode& node, const Component *component,
|
||||||
|
const QString &uuid);
|
||||||
QByteArray generateUuid(const ModelNode &node);
|
QByteArray generateUuid(const ModelNode &node);
|
||||||
|
|
||||||
signals:
|
signals:
|
||||||
@@ -87,6 +89,7 @@ private:
|
|||||||
void loadNextFile();
|
void loadNextFile();
|
||||||
|
|
||||||
void onQmlFileLoaded();
|
void onQmlFileLoaded();
|
||||||
|
Utils::FilePath componentExportDir(const Component *component) const;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
mutable class State {
|
mutable class State {
|
||||||
@@ -102,7 +105,8 @@ private:
|
|||||||
Utils::FilePaths m_exportFiles;
|
Utils::FilePaths m_exportFiles;
|
||||||
unsigned int m_totalFileCount = 0;
|
unsigned int m_totalFileCount = 0;
|
||||||
Utils::FilePath m_exportPath;
|
Utils::FilePath m_exportPath;
|
||||||
QJsonArray m_components;
|
bool m_perComponentExport = false;
|
||||||
|
std::vector<std::unique_ptr<Component>> m_components;
|
||||||
QSet<QByteArray> m_usedHashes;
|
QSet<QByteArray> m_usedHashes;
|
||||||
std::unique_ptr<AssetDumper> m_assetDumper;
|
std::unique_ptr<AssetDumper> m_assetDumper;
|
||||||
bool m_cancelled = false;
|
bool m_cancelled = false;
|
||||||
|
@@ -64,7 +64,9 @@ Component::Component(AssetExporter &exporter, const ModelNode &rootNode):
|
|||||||
m_exporter(exporter),
|
m_exporter(exporter),
|
||||||
m_rootNode(rootNode)
|
m_rootNode(rootNode)
|
||||||
{
|
{
|
||||||
|
m_name = m_rootNode.id();
|
||||||
|
if (m_name.isEmpty())
|
||||||
|
m_name = QString::fromUtf8(m_rootNode.type());
|
||||||
}
|
}
|
||||||
|
|
||||||
QJsonObject Component::json() const
|
QJsonObject Component::json() const
|
||||||
@@ -88,6 +90,11 @@ void Component::exportComponent()
|
|||||||
addImports();
|
addImports();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const QString &Component::name() const
|
||||||
|
{
|
||||||
|
return m_name;
|
||||||
|
}
|
||||||
|
|
||||||
ModelNodeParser *Component::createNodeParser(const ModelNode &node) const
|
ModelNodeParser *Component::createNodeParser(const ModelNode &node) const
|
||||||
{
|
{
|
||||||
QByteArrayList lineage = populateLineage(node);
|
QByteArrayList lineage = populateLineage(node);
|
||||||
|
@@ -75,6 +75,7 @@ public:
|
|||||||
Component(AssetExporter& exporter, const ModelNode &rootNode);
|
Component(AssetExporter& exporter, const ModelNode &rootNode);
|
||||||
|
|
||||||
void exportComponent();
|
void exportComponent();
|
||||||
|
const QString &name() const;
|
||||||
QJsonObject json() const;
|
QJsonObject json() const;
|
||||||
|
|
||||||
AssetExporter &exporter();
|
AssetExporter &exporter();
|
||||||
@@ -92,6 +93,7 @@ private:
|
|||||||
private:
|
private:
|
||||||
AssetExporter& m_exporter;
|
AssetExporter& m_exporter;
|
||||||
const ModelNode &m_rootNode;
|
const ModelNode &m_rootNode;
|
||||||
|
QString m_name;
|
||||||
QJsonObject m_json;
|
QJsonObject m_json;
|
||||||
static std::vector<std::unique_ptr<Internal::NodeParserCreatorBase>> m_readers;
|
static std::vector<std::unique_ptr<Internal::NodeParserCreatorBase>> m_readers;
|
||||||
};
|
};
|
||||||
|
@@ -54,7 +54,7 @@ QJsonObject AssetNodeParser::json(Component &component) const
|
|||||||
{
|
{
|
||||||
QJsonObject jsonObject = ItemNodeParser::json(component);
|
QJsonObject jsonObject = ItemNodeParser::json(component);
|
||||||
|
|
||||||
Utils::FilePath assetPath = component.exporter().exportAsset(objectNode(), uuid());
|
Utils::FilePath assetPath = component.exporter().exportAsset(objectNode(), &component, uuid());
|
||||||
QJsonObject assetData;
|
QJsonObject assetData;
|
||||||
assetData.insert(AssetPathTag, assetPath.toString());
|
assetData.insert(AssetPathTag, assetPath.toString());
|
||||||
|
|
||||||
|
Reference in New Issue
Block a user