From 7ffd4805ca739c1ebe5159512b8eb8998443aaed Mon Sep 17 00:00:00 2001 From: Mahmoud Badri Date: Tue, 14 May 2024 12:52:29 +0300 Subject: [PATCH] QmlDesigner: Handle content library user items empty state - Make sure search is working - Hide sections with no items - Other tweaks Fixes: QDS-12682 Fixes: QDS-12625 Change-Id: Ia304743323c0459dd314752dba0cf1dc5e4c4889 Reviewed-by: Qt CI Patch Build Bot Reviewed-by: Miikka Heikkinen --- .../ContentLibraryUserView.qml | 14 +- .../contentlibrary/contentlibrarytexture.cpp | 5 + .../contentlibrary/contentlibrarytexture.h | 2 + .../contentlibraryusermodel.cpp | 163 +++++++++--------- .../contentlibrary/contentlibraryusermodel.h | 22 ++- .../contentlibrary/contentlibrarywidget.cpp | 4 - 6 files changed, 106 insertions(+), 104 deletions(-) diff --git a/share/qtcreator/qmldesigner/contentLibraryQmlSource/ContentLibraryUserView.qml b/share/qtcreator/qmldesigner/contentLibraryQmlSource/ContentLibraryUserView.qml index cb976fc1465..f7a210f6afb 100644 --- a/share/qtcreator/qmldesigner/contentLibraryQmlSource/ContentLibraryUserView.qml +++ b/share/qtcreator/qmldesigner/contentLibraryQmlSource/ContentLibraryUserView.qml @@ -92,8 +92,6 @@ HelperWidgets.ScrollView { onCountChanged: root.assignMaxCount() - property int numVisibleItem: 1 // initially, the tab is invisible so this will be 0 - Grid { width: section.width - section.leftPadding - section.rightPadding spacing: StudioTheme.Values.sectionGridSpacing @@ -114,10 +112,6 @@ HelperWidgets.ScrollView { onShowContextMenu: ctxMenuItem.popupMenu(modelData) onAddToProject: ContentLibraryBackend.userModel.addToProject(modelData) - - onVisibleChanged: { - section.numVisibleItem += visible ? 1 : -1 - } } } DelegateChoice { @@ -149,7 +143,7 @@ HelperWidgets.ScrollView { color: StudioTheme.Values.themeTextColor font.pixelSize: StudioTheme.Values.baseFontSize leftPadding: 10 - visible: !searchBox.isEmpty() && section.numVisibleItem === 0 + visible: infoText.text === "" && !searchBox.isEmpty() && categoryNoMatch } } } @@ -157,9 +151,7 @@ HelperWidgets.ScrollView { Text { id: infoText text: { - if (!ContentLibraryBackend.effectsModel.bundleExists) - qsTr("User bundle couldn't be found.") - else if (!ContentLibraryBackend.rootView.isQt6Project) + if (!ContentLibraryBackend.rootView.isQt6Project) qsTr("Content Library is not supported in Qt5 projects.") else if (!ContentLibraryBackend.rootView.hasQuick3DImport) qsTr("To use Content Library, first add the QtQuick3D module in the Components view.") @@ -172,7 +164,7 @@ HelperWidgets.ScrollView { font.pixelSize: StudioTheme.Values.baseFontSize topPadding: 10 leftPadding: 10 - visible: ContentLibraryBackend.effectsModel.isEmpty + visible: infoText.text !== "" } } } diff --git a/src/plugins/qmldesigner/components/contentlibrary/contentlibrarytexture.cpp b/src/plugins/qmldesigner/components/contentlibrary/contentlibrarytexture.cpp index 80dd7e816f8..d2c2df2baaf 100644 --- a/src/plugins/qmldesigner/components/contentlibrary/contentlibrarytexture.cpp +++ b/src/plugins/qmldesigner/components/contentlibrary/contentlibrarytexture.cpp @@ -120,6 +120,11 @@ void ContentLibraryTexture::doSetDownloaded() m_toolTip = resolveToolTipText(); } +bool ContentLibraryTexture::visible() const +{ + return m_visible; +} + QString ContentLibraryTexture::parentDirPath() const { return m_dirPath; diff --git a/src/plugins/qmldesigner/components/contentlibrary/contentlibrarytexture.h b/src/plugins/qmldesigner/components/contentlibrary/contentlibrarytexture.h index 8f7197bc72e..7f5db6d7d60 100644 --- a/src/plugins/qmldesigner/components/contentlibrary/contentlibrarytexture.h +++ b/src/plugins/qmldesigner/components/contentlibrary/contentlibrarytexture.h @@ -46,6 +46,8 @@ public: void setHasUpdate(bool value); bool hasUpdate() const; + bool visible() const; + signals: void textureVisibleChanged(); void textureToolTipChanged(); diff --git a/src/plugins/qmldesigner/components/contentlibrary/contentlibraryusermodel.cpp b/src/plugins/qmldesigner/components/contentlibrary/contentlibraryusermodel.cpp index bb732080d7e..ca90c9c4517 100644 --- a/src/plugins/qmldesigner/components/contentlibrary/contentlibraryusermodel.cpp +++ b/src/plugins/qmldesigner/components/contentlibrary/contentlibraryusermodel.cpp @@ -46,18 +46,37 @@ QVariant ContentLibraryUserModel::data(const QModelIndex &index, int role) const return m_userCategories.at(index.row()); if (role == ItemsRole) { - if (index.row() == 0) + if (index.row() == MaterialsSectionIdx) return QVariant::fromValue(m_userMaterials); - if (index.row() == 1) + if (index.row() == TexturesSectionIdx) return QVariant::fromValue(m_userTextures); - if (index.row() == 2) + if (index.row() == Items3DSectionIdx) return QVariant::fromValue(m_user3DItems); - if (index.row() == 3) + if (index.row() == EffectsSectionIdx) return QVariant::fromValue(m_userEffects); } - if (role == VisibleRole) - return true; // TODO + 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 == 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(); + } return {}; } @@ -67,32 +86,25 @@ bool ContentLibraryUserModel::isValidIndex(int idx) const return idx > -1 && idx < rowCount(); } -void ContentLibraryUserModel::updateIsEmptyMaterials() +void ContentLibraryUserModel::updateNoMatchMaterials() { - bool anyMatVisible = Utils::anyOf(m_userMaterials, [&](ContentLibraryMaterial *mat) { - return mat->visible(); + m_noMatchMaterials = Utils::allOf(m_userMaterials, [&](ContentLibraryMaterial *item) { + return !item->visible(); }); - - bool newEmpty = !anyMatVisible || !m_widget->hasMaterialLibrary() || !hasRequiredQuick3DImport(); - - if (newEmpty != m_isEmptyMaterials) { - m_isEmptyMaterials = newEmpty; - emit isEmptyMaterialsChanged(); - } } -void ContentLibraryUserModel::updateIsEmpty3D() +void ContentLibraryUserModel::updateNoMatchTextures() { - bool anyItemVisible = Utils::anyOf(m_user3DItems, [&](ContentLibraryItem *item) { - return item->visible(); + m_noMatchTextures = Utils::allOf(m_userTextures, [&](ContentLibraryTexture *item) { + return !item->visible(); }); +} - bool newEmpty = !anyItemVisible || !m_widget->hasMaterialLibrary() || !hasRequiredQuick3DImport(); - - if (newEmpty != m_isEmpty3D) { - m_isEmpty3D = newEmpty; - emit isEmpty3DChanged(); - } +void ContentLibraryUserModel::updateNoMatch3D() +{ + m_noMatch3D = Utils::allOf(m_user3DItems, [&](ContentLibraryItem *item) { + return !item->visible(); + }); } void ContentLibraryUserModel::addMaterial(const QString &name, const QString &qml, @@ -107,8 +119,7 @@ void ContentLibraryUserModel::addMaterial(const QString &name, const QString &qm Paths::bundlesPathSetting().append("/User/materials")); m_userMaterials.append(libMat); - int matSectionIdx = 0; - emit dataChanged(index(matSectionIdx), index(matSectionIdx)); + emit dataChanged(index(MaterialsSectionIdx), index(MaterialsSectionIdx)); } void ContentLibraryUserModel::add3DItem(const QString &name, const QString &qml, @@ -124,8 +135,7 @@ void ContentLibraryUserModel::add3DItem(const QString &name, const QString &qml, void ContentLibraryUserModel::refresh3DSection() { - int sectionIdx = 2; - emit dataChanged(index(sectionIdx), index(sectionIdx)); + emit dataChanged(index(Items3DSectionIdx), index(Items3DSectionIdx)); } void ContentLibraryUserModel::addTextures(const QStringList &paths) @@ -147,20 +157,19 @@ void ContentLibraryUserModel::addTextures(const QStringList &paths) m_userTextures.append(tex); } - int texSectionIdx = 1; - emit dataChanged(index(texSectionIdx), index(texSectionIdx)); + emit dataChanged(index(TexturesSectionIdx), index(TexturesSectionIdx)); } void ContentLibraryUserModel::add3DInstance(ContentLibraryItem *bundleItem) { - QString err = m_widget->importer()->importComponent(m_bundlePath3D.path(), bundleItem->type(), - bundleItem->qml(), - bundleItem->files() + m_bundle3DSharedFiles); + QString err = m_widget->importer()->importComponent(m_bundlePath3D.path(), bundleItem->type(), + bundleItem->qml(), + bundleItem->files() + m_bundle3DSharedFiles); - if (err.isEmpty()) - m_widget->setImporterRunning(true); - else - qWarning() << __FUNCTION__ << err; + if (err.isEmpty()) + m_widget->setImporterRunning(true); + else + qWarning() << __FUNCTION__ << err; } void ContentLibraryUserModel::removeTexture(ContentLibraryTexture *tex) @@ -174,8 +183,7 @@ void ContentLibraryUserModel::removeTexture(ContentLibraryTexture *tex) tex->deleteLater(); // update model - int texSectionIdx = 1; - emit dataChanged(index(texSectionIdx), index(texSectionIdx)); + emit dataChanged(index(TexturesSectionIdx), index(TexturesSectionIdx)); } void ContentLibraryUserModel::removeFromContentLib(QObject *item) @@ -226,8 +234,7 @@ void ContentLibraryUserModel::removeMaterialFromContentLib(ContentLibraryMateria item->deleteLater(); // update model - int sectionIdx = 0; - emit dataChanged(index(sectionIdx), index(sectionIdx)); + emit dataChanged(index(MaterialsSectionIdx), index(MaterialsSectionIdx)); } void ContentLibraryUserModel::remove3DFromContentLib(ContentLibraryItem *item) @@ -268,8 +275,7 @@ void ContentLibraryUserModel::remove3DFromContentLib(ContentLibraryItem *item) item->deleteLater(); // update model - int sectionIdx = 2; - emit dataChanged(index(sectionIdx), index(sectionIdx)); + emit dataChanged(index(Items3DSectionIdx), index(Items3DSectionIdx)); } /** @@ -327,7 +333,8 @@ QHash ContentLibraryUserModel::roleNames() const static const QHash roles { {NameRole, "categoryName"}, {VisibleRole, "categoryVisible"}, - {ItemsRole, "categoryItems"} + {ItemsRole, "categoryItems"}, + {NoMatchRole, "categoryNoMatch"} }; return roles; } @@ -352,7 +359,6 @@ void ContentLibraryUserModel::loadBundles() void ContentLibraryUserModel::loadMaterialBundle() { auto compUtils = QmlDesignerPlugin::instance()->documentManager().generatedComponentUtils(); - if (m_matBundleExists && m_bundleIdMaterial == compUtils.userMaterialsBundleId()) return; @@ -360,12 +366,10 @@ void ContentLibraryUserModel::loadMaterialBundle() qDeleteAll(m_userMaterials); m_userMaterials.clear(); m_matBundleExists = false; - m_isEmptyMaterials = true; + m_noMatchMaterials = true; m_bundleObjMaterial = {}; m_bundleIdMaterial.clear(); - int sectionIdx = 0; - m_bundlePathMaterial = Utils::FilePath::fromString(Paths::bundlesPathSetting() + "/User/materials"); m_bundlePathMaterial.ensureWritableDir(); m_bundlePathMaterial.pathAppended("icons").ensureWritableDir(); @@ -379,7 +383,7 @@ void ContentLibraryUserModel::loadMaterialBundle() Utils::expected_str res = jsonFilePath.writeFileContents(jsonContent.toLatin1()); if (!res.has_value()) { qWarning() << __FUNCTION__ << res.error(); - emit dataChanged(index(sectionIdx), index(sectionIdx)); + emit dataChanged(index(MaterialsSectionIdx), index(MaterialsSectionIdx)); return; } } @@ -387,14 +391,14 @@ void ContentLibraryUserModel::loadMaterialBundle() Utils::expected_str jsonContents = jsonFilePath.fileContents(); if (!jsonContents.has_value()) { qWarning() << __FUNCTION__ << jsonContents.error(); - emit dataChanged(index(sectionIdx), index(sectionIdx)); + emit dataChanged(index(MaterialsSectionIdx), index(MaterialsSectionIdx)); return; } QJsonDocument bundleJsonDoc = QJsonDocument::fromJson(jsonContents.value()); if (bundleJsonDoc.isNull()) { qWarning() << __FUNCTION__ << "Invalid user_materials_bundle.json file"; - emit dataChanged(index(sectionIdx), index(sectionIdx)); + emit dataChanged(index(MaterialsSectionIdx), index(MaterialsSectionIdx)); return; } @@ -404,7 +408,7 @@ void ContentLibraryUserModel::loadMaterialBundle() // parse items QString typePrefix = compUtils.userMaterialsBundleType(); - const QJsonArray itemsArr = m_bundleObj3D.value("items").toArray(); + const QJsonArray itemsArr = m_bundleObjMaterial.value("items").toArray(); for (const QJsonValueConstRef &itemRef : itemsArr) { const QJsonObject itemObj = itemRef.toObject(); @@ -427,8 +431,8 @@ void ContentLibraryUserModel::loadMaterialBundle() m_bundleMaterialSharedFiles.append(file.toString()); m_matBundleExists = true; - updateIsEmptyMaterials(); - emit dataChanged(index(sectionIdx), index(sectionIdx)); + updateNoMatchMaterials(); + emit dataChanged(index(MaterialsSectionIdx), index(MaterialsSectionIdx)); } void ContentLibraryUserModel::load3DBundle() @@ -442,12 +446,10 @@ void ContentLibraryUserModel::load3DBundle() qDeleteAll(m_user3DItems); m_user3DItems.clear(); m_bundle3DExists = false; - m_isEmpty3D = true; + m_noMatch3D = true; m_bundleObj3D = {}; m_bundleId3D.clear(); - int sectionIdx = 2; - m_bundlePath3D = Utils::FilePath::fromString(Paths::bundlesPathSetting() + "/User/3d"); m_bundlePath3D.ensureWritableDir(); m_bundlePath3D.pathAppended("icons").ensureWritableDir(); @@ -461,7 +463,7 @@ void ContentLibraryUserModel::load3DBundle() Utils::expected_str res = jsonFilePath.writeFileContents(jsonContent); if (!res.has_value()) { qWarning() << __FUNCTION__ << res.error(); - emit dataChanged(index(sectionIdx), index(sectionIdx)); + emit dataChanged(index(Items3DSectionIdx), index(Items3DSectionIdx)); return; } } @@ -469,14 +471,14 @@ void ContentLibraryUserModel::load3DBundle() Utils::expected_str jsonContents = jsonFilePath.fileContents(); if (!jsonContents.has_value()) { qWarning() << __FUNCTION__ << jsonContents.error(); - emit dataChanged(index(sectionIdx), index(sectionIdx)); + emit dataChanged(index(Items3DSectionIdx), index(Items3DSectionIdx)); return; } QJsonDocument bundleJsonDoc = QJsonDocument::fromJson(jsonContents.value()); if (bundleJsonDoc.isNull()) { qWarning() << __FUNCTION__ << "Invalid user_3d_bundle.json file"; - emit dataChanged(index(sectionIdx), index(sectionIdx)); + emit dataChanged(index(Items3DSectionIdx), index(Items3DSectionIdx)); return; } @@ -508,8 +510,8 @@ void ContentLibraryUserModel::load3DBundle() m_bundle3DSharedFiles.append(file.toString()); m_bundle3DExists = true; - updateIsEmpty3D(); - emit dataChanged(index(sectionIdx), index(sectionIdx)); + updateNoMatch3D(); + emit dataChanged(index(Items3DSectionIdx), index(Items3DSectionIdx)); } void ContentLibraryUserModel::loadTextureBundle() @@ -534,8 +536,8 @@ void ContentLibraryUserModel::loadTextureBundle() m_userTextures.append(tex); } - int texSectionIdx = 1; - emit dataChanged(index(texSectionIdx), index(texSectionIdx)); + updateNoMatchTextures(); + emit dataChanged(index(TexturesSectionIdx), index(TexturesSectionIdx)); } bool ContentLibraryUserModel::hasRequiredQuick3DImport() const @@ -557,11 +559,19 @@ void ContentLibraryUserModel::setSearchText(const QString &searchText) m_searchText = lowerSearchText; - for (ContentLibraryMaterial *mat : std::as_const(m_userMaterials)) - mat->filter(m_searchText); + for (ContentLibraryMaterial *item : std::as_const(m_userMaterials)) + item->filter(m_searchText); - updateIsEmptyMaterials(); - updateIsEmpty3D(); + 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) @@ -570,10 +580,8 @@ void ContentLibraryUserModel::updateMaterialsImportedState(const QStringList &im for (ContentLibraryMaterial *mat : std::as_const(m_userMaterials)) changed |= mat->setImported(importedItems.contains(mat->qml().chopped(4))); - if (changed) { - int matSectionIdx = 0; - emit dataChanged(index(matSectionIdx), index(matSectionIdx)); - } + if (changed) + emit dataChanged(index(MaterialsSectionIdx), index(MaterialsSectionIdx)); } void ContentLibraryUserModel::update3DImportedState(const QStringList &importedItems) @@ -582,10 +590,8 @@ void ContentLibraryUserModel::update3DImportedState(const QStringList &importedI for (ContentLibraryItem *item : std::as_const(m_user3DItems)) changed |= item->setImported(importedItems.contains(item->qml().chopped(4))); - if (changed) { - int sectionIdx = 2; - emit dataChanged(index(sectionIdx), index(sectionIdx)); - } + if (changed) + emit dataChanged(index(Items3DSectionIdx), index(Items3DSectionIdx)); } void ContentLibraryUserModel::setQuick3DImportVersion(int major, int minor) @@ -601,9 +607,6 @@ void ContentLibraryUserModel::setQuick3DImportVersion(int major, int minor) return; emit hasRequiredQuick3DImportChanged(); - - updateIsEmptyMaterials(); - updateIsEmpty3D(); } void ContentLibraryUserModel::resetModel() diff --git a/src/plugins/qmldesigner/components/contentlibrary/contentlibraryusermodel.h b/src/plugins/qmldesigner/components/contentlibrary/contentlibraryusermodel.h index e38e84e5c08..67dc36b98e5 100644 --- a/src/plugins/qmldesigner/components/contentlibrary/contentlibraryusermodel.h +++ b/src/plugins/qmldesigner/components/contentlibrary/contentlibraryusermodel.h @@ -24,8 +24,6 @@ class ContentLibraryUserModel : public QAbstractListModel Q_PROPERTY(bool matBundleExists READ matBundleExists NOTIFY matBundleExistsChanged) Q_PROPERTY(bool bundle3DExists MEMBER m_bundle3DExists NOTIFY bundle3DExistsChanged) - Q_PROPERTY(bool isEmptyMaterials MEMBER m_isEmptyMaterials NOTIFY isEmptyMaterialsChanged) - Q_PROPERTY(bool isEmpty3D MEMBER m_isEmpty3D NOTIFY isEmpty3DChanged) Q_PROPERTY(bool hasRequiredQuick3DImport READ hasRequiredQuick3DImport NOTIFY hasRequiredQuick3DImportChanged) Q_PROPERTY(QList userMaterials MEMBER m_userMaterials NOTIFY userMaterialsChanged) Q_PROPERTY(QList userTextures MEMBER m_userTextures NOTIFY userTexturesChanged) @@ -53,8 +51,9 @@ public: bool matBundleExists() const; void resetModel(); - void updateIsEmptyMaterials(); - void updateIsEmpty3D(); + 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); @@ -76,8 +75,6 @@ public: Q_INVOKABLE void removeFromContentLib(QObject *item); signals: - void isEmptyMaterialsChanged(); - void isEmpty3DChanged(); void hasRequiredQuick3DImportChanged(); void userMaterialsChanged(); void userTexturesChanged(); @@ -88,6 +85,11 @@ signals: void bundle3DExistsChanged(); private: + enum SectionIndex { MaterialsSectionIdx = 0, + TexturesSectionIdx, + Items3DSectionIdx, + EffectsSectionIdx }; + void loadMaterialBundle(); void load3DBundle(); void loadTextureBundle(); @@ -115,15 +117,17 @@ private: QJsonObject m_bundleObjMaterial; QJsonObject m_bundleObj3D; - bool m_isEmptyMaterials = true; - bool m_isEmpty3D = true; + bool m_noMatchMaterials = true; + bool m_noMatchTextures = true; + bool m_noMatch3D = true; + bool m_noMatchEffects = true; bool m_matBundleExists = false; bool m_bundle3DExists = false; int m_quick3dMajorVersion = -1; int m_quick3dMinorVersion = -1; - enum Roles { NameRole = Qt::UserRole + 1, VisibleRole, ItemsRole }; + enum Roles { NameRole = Qt::UserRole + 1, VisibleRole, ItemsRole, NoMatchRole }; }; } // namespace QmlDesigner diff --git a/src/plugins/qmldesigner/components/contentlibrary/contentlibrarywidget.cpp b/src/plugins/qmldesigner/components/contentlibrary/contentlibrarywidget.cpp index 4d09eed05fc..3edad3d11dd 100644 --- a/src/plugins/qmldesigner/components/contentlibrary/contentlibrarywidget.cpp +++ b/src/plugins/qmldesigner/components/contentlibrary/contentlibrarywidget.cpp @@ -699,8 +699,6 @@ void ContentLibraryWidget::setHasQuick3DImport(bool b) m_materialsModel->updateIsEmpty(); m_effectsModel->updateIsEmpty(); - m_userModel->updateIsEmptyMaterials(); - m_userModel->updateIsEmpty3D(); } bool ContentLibraryWidget::hasMaterialLibrary() const @@ -717,8 +715,6 @@ void ContentLibraryWidget::setHasMaterialLibrary(bool b) emit hasMaterialLibraryChanged(); m_materialsModel->updateIsEmpty(); - m_userModel->updateIsEmptyMaterials(); - m_userModel->updateIsEmpty3D(); } bool ContentLibraryWidget::hasActive3DScene() const