diff --git a/share/qtcreator/qmldesigner/itemLibraryQmlSources/ItemsView.qml b/share/qtcreator/qmldesigner/itemLibraryQmlSources/ItemsView.qml index 0c2f8136daf..7ae0892bf6f 100644 --- a/share/qtcreator/qmldesigner/itemLibraryQmlSources/ItemsView.qml +++ b/share/qtcreator/qmldesigner/itemLibraryQmlSources/ItemsView.qml @@ -78,11 +78,14 @@ ScrollView { property string importToRemove: "" property string importToAdd: "" + property var currentItem: null + property var currentCategory: null + property var currentImport: null // called from C++ to close context menu on focus out function closeContextMenu() { - importContextMenu.close() + moduleContextMenu.close() itemContextMenu.close() } @@ -107,25 +110,73 @@ ScrollView { 2 * cellVerticalMargin + cellVerticalSpacing StudioControls.Menu { - id: importContextMenu + id: moduleContextMenu StudioControls.MenuItem { text: qsTr("Remove Module") + visible: currentCategory === null + height: visible ? implicitHeight : 0 enabled: importToRemove !== "" onTriggered: rootView.removeImport(importToRemove) } - StudioControls.MenuSeparator {} + StudioControls.MenuSeparator { + visible: currentCategory === null + height: StudioTheme.Values.border + } StudioControls.MenuItem { text: qsTr("Expand All") + visible: currentCategory === null + height: visible ? implicitHeight : 0 onTriggered: itemLibraryModel.expandAll() } StudioControls.MenuItem { text: qsTr("Collapse All") + visible: currentCategory === null + height: visible ? implicitHeight : 0 onTriggered: itemLibraryModel.collapseAll() } + + StudioControls.MenuSeparator { + visible: currentCategory === null + height: StudioTheme.Values.border + } + + StudioControls.MenuItem { + text: qsTr("Hide Category") + visible: currentCategory + height: visible ? implicitHeight : 0 + onTriggered: { + itemLibraryModel.isAnyCategoryHidden = true + currentCategory.categoryVisible = false + } + } + + StudioControls.MenuSeparator { + visible: currentCategory + height: StudioTheme.Values.border + } + + StudioControls.MenuItem { + text: qsTr("Show Module Hidden Categories") + enabled: currentImport && !currentImport.importCatVisibleState + onTriggered: { + currentImport.importCatVisibleState = true + if (!itemLibraryModel.getIsAnyCategoryHidden()) + itemLibraryModel.isAnyCategoryHidden = false + } + } + + StudioControls.MenuItem { + text: qsTr("Show All Hidden Categories") + enabled: itemLibraryModel.isAnyCategoryHidden + onTriggered: { + itemLibraryModel.isAnyCategoryHidden = false + itemLibraryModel.showHiddenCategories() + } + } } StudioControls.Menu { @@ -166,11 +217,14 @@ ScrollView { } onShowContextMenu: { importToRemove = importRemovable ? importUrl : "" - importContextMenu.popup() + currentImport = model + currentCategory = null + moduleContextMenu.popup() } Column { spacing: 2 + property var currentImportModel: model // allows accessing the import model from inside the category section Repeater { model: categoryModel delegate: Section { @@ -188,6 +242,11 @@ ScrollView { expanded: categoryExpanded expandOnClick: false onToggleExpand: categoryExpanded = !categoryExpanded + onShowContextMenu: { + currentCategory = model + currentImport = parent.currentImportModel + moduleContextMenu.popup() + } Grid { id: itemGrid diff --git a/src/plugins/qmldesigner/components/itemlibrary/itemlibrarycategoriesmodel.cpp b/src/plugins/qmldesigner/components/itemlibrary/itemlibrarycategoriesmodel.cpp index 3176d1ebb70..a9a772c9533 100644 --- a/src/plugins/qmldesigner/components/itemlibrary/itemlibrarycategoriesmodel.cpp +++ b/src/plugins/qmldesigner/components/itemlibrary/itemlibrarycategoriesmodel.cpp @@ -75,14 +75,18 @@ QVariant ItemLibraryCategoriesModel::data(const QModelIndex &index, int role) co bool ItemLibraryCategoriesModel::setData(const QModelIndex &index, const QVariant &value, int role) { - // currently only categoryExpanded property is updatable + // currently only categoryExpanded and categoryVisible properties is updatable if (index.isValid() && m_roleNames.contains(role)) { QVariant currValue = m_categoryList.at(index.row())->property(m_roleNames.value(role)); + if (currValue != value) { m_categoryList[index.row()]->setProperty(m_roleNames.value(role), value); if (m_roleNames.value(role) == "categoryExpanded") { ItemLibraryModel::saveExpandedState(value.toBool(), m_categoryList[index.row()]->categoryName()); + } else if (m_roleNames.value(role) == "categoryVisible") { + ItemLibraryModel::saveCategoryVisibleState(value.toBool(), + m_categoryList[index.row()]->categoryName()); } emit dataChanged(index, index, {role}); return true; @@ -139,6 +143,17 @@ void ItemLibraryCategoriesModel::resetModel() endResetModel(); } +void ItemLibraryCategoriesModel::showAllCategories(bool show) +{ + for (const auto &category : std::as_const(m_categoryList)) { + if (category->isCategoryVisible() != show) { + category->setCategoryVisible(show); + ItemLibraryModel::saveCategoryVisibleState(show, category->categoryName()); + } + } + emit dataChanged(index(0), index(m_categoryList.size() - 1), {m_roleNames.key("categoryVisible")}); +} + void ItemLibraryCategoriesModel::addRoleNames() { int role = 0; diff --git a/src/plugins/qmldesigner/components/itemlibrary/itemlibrarycategoriesmodel.h b/src/plugins/qmldesigner/components/itemlibrary/itemlibrarycategoriesmodel.h index 982083569d0..276d47ac480 100644 --- a/src/plugins/qmldesigner/components/itemlibrary/itemlibrarycategoriesmodel.h +++ b/src/plugins/qmldesigner/components/itemlibrary/itemlibrarycategoriesmodel.h @@ -54,6 +54,7 @@ public: void sortCategorySections(); void resetModel(); + void showAllCategories(bool show = true); private: void addRoleNames(); diff --git a/src/plugins/qmldesigner/components/itemlibrary/itemlibrarycategory.cpp b/src/plugins/qmldesigner/components/itemlibrary/itemlibrarycategory.cpp index f55fd309219..5f46d1e1ce2 100644 --- a/src/plugins/qmldesigner/components/itemlibrary/itemlibrarycategory.cpp +++ b/src/plugins/qmldesigner/components/itemlibrary/itemlibrarycategory.cpp @@ -87,6 +87,14 @@ bool ItemLibraryCategory::updateItemVisibility(const QString &searchText, bool * return hasVisibleItems; } +void ItemLibraryCategory::setCategoryVisible(bool isVisible) +{ + if (isVisible != m_isVisible) { + m_isVisible = isVisible; + emit categoryVisibilityChanged(); + } +} + bool ItemLibraryCategory::setVisible(bool isVisible) { if (isVisible != m_isVisible) { @@ -97,7 +105,7 @@ bool ItemLibraryCategory::setVisible(bool isVisible) return false; } -bool ItemLibraryCategory::isVisible() const +bool ItemLibraryCategory::isCategoryVisible() const { return m_isVisible; } diff --git a/src/plugins/qmldesigner/components/itemlibrary/itemlibrarycategory.h b/src/plugins/qmldesigner/components/itemlibrary/itemlibrarycategory.h index ad3f1579a00..1018402019f 100644 --- a/src/plugins/qmldesigner/components/itemlibrary/itemlibrarycategory.h +++ b/src/plugins/qmldesigner/components/itemlibrary/itemlibrarycategory.h @@ -36,7 +36,7 @@ class ItemLibraryCategory : public QObject Q_OBJECT Q_PROPERTY(QString categoryName READ categoryName FINAL) - Q_PROPERTY(bool categoryVisible READ isVisible NOTIFY visibilityChanged FINAL) + Q_PROPERTY(bool categoryVisible READ isCategoryVisible WRITE setCategoryVisible NOTIFY categoryVisibilityChanged FINAL) Q_PROPERTY(bool categoryExpanded READ categoryExpanded WRITE setExpanded NOTIFY expandedChanged FINAL) Q_PROPERTY(QObject *itemModel READ itemModel NOTIFY itemModelChanged FINAL) @@ -52,8 +52,9 @@ public: bool updateItemVisibility(const QString &searchText, bool *changed); + void setCategoryVisible(bool isVisible); bool setVisible(bool isVisible); - bool isVisible() const; + bool isCategoryVisible() const; void sortItems(); @@ -63,6 +64,7 @@ signals: void itemModelChanged(); void visibilityChanged(); void expandedChanged(); + void categoryVisibilityChanged(); private: ItemLibraryItemsModel m_itemModel; diff --git a/src/plugins/qmldesigner/components/itemlibrary/itemlibraryimport.cpp b/src/plugins/qmldesigner/components/itemlibrary/itemlibraryimport.cpp index 79acb29d58a..40892db07b3 100644 --- a/src/plugins/qmldesigner/components/itemlibrary/itemlibraryimport.cpp +++ b/src/plugins/qmldesigner/components/itemlibrary/itemlibraryimport.cpp @@ -116,19 +116,28 @@ bool ItemLibraryImport::updateCategoryVisibility(const QString &searchText, bool *changed = false; for (const auto &category : m_categoryModel.categorySections()) { - bool categoryChanged = false; - bool hasVisibleItems = category->updateItemVisibility(searchText, &categoryChanged); - categoryChanged |= category->setVisible(hasVisibleItems); + category->setCategoryVisible(ItemLibraryModel::loadCategoryVisibleState(category->categoryName())); - *changed |= categoryChanged; + if (!searchText.isEmpty() || category->isCategoryVisible()) { + bool categoryChanged = false; + bool hasVisibleItems = category->updateItemVisibility(searchText, &categoryChanged); + categoryChanged |= category->setVisible(hasVisibleItems); - if (hasVisibleItems) - hasVisibleCategories = true; + *changed |= categoryChanged; + + if (hasVisibleItems) + hasVisibleCategories = true; + } } return hasVisibleCategories; } +void ItemLibraryImport::showAllCategories(bool show) +{ + m_categoryModel.showAllCategories(show); +} + Import ItemLibraryImport::importEntry() const { return m_import; @@ -235,4 +244,22 @@ void ItemLibraryImport::updateRemovable() } } +// returns true if all categories are visible, otherwise false +bool ItemLibraryImport::importCatVisibleState() const +{ + if (m_categoryModel.rowCount() > 0) { + for (ItemLibraryCategory *cat : m_categoryModel.categorySections()) { + if (!cat->isCategoryVisible()) + return false; + } + } + + return true; +} + +void ItemLibraryImport::setImportCatVisibleState(bool show) +{ + m_categoryModel.showAllCategories(show); +} + } // namespace QmlDesigner diff --git a/src/plugins/qmldesigner/components/itemlibrary/itemlibraryimport.h b/src/plugins/qmldesigner/components/itemlibrary/itemlibraryimport.h index 3b860e488b5..81717439f9a 100644 --- a/src/plugins/qmldesigner/components/itemlibrary/itemlibraryimport.h +++ b/src/plugins/qmldesigner/components/itemlibrary/itemlibraryimport.h @@ -43,6 +43,7 @@ class ItemLibraryImport : public QObject Q_PROPERTY(bool importExpanded READ importExpanded WRITE setImportExpanded NOTIFY importExpandChanged FINAL) Q_PROPERTY(bool importRemovable READ importRemovable NOTIFY importRemovableChanged FINAL) Q_PROPERTY(bool importUnimported READ importUnimported FINAL) + Q_PROPERTY(bool importCatVisibleState READ importCatVisibleState WRITE setImportCatVisibleState NOTIFY importCatVisibleStateChanged FINAL) Q_PROPERTY(QObject *categoryModel READ categoryModel NOTIFY categoryModelChanged FINAL) public: @@ -64,6 +65,7 @@ public: bool importVisible() const; bool importUsed() const; bool importRemovable() const; + bool importCatVisibleState() const; bool hasCategories() const; bool hasSingleCategory() const; ItemLibraryCategory *getCategorySection(const QString &categoryName) const; @@ -75,7 +77,9 @@ public: void setImportUsed(bool importUsed); void sortCategorySections(); void setImportExpanded(bool expanded = true); + void setImportCatVisibleState(bool show); void expandCategories(bool expand = true); + void showAllCategories(bool show = true); static QString userComponentsTitle(); static QString quick3DAssetsTitle(); @@ -89,6 +93,7 @@ signals: void importUsedChanged(); void importExpandChanged(); void importRemovableChanged(); + void importCatVisibleStateChanged(); private: void updateRemovable(); diff --git a/src/plugins/qmldesigner/components/itemlibrary/itemlibrarymodel.cpp b/src/plugins/qmldesigner/components/itemlibrary/itemlibrarymodel.cpp index 91a930b7831..ae7fc0bc496 100644 --- a/src/plugins/qmldesigner/components/itemlibrary/itemlibrarymodel.cpp +++ b/src/plugins/qmldesigner/components/itemlibrary/itemlibrarymodel.cpp @@ -59,6 +59,49 @@ bool ItemLibraryModel::loadExpandedState(const QString §ionName) return expandedStateHash.value(sectionName, true); } +void ItemLibraryModel::saveCategoryVisibleState(bool isVisible, const QString &categoryName) +{ + categoryVisibleStateHash.insert(categoryName, isVisible); +} + +bool ItemLibraryModel::loadCategoryVisibleState(const QString &categoryName) +{ + return categoryVisibleStateHash.value(categoryName, true); +} + +void ItemLibraryModel::showHiddenCategories() +{ + for (const QPointer &import : std::as_const(m_importList)) { + if (import->hasCategories()) + import->showAllCategories(true); + } + + categoryVisibleStateHash.clear(); +} + +bool ItemLibraryModel::getIsAnyCategoryHidden() const +{ + for (const bool &catState : std::as_const(categoryVisibleStateHash)) { + if (!catState) + return true; + } + + return false; +} + +bool ItemLibraryModel::isAnyCategoryHidden() const +{ + return m_isAnyCategoryHidden; +} + +void ItemLibraryModel::setIsAnyCategoryHidden(bool state) +{ + if (state != m_isAnyCategoryHidden) { + m_isAnyCategoryHidden = state; + emit isAnyCategoryHiddenChanged(); + } +} + void ItemLibraryModel::expandAll() { int i = 0; diff --git a/src/plugins/qmldesigner/components/itemlibrary/itemlibrarymodel.h b/src/plugins/qmldesigner/components/itemlibrary/itemlibrarymodel.h index 2412550a3a0..1bb9447bd73 100644 --- a/src/plugins/qmldesigner/components/itemlibrary/itemlibrarymodel.h +++ b/src/plugins/qmldesigner/components/itemlibrary/itemlibrarymodel.h @@ -41,6 +41,7 @@ class ItemLibraryImport; class ItemLibraryModel : public QAbstractListModel { Q_OBJECT + Q_PROPERTY(bool isAnyCategoryHidden READ isAnyCategoryHidden WRITE setIsAnyCategoryHidden NOTIFY isAnyCategoryHiddenChanged FINAL) public: explicit ItemLibraryModel(QObject *parent = nullptr); @@ -62,15 +63,25 @@ public: void setSearchText(const QString &searchText); void setFlowMode(bool); + bool isAnyCategoryHidden() const; + void setIsAnyCategoryHidden(bool state); + static void registerQmlTypes(); static void saveExpandedState(bool expanded, const QString §ionName); static bool loadExpandedState(const QString §ionName); + static void saveCategoryVisibleState(bool isVisible, const QString &categoryName); + static bool loadCategoryVisibleState(const QString &categoryName); Q_INVOKABLE void expandAll(); Q_INVOKABLE void collapseAll(); + Q_INVOKABLE void showHiddenCategories(); + Q_INVOKABLE bool getIsAnyCategoryHidden() const; Import entryToImport(const ItemLibraryEntry &entry); +signals: + void isAnyCategoryHiddenChanged(); + private: void updateVisibility(bool *changed); void addRoleNames(); @@ -82,8 +93,10 @@ private: QString m_searchText; bool m_flowMode = false; + bool m_isAnyCategoryHidden = false; inline static QHash expandedStateHash; + inline static QHash categoryVisibleStateHash; }; } // namespace QmlDesigner