QmlDesigner: Implement hiding component library categories

Task-number: QDS-3822
Change-Id: I4e22385497c4e58725b7f7a62a4e4351d0b78661
Reviewed-by: Mahmoud Badri <mahmoud.badri@qt.io>
Reviewed-by: Thomas Hartmann <thomas.hartmann@qt.io>
This commit is contained in:
Miina Puuronen
2021-03-31 13:48:52 +03:00
parent 17e2a80e10
commit 24d88de228
9 changed files with 187 additions and 14 deletions

View File

@@ -78,11 +78,14 @@ ScrollView {
property string importToRemove: "" property string importToRemove: ""
property string importToAdd: "" 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 // called from C++ to close context menu on focus out
function closeContextMenu() function closeContextMenu()
{ {
importContextMenu.close() moduleContextMenu.close()
itemContextMenu.close() itemContextMenu.close()
} }
@@ -107,25 +110,73 @@ ScrollView {
2 * cellVerticalMargin + cellVerticalSpacing 2 * cellVerticalMargin + cellVerticalSpacing
StudioControls.Menu { StudioControls.Menu {
id: importContextMenu id: moduleContextMenu
StudioControls.MenuItem { StudioControls.MenuItem {
text: qsTr("Remove Module") text: qsTr("Remove Module")
visible: currentCategory === null
height: visible ? implicitHeight : 0
enabled: importToRemove !== "" enabled: importToRemove !== ""
onTriggered: rootView.removeImport(importToRemove) onTriggered: rootView.removeImport(importToRemove)
} }
StudioControls.MenuSeparator {} StudioControls.MenuSeparator {
visible: currentCategory === null
height: StudioTheme.Values.border
}
StudioControls.MenuItem { StudioControls.MenuItem {
text: qsTr("Expand All") text: qsTr("Expand All")
visible: currentCategory === null
height: visible ? implicitHeight : 0
onTriggered: itemLibraryModel.expandAll() onTriggered: itemLibraryModel.expandAll()
} }
StudioControls.MenuItem { StudioControls.MenuItem {
text: qsTr("Collapse All") text: qsTr("Collapse All")
visible: currentCategory === null
height: visible ? implicitHeight : 0
onTriggered: itemLibraryModel.collapseAll() 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 { StudioControls.Menu {
@@ -166,11 +217,14 @@ ScrollView {
} }
onShowContextMenu: { onShowContextMenu: {
importToRemove = importRemovable ? importUrl : "" importToRemove = importRemovable ? importUrl : ""
importContextMenu.popup() currentImport = model
currentCategory = null
moduleContextMenu.popup()
} }
Column { Column {
spacing: 2 spacing: 2
property var currentImportModel: model // allows accessing the import model from inside the category section
Repeater { Repeater {
model: categoryModel model: categoryModel
delegate: Section { delegate: Section {
@@ -188,6 +242,11 @@ ScrollView {
expanded: categoryExpanded expanded: categoryExpanded
expandOnClick: false expandOnClick: false
onToggleExpand: categoryExpanded = !categoryExpanded onToggleExpand: categoryExpanded = !categoryExpanded
onShowContextMenu: {
currentCategory = model
currentImport = parent.currentImportModel
moduleContextMenu.popup()
}
Grid { Grid {
id: itemGrid id: itemGrid

View File

@@ -75,14 +75,18 @@ QVariant ItemLibraryCategoriesModel::data(const QModelIndex &index, int role) co
bool ItemLibraryCategoriesModel::setData(const QModelIndex &index, const QVariant &value, int role) 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)) { if (index.isValid() && m_roleNames.contains(role)) {
QVariant currValue = m_categoryList.at(index.row())->property(m_roleNames.value(role)); QVariant currValue = m_categoryList.at(index.row())->property(m_roleNames.value(role));
if (currValue != value) { if (currValue != value) {
m_categoryList[index.row()]->setProperty(m_roleNames.value(role), value); m_categoryList[index.row()]->setProperty(m_roleNames.value(role), value);
if (m_roleNames.value(role) == "categoryExpanded") { if (m_roleNames.value(role) == "categoryExpanded") {
ItemLibraryModel::saveExpandedState(value.toBool(), ItemLibraryModel::saveExpandedState(value.toBool(),
m_categoryList[index.row()]->categoryName()); 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}); emit dataChanged(index, index, {role});
return true; return true;
@@ -139,6 +143,17 @@ void ItemLibraryCategoriesModel::resetModel()
endResetModel(); 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() void ItemLibraryCategoriesModel::addRoleNames()
{ {
int role = 0; int role = 0;

View File

@@ -54,6 +54,7 @@ public:
void sortCategorySections(); void sortCategorySections();
void resetModel(); void resetModel();
void showAllCategories(bool show = true);
private: private:
void addRoleNames(); void addRoleNames();

View File

@@ -87,6 +87,14 @@ bool ItemLibraryCategory::updateItemVisibility(const QString &searchText, bool *
return hasVisibleItems; return hasVisibleItems;
} }
void ItemLibraryCategory::setCategoryVisible(bool isVisible)
{
if (isVisible != m_isVisible) {
m_isVisible = isVisible;
emit categoryVisibilityChanged();
}
}
bool ItemLibraryCategory::setVisible(bool isVisible) bool ItemLibraryCategory::setVisible(bool isVisible)
{ {
if (isVisible != m_isVisible) { if (isVisible != m_isVisible) {
@@ -97,7 +105,7 @@ bool ItemLibraryCategory::setVisible(bool isVisible)
return false; return false;
} }
bool ItemLibraryCategory::isVisible() const bool ItemLibraryCategory::isCategoryVisible() const
{ {
return m_isVisible; return m_isVisible;
} }

View File

@@ -36,7 +36,7 @@ class ItemLibraryCategory : public QObject
Q_OBJECT Q_OBJECT
Q_PROPERTY(QString categoryName READ categoryName FINAL) 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(bool categoryExpanded READ categoryExpanded WRITE setExpanded NOTIFY expandedChanged FINAL)
Q_PROPERTY(QObject *itemModel READ itemModel NOTIFY itemModelChanged FINAL) Q_PROPERTY(QObject *itemModel READ itemModel NOTIFY itemModelChanged FINAL)
@@ -52,8 +52,9 @@ public:
bool updateItemVisibility(const QString &searchText, bool *changed); bool updateItemVisibility(const QString &searchText, bool *changed);
void setCategoryVisible(bool isVisible);
bool setVisible(bool isVisible); bool setVisible(bool isVisible);
bool isVisible() const; bool isCategoryVisible() const;
void sortItems(); void sortItems();
@@ -63,6 +64,7 @@ signals:
void itemModelChanged(); void itemModelChanged();
void visibilityChanged(); void visibilityChanged();
void expandedChanged(); void expandedChanged();
void categoryVisibilityChanged();
private: private:
ItemLibraryItemsModel m_itemModel; ItemLibraryItemsModel m_itemModel;

View File

@@ -116,19 +116,28 @@ bool ItemLibraryImport::updateCategoryVisibility(const QString &searchText, bool
*changed = false; *changed = false;
for (const auto &category : m_categoryModel.categorySections()) { for (const auto &category : m_categoryModel.categorySections()) {
bool categoryChanged = false; category->setCategoryVisible(ItemLibraryModel::loadCategoryVisibleState(category->categoryName()));
bool hasVisibleItems = category->updateItemVisibility(searchText, &categoryChanged);
categoryChanged |= category->setVisible(hasVisibleItems);
*changed |= categoryChanged; if (!searchText.isEmpty() || category->isCategoryVisible()) {
bool categoryChanged = false;
bool hasVisibleItems = category->updateItemVisibility(searchText, &categoryChanged);
categoryChanged |= category->setVisible(hasVisibleItems);
if (hasVisibleItems) *changed |= categoryChanged;
hasVisibleCategories = true;
if (hasVisibleItems)
hasVisibleCategories = true;
}
} }
return hasVisibleCategories; return hasVisibleCategories;
} }
void ItemLibraryImport::showAllCategories(bool show)
{
m_categoryModel.showAllCategories(show);
}
Import ItemLibraryImport::importEntry() const Import ItemLibraryImport::importEntry() const
{ {
return m_import; 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 } // namespace QmlDesigner

View File

@@ -43,6 +43,7 @@ class ItemLibraryImport : public QObject
Q_PROPERTY(bool importExpanded READ importExpanded WRITE setImportExpanded NOTIFY importExpandChanged FINAL) Q_PROPERTY(bool importExpanded READ importExpanded WRITE setImportExpanded NOTIFY importExpandChanged FINAL)
Q_PROPERTY(bool importRemovable READ importRemovable NOTIFY importRemovableChanged FINAL) Q_PROPERTY(bool importRemovable READ importRemovable NOTIFY importRemovableChanged FINAL)
Q_PROPERTY(bool importUnimported READ importUnimported 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) Q_PROPERTY(QObject *categoryModel READ categoryModel NOTIFY categoryModelChanged FINAL)
public: public:
@@ -64,6 +65,7 @@ public:
bool importVisible() const; bool importVisible() const;
bool importUsed() const; bool importUsed() const;
bool importRemovable() const; bool importRemovable() const;
bool importCatVisibleState() const;
bool hasCategories() const; bool hasCategories() const;
bool hasSingleCategory() const; bool hasSingleCategory() const;
ItemLibraryCategory *getCategorySection(const QString &categoryName) const; ItemLibraryCategory *getCategorySection(const QString &categoryName) const;
@@ -75,7 +77,9 @@ public:
void setImportUsed(bool importUsed); void setImportUsed(bool importUsed);
void sortCategorySections(); void sortCategorySections();
void setImportExpanded(bool expanded = true); void setImportExpanded(bool expanded = true);
void setImportCatVisibleState(bool show);
void expandCategories(bool expand = true); void expandCategories(bool expand = true);
void showAllCategories(bool show = true);
static QString userComponentsTitle(); static QString userComponentsTitle();
static QString quick3DAssetsTitle(); static QString quick3DAssetsTitle();
@@ -89,6 +93,7 @@ signals:
void importUsedChanged(); void importUsedChanged();
void importExpandChanged(); void importExpandChanged();
void importRemovableChanged(); void importRemovableChanged();
void importCatVisibleStateChanged();
private: private:
void updateRemovable(); void updateRemovable();

View File

@@ -59,6 +59,49 @@ bool ItemLibraryModel::loadExpandedState(const QString &sectionName)
return expandedStateHash.value(sectionName, true); 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<ItemLibraryImport> &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() void ItemLibraryModel::expandAll()
{ {
int i = 0; int i = 0;

View File

@@ -41,6 +41,7 @@ class ItemLibraryImport;
class ItemLibraryModel : public QAbstractListModel class ItemLibraryModel : public QAbstractListModel
{ {
Q_OBJECT Q_OBJECT
Q_PROPERTY(bool isAnyCategoryHidden READ isAnyCategoryHidden WRITE setIsAnyCategoryHidden NOTIFY isAnyCategoryHiddenChanged FINAL)
public: public:
explicit ItemLibraryModel(QObject *parent = nullptr); explicit ItemLibraryModel(QObject *parent = nullptr);
@@ -62,15 +63,25 @@ public:
void setSearchText(const QString &searchText); void setSearchText(const QString &searchText);
void setFlowMode(bool); void setFlowMode(bool);
bool isAnyCategoryHidden() const;
void setIsAnyCategoryHidden(bool state);
static void registerQmlTypes(); static void registerQmlTypes();
static void saveExpandedState(bool expanded, const QString &sectionName); static void saveExpandedState(bool expanded, const QString &sectionName);
static bool loadExpandedState(const QString &sectionName); static bool loadExpandedState(const QString &sectionName);
static void saveCategoryVisibleState(bool isVisible, const QString &categoryName);
static bool loadCategoryVisibleState(const QString &categoryName);
Q_INVOKABLE void expandAll(); Q_INVOKABLE void expandAll();
Q_INVOKABLE void collapseAll(); Q_INVOKABLE void collapseAll();
Q_INVOKABLE void showHiddenCategories();
Q_INVOKABLE bool getIsAnyCategoryHidden() const;
Import entryToImport(const ItemLibraryEntry &entry); Import entryToImport(const ItemLibraryEntry &entry);
signals:
void isAnyCategoryHiddenChanged();
private: private:
void updateVisibility(bool *changed); void updateVisibility(bool *changed);
void addRoleNames(); void addRoleNames();
@@ -82,8 +93,10 @@ private:
QString m_searchText; QString m_searchText;
bool m_flowMode = false; bool m_flowMode = false;
bool m_isAnyCategoryHidden = false;
inline static QHash<QString, bool> expandedStateHash; inline static QHash<QString, bool> expandedStateHash;
inline static QHash<QString, bool> categoryVisibleStateHash;
}; };
} // namespace QmlDesigner } // namespace QmlDesigner