forked from qt-creator/qt-creator
QmlDesigner: Refactor content lib user model
Add category classes for the model to make it tidier and easy to extend (i.e. adding more categories). Change-Id: Ied8641802f600c5cb0b036aba6ad44dbde612a09 Reviewed-by: Miikka Heikkinen <miikka.heikkinen@qt.io>
This commit is contained in:
@@ -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
|
||||
|
||||
|
@@ -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
|
||||
|
@@ -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
|
||||
|
@@ -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);
|
||||
}
|
||||
|
@@ -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
|
||||
|
@@ -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
|
||||
|
@@ -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
|
||||
|
@@ -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());
|
||||
UserCategory *currCat = 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);
|
||||
}
|
||||
if (role == TitleRole)
|
||||
return currCat->title();
|
||||
|
||||
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 == ItemsRole)
|
||||
return QVariant::fromValue(currCat->items());
|
||||
|
||||
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 == NoMatchRole)
|
||||
return currCat->noMatch();
|
||||
|
||||
if (role == EmptyRole)
|
||||
return currCat->isEmpty();
|
||||
|
||||
return {};
|
||||
}
|
||||
|
||||
void ContentLibraryUserModel::updateNoMatchMaterials()
|
||||
void ContentLibraryUserModel::createCategories()
|
||||
{
|
||||
m_noMatchMaterials = Utils::allOf(m_userMaterials, [&](ContentLibraryItem *item) {
|
||||
return !item->visible();
|
||||
});
|
||||
QTC_ASSERT(m_userCategories.isEmpty(), return);
|
||||
|
||||
auto compUtils = QmlDesignerPlugin::instance()->documentManager().generatedComponentUtils();
|
||||
auto userBundlePath = Utils::FilePath::fromString(Paths::bundlesPathSetting() + "/User");
|
||||
|
||||
auto catMaterial = new UserItemCategory{tr("Materials"),
|
||||
userBundlePath.pathAppended("materials"),
|
||||
compUtils.userMaterialsBundleId()};
|
||||
|
||||
auto catTexture = new UserTextureCategory{tr("Textures"), userBundlePath.pathAppended("textures")};
|
||||
|
||||
auto cat3D = new UserItemCategory{tr("3D"), userBundlePath.pathAppended("3d"),
|
||||
compUtils.user3DBundleId()};
|
||||
|
||||
m_userCategories << catMaterial << catTexture << cat3D;
|
||||
}
|
||||
|
||||
void ContentLibraryUserModel::updateNoMatchTextures()
|
||||
{
|
||||
m_noMatchTextures = Utils::allOf(m_userTextures, [&](ContentLibraryTexture *item) {
|
||||
return !item->visible();
|
||||
});
|
||||
}
|
||||
|
||||
void ContentLibraryUserModel::updateNoMatch3D()
|
||||
{
|
||||
m_noMatch3D = Utils::allOf(m_user3DItems, [&](ContentLibraryItem *item) {
|
||||
return !item->visible();
|
||||
});
|
||||
}
|
||||
|
||||
void ContentLibraryUserModel::addMaterial(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.userMaterialsBundleType();
|
||||
QString typePrefix = compUtils.userBundleType(bundleId);
|
||||
TypeName type = QLatin1String("%1.%2").arg(typePrefix, qml.chopped(4)).toLatin1();
|
||||
|
||||
auto libMat = new ContentLibraryItem(this, name, qml, type, icon, files, "material");
|
||||
m_userMaterials.append(libMat);
|
||||
|
||||
emit dataChanged(index(MaterialsSectionIdx), index(MaterialsSectionIdx));
|
||||
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::add3DItem(const QString &name, const QString &qml,
|
||||
const QUrl &icon, const QStringList &files)
|
||||
void ContentLibraryUserModel::refreshSection(const QString &bundleId)
|
||||
{
|
||||
auto compUtils = QmlDesignerPlugin::instance()->documentManager().generatedComponentUtils();
|
||||
|
||||
QString typePrefix = compUtils.user3DBundleType();
|
||||
TypeName type = QLatin1String("%1.%2").arg(typePrefix, qml.chopped(4)).toLatin1();
|
||||
|
||||
m_user3DItems.append(new ContentLibraryItem(this, name, qml, type, icon, files, "3d"));
|
||||
}
|
||||
|
||||
void ContentLibraryUserModel::refreshSection(SectionIndex sectionIndex)
|
||||
{
|
||||
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");
|
||||
auto texCat = qobject_cast<UserTextureCategory *>(m_userCategories[TexturesSectionIdx]);
|
||||
QTC_ASSERT(texCat, return);
|
||||
|
||||
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;
|
||||
texCat->addItems(paths);
|
||||
|
||||
auto tex = new ContentLibraryTexture(this, iconFileInfo, dirPath, suffix, imgDims, imgFileSize);
|
||||
m_userTextures.append(tex);
|
||||
}
|
||||
|
||||
emit dataChanged(index(TexturesSectionIdx), index(TexturesSectionIdx));
|
||||
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;
|
||||
UserItemCategory *itemCat = qobject_cast<UserItemCategory *>(item->parent());
|
||||
QTC_ASSERT(itemCat, return);
|
||||
|
||||
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;
|
||||
}
|
||||
Utils::FilePath bundlePath = itemCat->bundlePath();
|
||||
QJsonObject &bundleObj = itemCat->bundleObjRef();
|
||||
|
||||
QJsonArray itemsArr = bundleObj->value("items").toArray();
|
||||
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();
|
||||
}
|
||||
for (UserCategory *cat : std::as_const(m_userCategories))
|
||||
cat->loadBundle();
|
||||
|
||||
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();
|
||||
resetModel();
|
||||
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());
|
||||
|
||||
m_bundle3DLoaded = true;
|
||||
updateNoMatch3D();
|
||||
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 (UserCategory *cat : std::as_const(m_userCategories))
|
||||
cat->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);
|
||||
|
||||
updateNoMatchMaterials();
|
||||
updateNoMatchTextures();
|
||||
updateNoMatch3D();
|
||||
resetModel();
|
||||
}
|
||||
|
||||
void ContentLibraryUserModel::updateMaterialsImportedState(const QStringList &importedItems)
|
||||
void ContentLibraryUserModel::updateImportedState(const QStringList &importedItems,
|
||||
const QString &bundleId)
|
||||
{
|
||||
SectionIndex secIdx = bundleIdToSectionIndex(bundleId);
|
||||
UserItemCategory *cat = qobject_cast<UserItemCategory *>(m_userCategories.at(secIdx));
|
||||
const QObjectList items = cat->items();
|
||||
|
||||
bool changed = false;
|
||||
for (ContentLibraryItem *mat : std::as_const(m_userMaterials))
|
||||
changed |= mat->setImported(importedItems.contains(mat->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(MaterialsSectionIdx), index(MaterialsSectionIdx));
|
||||
}
|
||||
|
||||
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)));
|
||||
|
||||
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);
|
||||
UserItemCategory *itemCat = qobject_cast<UserItemCategory *>(item->parent());
|
||||
QTC_ASSERT(itemCat, return);
|
||||
|
||||
addItemToProject(castedItem);
|
||||
}
|
||||
|
||||
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);
|
||||
|
||||
|
@@ -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 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 addItemToProject(ContentLibraryItem *item);
|
||||
|
||||
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;
|
||||
QList<UserCategory *> m_userCategories;
|
||||
|
||||
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;
|
||||
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
|
||||
|
@@ -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);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@@ -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
|
||||
|
@@ -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
|
@@ -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
|
@@ -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
|
@@ -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
|
@@ -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
|
@@ -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
|
@@ -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();
|
||||
|
@@ -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;
|
||||
|
Reference in New Issue
Block a user