@@ -24,11 +24,20 @@
25#define CATEGORY_COLUMN 2
25#define CATEGORY_COLUMN 2
27+// TODO: use something from libunity once it's public
27Categories::Categories(QObject* parent)
36Categories::Categories(QObject* parent)
28 : DeeListModel(parent)
37 : DeeListModel(parent)
30 // FIXME: need to clean up unused filters on countChanged
39 // FIXME: need to clean up unused filters on countChanged
31− m_roles[Categories::RoleId] = "id";
40+ m_roles[Categories::RoleCategoryId] = "categoryId";
32 m_roles[Categories::RoleName] = "name";
41 m_roles[Categories::RoleName] = "name";
33 m_roles[Categories::RoleIcon] = "icon";
42 m_roles[Categories::RoleIcon] = "icon";
34 m_roles[Categories::RoleRenderer] = "renderer";
43 m_roles[Categories::RoleRenderer] = "renderer";
@@ -74,6 +83,25 @@ Categories::onCountChanged()
86+void Categories::onRowCountChanged()
88+ QAbstractItemModel* model = qobject_cast<QAbstractItemModel*>(sender());
89+ // find the corresponding category index
90+ for (auto iter = m_overriddenCategories.begin(); iter != m_overriddenCategories.end(); ++iter) {
91+ if (iter.value() == model) {
92+ for (int i = 0; i < rowCount(); i++) {
93+ auto id = data(index(i), RoleCategoryId).toString();
94+ if (id != iter.key()) continue;
96+ roles.append(RoleCount);
97+ QModelIndex changedIndex = index(i);
98+ Q_EMIT dataChanged(changedIndex, changedIndex, roles);
78Categories::onEmitCountChanged()
106Categories::onEmitCountChanged()
@@ -93,6 +121,41 @@ Categories::roleNames() const
93 return m_roles;
121 return m_roles;
124+void Categories::onOverrideModelDestroyed()
126+ QObject* model = sender();
127+ auto iter = m_overriddenCategories.begin();
128+ while (iter != m_overriddenCategories.end()) {
129+ if (iter.value() == model) {
130+ iter = m_overriddenCategories.erase(iter);
137+void Categories::overrideResults(const QString& categoryId, QAbstractItemModel* model)
139+ m_overriddenCategories[categoryId] = model;
141+ connect(model, &QObject::destroyed, this, &Categories::onOverrideModelDestroyed);
142+ connect(model, &QAbstractItemModel::rowsInserted, this, &Categories::onRowCountChanged);
143+ connect(model, &QAbstractItemModel::rowsRemoved, this, &Categories::onRowCountChanged);
144+ connect(model, &QAbstractItemModel::modelReset, this, &Categories::onRowCountChanged);
146+ // emit the dataChanged signal if the category is already in the model
147+ for (int i = 0; i < rowCount(); i++) {
148+ auto id = data(index(i), RoleCategoryId).toString();
149+ if (id != categoryId) continue;
151+ roles.append(RoleCount);
152+ roles.append(RoleResults);
153+ QModelIndex changedIndex = index(i);
154+ Q_EMIT dataChanged(changedIndex, changedIndex, roles);
96void Categories::setResultModel(DeeModel* model)
159void Categories::setResultModel(DeeModel* model)
98 // FIXME: should ref it
161 // FIXME: should ref it
@@ -154,24 +217,36 @@ Categories::data(const QModelIndex& index, int role) const
156 switch (role) {
219 switch (role) {
157− case RoleId:
220+ case RoleCategoryId:
158− return DeeListModel::data(index, 0); //ID
221+ return DeeListModel::data(index, CategoryColumn::ID);
159 case RoleName:
222 case RoleName:
160− return DeeListModel::data(index, 1); //DISPLAY_NAME
223+ return DeeListModel::data(index, CategoryColumn::DISPLAY_NAME);
161 case RoleIcon:
224 case RoleIcon:
162− return DeeListModel::data(index, 2); //ICON_HINT
225+ return DeeListModel::data(index, CategoryColumn::ICON_HINT);
163 case RoleRenderer:
226 case RoleRenderer:
164− return DeeListModel::data(index, 3); //RENDERER_NAME
227+ return DeeListModel::data(index, CategoryColumn::RENDERER_NAME);
165 case RoleContentType:
228 case RoleContentType:
167− auto hints = DeeListModel::data(index, 4).toHash();
230+ auto hints = DeeListModel::data(index, CategoryColumn::HINTS).toHash();
168− return hints.contains("content-type") ? hints["content-type"] : QVariant(QString("default"));
231+ return hints.contains("content-type") ? hints["content-type"] : QVariant(QString("default"));
170 case RoleHints:
233 case RoleHints:
171− return DeeListModel::data(index, 4); //HINTS
234+ return DeeListModel::data(index, CategoryColumn::HINTS);
172 case RoleResults:
235 case RoleResults:
236+ if (m_overriddenCategories.size() > 0)
238+ auto id = DeeListModel::data(index, CategoryColumn::ID).toString();
239+ if (m_overriddenCategories.find(id) != m_overriddenCategories.end())
240+ return QVariant::fromValue(m_overriddenCategories[id]);
173 return QVariant::fromValue(getFilter(index.row()));
242 return QVariant::fromValue(getFilter(index.row()));
174 case RoleCount:
243 case RoleCount:
244+ if (m_overriddenCategories.size() > 0)
246+ auto id = DeeListModel::data(index, CategoryColumn::ID).toString();
247+ if (m_overriddenCategories.find(id) != m_overriddenCategories.end())
248+ return QVariant::fromValue(m_overriddenCategories[id]->rowCount());
175 return QVariant::fromValue(getFilter(index.row())->rowCount());
250 return QVariant::fromValue(getFilter(index.row())->rowCount());
176 case RoleCategoryIndex:
251 case RoleCategoryIndex:
177 return QVariant::fromValue(index.row());
252 return QVariant::fromValue(index.row());