1 /****************************************************************************
2 **
3 ** Copyright (C) 2021 The Qt Company Ltd.
4 ** Contact: https://www.qt.io/licensing/
5 **
6 ** This file is part of Qt Creator.
7 **
8 ** Commercial License Usage
9 ** Licensees holding valid commercial Qt licenses may use this file in
10 ** accordance with the commercial license agreement provided with the
11 ** Software or, alternatively, in accordance with the terms contained in
12 ** a written agreement between you and The Qt Company. For licensing terms
13 ** and conditions see https://www.qt.io/terms-conditions. For further
14 ** information use the contact form at https://www.qt.io/contact-us.
15 **
16 ** GNU General Public License Usage
17 ** Alternatively, this file may be used under the terms of the GNU
18 ** General Public License version 3 as published by the Free Software
19 ** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
20 ** included in the packaging of this file. Please review the following
21 ** information to ensure the GNU General Public License requirements will
22 ** be met: https://www.gnu.org/licenses/gpl-3.0.html.
23 **
24 ****************************************************************************/
25 
26 #include "itemlibrarycategoriesmodel.h"
27 #include "itemlibrarycategory.h"
28 #include "itemlibrarymodel.h"
29 
30 #include <utils/algorithm.h>
31 #include <utils/qtcassert.h>
32 
33 #include <QDebug>
34 #include <QVariant>
35 #include <QMetaProperty>
36 #include <QMetaObject>
37 
38 namespace QmlDesigner {
39 
ItemLibraryCategoriesModel(QObject * parent)40 ItemLibraryCategoriesModel::ItemLibraryCategoriesModel(QObject *parent) :
41     QAbstractListModel(parent)
42 {
43     addRoleNames();
44 }
45 
~ItemLibraryCategoriesModel()46 ItemLibraryCategoriesModel::~ItemLibraryCategoriesModel()
47 {
48 }
49 
rowCount(const QModelIndex &) const50 int ItemLibraryCategoriesModel::rowCount(const QModelIndex &) const
51 {
52     return m_categoryList.count();
53 }
54 
data(const QModelIndex & index,int role) const55 QVariant ItemLibraryCategoriesModel::data(const QModelIndex &index, int role) const
56 {
57     if (!index.isValid() || index.row() >= m_categoryList.count()) {
58         qWarning() << Q_FUNC_INFO << "invalid index requested";
59         return {};
60     }
61 
62     if (m_roleNames.contains(role)) {
63         QVariant value = m_categoryList.at(index.row())->property(m_roleNames.value(role));
64 
65         if (auto model = qobject_cast<ItemLibraryItemsModel *>(value.value<QObject *>()))
66             return QVariant::fromValue(model);
67 
68         return value;
69     }
70 
71     qWarning() << Q_FUNC_INFO << "invalid role requested";
72 
73     return {};
74 }
75 
setData(const QModelIndex & index,const QVariant & value,int role)76 bool ItemLibraryCategoriesModel::setData(const QModelIndex &index, const QVariant &value, int role)
77 {
78     // currently only categoryExpanded and categoryVisible properties is updatable
79     if (index.isValid() && m_roleNames.contains(role)) {
80         QVariant currValue = m_categoryList.at(index.row())->property(m_roleNames.value(role));
81 
82         if (currValue != value) {
83             m_categoryList[index.row()]->setProperty(m_roleNames.value(role), value);
84             if (m_roleNames.value(role) == "categoryExpanded") {
85                 ItemLibraryModel::saveExpandedState(value.toBool(),
86                                                     m_categoryList[index.row()]->categoryName());
87             } else if (m_roleNames.value(role) == "categoryVisible") {
88                 const ItemLibraryCategory *category = m_categoryList[index.row()];
89                 ItemLibraryModel::saveCategoryVisibleState(value.toBool(), category->categoryName(),
90                                                            category->ownerImport()->importName());
91             }
92             emit dataChanged(index, index, {role});
93             return true;
94         }
95     }
96     return false;
97 }
98 
roleNames() const99 QHash<int, QByteArray> ItemLibraryCategoriesModel::roleNames() const
100 {
101     return m_roleNames;
102 }
103 
expandCategories(bool expand)104 void ItemLibraryCategoriesModel::expandCategories(bool expand)
105 {
106     int i = 0;
107     for (const auto &category : std::as_const(m_categoryList)) {
108         if (category->categoryExpanded() != expand) {
109             category->setExpanded(expand);
110             ItemLibraryModel::saveExpandedState(expand, category->categoryName());
111             emit dataChanged(index(i), index(i), {m_roleNames.key("categoryExpanded")});
112         }
113         ++i;
114     }
115 }
116 
addCategory(ItemLibraryCategory * category)117 void ItemLibraryCategoriesModel::addCategory(ItemLibraryCategory *category)
118 {
119     m_categoryList.append(category);
120 
121     category->setVisible(true);
122 }
123 
categorySections() const124 const QList<QPointer<ItemLibraryCategory>> &ItemLibraryCategoriesModel::categorySections() const
125 {
126     return m_categoryList;
127 }
128 
sortCategorySections()129 void ItemLibraryCategoriesModel::sortCategorySections()
130 {
131     auto categorySort = [](ItemLibraryCategory *first, ItemLibraryCategory *second) {
132         return QString::localeAwareCompare(first->sortingName(), second->sortingName()) < 0;
133     };
134 
135     std::sort(m_categoryList.begin(), m_categoryList.end(), categorySort);
136 
137     for (const auto &category : qAsConst(m_categoryList))
138         category->sortItems();
139 }
140 
resetModel()141 void ItemLibraryCategoriesModel::resetModel()
142 {
143     beginResetModel();
144     endResetModel();
145 }
146 
showAllCategories(bool show)147 void ItemLibraryCategoriesModel::showAllCategories(bool show)
148 {
149     for (const auto &category : std::as_const(m_categoryList)) {
150         if (category->isCategoryVisible() != show) {
151             category->setCategoryVisible(show);
152             ItemLibraryModel::saveCategoryVisibleState(show, category->categoryName(),
153                                                        category->ownerImport()->importName());
154         }
155     }
156     emit dataChanged(index(0), index(m_categoryList.size() - 1), {m_roleNames.key("categoryVisible")});
157 }
158 
addRoleNames()159 void ItemLibraryCategoriesModel::addRoleNames()
160 {
161     int role = 0;
162     const QMetaObject meta = ItemLibraryCategory::staticMetaObject;
163     for (int i = meta.propertyOffset(); i < meta.propertyCount(); ++i)
164         m_roleNames.insert(role++, meta.property(i).name());
165 }
166 
167 } // namespace QmlDesigner
168