aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--share/qtcreator/qmldesigner/contentLibraryQmlSource/ContentLibraryItemContextMenu.qml2
-rw-r--r--share/qtcreator/qmldesigner/contentLibraryQmlSource/ContentLibraryUserView.qml12
-rw-r--r--src/plugins/qmldesigner/CMakeLists.txt3
-rw-r--r--src/plugins/qmldesigner/components/contentlibrary/contentlibraryeffectsmodel.cpp2
-rw-r--r--src/plugins/qmldesigner/components/contentlibrary/contentlibraryitem.cpp8
-rw-r--r--src/plugins/qmldesigner/components/contentlibrary/contentlibraryitem.h8
-rw-r--r--src/plugins/qmldesigner/components/contentlibrary/contentlibrarytexture.h4
-rw-r--r--src/plugins/qmldesigner/components/contentlibrary/contentlibraryusermodel.cpp485
-rw-r--r--src/plugins/qmldesigner/components/contentlibrary/contentlibraryusermodel.h75
-rw-r--r--src/plugins/qmldesigner/components/contentlibrary/contentlibraryview.cpp56
-rw-r--r--src/plugins/qmldesigner/components/contentlibrary/contentlibrarywidget.cpp6
-rw-r--r--src/plugins/qmldesigner/components/contentlibrary/usercategory.cpp74
-rw-r--r--src/plugins/qmldesigner/components/contentlibrary/usercategory.h50
-rw-r--r--src/plugins/qmldesigner/components/contentlibrary/useritemcategory.cpp121
-rw-r--r--src/plugins/qmldesigner/components/contentlibrary/useritemcategory.h35
-rw-r--r--src/plugins/qmldesigner/components/contentlibrary/usertexturecategory.cpp66
-rw-r--r--src/plugins/qmldesigner/components/contentlibrary/usertexturecategory.h25
-rw-r--r--src/plugins/qmldesigner/designercore/generatedcomponentutils.cpp15
-rw-r--r--src/plugins/qmldesigner/designercore/generatedcomponentutils.h1
19 files changed, 578 insertions, 470 deletions
diff --git a/share/qtcreator/qmldesigner/contentLibraryQmlSource/ContentLibraryItemContextMenu.qml b/share/qtcreator/qmldesigner/contentLibraryQmlSource/ContentLibraryItemContextMenu.qml
index 6f505124300..a2e72335e9f 100644
--- a/share/qtcreator/qmldesigner/contentLibraryQmlSource/ContentLibraryItemContextMenu.qml
+++ b/share/qtcreator/qmldesigner/contentLibraryQmlSource/ContentLibraryItemContextMenu.qml
@@ -23,7 +23,7 @@ StudioControls.Menu {
{
root.targetItem = item
- let isMaterial = root.targetItem.itemType === "material"
+ let isMaterial = root.targetItem.bundleId === "UserMaterials"
applyToSelectedReplace.visible = isMaterial
applyToSelectedAdd.visible = isMaterial
diff --git a/share/qtcreator/qmldesigner/contentLibraryQmlSource/ContentLibraryUserView.qml b/share/qtcreator/qmldesigner/contentLibraryQmlSource/ContentLibraryUserView.qml
index d93895ec554..f0aa94bba87 100644
--- a/share/qtcreator/qmldesigner/contentLibraryQmlSource/ContentLibraryUserView.qml
+++ b/share/qtcreator/qmldesigner/contentLibraryQmlSource/ContentLibraryUserView.qml
@@ -80,8 +80,8 @@ HelperWidgets.ScrollView {
topPadding: StudioTheme.Values.sectionPadding
bottomPadding: StudioTheme.Values.sectionPadding
- caption: categoryName
- visible: categoryVisible && infoText.text === ""
+ caption: categoryTitle
+ visible: !categoryEmpty && infoText.text === ""
category: "ContentLib_User"
function expandSection() {
@@ -102,10 +102,10 @@ HelperWidgets.ScrollView {
model: categoryItems
delegate: DelegateChooser {
- role: "itemType"
+ role: "bundleId"
DelegateChoice {
- roleValue: "material"
+ roleValue: "UserMaterials"
ContentLibraryItem {
width: root.cellWidth
height: root.cellHeight
@@ -115,7 +115,7 @@ HelperWidgets.ScrollView {
}
}
DelegateChoice {
- roleValue: "texture"
+ roleValue: "UserTextures"
delegate: ContentLibraryTexture {
width: root.cellWidth
height: root.cellWidth // for textures use a square size since there is no name row
@@ -124,7 +124,7 @@ HelperWidgets.ScrollView {
}
}
DelegateChoice {
- roleValue: "3d"
+ roleValue: "User3D"
delegate: ContentLibraryItem {
width: root.cellWidth
height: root.cellHeight
diff --git a/src/plugins/qmldesigner/CMakeLists.txt b/src/plugins/qmldesigner/CMakeLists.txt
index 1ee5b7ca139..add610e0268 100644
--- a/src/plugins/qmldesigner/CMakeLists.txt
+++ b/src/plugins/qmldesigner/CMakeLists.txt
@@ -839,6 +839,9 @@ extend_qtc_plugin(QmlDesigner
contentlibraryeffectscategory.cpp contentlibraryeffectscategory.h
contentlibraryeffectsmodel.cpp contentlibraryeffectsmodel.h
contentlibraryusermodel.cpp contentlibraryusermodel.h
+ usercategory.cpp usercategory.h
+ useritemcategory.cpp useritemcategory.h
+ usertexturecategory.cpp usertexturecategory.h
)
extend_qtc_plugin(QmlDesigner
diff --git a/src/plugins/qmldesigner/components/contentlibrary/contentlibraryeffectsmodel.cpp b/src/plugins/qmldesigner/components/contentlibrary/contentlibraryeffectsmodel.cpp
index d8bcdf5b4a2..ac4a75a293d 100644
--- a/src/plugins/qmldesigner/components/contentlibrary/contentlibraryeffectsmodel.cpp
+++ b/src/plugins/qmldesigner/components/contentlibrary/contentlibraryeffectsmodel.cpp
@@ -171,7 +171,7 @@ void ContentLibraryEffectsModel::loadBundle()
TypeName type = QLatin1String("%1.%2")
.arg(bundleType, qml.chopped(4)).toLatin1(); // chopped(4): remove .qml
- auto bundleItem = new ContentLibraryItem(category, itemName, qml, type, icon, files, "effect");
+ auto bundleItem = new ContentLibraryItem(category, itemName, qml, type, icon, files, m_bundleId);
category->addBundleItem(bundleItem);
}
diff --git a/src/plugins/qmldesigner/components/contentlibrary/contentlibraryitem.cpp b/src/plugins/qmldesigner/components/contentlibrary/contentlibraryitem.cpp
index 6ab26885d4f..010cc065a53 100644
--- a/src/plugins/qmldesigner/components/contentlibrary/contentlibraryitem.cpp
+++ b/src/plugins/qmldesigner/components/contentlibrary/contentlibraryitem.cpp
@@ -11,9 +11,9 @@ ContentLibraryItem::ContentLibraryItem(QObject *parent,
const TypeName &type,
const QUrl &icon,
const QStringList &files,
- const QString &itemType)
+ const QString &bundleId)
: QObject(parent), m_name(name), m_qml(qml), m_type(type), m_icon(icon), m_files(files),
- m_itemType(itemType)
+ m_bundleId(bundleId)
{
m_allFiles = m_files;
m_allFiles.push_back(m_qml);
@@ -75,9 +75,9 @@ QStringList ContentLibraryItem::allFiles() const
return m_allFiles;
}
-QString ContentLibraryItem::itemType() const
+QString ContentLibraryItem::bundleId() const
{
- return m_itemType;
+ return m_bundleId;
}
} // namespace QmlDesigner
diff --git a/src/plugins/qmldesigner/components/contentlibrary/contentlibraryitem.h b/src/plugins/qmldesigner/components/contentlibrary/contentlibraryitem.h
index b2610953ae8..36fd9464c08 100644
--- a/src/plugins/qmldesigner/components/contentlibrary/contentlibraryitem.h
+++ b/src/plugins/qmldesigner/components/contentlibrary/contentlibraryitem.h
@@ -19,7 +19,7 @@ class ContentLibraryItem : public QObject
Q_PROPERTY(QStringList bundleItemFiles READ allFiles CONSTANT)
Q_PROPERTY(bool bundleItemVisible MEMBER m_visible NOTIFY itemVisibleChanged)
Q_PROPERTY(bool bundleItemImported READ imported WRITE setImported NOTIFY itemImportedChanged)
- Q_PROPERTY(QString itemType READ itemType CONSTANT)
+ Q_PROPERTY(QString bundleId READ bundleId CONSTANT)
public:
ContentLibraryItem(QObject *parent,
@@ -28,7 +28,7 @@ public:
const TypeName &type,
const QUrl &icon,
const QStringList &files,
- const QString &itemType);
+ const QString &bundleId);
bool filter(const QString &searchText);
@@ -38,7 +38,7 @@ public:
QStringList files() const;
bool visible() const;
- QString itemType() const;
+ QString bundleId() const;
bool setImported(bool imported);
bool imported() const;
@@ -59,7 +59,7 @@ private:
bool m_imported = false;
QStringList m_allFiles;
- const QString m_itemType;
+ const QString m_bundleId;
};
} // namespace QmlDesigner
diff --git a/src/plugins/qmldesigner/components/contentlibrary/contentlibrarytexture.h b/src/plugins/qmldesigner/components/contentlibrary/contentlibrarytexture.h
index 7f5db6d7d60..aa05667a1cd 100644
--- a/src/plugins/qmldesigner/components/contentlibrary/contentlibrarytexture.h
+++ b/src/plugins/qmldesigner/components/contentlibrary/contentlibrarytexture.h
@@ -24,7 +24,7 @@ class ContentLibraryTexture : public QObject
Q_PROPERTY(bool textureHasUpdate WRITE setHasUpdate READ hasUpdate NOTIFY hasUpdateChanged)
Q_PROPERTY(bool textureIsNew MEMBER m_isNew CONSTANT)
Q_PROPERTY(QString textureKey MEMBER m_textureKey CONSTANT)
- Q_PROPERTY(QString itemType MEMBER m_itemType CONSTANT)
+ Q_PROPERTY(QString bundleId MEMBER m_bundleId CONSTANT)
public:
ContentLibraryTexture(QObject *parent, const QFileInfo &iconFileInfo, const QString &dirPath,
@@ -74,7 +74,7 @@ private:
bool m_visible = true;
bool m_hasUpdate = false;
bool m_isNew = false;
- const QString m_itemType = "texture";
+ const QString m_bundleId = "UserTextures";
};
} // namespace QmlDesigner
diff --git a/src/plugins/qmldesigner/components/contentlibrary/contentlibraryusermodel.cpp b/src/plugins/qmldesigner/components/contentlibrary/contentlibraryusermodel.cpp
index 65489dc9c05..030e2022c6b 100644
--- a/src/plugins/qmldesigner/components/contentlibrary/contentlibraryusermodel.cpp
+++ b/src/plugins/qmldesigner/components/contentlibrary/contentlibraryusermodel.cpp
@@ -2,6 +2,8 @@
// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
#include "contentlibraryusermodel.h"
+#include "useritemcategory.h"
+#include "usertexturecategory.h"
#include "contentlibrarybundleimporter.h"
#include "contentlibraryitem.h"
@@ -28,6 +30,7 @@ ContentLibraryUserModel::ContentLibraryUserModel(ContentLibraryWidget *parent)
: QAbstractListModel(parent)
, m_widget(parent)
{
+ createCategories();
}
int ContentLibraryUserModel::rowCount(const QModelIndex &) const
@@ -40,119 +43,73 @@ QVariant ContentLibraryUserModel::data(const QModelIndex &index, int role) const
QTC_ASSERT(index.isValid() && index.row() < m_userCategories.size(), return {});
QTC_ASSERT(roleNames().contains(role), return {});
- if (role == NameRole)
- return m_userCategories.at(index.row());
-
- if (role == ItemsRole) {
- if (index.row() == MaterialsSectionIdx)
- return QVariant::fromValue(m_userMaterials);
- if (index.row() == TexturesSectionIdx)
- return QVariant::fromValue(m_userTextures);
- if (index.row() == Items3DSectionIdx)
- return QVariant::fromValue(m_user3DItems);
- if (index.row() == EffectsSectionIdx)
- return QVariant::fromValue(m_userEffects);
- }
+ UserCategory *currCat = m_userCategories.at(index.row());
- if (role == NoMatchRole) {
- if (index.row() == MaterialsSectionIdx)
- return m_noMatchMaterials;
- if (index.row() == TexturesSectionIdx)
- return m_noMatchTextures;
- if (index.row() == Items3DSectionIdx)
- return m_noMatch3D;
- if (index.row() == EffectsSectionIdx)
- return m_noMatchEffects;
- }
+ if (role == TitleRole)
+ return currCat->title();
- if (role == VisibleRole) {
- if (index.row() == MaterialsSectionIdx)
- return !m_userMaterials.isEmpty();
- if (index.row() == TexturesSectionIdx)
- return !m_userTextures.isEmpty();
- if (index.row() == Items3DSectionIdx)
- return !m_user3DItems.isEmpty();
- if (index.row() == EffectsSectionIdx)
- return !m_userEffects.isEmpty();
- }
+ if (role == ItemsRole)
+ return QVariant::fromValue(currCat->items());
- return {};
-}
+ if (role == NoMatchRole)
+ return currCat->noMatch();
-void ContentLibraryUserModel::updateNoMatchMaterials()
-{
- m_noMatchMaterials = Utils::allOf(m_userMaterials, [&](ContentLibraryItem *item) {
- return !item->visible();
- });
-}
+ if (role == EmptyRole)
+ return currCat->isEmpty();
-void ContentLibraryUserModel::updateNoMatchTextures()
-{
- m_noMatchTextures = Utils::allOf(m_userTextures, [&](ContentLibraryTexture *item) {
- return !item->visible();
- });
+ return {};
}
-void ContentLibraryUserModel::updateNoMatch3D()
+void ContentLibraryUserModel::createCategories()
{
- m_noMatch3D = Utils::allOf(m_user3DItems, [&](ContentLibraryItem *item) {
- return !item->visible();
- });
-}
+ QTC_ASSERT(m_userCategories.isEmpty(), return);
-void ContentLibraryUserModel::addMaterial(const QString &name, const QString &qml,
- const QUrl &icon, const QStringList &files)
-{
auto compUtils = QmlDesignerPlugin::instance()->documentManager().generatedComponentUtils();
+ auto userBundlePath = Utils::FilePath::fromString(Paths::bundlesPathSetting() + "/User");
- QString typePrefix = compUtils.userMaterialsBundleType();
- TypeName type = QLatin1String("%1.%2").arg(typePrefix, qml.chopped(4)).toLatin1();
+ auto catMaterial = new UserItemCategory{tr("Materials"),
+ userBundlePath.pathAppended("materials"),
+ compUtils.userMaterialsBundleId()};
- auto libMat = new ContentLibraryItem(this, name, qml, type, icon, files, "material");
- m_userMaterials.append(libMat);
+ auto catTexture = new UserTextureCategory{tr("Textures"), userBundlePath.pathAppended("textures")};
- emit dataChanged(index(MaterialsSectionIdx), index(MaterialsSectionIdx));
+ auto cat3D = new UserItemCategory{tr("3D"), userBundlePath.pathAppended("3d"),
+ compUtils.user3DBundleId()};
- updateIsEmpty();
+ m_userCategories << catMaterial << catTexture << cat3D;
}
-void ContentLibraryUserModel::add3DItem(const QString &name, const QString &qml,
- const QUrl &icon, const QStringList &files)
+void ContentLibraryUserModel::addItem(const QString &bundleId, const QString &name,
+ const QString &qml, const QUrl &icon, const QStringList &files)
{
auto compUtils = QmlDesignerPlugin::instance()->documentManager().generatedComponentUtils();
- QString typePrefix = compUtils.user3DBundleType();
+ QString typePrefix = compUtils.userBundleType(bundleId);
TypeName type = QLatin1String("%1.%2").arg(typePrefix, qml.chopped(4)).toLatin1();
- m_user3DItems.append(new ContentLibraryItem(this, name, qml, type, icon, files, "3d"));
+ SectionIndex sectionIndex = bundleIdToSectionIndex(bundleId);
+
+ UserCategory *cat = m_userCategories[sectionIndex];
+ cat->addItem(new ContentLibraryItem(cat, name, qml, type, icon, files, bundleId));
+ emit dataChanged(index(sectionIndex), index(sectionIndex), {ItemsRole, EmptyRole});
+ updateIsEmpty();
}
-void ContentLibraryUserModel::refreshSection(SectionIndex sectionIndex)
+void ContentLibraryUserModel::refreshSection(const QString &bundleId)
{
- emit dataChanged(index(sectionIndex), index(sectionIndex));
+ SectionIndex sectionIdx = bundleIdToSectionIndex(bundleId);
+ emit dataChanged(index(sectionIdx), index(sectionIdx), {ItemsRole, EmptyRole});
updateIsEmpty();
}
-void ContentLibraryUserModel::addTextures(const QStringList &paths)
+void ContentLibraryUserModel::addTextures(const Utils::FilePaths &paths)
{
- QDir bundleDir{Paths::bundlesPathSetting() + "/User/textures"};
- bundleDir.mkpath(".");
- bundleDir.mkdir("icons");
-
- for (const QString &path : paths) {
- QFileInfo fileInfo(path);
- QString suffix = '.' + fileInfo.suffix();
- auto iconFileInfo = QFileInfo(fileInfo.path().append("/icons/").append(fileInfo.baseName() + ".png"));
- QPair<QSize, qint64> info = ImageUtils::imageInfo(path);
- QString dirPath = fileInfo.path();
- QSize imgDims = info.first;
- qint64 imgFileSize = info.second;
-
- auto tex = new ContentLibraryTexture(this, iconFileInfo, dirPath, suffix, imgDims, imgFileSize);
- m_userTextures.append(tex);
- }
+ auto texCat = qobject_cast<UserTextureCategory *>(m_userCategories[TexturesSectionIdx]);
+ QTC_ASSERT(texCat, return);
- emit dataChanged(index(TexturesSectionIdx), index(TexturesSectionIdx));
+ texCat->addItems(paths);
+
+ emit dataChanged(index(TexturesSectionIdx), index(TexturesSectionIdx), {ItemsRole, EmptyRole});
}
void ContentLibraryUserModel::removeTexture(ContentLibraryTexture *tex)
@@ -162,8 +119,7 @@ void ContentLibraryUserModel::removeTexture(ContentLibraryTexture *tex)
Utils::FilePath::fromString(tex->iconPath()).removeFile();
// remove from model
- m_userTextures.removeOne(tex);
- tex->deleteLater();
+ m_userCategories[TexturesSectionIdx]->removeItem(tex);
// update model
emit dataChanged(index(TexturesSectionIdx), index(TexturesSectionIdx));
@@ -178,23 +134,20 @@ void ContentLibraryUserModel::removeFromContentLib(QObject *item)
removeItem(castedItem);
}
-void ContentLibraryUserModel::remove3DFromContentLibByName(const QString &qmlFileName)
+void ContentLibraryUserModel::removeItemByName(const QString &qmlFileName, const QString &bundleId)
{
- ContentLibraryItem *itemToRemove = Utils::findOr(m_user3DItems, nullptr,
- [&qmlFileName](ContentLibraryItem *item) {
- return item->qml() == qmlFileName;
- });
+ ContentLibraryItem *itemToRemove = nullptr;
+ const QObjectList items = m_userCategories[bundleIdToSectionIndex(bundleId)]->items();
- if (itemToRemove)
- removeItem(itemToRemove);
-}
+ for (QObject *item : items) {
+ ContentLibraryItem *castedItem = qobject_cast<ContentLibraryItem *>(item);
+ QTC_ASSERT(castedItem, return);
-void ContentLibraryUserModel::removeMaterialFromContentLibByName(const QString &qmlFileName)
-{
- ContentLibraryItem *itemToRemove = Utils::findOr(m_userMaterials, nullptr,
- [&qmlFileName](ContentLibraryItem *item) {
- return item->qml() == qmlFileName;
- });
+ if (castedItem->qml() == qmlFileName) {
+ itemToRemove = castedItem;
+ break;
+ }
+ }
if (itemToRemove)
removeItem(itemToRemove);
@@ -202,30 +155,16 @@ void ContentLibraryUserModel::removeMaterialFromContentLibByName(const QString &
void ContentLibraryUserModel::removeItem(ContentLibraryItem *item)
{
- Utils::FilePath *bundlePath = nullptr;
- QJsonObject *bundleObj = nullptr;
- QList<ContentLibraryItem *> *userItems = nullptr;
- SectionIndex sectionIdx;
-
- if (item->itemType() == "material") {
- bundlePath = &m_bundlePathMaterial;
- bundleObj = &m_bundleObjMaterial;
- userItems = &m_userMaterials;
- sectionIdx = MaterialsSectionIdx;
- } else if (item->itemType() == "3d") {
- bundlePath = &m_bundlePath3D;
- bundleObj = &m_bundleObj3D;
- userItems = &m_user3DItems;
- sectionIdx = Items3DSectionIdx;
- } else {
- qWarning() << __FUNCTION__ << "Unsupported item";
- return;
- }
+ UserItemCategory *itemCat = qobject_cast<UserItemCategory *>(item->parent());
+ QTC_ASSERT(itemCat, return);
- QJsonArray itemsArr = bundleObj->value("items").toArray();
+ Utils::FilePath bundlePath = itemCat->bundlePath();
+ QJsonObject &bundleObj = itemCat->bundleObjRef();
+
+ QJsonArray itemsArr = bundleObj.value("items").toArray();
// remove qml and icon files
- bundlePath->pathAppended(item->qml()).removeFile();
+ bundlePath.pathAppended(item->qml()).removeFile();
Utils::FilePath::fromUrl(item->icon()).removeFile();
// remove from the bundle json file
@@ -235,10 +174,10 @@ void ContentLibraryUserModel::removeItem(ContentLibraryItem *item)
break;
}
}
- bundleObj->insert("items", itemsArr);
+ bundleObj.insert("items", itemsArr);
- auto result = bundlePath->pathAppended(Constants::BUNDLE_JSON_FILENAME)
- .writeFileContents(QJsonDocument(*bundleObj).toJson());
+ auto result = bundlePath.pathAppended(Constants::BUNDLE_JSON_FILENAME)
+ .writeFileContents(QJsonDocument(bundleObj).toJson());
if (!result)
qWarning() << __FUNCTION__ << result.error();
@@ -250,18 +189,36 @@ void ContentLibraryUserModel::removeItem(ContentLibraryItem *item)
const QStringList itemFiles = item->files();
for (const QString &file : itemFiles) {
if (allFiles.count(file) == 0) // only used by the deleted item
- bundlePath->pathAppended(file).removeFile();
+ bundlePath.pathAppended(file).removeFile();
}
// remove from model
- userItems->removeOne(item);
- item->deleteLater();
+ itemCat->removeItem(item);
// update model
- emit dataChanged(index(sectionIdx), index(sectionIdx));
+ SectionIndex sectionIdx = bundleIdToSectionIndex(item->bundleId());
+ emit dataChanged(index(sectionIdx), index(sectionIdx), {ItemsRole, EmptyRole});
updateIsEmpty();
}
+ContentLibraryUserModel::SectionIndex ContentLibraryUserModel::bundleIdToSectionIndex(
+ const QString &bundleId) const
+{
+ auto compUtils = QmlDesignerPlugin::instance()->documentManager().generatedComponentUtils();
+
+ if (bundleId == compUtils.userMaterialsBundleId())
+ return MaterialsSectionIdx;
+
+ if (bundleId == compUtils.user3DBundleId())
+ return Items3DSectionIdx;
+
+ if (bundleId == compUtils.userEffectsBundleId())
+ return EffectsSectionIdx;
+
+ qWarning() << __FUNCTION__ << "Invalid section index for bundleId:" << bundleId;
+ return {};
+}
+
/**
* @brief Gets unique Qml component and icon file material names from a given name
* @param defaultName input name
@@ -269,7 +226,9 @@ void ContentLibraryUserModel::removeItem(ContentLibraryItem *item)
*/
QPair<QString, QString> ContentLibraryUserModel::getUniqueLibMaterialNames(const QString &defaultName) const
{
- return getUniqueLibItemNames(defaultName, m_bundleObjMaterial);
+ const QJsonObject bundleObj = qobject_cast<UserItemCategory *>(
+ m_userCategories.at(Items3DSectionIdx))->bundleObjRef();
+ return getUniqueLibItemNames(defaultName, bundleObj);
}
/**
@@ -279,7 +238,9 @@ QPair<QString, QString> ContentLibraryUserModel::getUniqueLibMaterialNames(const
*/
QPair<QString, QString> ContentLibraryUserModel::getUniqueLib3DNames(const QString &defaultName) const
{
- return getUniqueLibItemNames(defaultName, m_bundleObj3D);
+ const QJsonObject bundleObj = qobject_cast<UserItemCategory *>(
+ m_userCategories.at(Items3DSectionIdx))->bundleObjRef();
+ return getUniqueLibItemNames(defaultName, bundleObj);
}
QPair<QString, QString> ContentLibraryUserModel::getUniqueLibItemNames(const QString &defaultName,
@@ -319,208 +280,27 @@ QPair<QString, QString> ContentLibraryUserModel::getUniqueLibItemNames(const QSt
QHash<int, QByteArray> ContentLibraryUserModel::roleNames() const
{
static const QHash<int, QByteArray> roles {
- {NameRole, "categoryName"},
- {VisibleRole, "categoryVisible"},
+ {TitleRole, "categoryTitle"},
+ {EmptyRole, "categoryEmpty"},
{ItemsRole, "categoryItems"},
{NoMatchRole, "categoryNoMatch"}
};
return roles;
}
-QJsonObject &ContentLibraryUserModel::bundleJsonMaterialObjectRef()
+QJsonObject &ContentLibraryUserModel::bundleObjectRef(const QString &bundleId)
{
- return m_bundleObjMaterial;
-}
-
-QJsonObject &ContentLibraryUserModel::bundleJson3DObjectRef()
-{
- return m_bundleObj3D;
+ auto secIdx = bundleIdToSectionIndex(bundleId);
+ return qobject_cast<UserItemCategory *>(m_userCategories[secIdx])->bundleObjRef();
}
void ContentLibraryUserModel::loadBundles()
{
- loadMaterialBundle();
- load3DBundle();
- loadTextureBundle();
-}
-
-void ContentLibraryUserModel::loadMaterialBundle()
-{
- auto compUtils = QmlDesignerPlugin::instance()->documentManager().generatedComponentUtils();
- if (m_matBundleLoaded && m_bundleIdMaterial == compUtils.userMaterialsBundleId())
- return;
-
- // clean up
- qDeleteAll(m_userMaterials);
- m_userMaterials.clear();
- m_matBundleLoaded = false;
- m_noMatchMaterials = true;
- m_bundleObjMaterial = {};
- m_bundleIdMaterial.clear();
-
- m_bundlePathMaterial = Utils::FilePath::fromString(Paths::bundlesPathSetting() + "/User/materials");
- m_bundlePathMaterial.ensureWritableDir();
- m_bundlePathMaterial.pathAppended("icons").ensureWritableDir();
-
- auto jsonFilePath = m_bundlePathMaterial.pathAppended(Constants::BUNDLE_JSON_FILENAME);
- if (!jsonFilePath.exists()) {
- QString jsonContent = "{\n";
- jsonContent += " \"id\": \"UserMaterials\",\n";
- jsonContent += " \"items\": []\n";
- jsonContent += "}";
- Utils::expected_str<qint64> res = jsonFilePath.writeFileContents(jsonContent.toLatin1());
- if (!res.has_value()) {
- qWarning() << __FUNCTION__ << res.error();
- emit dataChanged(index(MaterialsSectionIdx), index(MaterialsSectionIdx));
- return;
- }
- }
-
- Utils::expected_str<QByteArray> jsonContents = jsonFilePath.fileContents();
- if (!jsonContents.has_value()) {
- qWarning() << __FUNCTION__ << jsonContents.error();
- emit dataChanged(index(MaterialsSectionIdx), index(MaterialsSectionIdx));
- return;
- }
-
- QJsonDocument bundleJsonDoc = QJsonDocument::fromJson(jsonContents.value());
- if (bundleJsonDoc.isNull()) {
- qWarning() << __FUNCTION__ << "Invalid json file" << jsonFilePath;
- emit dataChanged(index(MaterialsSectionIdx), index(MaterialsSectionIdx));
- return;
- }
-
- m_bundleIdMaterial = compUtils.userMaterialsBundleId();
- m_bundleObjMaterial = bundleJsonDoc.object();
- m_bundleObjMaterial["id"] = m_bundleIdMaterial;
-
- // parse items
- QString typePrefix = compUtils.userMaterialsBundleType();
- const QJsonArray itemsArr = m_bundleObjMaterial.value("items").toArray();
- for (const QJsonValueConstRef &itemRef : itemsArr) {
- const QJsonObject itemObj = itemRef.toObject();
-
- QString name = itemObj.value("name").toString();
- QString qml = itemObj.value("qml").toString();
- TypeName type = QLatin1String("%1.%2").arg(typePrefix, qml.chopped(4)).toLatin1();
- QUrl icon = m_bundlePathMaterial.pathAppended(itemObj.value("icon").toString()).toUrl();
- QStringList files = itemObj.value("files").toVariant().toStringList();
-
- m_userMaterials.append(new ContentLibraryItem(this, name, qml, type, icon, files, "material"));
- }
-
- m_bundleMaterialSharedFiles.clear();
- const QJsonArray sharedFilesArr = m_bundleObjMaterial.value("sharedFiles").toArray();
- for (const QJsonValueConstRef &file : sharedFilesArr)
- m_bundleMaterialSharedFiles.append(file.toString());
-
- m_matBundleLoaded = true;
- updateNoMatchMaterials();
- updateIsEmpty();
- emit dataChanged(index(MaterialsSectionIdx), index(MaterialsSectionIdx));
-}
-
-void ContentLibraryUserModel::load3DBundle()
-{
- auto compUtils = QmlDesignerPlugin::instance()->documentManager().generatedComponentUtils();
-
- if (m_bundle3DLoaded && m_bundleId3D == compUtils.user3DBundleId())
- return;
-
- // clean up
- qDeleteAll(m_user3DItems);
- m_user3DItems.clear();
- m_bundle3DLoaded = false;
- m_noMatch3D = true;
- m_bundleObj3D = {};
- m_bundleId3D.clear();
-
- m_bundlePath3D = Utils::FilePath::fromString(Paths::bundlesPathSetting() + "/User/3d");
- m_bundlePath3D.ensureWritableDir();
- m_bundlePath3D.pathAppended("icons").ensureWritableDir();
-
- auto jsonFilePath = m_bundlePath3D.pathAppended(Constants::BUNDLE_JSON_FILENAME);
- if (!jsonFilePath.exists()) {
- QByteArray jsonContent = "{\n";
- jsonContent += " \"id\": \"User3D\",\n";
- jsonContent += " \"items\": []\n";
- jsonContent += "}";
- Utils::expected_str<qint64> res = jsonFilePath.writeFileContents(jsonContent);
- if (!res.has_value()) {
- qWarning() << __FUNCTION__ << res.error();
- emit dataChanged(index(Items3DSectionIdx), index(Items3DSectionIdx));
- return;
- }
- }
-
- Utils::expected_str<QByteArray> jsonContents = jsonFilePath.fileContents();
- if (!jsonContents.has_value()) {
- qWarning() << __FUNCTION__ << jsonContents.error();
- emit dataChanged(index(Items3DSectionIdx), index(Items3DSectionIdx));
- return;
- }
-
- QJsonDocument bundleJsonDoc = QJsonDocument::fromJson(jsonContents.value());
- if (bundleJsonDoc.isNull()) {
- qWarning() << __FUNCTION__ << "Invalid json file" << jsonFilePath;
- emit dataChanged(index(Items3DSectionIdx), index(Items3DSectionIdx));
- return;
- }
-
- m_bundleId3D = compUtils.user3DBundleId();
- m_bundleObj3D = bundleJsonDoc.object();
- m_bundleObj3D["id"] = m_bundleId3D;
-
- // parse items
- QString typePrefix = compUtils.user3DBundleType();
- const QJsonArray itemsArr = m_bundleObj3D.value("items").toArray();
- for (const QJsonValueConstRef &itemRef : itemsArr) {
- const QJsonObject itemObj = itemRef.toObject();
-
- QString name = itemObj.value("name").toString();
- QString qml = itemObj.value("qml").toString();
- TypeName type = QLatin1String("%1.%2").arg(typePrefix, qml.chopped(4)).toLatin1();
- QUrl icon = m_bundlePath3D.pathAppended(itemObj.value("icon").toString()).toUrl();
- QStringList files = itemObj.value("files").toVariant().toStringList();
-
- m_user3DItems.append(new ContentLibraryItem(nullptr, name, qml, type, icon, files, "3d"));
- }
-
- m_bundle3DSharedFiles.clear();
- const QJsonArray sharedFilesArr = m_bundleObj3D.value("sharedFiles").toArray();
- for (const QJsonValueConstRef &file : sharedFilesArr)
- m_bundle3DSharedFiles.append(file.toString());
+ for (UserCategory *cat : std::as_const(m_userCategories))
+ cat->loadBundle();
- m_bundle3DLoaded = true;
- updateNoMatch3D();
+ resetModel();
updateIsEmpty();
- emit dataChanged(index(Items3DSectionIdx), index(Items3DSectionIdx));
-}
-
-void ContentLibraryUserModel::loadTextureBundle()
-{
- if (!m_userTextures.isEmpty())
- return;
-
- QDir bundleDir{Paths::bundlesPathSetting() + "/User/textures"};
- bundleDir.mkpath(".");
- bundleDir.mkdir("icons");
-
- const QFileInfoList fileInfos = bundleDir.entryInfoList(QDir::Files);
- for (const QFileInfo &fileInfo : fileInfos) {
- QString suffix = '.' + fileInfo.suffix();
- auto iconFileInfo = QFileInfo(fileInfo.path().append("/icons/").append(fileInfo.baseName() + ".png"));
- QPair<QSize, qint64> info = ImageUtils::imageInfo(fileInfo.path());
- QString dirPath = fileInfo.path();
- QSize imgDims = info.first;
- qint64 imgFileSize = info.second;
-
- auto tex = new ContentLibraryTexture(this, iconFileInfo, dirPath, suffix, imgDims, imgFileSize);
- m_userTextures.append(tex);
- }
-
- updateNoMatchTextures();
- emit dataChanged(index(TexturesSectionIdx), index(TexturesSectionIdx));
}
bool ContentLibraryUserModel::hasRequiredQuick3DImport() const
@@ -530,8 +310,9 @@ bool ContentLibraryUserModel::hasRequiredQuick3DImport() const
void ContentLibraryUserModel::updateIsEmpty()
{
- bool newIsEmpty = m_user3DItems.isEmpty() && m_userMaterials.isEmpty() && m_userTextures.isEmpty()
- && m_userEffects.isEmpty();
+ bool newIsEmpty = std::ranges::all_of(std::as_const(m_userCategories),
+ [](UserCategory *cat) { return cat->isEmpty(); });
+
if (m_isEmpty == newIsEmpty)
return;
@@ -548,39 +329,27 @@ void ContentLibraryUserModel::setSearchText(const QString &searchText)
m_searchText = lowerSearchText;
- for (ContentLibraryItem *item : std::as_const(m_userMaterials))
- item->filter(m_searchText);
-
- for (ContentLibraryTexture *item : std::as_const(m_userTextures))
- item->filter(m_searchText);
-
- for (ContentLibraryItem *item : std::as_const(m_user3DItems))
- item->filter(m_searchText);
+ for (UserCategory *cat : std::as_const(m_userCategories))
+ cat->filter(m_searchText);
- updateNoMatchMaterials();
- updateNoMatchTextures();
- updateNoMatch3D();
resetModel();
}
-void ContentLibraryUserModel::updateMaterialsImportedState(const QStringList &importedItems)
+void ContentLibraryUserModel::updateImportedState(const QStringList &importedItems,
+ const QString &bundleId)
{
- bool changed = false;
- for (ContentLibraryItem *mat : std::as_const(m_userMaterials))
- changed |= mat->setImported(importedItems.contains(mat->qml().chopped(4)));
-
- if (changed)
- emit dataChanged(index(MaterialsSectionIdx), index(MaterialsSectionIdx));
-}
+ SectionIndex secIdx = bundleIdToSectionIndex(bundleId);
+ UserItemCategory *cat = qobject_cast<UserItemCategory *>(m_userCategories.at(secIdx));
+ const QObjectList items = cat->items();
-void ContentLibraryUserModel::update3DImportedState(const QStringList &importedItems)
-{
bool changed = false;
- for (ContentLibraryItem *item : std::as_const(m_user3DItems))
- changed |= item->setImported(importedItems.contains(item->qml().chopped(4)));
+ for (QObject *item : items) {
+ ContentLibraryItem *castedItem = qobject_cast<ContentLibraryItem *>(item);
+ changed |= castedItem->setImported(importedItems.contains(castedItem->qml().chopped(4)));
+ }
if (changed)
- emit dataChanged(index(Items3DSectionIdx), index(Items3DSectionIdx));
+ emit dataChanged(index(secIdx), index(secIdx), {ItemsRole});
}
void ContentLibraryUserModel::setQuick3DImportVersion(int major, int minor)
@@ -609,31 +378,15 @@ void ContentLibraryUserModel::applyToSelected(ContentLibraryItem *mat, bool add)
emit applyToSelectedTriggered(mat, add);
}
-void ContentLibraryUserModel::addToProject(QObject *item)
+void ContentLibraryUserModel::addToProject(ContentLibraryItem *item)
{
- auto castedItem = qobject_cast<ContentLibraryItem *>(item);
- QTC_ASSERT(castedItem, return);
-
- addItemToProject(castedItem);
-}
+ UserItemCategory *itemCat = qobject_cast<UserItemCategory *>(item->parent());
+ QTC_ASSERT(itemCat, return);
-void ContentLibraryUserModel::addItemToProject(ContentLibraryItem *item)
-{
- QString bundlePath;
+ QString bundlePath = itemCat->bundlePath().toFSPathString();
TypeName type = item->type();
QString qmlFile = item->qml();
- QStringList files = item->files();
-
- if (item->itemType() == "material") {
- bundlePath = m_bundlePathMaterial.toFSPathString();
- files << m_bundleMaterialSharedFiles;
- } else if (item->itemType() == "3d") {
- bundlePath = m_bundlePath3D.toFSPathString();
- files << m_bundle3DSharedFiles;
- } else {
- qWarning() << __FUNCTION__ << "Unsupported Item";
- return;
- }
+ QStringList files = item->files() + itemCat->sharedFiles();
QString err = m_widget->importer()->importComponent(bundlePath, type, qmlFile, files);
diff --git a/src/plugins/qmldesigner/components/contentlibrary/contentlibraryusermodel.h b/src/plugins/qmldesigner/components/contentlibrary/contentlibraryusermodel.h
index f5805946fb6..094a5c75178 100644
--- a/src/plugins/qmldesigner/components/contentlibrary/contentlibraryusermodel.h
+++ b/src/plugins/qmldesigner/components/contentlibrary/contentlibraryusermodel.h
@@ -3,6 +3,8 @@
#pragma once
+#include "usercategory.h"
+
#include <utils/filepath.h>
#include <QAbstractListModel>
@@ -23,17 +25,8 @@ class ContentLibraryUserModel : public QAbstractListModel
Q_PROPERTY(bool hasRequiredQuick3DImport READ hasRequiredQuick3DImport NOTIFY hasRequiredQuick3DImportChanged)
Q_PROPERTY(bool isEmpty MEMBER m_isEmpty NOTIFY isEmptyChanged)
- Q_PROPERTY(QList<ContentLibraryItem *> userMaterials MEMBER m_userMaterials NOTIFY userMaterialsChanged)
- Q_PROPERTY(QList<ContentLibraryTexture *> userTextures MEMBER m_userTextures NOTIFY userTexturesChanged)
- Q_PROPERTY(QList<ContentLibraryItem *> user3DItems MEMBER m_user3DItems NOTIFY user3DItemsChanged)
- Q_PROPERTY(QList<ContentLibraryItem *> userEffects MEMBER m_userEffects NOTIFY userEffectsChanged)
public:
- enum SectionIndex { MaterialsSectionIdx = 0,
- TexturesSectionIdx,
- Items3DSectionIdx,
- EffectsSectionIdx };
-
ContentLibraryUserModel(ContentLibraryWidget *parent = nullptr);
int rowCount(const QModelIndex &parent = QModelIndex()) const override;
@@ -41,8 +34,7 @@ public:
QHash<int, QByteArray> roleNames() const override;
void setSearchText(const QString &searchText);
- void updateMaterialsImportedState(const QStringList &importedItems);
- void update3DImportedState(const QStringList &importedItems);
+ void updateImportedState(const QStringList &importedItems, const QString &bundleId);
QPair<QString, QString> getUniqueLibMaterialNames(const QString &defaultName = "Material") const;
QPair<QString, QString> getUniqueLib3DNames(const QString &defaultName = "Item") const;
@@ -56,28 +48,21 @@ public:
void updateIsEmpty();
void resetModel();
- void updateNoMatchMaterials();
- void updateNoMatchTextures();
- void updateNoMatch3D();
-
- void addMaterial(const QString &name, const QString &qml, const QUrl &icon, const QStringList &files);
- void add3DItem(const QString &name, const QString &qml, const QUrl &icon, const QStringList &files);
- void refreshSection(SectionIndex sectionIndex);
- void addTextures(const QStringList &paths);
- void addItemToProject(ContentLibraryItem *item);
+ void addItem(const QString &bundleId, const QString &name, const QString &qml,const QUrl &icon,
+ const QStringList &files);
+ void refreshSection(const QString &bundleId);
+ void addTextures(const Utils::FilePaths &paths);
- void remove3DFromContentLibByName(const QString &qmlFileName);
- void removeMaterialFromContentLibByName(const QString &qmlFileName);
+ void removeItemByName(const QString &qmlFileName, const QString &bundleId);
void setBundleObj(const QJsonObject &newBundleObj);
- QJsonObject &bundleJsonMaterialObjectRef();
- QJsonObject &bundleJson3DObjectRef();
+ QJsonObject &bundleObjectRef(const QString &bundleId);
void loadBundles();
Q_INVOKABLE void applyToSelected(QmlDesigner::ContentLibraryItem *mat, bool add = false);
- Q_INVOKABLE void addToProject(QObject *item);
+ Q_INVOKABLE void addToProject(ContentLibraryItem *item);
Q_INVOKABLE void removeFromProject(QObject *item);
Q_INVOKABLE void removeTexture(QmlDesigner::ContentLibraryTexture *tex);
Q_INVOKABLE void removeFromContentLib(QObject *item);
@@ -85,49 +70,33 @@ public:
signals:
void hasRequiredQuick3DImportChanged();
void isEmptyChanged();
- void userMaterialsChanged();
- void userTexturesChanged();
- void user3DItemsChanged();
- void userEffectsChanged();
void applyToSelectedTriggered(QmlDesigner::ContentLibraryItem *mat, bool add = false);
private:
+ // section indices must match the order in initModel()
+ enum SectionIndex { MaterialsSectionIdx = 0,
+ TexturesSectionIdx,
+ Items3DSectionIdx,
+ EffectsSectionIdx };
+
+ void createCategories();
void loadMaterialBundle();
void load3DBundle();
void loadTextureBundle();
void removeItem(ContentLibraryItem *item);
+ SectionIndex bundleIdToSectionIndex(const QString &bundleId) const;
ContentLibraryWidget *m_widget = nullptr;
QString m_searchText;
- QString m_bundleIdMaterial;
- QString m_bundleId3D;
- QStringList m_bundleMaterialSharedFiles;
- QStringList m_bundle3DSharedFiles;
- Utils::FilePath m_bundlePathMaterial;
- Utils::FilePath m_bundlePath3D;
-
- QList<ContentLibraryItem *> m_userMaterials;
- QList<ContentLibraryTexture *> m_userTextures;
- QList<ContentLibraryItem *> m_userEffects;
- QList<ContentLibraryItem *> m_user3DItems;
- const QStringList m_userCategories = {tr("Materials"), tr("Textures"), tr("3D"),
- /*tr("Effects"), tr("2D components")*/}; // TODO;
-
- QJsonObject m_bundleObjMaterial;
- QJsonObject m_bundleObj3D;
-
- bool m_noMatchMaterials = true;
- bool m_noMatchTextures = true;
- bool m_noMatch3D = true;
- bool m_noMatchEffects = true;
- bool m_matBundleLoaded = false;
- bool m_bundle3DLoaded = false;
+
+ QList<UserCategory *> m_userCategories;
+
bool m_isEmpty = true;
int m_quick3dMajorVersion = -1;
int m_quick3dMinorVersion = -1;
- enum Roles { NameRole = Qt::UserRole + 1, VisibleRole, ItemsRole, NoMatchRole };
+ enum Roles { TitleRole = Qt::UserRole + 1, ItemsRole, EmptyRole, NoMatchRole };
};
} // namespace QmlDesigner
diff --git a/src/plugins/qmldesigner/components/contentlibrary/contentlibraryview.cpp b/src/plugins/qmldesigner/components/contentlibrary/contentlibraryview.cpp
index 675b60e0bcc..c0b16b6c556 100644
--- a/src/plugins/qmldesigner/components/contentlibrary/contentlibraryview.cpp
+++ b/src/plugins/qmldesigner/components/contentlibrary/contentlibraryview.cpp
@@ -365,7 +365,7 @@ void ContentLibraryView::customNotification(const AbstractView *view,
m_bundleItemPos = data.size() == 1 ? data.first() : QVariant();
if (is3D)
- m_widget->userModel()->addItemToProject(m_draggedBundleItem);
+ m_widget->userModel()->addToProject(m_draggedBundleItem);
else
m_widget->effectsModel()->addInstance(m_draggedBundleItem);
m_bundleItemTarget = nodeList.first() ? nodeList.first() : Utils3D::active3DSceneNode(this);
@@ -545,7 +545,9 @@ void ContentLibraryView::addLibMaterial(const ModelNode &node, const QPixmap &ic
QTC_ASSERT_EXPECTED(result,);
// add the material to the bundle json
- QJsonObject &jsonRef = m_widget->userModel()->bundleJsonMaterialObjectRef();
+ auto compUtils = QmlDesignerPlugin::instance()->documentManager().generatedComponentUtils();
+ QString bundleId = compUtils.userMaterialsBundleId();
+ QJsonObject &jsonRef = m_widget->userModel()->bundleObjectRef(bundleId);
QJsonArray itemsArr = jsonRef.value("items").toArray();
itemsArr.append(QJsonObject {
{"name", name},
@@ -570,7 +572,7 @@ void ContentLibraryView::addLibMaterial(const ModelNode &node, const QPixmap &ic
QTC_ASSERT_EXPECTED(result,);
}
- m_widget->userModel()->addMaterial(name, qml, QUrl::fromLocalFile(fullIconPath), depAssetsList);
+ m_widget->userModel()->addItem(bundleId, name, qml, QUrl::fromLocalFile(fullIconPath), depAssetsList);
}
QPair<QString, QSet<QString>> ContentLibraryView::modelNodeToQmlString(const ModelNode &node, int depth)
@@ -653,7 +655,7 @@ QPair<QString, QSet<QString>> ContentLibraryView::modelNodeToQmlString(const Mod
void ContentLibraryView::addLibAssets(const QStringList &paths)
{
auto bundlePath = Utils::FilePath::fromString(Paths::bundlesPathSetting() + "/User/textures");
- QStringList pathsInBundle;
+ Utils::FilePaths pathsInBundle;
const QStringList existingTextures = Utils::transform(bundlePath.dirEntries(QDir::Files),
[](const Utils::FilePath &path) {
@@ -679,7 +681,7 @@ void ContentLibraryView::addLibAssets(const QStringList &paths)
auto result = assetFilePath.copyFile(bundlePath.pathAppended(asset.fileName()));
QTC_ASSERT_EXPECTED(result,);
- pathsInBundle.append(bundlePath.pathAppended(asset.fileName()).toFSPathString());
+ pathsInBundle.append(bundlePath.pathAppended(asset.fileName()));
}
m_widget->userModel()->addTextures(pathsInBundle);
@@ -687,6 +689,10 @@ void ContentLibraryView::addLibAssets(const QStringList &paths)
void ContentLibraryView::addLib3DComponent(const ModelNode &node)
{
+ auto compUtils = QmlDesignerPlugin::instance()->documentManager().generatedComponentUtils();
+
+ QString bundleId = compUtils.user3DBundleId();
+
QString compBaseName = node.simplifiedTypeName();
QString compFileName = compBaseName + ".qml";
@@ -703,7 +709,7 @@ void ContentLibraryView::addLib3DComponent(const ModelNode &node)
return;
// before overwriting remove old item (to avoid partial items and dangling assets)
- m_widget->userModel()->remove3DFromContentLibByName(compFileName);
+ m_widget->userModel()->removeItemByName(compFileName, bundleId);
}
// generate and save icon
@@ -713,7 +719,7 @@ void ContentLibraryView::addLib3DComponent(const ModelNode &node)
getImageFromCache(compDir.pathAppended(compFileName).path(), [&](const QImage &image) {
bool iconSaved = image.save(m_iconSavePath.toFSPathString());
if (iconSaved)
- m_widget->userModel()->refreshSection(ContentLibraryUserModel::Items3DSectionIdx);
+ m_widget->userModel()->refreshSection(compUtils.user3DBundleId());
else
qWarning() << "ContentLibraryView::getImageFromCache(): icon save failed" << iconPath;
});
@@ -739,7 +745,7 @@ void ContentLibraryView::addLib3DComponent(const ModelNode &node)
}
// add the item to the bundle json
- QJsonObject &jsonRef = m_widget->userModel()->bundleJson3DObjectRef();
+ QJsonObject &jsonRef = m_widget->userModel()->bundleObjectRef(bundleId);
QJsonArray itemsArr = jsonRef.value("items").toArray();
itemsArr.append(QJsonObject {
{"name", node.simplifiedTypeName()},
@@ -754,7 +760,7 @@ void ContentLibraryView::addLib3DComponent(const ModelNode &node)
.writeFileContents(QJsonDocument(jsonRef).toJson());
QTC_ASSERT_EXPECTED(result,);
- m_widget->userModel()->add3DItem(compBaseName, compFileName, m_iconSavePath.toUrl(), filesList);
+ m_widget->userModel()->addItem(bundleId, compBaseName, compFileName, m_iconSavePath.toUrl(), filesList);
}
void ContentLibraryView::exportLib3DComponent(const ModelNode &node)
@@ -828,14 +834,17 @@ void ContentLibraryView::exportLib3DComponent(const ModelNode &node)
void ContentLibraryView::addLib3DItem(const ModelNode &node)
{
+ auto compUtils = QmlDesignerPlugin::instance()->documentManager().generatedComponentUtils();
auto bundlePath = Utils::FilePath::fromString(Paths::bundlesPathSetting() + "/User/3d/");
+ QString bundleId = compUtils.user3DBundleId();
QString name = node.variantProperty("objectName").value().toString();
if (name.isEmpty())
name = node.displayName();
- auto [qml, icon] = m_widget->userModel()->getUniqueLibItemNames(name,
- m_widget->userModel()->bundleJson3DObjectRef());
+ QJsonObject &jsonRef = m_widget->userModel()->bundleObjectRef(bundleId);
+
+ auto [qml, icon] = m_widget->userModel()->getUniqueLibItemNames(name, jsonRef);
// generate and save Qml file
auto [qmlString, depAssets] = modelNodeToQmlString(node);
@@ -852,13 +861,12 @@ void ContentLibraryView::addLib3DItem(const ModelNode &node)
getImageFromCache(qmlPath, [&](const QImage &image) {
bool iconSaved = image.save(m_iconSavePath.toFSPathString());
if (iconSaved)
- m_widget->userModel()->refreshSection(ContentLibraryUserModel::Items3DSectionIdx);
+ m_widget->userModel()->refreshSection(compUtils.user3DBundleId());
else
qWarning() << "ContentLibraryView::getImageFromCache(): icon save failed" << iconPath;
});
// add the item to the bundle json
- QJsonObject &jsonRef = m_widget->userModel()->bundleJson3DObjectRef();
QJsonArray itemsArr = jsonRef.value("items").toArray();
itemsArr.append(QJsonObject {
{"name", name},
@@ -883,7 +891,7 @@ void ContentLibraryView::addLib3DItem(const ModelNode &node)
QTC_ASSERT_EXPECTED(result,);
}
- m_widget->userModel()->add3DItem(name, qml, m_iconSavePath.toUrl(), depAssetsList);
+ m_widget->userModel()->addItem(bundleId, name, qml, m_iconSavePath.toUrl(), depAssetsList);
}
QString ContentLibraryView::getExportPath(const ModelNode &node) const
@@ -1013,14 +1021,14 @@ void ContentLibraryView::importBundle()
tr("The chosen bundle was created with an incompatible version of Qt Design Studio"));
return;
}
- bool isMat = isMaterialBundle(importedJsonObj.value("id").toString());
+ QString bundleId = importedJsonObj.value("id").toString();
+ bool isMat = isMaterialBundle(bundleId);
QString bundleFolderName = isMat ? QLatin1String("materials") : QLatin1String("3d");
auto bundlePath = Utils::FilePath::fromString(QLatin1String("%1/User/%3/")
.arg(Paths::bundlesPathSetting(), bundleFolderName));
- QJsonObject &jsonRef = isMat ? m_widget->userModel()->bundleJsonMaterialObjectRef()
- : m_widget->userModel()->bundleJson3DObjectRef();
+ QJsonObject &jsonRef = m_widget->userModel()->bundleObjectRef(bundleId);
QJsonArray itemsArr = jsonRef.value("items").toArray();
QStringList existingQmls;
@@ -1042,10 +1050,7 @@ void ContentLibraryView::importBundle()
continue;
// before overwriting remove old item (to avoid partial items and dangling assets)
- if (isMat)
- m_widget->userModel()->removeMaterialFromContentLibByName(qml);
- else
- m_widget->userModel()->remove3DFromContentLibByName(qml);
+ m_widget->userModel()->removeItemByName(qml, bundleId);
}
// add entry to json
@@ -1065,10 +1070,7 @@ void ContentLibraryView::importBundle()
QTC_ASSERT_EXPECTED(filePath.writeFileContents(zipReader.fileData(file)),);
}
- if (isMat)
- m_widget->userModel()->addMaterial(name, qml, iconUrl, files);
- else
- m_widget->userModel()->add3DItem(name, qml, iconUrl, files);
+ m_widget->userModel()->addItem(bundleId, name, qml, iconUrl, files);
}
zipReader.close();
@@ -1078,10 +1080,6 @@ void ContentLibraryView::importBundle()
auto result = bundlePath.pathAppended(Constants::BUNDLE_JSON_FILENAME)
.writeFileContents(QJsonDocument(jsonRef).toJson());
QTC_ASSERT_EXPECTED(result,);
-
- auto sectionIdx = isMat ? ContentLibraryUserModel::MaterialsSectionIdx
- : ContentLibraryUserModel::Items3DSectionIdx;
- m_widget->userModel()->refreshSection(sectionIdx);
}
/**
diff --git a/src/plugins/qmldesigner/components/contentlibrary/contentlibrarywidget.cpp b/src/plugins/qmldesigner/components/contentlibrary/contentlibrarywidget.cpp
index e4346f7a991..c5cf6d21e9b 100644
--- a/src/plugins/qmldesigner/components/contentlibrary/contentlibrarywidget.cpp
+++ b/src/plugins/qmldesigner/components/contentlibrary/contentlibrarywidget.cpp
@@ -230,10 +230,8 @@ void ContentLibraryWidget::updateImportedState(const QString &bundleId)
m_materialsModel->updateImportedState(importedItems);
else if (bundleId == compUtils.effectsBundleId())
m_effectsModel->updateImportedState(importedItems);
- else if (bundleId == compUtils.userMaterialsBundleId())
- m_userModel->updateMaterialsImportedState(importedItems);
- else if (bundleId == compUtils.user3DBundleId())
- m_userModel->update3DImportedState(importedItems);
+ else
+ m_userModel->updateImportedState(importedItems, bundleId);
}
ContentLibraryBundleImporter *ContentLibraryWidget::importer() const
diff --git a/src/plugins/qmldesigner/components/contentlibrary/usercategory.cpp b/src/plugins/qmldesigner/components/contentlibrary/usercategory.cpp
new file mode 100644
index 00000000000..0d413752995
--- /dev/null
+++ b/src/plugins/qmldesigner/components/contentlibrary/usercategory.cpp
@@ -0,0 +1,74 @@
+// 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 "usercategory.h"
+
+namespace QmlDesigner {
+
+UserCategory::UserCategory(const QString &title, const Utils::FilePath &bundlePath)
+ : m_title(title)
+ , m_bundlePath(bundlePath)
+{
+}
+
+QString UserCategory::title() const
+{
+ return m_title;
+}
+
+bool UserCategory::isEmpty() const
+{
+ return m_isEmpty;
+}
+
+void UserCategory::setIsEmpty(bool val)
+{
+ if (m_isEmpty == val)
+ return;
+
+ m_isEmpty = val;
+ emit isEmptyChanged();
+}
+
+bool UserCategory::noMatch() const
+{
+ return m_noMatch;
+}
+
+void UserCategory::setNoMatch(bool val)
+{
+ if (m_noMatch == val)
+ return;
+
+ m_noMatch = val;
+ emit noMatchChanged();
+}
+
+void UserCategory::addItem(QObject *item)
+{
+ m_items.append(item);
+ emit itemsChanged();
+
+ setIsEmpty(false);
+}
+
+void UserCategory::removeItem(QObject *item)
+{
+ m_items.removeOne(item);
+ item->deleteLater();
+ emit itemsChanged();
+
+ setIsEmpty(m_items.isEmpty());
+}
+
+Utils::FilePath UserCategory::bundlePath() const
+{
+ return m_bundlePath;
+}
+
+QObjectList UserCategory::items() const
+{
+ return m_items;
+}
+
+} // namespace QmlDesigner
diff --git a/src/plugins/qmldesigner/components/contentlibrary/usercategory.h b/src/plugins/qmldesigner/components/contentlibrary/usercategory.h
new file mode 100644
index 00000000000..38421c293cb
--- /dev/null
+++ b/src/plugins/qmldesigner/components/contentlibrary/usercategory.h
@@ -0,0 +1,50 @@
+// 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 <utils/filepath.h>
+
+#include <QObject>
+
+namespace QmlDesigner {
+
+class UserCategory : public QObject
+{
+ Q_OBJECT
+
+public:
+ UserCategory(const QString &title, const Utils::FilePath &bundlePath);
+
+ QString title() const;
+ QObjectList items() const;
+
+ bool isEmpty() const;
+ void setIsEmpty(bool val);
+
+ bool noMatch() const;
+ void setNoMatch(bool val);
+
+ virtual void loadBundle() = 0;
+ virtual void filter(const QString &searchText) = 0;
+
+ void addItem(QObject *item);
+ void removeItem(QObject *item);
+
+ Utils::FilePath bundlePath() const;
+
+signals:
+ void itemsChanged();
+ void isEmptyChanged();
+ void noMatchChanged();
+
+protected:
+ QString m_title;
+ Utils::FilePath m_bundlePath;
+ QObjectList m_items;
+ bool m_isEmpty = true;
+ bool m_noMatch = true;
+ bool m_bundleLoaded = false;
+};
+
+} // namespace QmlDesigner
diff --git a/src/plugins/qmldesigner/components/contentlibrary/useritemcategory.cpp b/src/plugins/qmldesigner/components/contentlibrary/useritemcategory.cpp
new file mode 100644
index 00000000000..40a467b8dd9
--- /dev/null
+++ b/src/plugins/qmldesigner/components/contentlibrary/useritemcategory.cpp
@@ -0,0 +1,121 @@
+// 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 "useritemcategory.h"
+
+#include "contentlibraryitem.h"
+
+#include <qmldesignerconstants.h>
+#include <qmldesignerplugin.h>
+
+#include <QJsonArray>
+#include <QJsonDocument>
+
+namespace QmlDesigner {
+
+UserItemCategory::UserItemCategory(const QString &title, const Utils::FilePath &bundlePath,
+ const QString &bundleId)
+ : UserCategory(title, bundlePath)
+ , m_bundleId(bundleId)
+{
+}
+
+void UserItemCategory::loadBundle()
+{
+ if (m_bundleLoaded)
+ return;
+
+ // clean up
+ qDeleteAll(m_items);
+ m_items.clear();
+ m_bundleLoaded = false;
+ m_noMatch = false;
+ m_bundleObj = {};
+
+ m_bundlePath.ensureWritableDir();
+ m_bundlePath.pathAppended("icons").ensureWritableDir();
+
+ auto jsonFilePath = m_bundlePath.pathAppended(Constants::BUNDLE_JSON_FILENAME);
+ if (!jsonFilePath.exists()) {
+ QString jsonContent = "{\n";
+ jsonContent += " \"id\": \"" + m_bundleId + "\",\n";
+ jsonContent += " \"items\": []\n";
+ jsonContent += "}";
+ Utils::expected_str<qint64> res = jsonFilePath.writeFileContents(jsonContent.toLatin1());
+ if (!res.has_value()) {
+ qWarning() << __FUNCTION__ << res.error();
+ setIsEmpty(true);
+ emit itemsChanged();
+ return;
+ }
+ }
+
+ Utils::expected_str<QByteArray> jsonContents = jsonFilePath.fileContents();
+ if (!jsonContents.has_value()) {
+ qWarning() << __FUNCTION__ << jsonContents.error();
+ setIsEmpty(true);
+ emit itemsChanged();
+ return;
+ }
+
+ QJsonDocument bundleJsonDoc = QJsonDocument::fromJson(jsonContents.value());
+ if (bundleJsonDoc.isNull()) {
+ qWarning() << __FUNCTION__ << "Invalid json file" << jsonFilePath;
+ setIsEmpty(true);
+ emit itemsChanged();
+ return;
+ }
+
+ auto compUtils = QmlDesignerPlugin::instance()->documentManager().generatedComponentUtils();
+
+ m_bundleObj = bundleJsonDoc.object();
+ m_bundleObj["id"] = m_bundleId;
+
+ // parse items
+ QString typePrefix = compUtils.userBundleType(m_bundleId);
+ const QJsonArray itemsArr = m_bundleObj.value("items").toArray();
+ for (const QJsonValueConstRef &itemRef : itemsArr) {
+ const QJsonObject itemObj = itemRef.toObject();
+
+ QString name = itemObj.value("name").toString();
+ QString qml = itemObj.value("qml").toString();
+ TypeName type = QLatin1String("%1.%2").arg(typePrefix, qml.chopped(4)).toLatin1();
+ QUrl icon = m_bundlePath.pathAppended(itemObj.value("icon").toString()).toUrl();
+ QStringList files = itemObj.value("files").toVariant().toStringList();
+
+ m_items.append(new ContentLibraryItem(this, name, qml, type, icon, files, m_bundleId));
+ }
+
+ m_sharedFiles.clear();
+ const QJsonArray sharedFilesArr = m_bundleObj.value("sharedFiles").toArray();
+ for (const QJsonValueConstRef &file : sharedFilesArr)
+ m_sharedFiles.append(file.toString());
+
+ m_bundleLoaded = true;
+ setIsEmpty(m_items.isEmpty());
+ emit itemsChanged();
+}
+
+void UserItemCategory::filter(const QString &searchText)
+{
+ bool noMatch = true;
+ for (QObject *item : std::as_const(m_items)) {
+ ContentLibraryItem *castedItem = qobject_cast<ContentLibraryItem *>(item);
+ bool itemVisible = castedItem->filter(searchText);
+ if (itemVisible)
+ noMatch = false;
+ }
+ setNoMatch(noMatch);
+}
+
+QStringList UserItemCategory::sharedFiles() const
+{
+ return m_sharedFiles;
+}
+
+QJsonObject &UserItemCategory::bundleObjRef()
+{
+ return m_bundleObj;
+}
+
+} // namespace QmlDesigner
diff --git a/src/plugins/qmldesigner/components/contentlibrary/useritemcategory.h b/src/plugins/qmldesigner/components/contentlibrary/useritemcategory.h
new file mode 100644
index 00000000000..1d55fc077a9
--- /dev/null
+++ b/src/plugins/qmldesigner/components/contentlibrary/useritemcategory.h
@@ -0,0 +1,35 @@
+// 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 "usercategory.h"
+
+#include <QJsonObject>
+
+namespace QmlDesigner {
+
+class ContentLibraryItem;
+
+class UserItemCategory : public UserCategory
+{
+ Q_OBJECT
+
+public:
+ UserItemCategory(const QString &title, const Utils::FilePath &bundlePath, const QString &bundleId);
+
+ void loadBundle() override;
+ void filter(const QString &searchText) override;
+
+ QStringList sharedFiles() const;
+
+ QJsonObject &bundleObjRef();
+
+private:
+ QString m_bundleId;
+ QJsonObject m_bundleObj;
+ QStringList m_sharedFiles;
+
+};
+
+} // namespace QmlDesigner
diff --git a/src/plugins/qmldesigner/components/contentlibrary/usertexturecategory.cpp b/src/plugins/qmldesigner/components/contentlibrary/usertexturecategory.cpp
new file mode 100644
index 00000000000..5c3e99069fc
--- /dev/null
+++ b/src/plugins/qmldesigner/components/contentlibrary/usertexturecategory.cpp
@@ -0,0 +1,66 @@
+// 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 "usertexturecategory.h"
+
+#include "contentlibrarytexture.h"
+
+#include <designerpaths.h>
+#include <imageutils.h>
+
+namespace QmlDesigner {
+
+UserTextureCategory::UserTextureCategory(const QString &title, const Utils::FilePath &bundlePath)
+ : UserCategory(title, bundlePath)
+{
+}
+
+void UserTextureCategory::loadBundle()
+{
+ if (m_bundleLoaded)
+ return;
+
+ // clean up
+ qDeleteAll(m_items);
+ m_items.clear();
+
+ m_bundlePath.ensureWritableDir();
+ m_bundlePath.pathAppended("icons").ensureWritableDir();
+
+ addItems(m_bundlePath.dirEntries(QDir::Files));
+
+ m_bundleLoaded = true;
+}
+
+void UserTextureCategory::filter(const QString &searchText)
+{
+ bool noMatch = true;
+ for (QObject *item : std::as_const(m_items)) {
+ ContentLibraryTexture *castedItem = qobject_cast<ContentLibraryTexture *>(item);
+ bool itemVisible = castedItem->filter(searchText);
+ if (itemVisible)
+ noMatch = false;
+ }
+ setNoMatch(noMatch);
+}
+
+void UserTextureCategory::addItems(const Utils::FilePaths &paths)
+{
+ for (const Utils::FilePath &filePath : paths) {
+ QString suffix = '.' + filePath.suffix();
+ auto iconFileInfo = filePath.parentDir().pathAppended("icons/" + filePath.baseName() + ".png")
+ .toFileInfo();
+ QPair<QSize, qint64> info = ImageUtils::imageInfo(filePath.path());
+ QString dirPath = filePath.parentDir().toFSPathString();
+ QSize imgDims = info.first;
+ qint64 imgFileSize = info.second;
+
+ auto tex = new ContentLibraryTexture(this, iconFileInfo, dirPath, suffix, imgDims, imgFileSize);
+ m_items.append(tex);
+ }
+
+ setIsEmpty(m_items.isEmpty());
+ emit itemsChanged();
+}
+
+} // namespace QmlDesigner
diff --git a/src/plugins/qmldesigner/components/contentlibrary/usertexturecategory.h b/src/plugins/qmldesigner/components/contentlibrary/usertexturecategory.h
new file mode 100644
index 00000000000..5e58f8f0059
--- /dev/null
+++ b/src/plugins/qmldesigner/components/contentlibrary/usertexturecategory.h
@@ -0,0 +1,25 @@
+// 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 "usercategory.h"
+
+namespace QmlDesigner {
+
+class ContentLibraryTexture;
+
+class UserTextureCategory : public UserCategory
+{
+ Q_OBJECT
+
+public:
+ UserTextureCategory(const QString &title, const Utils::FilePath &bundlePath);
+
+ void loadBundle() override;
+ void filter(const QString &searchText) override;
+
+ void addItems(const Utils::FilePaths &paths);
+};
+
+} // namespace QmlDesigner
diff --git a/src/plugins/qmldesigner/designercore/generatedcomponentutils.cpp b/src/plugins/qmldesigner/designercore/generatedcomponentutils.cpp
index da40c4d387d..9d67d1cbf82 100644
--- a/src/plugins/qmldesigner/designercore/generatedcomponentutils.cpp
+++ b/src/plugins/qmldesigner/designercore/generatedcomponentutils.cpp
@@ -273,6 +273,21 @@ QString GeneratedComponentUtils::effectsBundleType() const
return componentBundlesTypePrefix() + '.' + effectsBundleId();
}
+QString GeneratedComponentUtils::userBundleType(const QString &bundleId) const
+{
+ if (bundleId == userMaterialsBundleId())
+ return userMaterialsBundleType();
+
+ if (bundleId == userEffectsBundleId())
+ return userEffectsBundleType();
+
+ if (bundleId == user3DBundleId())
+ return user3DBundleType();
+
+ qWarning() << __FUNCTION__ << "no bundleType for bundleId:" << bundleId;
+ return {};
+}
+
QString GeneratedComponentUtils::userMaterialsBundleType() const
{
return componentBundlesTypePrefix() + '.' + userMaterialsBundleId();
diff --git a/src/plugins/qmldesigner/designercore/generatedcomponentutils.h b/src/plugins/qmldesigner/designercore/generatedcomponentutils.h
index ceddb405a34..df15d252cc3 100644
--- a/src/plugins/qmldesigner/designercore/generatedcomponentutils.h
+++ b/src/plugins/qmldesigner/designercore/generatedcomponentutils.h
@@ -44,6 +44,7 @@ public:
QString materialsBundleType() const;
QString effectsBundleType() const;
+ QString userBundleType(const QString &bundleId) const;
QString userMaterialsBundleType() const;
QString userEffectsBundleType() const;
QString user3DBundleType() const;