forked from qt-creator/qt-creator
QmlDesigner: Allow adding imported 3D components to content library
Fixes: QDS-12784 Change-Id: I87edf8f6c14fabb066c85e8536c91b58e439e5d0 Reviewed-by: Marco Bubke <marco.bubke@qt.io> Reviewed-by: Ali Kianian <ali.kianian@qt.io> Reviewed-by: Miikka Heikkinen <miikka.heikkinen@qt.io>
This commit is contained in:
@@ -312,8 +312,7 @@ QPair<QString, QString> ContentLibraryUserModel::getUniqueLibItemNames(const QSt
|
|||||||
itemIcons.append(QFileInfo(obj.value("icon").toString()).baseName());
|
itemIcons.append(QFileInfo(obj.value("icon").toString()).baseName());
|
||||||
}
|
}
|
||||||
|
|
||||||
QString baseQml = defaultName.trimmed();
|
QString baseQml = UniqueName::generateId(defaultName);
|
||||||
baseQml.remove(' ');
|
|
||||||
baseQml[0] = baseQml.at(0).toUpper();
|
baseQml[0] = baseQml.at(0).toUpper();
|
||||||
baseQml.prepend("My");
|
baseQml.prepend("My");
|
||||||
|
|
||||||
|
@@ -23,8 +23,9 @@
|
|||||||
#include <qmldesignerconstants.h>
|
#include <qmldesignerconstants.h>
|
||||||
#include <qmldesignerplugin.h>
|
#include <qmldesignerplugin.h>
|
||||||
#include <qmlobjectnode.h>
|
#include <qmlobjectnode.h>
|
||||||
#include <variantproperty.h>
|
#include <uniquename.h>
|
||||||
#include <utils3d.h>
|
#include <utils3d.h>
|
||||||
|
#include <variantproperty.h>
|
||||||
|
|
||||||
#include <utils/algorithm.h>
|
#include <utils/algorithm.h>
|
||||||
|
|
||||||
@@ -367,7 +368,10 @@ void ContentLibraryView::customNotification(const AbstractView *view,
|
|||||||
} else if (identifier == "add_assets_to_content_lib") {
|
} else if (identifier == "add_assets_to_content_lib") {
|
||||||
addLibAssets(data.first().toStringList());
|
addLibAssets(data.first().toStringList());
|
||||||
} else if (identifier == "add_3d_to_content_lib") {
|
} else if (identifier == "add_3d_to_content_lib") {
|
||||||
addLib3DItem(nodeList.first());
|
if (nodeList.first().isComponent())
|
||||||
|
addLib3DComponent(nodeList.first());
|
||||||
|
else
|
||||||
|
addLib3DItem(nodeList.first());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -663,6 +667,67 @@ void ContentLibraryView::addLibAssets(const QStringList &paths)
|
|||||||
m_widget->userModel()->addTextures(pathsInBundle);
|
m_widget->userModel()->addTextures(pathsInBundle);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void ContentLibraryView::addLib3DComponent(const ModelNode &node)
|
||||||
|
{
|
||||||
|
auto compUtils = QmlDesignerPlugin::instance()->documentManager().generatedComponentUtils();
|
||||||
|
|
||||||
|
// TODO: check component with existing name and show a confirmation dialog
|
||||||
|
QString compBaseName = node.simplifiedTypeName();
|
||||||
|
QString compFileName = compBaseName + ".qml";
|
||||||
|
|
||||||
|
Utils::FilePath compDir = DocumentManager::currentProjectDirPath()
|
||||||
|
.pathAppended(compUtils.import3dTypePath() + '/' + compBaseName);
|
||||||
|
|
||||||
|
auto bundlePath = Utils::FilePath::fromString(Paths::bundlesPathSetting() + "/User/3d/");
|
||||||
|
|
||||||
|
// generate and save icon
|
||||||
|
UniqueName::generateId(compBaseName);
|
||||||
|
QString iconPath = QLatin1String("icons/%1").arg(UniqueName::generateId(compBaseName) + ".png");
|
||||||
|
QString fullIconPath = bundlePath.pathAppended(iconPath).toString();
|
||||||
|
genAndSaveIcon(compDir.pathAppended(compFileName).path(), fullIconPath);
|
||||||
|
|
||||||
|
const Utils::FilePaths sourceFiles = compDir.dirEntries({{}, QDir::Files, QDirIterator::Subdirectories});
|
||||||
|
const QStringList ignoreList {"_importdata.json", "qmldir", compBaseName + ".hints"};
|
||||||
|
QStringList filesList; // 3D component's assets (dependencies)
|
||||||
|
|
||||||
|
for (const Utils::FilePath &sourcePath : sourceFiles) {
|
||||||
|
Utils::FilePath relativePath = sourcePath.relativePathFrom(compDir);
|
||||||
|
if (ignoreList.contains(sourcePath.fileName()) || relativePath.startsWith("source scene"))
|
||||||
|
continue;
|
||||||
|
|
||||||
|
Utils::FilePath targetPath = bundlePath.pathAppended(relativePath.path());
|
||||||
|
targetPath.parentDir().ensureWritableDir();
|
||||||
|
|
||||||
|
// copy item from project to user bundle
|
||||||
|
auto result = sourcePath.copyFile(targetPath);
|
||||||
|
if (!result)
|
||||||
|
qWarning() << __FUNCTION__ << result.error();
|
||||||
|
|
||||||
|
if (sourcePath.fileName() != compFileName) // skip component file (only collect dependencies)
|
||||||
|
filesList.append(relativePath.path());
|
||||||
|
}
|
||||||
|
|
||||||
|
// add the item to the bundle json
|
||||||
|
QJsonObject &jsonRef = m_widget->userModel()->bundleJson3DObjectRef();
|
||||||
|
QJsonArray itemsArr = jsonRef.value("items").toArray();
|
||||||
|
itemsArr.append(QJsonObject {
|
||||||
|
{"name", node.simplifiedTypeName()},
|
||||||
|
{"qml", compFileName},
|
||||||
|
{"icon", iconPath},
|
||||||
|
{"files", QJsonArray::fromStringList(filesList)}
|
||||||
|
});
|
||||||
|
|
||||||
|
jsonRef["items"] = itemsArr;
|
||||||
|
|
||||||
|
auto result = bundlePath.pathAppended("user_3d_bundle.json")
|
||||||
|
.writeFileContents(QJsonDocument(jsonRef).toJson());
|
||||||
|
if (!result)
|
||||||
|
qWarning() << __FUNCTION__ << result.error();
|
||||||
|
|
||||||
|
m_widget->userModel()->add3DItem(compBaseName, compFileName, QUrl::fromLocalFile(fullIconPath),
|
||||||
|
filesList);
|
||||||
|
}
|
||||||
|
|
||||||
void ContentLibraryView::addLib3DItem(const ModelNode &node)
|
void ContentLibraryView::addLib3DItem(const ModelNode &node)
|
||||||
{
|
{
|
||||||
auto bundlePath = Utils::FilePath::fromString(Paths::bundlesPathSetting() + "/User/3d/");
|
auto bundlePath = Utils::FilePath::fromString(Paths::bundlesPathSetting() + "/User/3d/");
|
||||||
@@ -682,16 +747,13 @@ void ContentLibraryView::addLib3DItem(const ModelNode &node)
|
|||||||
// add the item to the bundle json
|
// add the item to the bundle json
|
||||||
QJsonObject &jsonRef = m_widget->userModel()->bundleJson3DObjectRef();
|
QJsonObject &jsonRef = m_widget->userModel()->bundleJson3DObjectRef();
|
||||||
QJsonArray itemsArr = jsonRef.value("items").toArray();
|
QJsonArray itemsArr = jsonRef.value("items").toArray();
|
||||||
QJsonObject itemObj;
|
itemsArr.append(QJsonObject {
|
||||||
itemObj.insert("name", name);
|
{"name", name},
|
||||||
itemObj.insert("qml", qml);
|
{"qml", qml},
|
||||||
itemObj.insert("icon", iconPath);
|
{"icon", iconPath},
|
||||||
QJsonArray filesArr;
|
{"files", QJsonArray::fromStringList(depAssets)}
|
||||||
for (const QString &assetPath : depAssets)
|
});
|
||||||
filesArr.append(assetPath);
|
|
||||||
itemObj.insert("files", filesArr);
|
|
||||||
|
|
||||||
itemsArr.append(itemObj);
|
|
||||||
jsonRef["items"] = itemsArr;
|
jsonRef["items"] = itemsArr;
|
||||||
|
|
||||||
auto result = bundlePath.pathAppended("user_3d_bundle.json")
|
auto result = bundlePath.pathAppended("user_3d_bundle.json")
|
||||||
|
@@ -57,6 +57,7 @@ private:
|
|||||||
void updateBundlesQuick3DVersion();
|
void updateBundlesQuick3DVersion();
|
||||||
void addLibMaterial(const ModelNode &node, const QPixmap &iconPixmap);
|
void addLibMaterial(const ModelNode &node, const QPixmap &iconPixmap);
|
||||||
void addLibAssets(const QStringList &paths);
|
void addLibAssets(const QStringList &paths);
|
||||||
|
void addLib3DComponent(const ModelNode &node);
|
||||||
void addLib3DItem(const ModelNode &node);
|
void addLib3DItem(const ModelNode &node);
|
||||||
void genAndSaveIcon(const QString &qmlPath, const QString &iconPath);
|
void genAndSaveIcon(const QString &qmlPath, const QString &iconPath);
|
||||||
QStringList writeLibItemQml(const ModelNode &node, const QString &qml);
|
QStringList writeLibItemQml(const ModelNode &node, const QString &qml);
|
||||||
|
@@ -156,6 +156,9 @@ QString generateId(const QString &id, std::function<bool(const QString &)> predi
|
|||||||
if (newId.at(0).isDigit() || std::binary_search(std::begin(keywords), std::end(keywords), newId))
|
if (newId.at(0).isDigit() || std::binary_search(std::begin(keywords), std::end(keywords), newId))
|
||||||
newId.prepend('_');
|
newId.prepend('_');
|
||||||
|
|
||||||
|
if (!predicate)
|
||||||
|
return newId;
|
||||||
|
|
||||||
return UniqueName::generate(newId, predicate);
|
return UniqueName::generate(newId, predicate);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@@ -11,6 +11,7 @@ namespace QmlDesigner::UniqueName {
|
|||||||
|
|
||||||
QString generate(const QString &name, std::function<bool(const QString &)> predicate);
|
QString generate(const QString &name, std::function<bool(const QString &)> predicate);
|
||||||
QString generatePath(const QString &path);
|
QString generatePath(const QString &path);
|
||||||
QMLDESIGNERCORE_EXPORT QString generateId(const QString &id, std::function<bool(const QString &)> predicate);
|
QMLDESIGNERCORE_EXPORT QString generateId(const QString &id,
|
||||||
|
std::function<bool(const QString &)> predicate = {});
|
||||||
|
|
||||||
} // namespace QmlDesigner::UniqueName
|
} // namespace QmlDesigner::UniqueName
|
||||||
|
@@ -21,6 +21,15 @@ TEST(UniqueName, generate_returns_same_input_if_predicate_returns_false)
|
|||||||
ASSERT_THAT(uniqueName, "abc");
|
ASSERT_THAT(uniqueName, "abc");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
TEST(UniqueName, generateId_returns_properly_formatted_id_when_predicate_is_not_provided)
|
||||||
|
{
|
||||||
|
QString id = " A bc d _";
|
||||||
|
|
||||||
|
QString uniqueId = UniqueName::generateId(id);
|
||||||
|
|
||||||
|
ASSERT_THAT(uniqueId, "aBcD_");
|
||||||
|
}
|
||||||
|
|
||||||
TEST(UniqueName, generateId_returns_properly_formatted_id)
|
TEST(UniqueName, generateId_returns_properly_formatted_id)
|
||||||
{
|
{
|
||||||
auto pred = [] (const QString &id) -> bool {
|
auto pred = [] (const QString &id) -> bool {
|
||||||
|
Reference in New Issue
Block a user