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>
This commit is contained in:
Vikas Pachdha
2021-01-06 10:51:57 +01:00
parent 4618018c4b
commit f1268a9f86
7 changed files with 85 additions and 29 deletions

View File

@@ -96,6 +96,11 @@ AssetExportDialog::AssetExportDialog(const Utils::FilePath &exportPath,
m_exportAssetsCheck->setChecked(true);
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->stackedWidget->addWidget(m_filesView);
@@ -149,7 +154,8 @@ void AssetExportDialog::onExport()
m_exportLogs->clear();
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)

View File

@@ -74,6 +74,7 @@ private:
std::unique_ptr<Ui::AssetExportDialog> m_ui;
QPushButton *m_exportBtn = nullptr;
QCheckBox *m_exportAssetsCheck = nullptr;
QCheckBox *m_perComponentExportCheck = nullptr;
QListView *m_filesView = nullptr;
QPlainTextEdit *m_exportLogs = nullptr;
Utils::OutputFormatter *m_outputFormatter = nullptr;

View File

@@ -115,15 +115,20 @@ AssetExporter::~AssetExporter()
}
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(exportAssets? tr("Yes") : tr("No")));
if (m_perComponentExport)
ExportNotification::addInfo(tr("Each component is exported separately"));
notifyProgress(0.0);
m_exportFiles = qmlFiles;
m_totalFileCount = m_exportFiles.count();
m_components = QJsonArray();
m_components.clear();
m_exportPath = exportPath;
m_currentState.change(ParsingState::Parsing);
triggerLoadNextFile();
@@ -149,22 +154,26 @@ bool AssetExporter::isBusy() const
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)
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)
m_assetDumper->dumpAsset(node.toQmlItemNode().instanceRenderPixmap(), assetPath);
return assetPath;
}
void AssetExporter::exportComponent(const ModelNode &rootNode)
{
qCDebug(loggerInfo) << "Exporting component" << rootNode.id();
Component exporter(*this, rootNode);
exporter.exportComponent();
m_components.append(exporter.json());
m_components.push_back(make_unique<Component>(*this, rootNode));
m_components.back()->exportComponent();
}
void AssetExporter::notifyLoadError(AssetExporterView::LoadState state)
@@ -212,6 +221,11 @@ void AssetExporter::onQmlFileLoaded()
triggerLoadNextFile();
}
Utils::FilePath AssetExporter::componentExportDir(const Component *component) const
{
return m_exportPath.pathAppended(component->name());
}
QByteArray AssetExporter::generateUuid(const ModelNode &node)
{
QByteArray uuid;
@@ -252,26 +266,48 @@ void AssetExporter::writeMetadata() const
return;
}
auto const startupProject = ProjectExplorer::SessionManager::startupProject();
QTC_ASSERT(startupProject, return);
const QString projectName = startupProject->displayName();
Utils::FilePath metadataPath = m_exportPath.pathAppended(projectName + ".metadata");
ExportNotification::addInfo(tr("Writing metadata to file %1.").
arg(metadataPath.toUserOutput()));
makeParentPath(metadataPath);
m_currentState.change(ParsingState::WritingJson);
QJsonObject jsonRoot; // TODO: Write plugin info to root
jsonRoot.insert("artboards", m_components);
QJsonDocument doc(jsonRoot);
if (doc.isNull() || doc.isEmpty()) {
ExportNotification::addError(tr("Empty JSON document."));
} else {
Utils::FileSaver saver(metadataPath.toString(), QIODevice::Text);
auto writeFile = [](const Utils::FilePath &path, const QJsonArray &artboards) {
if (!makeParentPath(path)) {
ExportNotification::addError(tr("Writing metadata failed. Cannot create file %1").
arg(path.toString()));
return;
}
ExportNotification::addInfo(tr("Writing metadata to file %1.").arg(path.toUserOutput()));
QJsonObject jsonRoot; // TODO: Write plugin info to root
jsonRoot.insert("artboards", artboards);
QJsonDocument doc(jsonRoot);
if (doc.isNull() || doc.isEmpty()) {
ExportNotification::addError(tr("Empty JSON document."));
return;
}
Utils::FileSaver saver(path.toString(), QIODevice::Text);
saver.write(doc.toJson(QJsonDocument::Indented));
if (!saver.finalize()) {
ExportNotification::addError(tr("Writing metadata failed. %1").
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);
ExportNotification::addInfo(tr("Export finished."));

View File

@@ -43,6 +43,7 @@ class Project;
namespace QmlDesigner {
class AssetDumper;
class Component;
class AssetExporter : public QObject
{
@@ -65,12 +66,13 @@ public:
~AssetExporter();
void exportQml(const Utils::FilePaths &qmlFiles, const Utils::FilePath &exportPath,
bool exportAssets = false);
bool exportAssets, bool perComponentExport);
void cancel();
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);
signals:
@@ -87,6 +89,7 @@ private:
void loadNextFile();
void onQmlFileLoaded();
Utils::FilePath componentExportDir(const Component *component) const;
private:
mutable class State {
@@ -102,7 +105,8 @@ private:
Utils::FilePaths m_exportFiles;
unsigned int m_totalFileCount = 0;
Utils::FilePath m_exportPath;
QJsonArray m_components;
bool m_perComponentExport = false;
std::vector<std::unique_ptr<Component>> m_components;
QSet<QByteArray> m_usedHashes;
std::unique_ptr<AssetDumper> m_assetDumper;
bool m_cancelled = false;

View File

@@ -64,7 +64,9 @@ Component::Component(AssetExporter &exporter, const ModelNode &rootNode):
m_exporter(exporter),
m_rootNode(rootNode)
{
m_name = m_rootNode.id();
if (m_name.isEmpty())
m_name = QString::fromUtf8(m_rootNode.type());
}
QJsonObject Component::json() const
@@ -88,6 +90,11 @@ void Component::exportComponent()
addImports();
}
const QString &Component::name() const
{
return m_name;
}
NodeDumper *Component::createNodeDumper(const ModelNode &node) const
{
QByteArrayList lineage = populateLineage(node);

View File

@@ -75,6 +75,7 @@ public:
Component(AssetExporter& exporter, const ModelNode &rootNode);
void exportComponent();
const QString &name() const;
QJsonObject json() const;
AssetExporter &exporter();
@@ -92,6 +93,7 @@ private:
private:
AssetExporter& m_exporter;
const ModelNode &m_rootNode;
QString m_name;
QJsonObject m_json;
static std::vector<std::unique_ptr<Internal::NodeDumperCreatorBase>> m_readers;
};

View File

@@ -54,7 +54,7 @@ QJsonObject AssetNodeDumper::json(Component &component) const
{
QJsonObject jsonObject = ItemNodeDumper::json(component);
Utils::FilePath assetPath = component.exporter().exportAsset(objectNode(), uuid());
Utils::FilePath assetPath = component.exporter().exportAsset(objectNode(), &component, uuid());
QJsonObject assetData;
assetData.insert(AssetPathTag, assetPath.toString());