QmlDesigner: Change asset import path

The only import path should be project root, so change things that
are generated under asset_imports to be generated in new folder
GeneratedComponents under project root. GeneratedComponents is prefixed
to the type names of generated items as well.

If project already contains asset_imports folder, then old location is
used.

Fixes: QDS-12430
Change-Id: I7a419fe1c5411e3d39bf3c1e659df0043c60ba33
Reviewed-by: Mahmoud Badri <mahmoud.badri@qt.io>
Reviewed-by: Qt CI Patch Build Bot <ci_patchbuild_bot@qt.io>
Reviewed-by: Thomas Hartmann <thomas.hartmann@qt.io>
This commit is contained in:
Miikka Heikkinen
2024-04-09 15:27:42 +03:00
parent 8b877e7d4c
commit eae76dedff
28 changed files with 336 additions and 128 deletions

View File

@@ -448,9 +448,10 @@ Row {
for (var j = 0; j < myModel.length; ++j) {
let item = myModel[j]
if (root.hideDuplicates && nameMap.has(item.fileName)) {
// Prefer hiding imported asset files rather than other project files
// Prefer hiding generated component files rather than other project files
let listIndex = nameMap.get(item.fileName)
if (comboBox.listModel.get(listIndex).absoluteFilePath.includes("/asset_imports/")) {
let absPath = comboBox.listModel.get(listIndex).absoluteFilePath
if (absPath.includes("/GeneratedComponents/") || absPath.includes("/asset_imports/")) {
comboBox.listModel.set(listIndex, {
absoluteFilePath: item.absoluteFilePath,
relativeFilePath: item.relativeFilePath,

View File

@@ -94,6 +94,11 @@ bool EffectComposerModel::setData(const QModelIndex &index, const QVariant &valu
return true;
}
void EffectComposerModel::setEffectsTypePrefix(const QString &prefix)
{
m_effectTypePrefix = prefix;
}
void EffectComposerModel::setIsEmpty(bool val)
{
if (m_isEmpty != val) {
@@ -1059,7 +1064,7 @@ void EffectComposerModel::saveResources(const QString &name)
Utils::FilePath qmldirPath = effectsResDir.resolvePath(qmldirFileName);
QString qmldirContent = QString::fromUtf8(qmldirPath.fileContents().value_or(QByteArray()));
if (qmldirContent.isEmpty()) {
qmldirContent.append("module Effects\n");
qmldirContent.append(QString("module %1\n").arg(m_effectTypePrefix));
qmldirPath.writeFileContents(qmldirContent.toUtf8());
}
@@ -1077,7 +1082,7 @@ void EffectComposerModel::saveResources(const QString &name)
qmldirPath = effectPath.resolvePath(qmldirFileName);
qmldirContent = QString::fromUtf8(qmldirPath.fileContents().value_or(QByteArray()));
if (qmldirContent.isEmpty()) {
qmldirContent.append("module Effects.");
qmldirContent.append(QString("module %1.").arg(m_effectTypePrefix));
qmldirContent.append(name);
qmldirContent.append('\n');
qmldirContent.append(name);
@@ -1187,7 +1192,7 @@ void EffectComposerModel::saveResources(const QString &name)
endResetModel();
}
emit resourcesSaved(QString("Effects.%1.%1").arg(name).toUtf8(), effectPath);
emit resourcesSaved(QString("%1.%2.%2").arg(m_effectTypePrefix, name).toUtf8(), effectPath);
}
void EffectComposerModel::resetEffectError(int type)

View File

@@ -59,6 +59,8 @@ public:
QVariant data(const QModelIndex &index, int role = Qt::DisplayRole) const override;
bool setData(const QModelIndex &index, const QVariant &value, int role) override;
void setEffectsTypePrefix(const QString &prefix);
bool isEmpty() const { return m_isEmpty; }
void setIsEmpty(bool val);
@@ -221,6 +223,7 @@ private:
QString m_currentComposition;
QTimer m_rebakeTimer;
int m_extraMargin = 0;
QString m_effectTypePrefix;
const QRegularExpression m_spaceReg = QRegularExpression("\\s+");
};

View File

@@ -31,6 +31,7 @@ void EffectComposerContext::contextHelp(const HelpCallback &callback) const
EffectComposerView::EffectComposerView(QmlDesigner::ExternalDependenciesInterface &externalDependencies)
: AbstractView{externalDependencies}
, m_componentUtils(externalDependencies)
{
}
@@ -91,6 +92,7 @@ void EffectComposerView::modelAttached(QmlDesigner::Model *model)
if (m_currProjectPath != currProjectPath) { // starting a new project
m_widget->effectComposerNodesModel()->loadModel();
m_widget->effectComposerModel()->clear(true);
m_widget->effectComposerModel()->setEffectsTypePrefix(m_componentUtils.composedEffectsTypePrefix());
m_widget->effectComposerModel()->setIsEnabled(
!QmlDesigner::DesignerMcuManager::instance().isMCUProject());
m_widget->initView();

View File

@@ -6,6 +6,7 @@
#include "abstractview.h"
#include "modelnode.h"
#include <generatedcomponentutils.h>
#include <coreplugin/icontext.h>
#include <QPointer>
@@ -45,6 +46,7 @@ private:
QPointer<EffectComposerWidget> m_widget;
QString m_currProjectPath;
QmlDesigner::GeneratedComponentUtils m_componentUtils;
};
} // namespace EffectComposer

View File

@@ -94,6 +94,8 @@ add_qtc_library(QmlDesignerCore STATIC
SOURCES
rewritertransaction.cpp
rewritertransaction.h
generatedcomponentutils.cpp
generatedcomponentutils.h
)
extend_qtc_library(QmlDesignerCore

View File

@@ -287,14 +287,16 @@ void AssetsLibraryWidget::handleDeleteEffects([[maybe_unused]] const QStringList
// Remove usages of deleted effects from the current document
m_assetsView->executeInTransaction(__FUNCTION__, [&]() {
QList<ModelNode> allNodes = m_assetsView->allModelNodes();
const QString typeTemplate = "Effects.%1.%1";
const QString importUrlTemplate = "Effects.%1";
const QString typeTemplate = "%1.%2.%2";
const QString importUrlTemplate = "%1.%2";
const Imports imports = m_assetsView->model()->imports();
Imports removedImports;
const QString typePrefix = QmlDesignerPlugin::instance()->documentManager()
.generatedComponentUtils().composedEffectsTypePrefix();
for (const QString &effectName : effectNames) {
if (effectName.isEmpty())
continue;
const TypeName type = typeTemplate.arg(effectName).toUtf8();
const TypeName type = typeTemplate.arg(typePrefix, effectName).toUtf8();
for (ModelNode &node : allNodes) {
if (node.metaInfo().typeName() == type) {
clearStacks = true;
@@ -302,7 +304,7 @@ void AssetsLibraryWidget::handleDeleteEffects([[maybe_unused]] const QStringList
}
}
const QString importPath = importUrlTemplate.arg(effectName);
const QString importPath = importUrlTemplate.arg(typePrefix, effectName);
Import removedImport = Utils::findOrDefault(imports, [&importPath](const Import &import) {
return import.url() == importPath;
});

View File

@@ -105,8 +105,10 @@ bool selectionIsImported3DAsset(const SelectionContext &selectionState)
// Node is not a file component, so we have to check if the current doc itself is
fileName = node.model()->fileUrl().toLocalFile();
}
if (fileName.contains(Constants::QUICK_3D_ASSETS_FOLDER))
if (fileName.contains(Constants::OLD_QUICK_3D_ASSETS_FOLDER)
|| fileName.contains(Constants::QUICK_3D_COMPONENTS_FOLDER)) {
return true;
}
}
return false;
}

View File

@@ -1145,11 +1145,8 @@ static QString getAssetDefaultDirectory(const QString &assetDir, const QString &
Utils::FilePath assetPath = contentPath.pathAppended(assetDir);
if (!assetPath.exists()) {
// Create the default asset type directory if it doesn't exist
QDir dir(contentPath.toString());
dir.mkpath(assetDir);
}
if (!assetPath.exists())
assetPath.createDir();
if (assetPath.exists() && assetPath.isDir())
adjustedDefaultDirectory = assetPath.toString();
@@ -1727,13 +1724,12 @@ void openOldEffectMaker(const QString &filePath)
return;
}
Utils::FilePath projectPath = target->project()->projectDirectory();
QString effectName = QFileInfo(filePath).baseName();
QString effectResDir = QLatin1String(Constants::DEFAULT_EFFECTS_IMPORT_FOLDER)
+ "/" + effectName;
Utils::FilePath effectResPath = projectPath.pathAppended(effectResDir);
Utils::FilePath effectResPath = QmlDesignerPlugin::instance()->documentManager()
.generatedComponentUtils().composedEffectsBasePath()
.pathAppended(QFileInfo(filePath).baseName());
if (!effectResPath.exists())
QDir().mkpath(effectResPath.toString());
effectResPath.createDir();
const QtSupport::QtVersion *baseQtVersion = QtSupport::QtKitAspect::qtVersion(target->kit());
if (baseQtVersion) {
@@ -1769,14 +1765,11 @@ void openOldEffectMaker(const QString &filePath)
Utils::FilePath getEffectsImportDirectory()
{
QString defaultDir = QLatin1String(Constants::DEFAULT_EFFECTS_IMPORT_FOLDER);
Utils::FilePath projectPath = QmlDesignerPlugin::instance()->documentManager().currentProjectDirPath();
Utils::FilePath effectsPath = projectPath.pathAppended(defaultDir);
Utils::FilePath effectsPath = QmlDesignerPlugin::instance()->documentManager()
.generatedComponentUtils().composedEffectsBasePath();
if (!effectsPath.exists()) {
QDir dir(projectPath.toString());
dir.mkpath(effectsPath.toString());
}
if (!effectsPath.exists())
effectsPath.createDir();
return effectsPath;
}
@@ -1794,12 +1787,9 @@ QString getEffectsDefaultDirectory(const QString &defaultDir)
QString getEffectIcon(const QString &effectPath)
{
Utils::FilePath projectPath = QmlDesignerPlugin::instance()->documentManager().currentProjectDirPath();
QString effectName = QFileInfo(effectPath).baseName();
QString effectResDir = "asset_imports/Effects/" + effectName;
Utils::FilePath effectResPath = projectPath.resolvePath(effectResDir + "/" + effectName + ".qml");
return effectResPath.exists() ? QString("effectExported") : QString("effectClass");
Utils::FilePath effectFile = QmlDesignerPlugin::instance()->documentManager()
.generatedComponentUtils().composedEffectPath(effectPath);
return effectFile.exists() ? QString("effectExported") : QString("effectClass");
}
bool useLayerEffect()

View File

@@ -32,9 +32,6 @@ ContentLibraryBundleImporter::ContentLibraryBundleImporter(const QString &bundle
{
m_importTimer.setInterval(200);
connect(&m_importTimer, &QTimer::timeout, this, &ContentLibraryBundleImporter::handleImportTimer);
m_moduleName = QStringLiteral("%1.%2").arg(
QLatin1String(Constants::COMPONENT_BUNDLES_FOLDER),
m_bundleId).mid(1); // Chop leading slash
}
// Returns empty string on success or an error message on failure.
@@ -69,7 +66,7 @@ QString ContentLibraryBundleImporter::importComponent(const QString &qmlFile,
QString qmldirContent = QString::fromUtf8(qmldirPath.fileContents().value_or(QByteArray()));
if (qmldirContent.isEmpty()) {
qmldirContent.append("module ");
qmldirContent.append(m_moduleName);
qmldirContent.append(moduleName());
qmldirContent.append('\n');
}
@@ -77,7 +74,9 @@ QString ContentLibraryBundleImporter::importComponent(const QString &qmlFile,
const bool qmlFileExists = qmlSourceFile.exists();
const QString qmlType = qmlSourceFile.baseName();
const QString fullTypeName = QStringLiteral("%1.%2.%3")
.arg(QLatin1String(Constants::COMPONENT_BUNDLES_FOLDER).mid(1), m_bundleId, qmlType);
.arg(QmlDesignerPlugin::instance()->documentManager()
.generatedComponentUtils().componentBundlesTypePrefix(),
m_bundleId, qmlType);
if (m_pendingTypes.contains(fullTypeName) && !m_pendingTypes[fullTypeName])
return QStringLiteral("Unable to import while unimporting the same type: '%1'").arg(fullTypeName);
if (!qmldirContent.contains(qmlFile)) {
@@ -126,7 +125,7 @@ QString ContentLibraryBundleImporter::importComponent(const QString &qmlFile,
if (!model)
return "Model not available, cannot add import statement or update code model";
Import import = Import::createLibraryImport(m_moduleName, "1.0");
Import import = Import::createLibraryImport(moduleName(), "1.0");
if (!model->hasImport(import)) {
if (model->possibleImports().contains(import)) {
m_importAddPending = false;
@@ -134,7 +133,7 @@ QString ContentLibraryBundleImporter::importComponent(const QString &qmlFile,
model->changeImports({import}, {});
} catch (const RewritingException &) {
// No point in trying to add import asynchronously either, so just fail out
return QStringLiteral("Failed to add import statement for: '%1'").arg(m_moduleName);
return QStringLiteral("Failed to add import statement for: '%1'").arg(moduleName());
}
} else {
// If import is not yet possible, import statement needs to be added asynchronously to
@@ -188,7 +187,7 @@ void ContentLibraryBundleImporter::handleImportTimer()
if (m_importAddPending) {
try {
Import import = Import::createLibraryImport(m_moduleName, "1.0");
Import import = Import::createLibraryImport(moduleName(), "1.0");
if (model->possibleImports().contains(import)) {
model->changeImports({import}, {});
m_importAddPending = false;
@@ -253,6 +252,13 @@ void ContentLibraryBundleImporter::writeAssetRefMap(const Utils::FilePath &bundl
}
}
QString ContentLibraryBundleImporter::moduleName()
{
return QStringLiteral("%1.%2").arg(QmlDesignerPlugin::instance()->documentManager()
.generatedComponentUtils().componentBundlesTypePrefix(),
m_bundleId);
}
QString ContentLibraryBundleImporter::unimportComponent(const QString &qmlFile)
{
FilePath bundleImportPath = resolveBundleImportPath();
@@ -275,7 +281,9 @@ QString ContentLibraryBundleImporter::unimportComponent(const QString &qmlFile)
QString qmlType = qmlFilePath.baseName();
const QString fullTypeName = QStringLiteral("%1.%2.%3")
.arg(QLatin1String(Constants::COMPONENT_BUNDLES_FOLDER).mid(1), m_bundleId, qmlType);
.arg(QmlDesignerPlugin::instance()->documentManager()
.generatedComponentUtils().componentBundlesTypePrefix(),
m_bundleId, qmlType);
if (m_pendingTypes.contains(fullTypeName) && m_pendingTypes[fullTypeName])
return QStringLiteral("Unable to unimport while importing the same type: '%1'").arg(fullTypeName);
@@ -327,7 +335,7 @@ QString ContentLibraryBundleImporter::unimportComponent(const QString &qmlFile)
auto doc = QmlDesignerPlugin::instance()->currentDesignDocument();
Model *model = doc ? doc->currentModel() : nullptr;
if (model) {
Import import = Import::createLibraryImport(m_moduleName, "1.0");
Import import = Import::createLibraryImport(moduleName(), "1.0");
if (model->imports().contains(import))
model->changeImports({}, {import});
}
@@ -342,16 +350,12 @@ QString ContentLibraryBundleImporter::unimportComponent(const QString &qmlFile)
FilePath ContentLibraryBundleImporter::resolveBundleImportPath()
{
FilePath bundleImportPath = QmlDesignerPlugin::instance()->documentManager().currentProjectDirPath();
FilePath bundleImportPath = QmlDesignerPlugin::instance()->documentManager()
.generatedComponentUtils().componentBundlesBasePath();
if (bundleImportPath.isEmpty())
return bundleImportPath;
const QString projectBundlePath = QStringLiteral("%1%2/%3").arg(
QLatin1String(Constants::DEFAULT_ASSET_IMPORT_FOLDER),
QLatin1String(Constants::COMPONENT_BUNDLES_FOLDER),
m_bundleId).mid(1); // Chop leading slash
return bundleImportPath.resolvePath(projectBundlePath);
return bundleImportPath.resolvePath(m_bundleId);
}
} // namespace QmlDesigner::Internal

View File

@@ -46,10 +46,10 @@ private:
void handleImportTimer();
QVariantHash loadAssetRefMap(const Utils::FilePath &bundlePath);
void writeAssetRefMap(const Utils::FilePath &bundlePath, const QVariantHash &assetRefMap);
QString moduleName();
Utils::FilePath m_bundleDir;
QString m_bundleId;
QString m_moduleName;
QStringList m_sharedFiles;
QTimer m_importTimer;
int m_importTimerCount = 0;

View File

@@ -7,8 +7,8 @@
#include "contentlibraryeffect.h"
#include "contentlibraryeffectscategory.h"
#include "contentlibrarywidget.h"
#include "qmldesignerconstants.h"
#include <qmldesignerplugin.h>
#include <utils/algorithm.h>
#include <utils/qtcassert.h>
#include <utils/hostosinfo.h>
@@ -187,10 +187,11 @@ void ContentLibraryEffectsModel::loadBundle()
QUrl icon = QUrl::fromLocalFile(bundleDir.filePath(itemObj.value("icon").toString()));
QString qml = itemObj.value("qml").toString();
TypeName type = QLatin1String("%1.%2.%3").arg(
QLatin1String(Constants::COMPONENT_BUNDLES_FOLDER).mid(1),
bundleId,
qml.chopped(4)).toLatin1(); // chopped(4): remove .qml
TypeName type = QLatin1String("%1.%2.%3")
.arg(QmlDesignerPlugin::instance()->documentManager()
.generatedComponentUtils().componentBundlesTypePrefix(),
bundleId,
qml.chopped(4)).toLatin1(); // chopped(4): remove .qml
auto bundleItem = new ContentLibraryEffect(category, item, qml, type, icon, files);

View File

@@ -8,12 +8,12 @@
#include "contentlibrarymaterialscategory.h"
#include "contentlibrarywidget.h"
#include <designerpaths.h>
#include "designerpaths.h"
#include "filedownloader.h"
#include "fileextractor.h"
#include "multifiledownloader.h"
#include "qmldesignerconstants.h"
#include "qmldesignerplugin.h"
#include <qmldesignerplugin.h>
#include <utils/algorithm.h>
#include <utils/hostosinfo.h>
@@ -286,10 +286,11 @@ void ContentLibraryMaterialsModel::loadMaterialBundle(const QDir &matBundleDir)
QUrl icon = QUrl::fromLocalFile(matBundleDir.filePath(matObj.value("icon").toString()));
QString qml = matObj.value("qml").toString();
TypeName type = QLatin1String("%1.%2.%3").arg(
QLatin1String(Constants::COMPONENT_BUNDLES_FOLDER).mid(1),
bundleId,
qml.chopped(4)).toLatin1(); // chopped(4): remove .qml
TypeName type = QLatin1String("%1.%2.%3")
.arg(QmlDesignerPlugin::instance()->documentManager()
.generatedComponentUtils().componentBundlesTypePrefix(),
bundleId,
qml.chopped(4)).toLatin1(); // chopped(4): remove .qml
auto bundleMat = new ContentLibraryMaterial(category, mat, qml, type, icon, files,
m_downloadPath, m_baseUrl);

View File

@@ -7,9 +7,9 @@
#include "contentlibrarymaterial.h"
#include "contentlibrarymaterialscategory.h"
#include "contentlibrarywidget.h"
#include "qmldesignerconstants.h"
#include <designerpaths.h>
#include <qmldesignerplugin.h>
#include <utils/algorithm.h>
#include <utils/hostosinfo.h>
@@ -133,7 +133,8 @@ QPair<QString, QString> ContentLibraryUserModel::getUniqueLibMaterialNameAndQml(
TypeName ContentLibraryUserModel::qmlToModule(const QString &qmlName) const
{
return QLatin1String("%1.%2.%3").arg(QLatin1String(Constants::COMPONENT_BUNDLES_FOLDER).mid(1),
return QLatin1String("%1.%2.%3").arg(QmlDesignerPlugin::instance()->documentManager()
.generatedComponentUtils().componentBundlesTypePrefix(),
m_bundleId,
qmlName.chopped(4)).toLatin1(); // chopped(4): remove .qml
}

View File

@@ -356,7 +356,8 @@ void Edit3DView::handleEntriesChanged()
append(model()->qtQuick3DOrthographicCameraMetaInfo(), EK_cameras);
append(model()->qtQuick3DPerspectiveCameraMetaInfo(), EK_cameras);
auto assetsModule = model()->module("Quick3DAssets");
auto assetsModule = model()->module(QmlDesignerPlugin::instance()->documentManager()
.generatedComponentUtils().import3dTypePrefix());
for (const auto &metaInfo : model()->metaInfosForModule(assetsModule))
append(metaInfo, EK_importedModels);
@@ -373,7 +374,8 @@ void Edit3DView::handleEntriesChanged()
} else if (entry.typeName() == "QtQuick3D.OrthographicCamera"
|| entry.typeName() == "QtQuick3D.PerspectiveCamera") {
entryKey = EK_cameras;
} else if (entry.typeName().startsWith("Quick3DAssets.")
} else if (entry.typeName().startsWith(QmlDesignerPlugin::instance()->documentManager()
.generatedComponentUtils().import3dTypePrefix().toUtf8())
&& NodeHints::fromItemLibraryEntry(entry).canBeDroppedInView3D()) {
entryKey = EK_importedModels;
} else {

View File

@@ -766,7 +766,10 @@ void Edit3DWidget::dropEvent(QDropEvent *dropEvent)
QString fileName = QFileInfo(assetPath).baseName();
fileName = fileName.at(0).toUpper() + fileName.mid(1); // capitalize first letter
auto model = m_view->model();
auto metaInfo = model->metaInfo(model->module("Quick3DAssets"), fileName.toUtf8());
auto metaInfo = model->metaInfo(model->module(
QmlDesignerPlugin::instance()->documentManager()
.generatedComponentUtils().import3dTypePrefix()),
fileName.toUtf8());
if (auto entries = metaInfo.itemLibrariesEntries(); entries.size()) {
auto entry = ItemLibraryEntry{entries.front(), *model->projectStorage()};
QmlVisualNode::createQml3DNode(view(), entry, m_canvas->activeScene(), {}, false);
@@ -780,7 +783,9 @@ void Edit3DWidget::dropEvent(QDropEvent *dropEvent)
for (const QString &assetPath : added3DAssets) {
QString fileName = QFileInfo(assetPath).baseName();
fileName = fileName.at(0).toUpper() + fileName.mid(1); // capitalize first letter
QString type = QString("Quick3DAssets.%1.%1").arg(fileName);
QString type = QString("%1.%2.%2").arg(QmlDesignerPlugin::instance()->documentManager()
.generatedComponentUtils().import3dTypePrefix(),
fileName);
QList<ItemLibraryEntry> entriesForType = itemLibInfo->entriesForType(type.toUtf8());
if (!entriesForType.isEmpty()) { // should always be true, but just in case
QmlVisualNode::createQml3DNode(view(),

View File

@@ -12,6 +12,7 @@
#include <variantproperty.h>
#include <theme.h>
#include <utils/filepath.h>
#include <utils/outputformatter.h>
#include <projectexplorer/project.h>
@@ -130,43 +131,8 @@ ItemLibraryAssetImportDialog::ItemLibraryAssetImportDialog(
if (targetDir.isEmpty())
targetDir = defaulTargetDirectory;
// Import is always done under known folder. The order of preference for folder is:
// 1) An existing QUICK_3D_ASSETS_FOLDER under DEFAULT_ASSET_IMPORT_FOLDER project import path
// 2) An existing QUICK_3D_ASSETS_FOLDER under any project import path
// 3) New QUICK_3D_ASSETS_FOLDER under DEFAULT_ASSET_IMPORT_FOLDER project import path
// 4) New QUICK_3D_ASSETS_FOLDER under any project import path
// 5) New QUICK_3D_ASSETS_FOLDER under new DEFAULT_ASSET_IMPORT_FOLDER under project
const QString defaultAssetFolder = QLatin1String(Constants::DEFAULT_ASSET_IMPORT_FOLDER);
const QString quick3DFolder = QLatin1String(Constants::QUICK_3D_ASSETS_FOLDER);
QString candidatePath = targetDir + defaultAssetFolder + quick3DFolder;
int candidatePriority = 5;
for (const auto &importPath : std::as_const(importPaths)) {
if (importPath.startsWith(targetDir)) {
const bool isDefaultFolder = importPath.endsWith(defaultAssetFolder);
const QString assetFolder = importPath + quick3DFolder;
const bool exists = QFileInfo::exists(assetFolder);
if (exists) {
if (isDefaultFolder) {
// Priority one location, stop looking
candidatePath = assetFolder;
break;
} else if (candidatePriority > 2) {
candidatePriority = 2;
candidatePath = assetFolder;
}
} else {
if (candidatePriority > 3 && isDefaultFolder) {
candidatePriority = 3;
candidatePath = assetFolder;
} else if (candidatePriority > 4) {
candidatePriority = 4;
candidatePath = assetFolder;
}
}
}
}
m_quick3DImportPath = candidatePath;
m_quick3DImportPath = QmlDesignerPlugin::instance()->documentManager()
.generatedComponentUtils().import3dBasePath().toString();
if (!m_quick3DFiles.isEmpty()) {
QVector<QJsonObject> groups;
@@ -294,11 +260,14 @@ void ItemLibraryAssetImportDialog::updateImport(const ModelNode &updateNode,
QFileInfo compFileInfo{compFileName};
// Find to top asset folder
const QString assetFolder = QLatin1String(Constants::QUICK_3D_ASSETS_FOLDER).mid(1);
const QString oldAssetFolder = QLatin1String(Constants::OLD_QUICK_3D_ASSETS_FOLDER);
QString assetFolder = QLatin1String(Constants::QUICK_3D_COMPONENTS_FOLDER);
const QStringList parts = compFileName.split('/');
int i = parts.size() - 1;
int previousSize = 0;
for (; i >= 0; --i) {
if (parts[i] == oldAssetFolder)
assetFolder = oldAssetFolder;
if (parts[i] == assetFolder)
break;
previousSize = parts[i].size();

View File

@@ -1,6 +1,7 @@
// Copyright (C) 2019 The Qt Company Ltd.
// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
#include "itemlibraryassetimporter.h"
#include "assetimportupdatedialog.h"
#include "qmldesignerplugin.h"
#include "qmldesignerconstants.h"
@@ -329,12 +330,15 @@ void ItemLibraryAssetImporter::postParseQuick3DAsset(ParseData &pd)
if (qmldirFile.open(QIODevice::WriteOnly | QIODevice::Truncate)) {
QString qmlInfo;
qmlInfo.append("module ");
qmlInfo.append(m_importPath.split('/').last());
qmlInfo.append(QmlDesignerPlugin::instance()->documentManager()
.generatedComponentUtils().import3dTypePrefix());
qmlInfo.append(".");
qmlInfo.append(pd.assetName);
qmlInfo.append('\n');
m_requiredImports.append(
QStringLiteral("%1.%2").arg(pd.targetDir.dirName(), pd.assetName));
QStringLiteral("%1.%2").arg(QmlDesignerPlugin::instance()->documentManager()
.generatedComponentUtils().import3dTypePrefix(),
pd.assetName));
while (qmlIt.hasNext()) {
qmlIt.next();
QFileInfo fi = QFileInfo(qmlIt.filePath());

View File

@@ -312,9 +312,12 @@ void ItemLibraryModel::update([[maybe_unused]] ItemLibraryInfo *itemLibraryInfo,
beginResetModel();
clearSections();
GeneratedComponentUtils compUtils = QmlDesignerPlugin::instance()->documentManager()
.generatedComponentUtils();
QStringList excludedImports {
QLatin1String(Constants::COMPONENT_BUNDLES_FOLDER).mid(1) + ".MaterialBundle",
QLatin1String(Constants::COMPONENT_BUNDLES_FOLDER).mid(1) + ".EffectBundle"
compUtils.componentBundlesTypePrefix() + ".MaterialBundle",
compUtils.componentBundlesTypePrefix() + ".EffectBundle"
};
// create import sections
@@ -323,10 +326,12 @@ void ItemLibraryModel::update([[maybe_unused]] ItemLibraryInfo *itemLibraryInfo,
QHash<QString, ItemLibraryImport *> importHash;
for (const Import &import : model->imports()) {
if (import.url() != projectName) {
if (excludedImports.contains(import.url()) || import.url().startsWith("Effects."))
if (excludedImports.contains(import.url())
|| import.url().startsWith(compUtils.composedEffectsTypePrefix())) {
continue;
}
bool addNew = true;
bool isQuick3DAsset = import.url().startsWith("Quick3DAssets.");
bool isQuick3DAsset = import.url().startsWith(compUtils.import3dTypePrefix());
QString importUrl = import.url();
if (isQuick3DAsset)
importUrl = ItemLibraryImport::quick3DAssetsTitle();

View File

@@ -5,6 +5,8 @@
#include "nodemetainfo.h"
#include "ui_choosefrompropertylistdialog.h"
#include <qmldesignerplugin.h>
namespace QmlDesigner {
// This will filter and return possible properties that the given type can be bound to
@@ -100,7 +102,10 @@ ChooseFromPropertyListFilter::ChooseFromPropertyListFilter(const NodeMetaInfo &i
#ifdef QDS_USE_PROJECTSTORAGE
// TODO add the types here or use the module
#else
} else if (insertInfo.typeName().startsWith("ComponentBundles.MaterialBundle")) {
} else if (insertInfo.typeName().startsWith(
QString("%1.MaterialBundle").arg(QmlDesignerPlugin::instance()->documentManager()
.generatedComponentUtils().componentBundlesTypePrefix())
.toUtf8())) {
if (parentInfo.isQtQuick3DModel())
propertyList.append("materials");
#endif

View File

@@ -0,0 +1,141 @@
// Copyright (C) 2024 The Qt Company Ltd.
// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
#include "generatedcomponentutils.h"
#include <qmldesignerconstants.h>
namespace QmlDesigner {
GeneratedComponentUtils::GeneratedComponentUtils(ExternalDependenciesInterface &externalDependencies)
: m_externalDependencies(externalDependencies)
{
}
Utils::FilePath GeneratedComponentUtils::generatedComponentsPath() const
{
Utils::FilePath projectPath = Utils::FilePath::fromString(m_externalDependencies.currentProjectDirPath());
if (projectPath.isEmpty())
return {};
Utils::FilePath assetImportsPath = projectPath.resolvePath(QLatin1String(Constants::OLD_ASSET_IMPORT_FOLDER));
if (assetImportsPath.exists())
return assetImportsPath;
Utils::FilePath componentsPath = projectPath.resolvePath(QLatin1String(Constants::GENERATED_COMPONENTS_FOLDER));
if (!componentsPath.exists())
componentsPath.createDir();
return componentsPath;
}
Utils::FilePath GeneratedComponentUtils::composedEffectsBasePath() const
{
Utils::FilePath basePath = generatedComponentsPath();
if (basePath.isEmpty())
return {};
QString effectsImportPath;
if (basePath.endsWith(Constants::OLD_ASSET_IMPORT_FOLDER))
effectsImportPath = Constants::OLD_EFFECTS_FOLDER;
else
effectsImportPath = Constants::COMPOSED_EFFECTS_TYPE;
return basePath.resolvePath(effectsImportPath);
}
Utils::FilePath GeneratedComponentUtils::composedEffectPath(const QString &effectPath) const
{
Utils::FilePath effectsBasePath = composedEffectsBasePath();
QString effectName = Utils::FilePath::fromString(effectPath).baseName();
return effectsBasePath.resolvePath(effectName + "/" + effectName + ".qml");
}
Utils::FilePath GeneratedComponentUtils::componentBundlesBasePath() const
{
Utils::FilePath basePath = generatedComponentsPath();
if (basePath.isEmpty())
return {};
return basePath.resolvePath(QLatin1String(Constants::COMPONENT_BUNDLES_TYPE));
}
Utils::FilePath GeneratedComponentUtils::import3dBasePath() const
{
Utils::FilePath basePath = generatedComponentsPath();
if (basePath.isEmpty())
return {};
Utils::FilePath import3dPath;
if (basePath.endsWith(Constants::OLD_ASSET_IMPORT_FOLDER))
return basePath.resolvePath(QLatin1String(Constants::OLD_QUICK_3D_ASSETS_FOLDER));
return basePath.resolvePath(QLatin1String(Constants::QUICK_3D_COMPONENTS_FOLDER));
}
bool GeneratedComponentUtils::isImport3dPath(const QString &path) const
{
return path.contains('/' + QLatin1String(Constants::OLD_QUICK_3D_ASSETS_FOLDER))
|| path.contains('/' + QLatin1String(Constants::QUICK_3D_COMPONENTS_FOLDER));
}
bool GeneratedComponentUtils::isComposedEffectPath(const QString &path) const
{
return path.contains(Constants::OLD_EFFECTS_IMPORT_FOLDER)
|| path.contains('/' + QLatin1String(Constants::COMPOSED_EFFECTS_TYPE));
}
QString GeneratedComponentUtils::generatedComponentTypePrefix() const
{
Utils::FilePath basePath = generatedComponentsPath();
if (basePath.isEmpty() || basePath.endsWith(Constants::OLD_ASSET_IMPORT_FOLDER))
return {};
return Constants::GENERATED_COMPONENTS_FOLDER;
}
QString GeneratedComponentUtils::import3dTypePrefix() const
{
QString basePrefix = generatedComponentTypePrefix();
if (basePrefix == Constants::GENERATED_COMPONENTS_FOLDER)
return basePrefix + '.' + QLatin1String(Constants::QUICK_3D_COMPONENTS_FOLDER);
return Constants::OLD_QUICK_3D_ASSETS_FOLDER;
}
QString GeneratedComponentUtils::import3dSimplifiedTypePrefix() const
{
QString basePrefix = generatedComponentTypePrefix();
if (basePrefix.endsWith(Constants::QUICK_3D_COMPONENTS_FOLDER))
return Constants::QUICK_3D_COMPONENTS_FOLDER;
return Constants::OLD_QUICK_3D_ASSETS_FOLDER;
}
QString GeneratedComponentUtils::componentBundlesTypePrefix() const
{
QString basePrefix = generatedComponentTypePrefix();
if (basePrefix.endsWith(Constants::GENERATED_COMPONENTS_FOLDER))
return basePrefix + '.' + QLatin1String(Constants::COMPONENT_BUNDLES_TYPE);
return Constants::COMPONENT_BUNDLES_TYPE;
}
QString GeneratedComponentUtils::composedEffectsTypePrefix() const
{
QString basePrefix = generatedComponentTypePrefix();
if (basePrefix == Constants::GENERATED_COMPONENTS_FOLDER)
return basePrefix + '.' + QLatin1String(Constants::COMPOSED_EFFECTS_TYPE);
return Constants::OLD_EFFECTS_FOLDER;
}
} // namespace QmlDesigner

View File

@@ -0,0 +1,38 @@
// Copyright (C) 2024 The Qt Company Ltd.
// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
#pragma once
#include <externaldependenciesinterface.h>
#include <qmldesignercorelib_exports.h>
#include <utils/filepath.h>
#include <QString>
namespace QmlDesigner {
class QMLDESIGNERCORE_EXPORT GeneratedComponentUtils {
public:
GeneratedComponentUtils(ExternalDependenciesInterface &externalDependencies);
Utils::FilePath generatedComponentsPath() const;
Utils::FilePath composedEffectsBasePath() const;
Utils::FilePath composedEffectPath(const QString &effectPath) const;
Utils::FilePath componentBundlesBasePath() const;
Utils::FilePath import3dBasePath() const;
bool isImport3dPath(const QString &path) const;
bool isComposedEffectPath(const QString &path) const;
QString generatedComponentTypePrefix() const;
QString import3dTypePrefix() const;
QString import3dSimplifiedTypePrefix() const;
QString componentBundlesTypePrefix() const;
QString composedEffectsTypePrefix() const;
private:
ExternalDependenciesInterface &m_externalDependencies;
};
} // namespace QmlDesigner

View File

@@ -7,6 +7,7 @@
# include "qmldesignercorelib_global.h"
# include <generatedcomponentutils.h>
# include <import.h>
# include <QObject>
@@ -62,6 +63,7 @@ private: // variables
QDir m_filePathDir;
QPointer<Model> m_model;
ExternalDependenciesInterface &m_externalDependencies;
GeneratedComponentUtils m_componentUtils;
};
} // namespace QmlDesigner

View File

@@ -44,6 +44,7 @@ SubComponentManager::SubComponentManager(Model *model,
ExternalDependenciesInterface &externalDependencies)
: m_model(model)
, m_externalDependencies{externalDependencies}
, m_componentUtils{externalDependencies}
{
connect(&m_watcher, &QFileSystemWatcher::directoryChanged,
this, [this](const QString &path) { parseDirectory(path); });
@@ -192,7 +193,7 @@ void SubComponentManager::parseDirectory(const QString &canonicalDirPath, bool a
if (!model() || !model()->rewriterView())
return;
if (canonicalDirPath.endsWith(QLatin1String(Constants::QUICK_3D_ASSETS_FOLDER))) {
if (m_componentUtils.isImport3dPath(canonicalDirPath)) {
parseQuick3DAssetsDir(canonicalDirPath);
return;
}
@@ -345,8 +346,8 @@ void SubComponentManager::registerQmlFile(const QFileInfo &fileInfo, const QStri
bool addToLibrary)
{
if (!addToLibrary || !model()
|| fileInfo.path().contains(QLatin1String(Constants::QUICK_3D_ASSETS_FOLDER))
|| fileInfo.path().contains(QLatin1String(Constants::DEFAULT_EFFECTS_IMPORT_FOLDER))) {
|| m_componentUtils.isImport3dPath(fileInfo.path())
|| m_componentUtils.isComposedEffectPath(fileInfo.path())) {
return;
}
@@ -395,7 +396,7 @@ void SubComponentManager::parseQuick3DAssetsDir(const QString &quick3DAssetsPath
QDir quick3DAssetsDir(quick3DAssetsPath);
QStringList assets = quick3DAssetsDir.entryList(QDir::Dirs | QDir::NoDot | QDir::NoDotDot);
for (QString &asset : assets)
asset.prepend(QString(Constants::QUICK_3D_ASSETS_FOLDER).mid(1) + '.');
asset.prepend(m_componentUtils.import3dTypePrefix() + '.');
// Create item library entries for Quick3D assets that are imported by document
for (auto &import : std::as_const(m_imports)) {
@@ -460,7 +461,9 @@ QStringList SubComponentManager::quick3DAssetPaths() const
const auto impPaths = importPaths();
QStringList retPaths;
for (const auto &impPath : impPaths) {
const QString assetPath = impPath + QLatin1String(Constants::QUICK_3D_ASSETS_FOLDER);
QString path3d = m_componentUtils.import3dTypePrefix();
path3d.replace('.', '/');
const QString assetPath = impPath + '/' + path3d;
if (QFileInfo::exists(assetPath))
retPaths << assetPath;
}
@@ -520,7 +523,7 @@ void SubComponentManager::update(const QUrl &filePath, const Imports &imports)
// Remove old watched asset paths
const QStringList watchPaths = m_watcher.directories();
const QString &quick3DAssetFolder = QLatin1String(Constants::QUICK_3D_ASSETS_FOLDER);
const QString &quick3DAssetFolder = m_componentUtils.import3dSimplifiedTypePrefix();
for (const auto &watchPath : watchPaths) {
if (watchPath.endsWith(quick3DAssetFolder))
m_watcher.removePath(watchPath);
@@ -580,7 +583,7 @@ void SubComponentManager::addAndParseImport(const Import &import)
} else {
QString url = import.url();
if (url.startsWith(QString(Constants::QUICK_3D_ASSETS_FOLDER).mid(1))) {
if (url.startsWith(m_componentUtils.import3dTypePrefix())) {
parseQuick3DAssetsItem(import.url());
return;
}

View File

@@ -9,8 +9,9 @@
#include "bindingproperty.h"
#include "qmlanchors.h"
#include <model.h>
#include <abstractview.h>
#include <generatedcomponentutils.h>
#include <model.h>
#include <coreplugin/icore.h>
@@ -196,7 +197,9 @@ QmlItemNode QmlItemNode::createQmlItemNodeForEffect(AbstractView *view,
auto createEffectNode = [=, &newQmlItemNode, &parentProperty]() {
const QString effectName = QFileInfo(effectPath).baseName();
Import import = Import::createLibraryImport("Effects." + effectName, "1.0");
Import import = Import::createLibraryImport(GeneratedComponentUtils(view->externalDependencies())
.composedEffectsTypePrefix()
+ '.' + effectName, "1.0");
try {
if (!view->model()->hasImport(import, true, true))
view->model()->changeImports({import}, {});

View File

@@ -266,6 +266,11 @@ void DocumentManager::resetPossibleImports()
}
}
const GeneratedComponentUtils &DocumentManager::generatedComponentUtils() const
{
return m_generatedComponentUtils;
}
bool DocumentManager::goIntoComponent(const ModelNode &modelNode)
{
QImage image = QmlDesignerPlugin::instance()->viewManager().takeFormEditorScreenshot();

View File

@@ -5,6 +5,8 @@
#include "qmldesigner_global.h"
#include <generatedcomponentutils.h>
#include <QObject>
#include <QList>
#include <QLoggingCategory>
@@ -31,6 +33,7 @@ public:
ExternalDependenciesInterface &externalDependencies)
: m_projectManager{projectManager}
, m_externalDependencies{externalDependencies}
, m_generatedComponentUtils(externalDependencies)
{}
void setCurrentDesignDocument(Core::IEditor *editor);
@@ -41,6 +44,8 @@ public:
void resetPossibleImports();
const GeneratedComponentUtils &generatedComponentUtils() const;
static bool goIntoComponent(const ModelNode &modelNode);
static void goIntoComponent(const QString &fileName);
@@ -64,6 +69,7 @@ private:
QPointer<DesignDocument> m_currentDesignDocument;
QmlDesignerProjectManager &m_projectManager;
ExternalDependenciesInterface &m_externalDependencies;
GeneratedComponentUtils m_generatedComponentUtils;
};
} // namespace QmlDesigner

View File

@@ -78,15 +78,19 @@ inline constexpr char EDIT3D_SNAP_CONFIG[] = "QmlDesigner.Editor3D.SnapConfig";
inline constexpr char EDIT3D_CAMERA_SPEED_CONFIG[] = "QmlDesigner.Editor3D.CameraSpeedConfig";
inline constexpr char QML_DESIGNER_SUBFOLDER[] = "/designer/";
inline constexpr char COMPONENT_BUNDLES_FOLDER[] = "/ComponentBundles";
inline constexpr char COMPONENT_BUNDLES_TYPE[] = "ComponentBundles";
inline constexpr char GENERATED_COMPONENTS_FOLDER[] = "GeneratedComponents";
inline constexpr char COMPONENT_BUNDLES_ASSET_REF_FILE[] = "_asset_ref.json";
inline constexpr char QUICK_3D_ASSETS_FOLDER[] = "/Quick3DAssets";
inline constexpr char OLD_QUICK_3D_ASSETS_FOLDER[] = "Quick3DAssets";
inline constexpr char QUICK_3D_COMPONENTS_FOLDER[] = "QtQuick3DComponents";
inline constexpr char QUICK_3D_ASSET_LIBRARY_ICON_SUFFIX[] = "_libicon";
inline constexpr char QUICK_3D_ASSET_IMPORT_DATA_NAME[] = "_importdata.json";
inline constexpr char QUICK_3D_ASSET_IMPORT_DATA_OPTIONS_KEY[] = "import_options";
inline constexpr char QUICK_3D_ASSET_IMPORT_DATA_SOURCE_KEY[] = "source_scene";
inline constexpr char DEFAULT_ASSET_IMPORT_FOLDER[] = "/asset_imports";
inline constexpr char DEFAULT_EFFECTS_IMPORT_FOLDER[] = "/asset_imports/Effects";
inline constexpr char OLD_ASSET_IMPORT_FOLDER[] = "asset_imports";
inline constexpr char OLD_EFFECTS_IMPORT_FOLDER[] = "/asset_imports/Effects";
inline constexpr char OLD_EFFECTS_FOLDER[] = "Effects";
inline constexpr char COMPOSED_EFFECTS_TYPE[] = "ComposedEffects";
inline constexpr char MATERIAL_LIB_ID[] = "__materialLibrary__";
inline constexpr char MIME_TYPE_ITEM_LIBRARY_INFO[]