on xenial help sign in
Handle category_order_changes signal from scopes (used in Home only) and reorder categories accordingly.
cc21ad5Pawel Stolowski
plugins/Unity/categories.cpp+70−17
@@ -90,9 +90,37 @@ void Categories::onCategoriesModelChanged(unity::glib::Object<DeeModel> model)
90 delete model;
90 delete model;
91 }
91 }
92 m_results.clear();
92 m_results.clear();
93+ m_categoryOrder.clear();
94+
93 setModel(model);
95 setModel(model);
94}
96}
95
97
98+void Categories::onCategoryOrderChanged(const std::vector<unsigned int>& cat_order)
99+{
100+ for (unsigned int pos = 0; pos<cat_order.size(); pos++)
101+ {
102+ unsigned int cat = cat_order[pos];
103+ const int old_pos = m_categoryOrder.indexOf(cat);
104+
105+ if (old_pos < 0) {
106+ qWarning() << "No such category index:" << cat;
107+ continue;
108+ }
109+
110+ if (static_cast<int>(pos) != old_pos) {
111+ int target_pos = pos;
112+ if (target_pos > old_pos)
113+ target_pos++;
114+ const bool status = beginMoveRows(QModelIndex(), old_pos, old_pos, QModelIndex(), target_pos);
115+ if (status)
116+ m_categoryOrder.move(old_pos, pos);
117+ else
118+ qWarning() << "beginMoveRows failed:" << old_pos << target_pos;
119+ endMoveRows();
120+ }
121+ }
122+}
123+
96void
124void
97Categories::setUnityScope(const unity::dash::Scope::Ptr& scope)
125Categories::setUnityScope(const unity::dash::Scope::Ptr& scope)
98{
126{
@@ -101,9 +129,9 @@ Categories::setUnityScope(const unity::dash::Scope::Ptr& scope)
101 // no need to call this, we'll get notified
129 // no need to call this, we'll get notified
102 //setModel(m_unityScope->categories()->model());
130 //setModel(m_unityScope->categories()->model());
103
131
104− m_categoriesChangedConnection.disconnect();
132+ m_signals.disconnectAll();
105− m_categoriesChangedConnection =
106− m_unityScope->categories()->model.changed.connect(sigc::mem_fun(this, &Categories::onCategoriesModelChanged));
133+ m_signals << m_unityScope->categories()->model.changed.connect(sigc::mem_fun(this, &Categories::onCategoriesModelChanged));
134+ m_signals << m_unityScope->category_order.changed.connect(sigc::mem_fun(this, &Categories::onCategoryOrderChanged));
107}
135}
108
136
109void
137void
@@ -111,7 +139,9 @@ Categories::onCountChanged()
111{
139{
112 CategoryResults* results = qobject_cast<CategoryResults*>(sender());
140 CategoryResults* results = qobject_cast<CategoryResults*>(sender());
113 if (results) {
141 if (results) {
142+ if (!m_updatedCategories.contains(results->categoryIndex())) {
114− m_updatedCategories << results->categoryIndex();
143+ m_updatedCategories << results->categoryIndex();
144+ }
115 m_timer.start();
145 m_timer.start();
116 }
146 }
117}
147}
@@ -142,7 +172,8 @@ Categories::onEmitCountChanged()
142 roles.append(Categories::RoleCount);
172 roles.append(Categories::RoleCount);
143 Q_FOREACH(int categoryIndex, m_updatedCategories) {
173 Q_FOREACH(int categoryIndex, m_updatedCategories) {
144 if (!m_results.contains(categoryIndex)) continue;
174 if (!m_results.contains(categoryIndex)) continue;
175+ const int realIndex = m_categoryOrder.indexOf(categoryIndex);
145− QModelIndex changedIndex = index(categoryIndex);
176+ const QModelIndex changedIndex = index(realIndex);
146 Q_EMIT dataChanged(changedIndex, changedIndex, roles);
177 Q_EMIT dataChanged(changedIndex, changedIndex, roles);
147 }
178 }
148 m_updatedCategories.clear();
179 m_updatedCategories.clear();
@@ -196,48 +227,70 @@ Categories::data(const QModelIndex& index, int role) const
196 return QVariant();
227 return QVariant();
197 }
228 }
198
229
230+ if (m_categoryOrder.size() != rowCount())
231+ {
232+ // populate category order vector with 0..n
233+ m_categoryOrder.clear();
234+ const unsigned int lim = rowCount();
235+ for (unsigned int i = 0; i<lim; i++) {
236+ m_categoryOrder.append(i);
237+ }
238+ }
239+
240+ int realRow = index.row();
241+ if (index.row() < m_categoryOrder.size()) {
242+ realRow = m_categoryOrder[index.row()];
243+ } else {
244+ qWarning() << "Invalid index" << index.row();
245+ return QVariant();
246+ }
247+
248+ const QModelIndex realIndex = createIndex(realRow, index.column());
249+
199 switch (role) {
250 switch (role) {
200 case RoleCategoryId:
251 case RoleCategoryId:
201− return DeeListModel::data(index, CategoryColumn::ID);
252+ return DeeListModel::data(realIndex, CategoryColumn::ID);
202 case RoleName:
253 case RoleName:
203− return DeeListModel::data(index, CategoryColumn::DISPLAY_NAME);
254+ return DeeListModel::data(realIndex, CategoryColumn::DISPLAY_NAME);
204 case RoleIcon:
255 case RoleIcon:
205− return DeeListModel::data(index, CategoryColumn::ICON_HINT);
256+ return DeeListModel::data(realIndex, CategoryColumn::ICON_HINT);
206 case RoleRenderer:
257 case RoleRenderer:
207− return DeeListModel::data(index, CategoryColumn::RENDERER_NAME);
258+ return DeeListModel::data(realIndex, CategoryColumn::RENDERER_NAME);
208 case RoleContentType:
259 case RoleContentType:
209 {
260 {
210− auto hints = DeeListModel::data(index, CategoryColumn::HINTS).toHash();
261+ auto hints = DeeListModel::data(realIndex, CategoryColumn::HINTS).toHash();
211 return hints.contains("content-type") ? hints["content-type"] : QVariant(QString("default"));
262 return hints.contains("content-type") ? hints["content-type"] : QVariant(QString("default"));
212 }
263 }
213 case RoleRendererHint:
264 case RoleRendererHint:
214 {
265 {
215− auto hints = DeeListModel::data(index, CategoryColumn::HINTS).toHash();
266+ auto hints = DeeListModel::data(realIndex, CategoryColumn::HINTS).toHash();
216 return hints.contains("renderer-hint") ? hints["renderer-hint"] : QVariant(QString());
267 return hints.contains("renderer-hint") ? hints["renderer-hint"] : QVariant(QString());
217 }
268 }
218 case RoleProgressSource:
269 case RoleProgressSource:
219 {
270 {
220− auto hints = DeeListModel::data(index, CategoryColumn::HINTS).toHash();
271+ auto hints = DeeListModel::data(realIndex, CategoryColumn::HINTS).toHash();
221 return hints.contains("progress-source") ? hints["progress-source"] : QVariant();
272 return hints.contains("progress-source") ? hints["progress-source"] : QVariant();
222 }
273 }
223 case RoleHints:
274 case RoleHints:
224− return DeeListModel::data(index, CategoryColumn::HINTS);
275+ return DeeListModel::data(realIndex, CategoryColumn::HINTS);
225 case RoleResults:
276 case RoleResults:
226 if (m_overriddenCategories.size() > 0)
277 if (m_overriddenCategories.size() > 0)
227 {
278 {
228− auto id = DeeListModel::data(index, CategoryColumn::ID).toString();
279+ auto id = DeeListModel::data(realIndex, CategoryColumn::ID).toString();
229 if (m_overriddenCategories.find(id) != m_overriddenCategories.end())
280 if (m_overriddenCategories.find(id) != m_overriddenCategories.end())
230 return QVariant::fromValue(m_overriddenCategories[id]);
281 return QVariant::fromValue(m_overriddenCategories[id]);
231 }
282 }
232− return QVariant::fromValue(getResults(index.row()));
283+ return QVariant::fromValue(getResults(realRow));
233 case RoleCount:
284 case RoleCount:
234 if (m_overriddenCategories.size() > 0)
285 if (m_overriddenCategories.size() > 0)
235 {
286 {
236− auto id = DeeListModel::data(index, CategoryColumn::ID).toString();
287+ auto id = DeeListModel::data(realIndex, CategoryColumn::ID).toString();
237 if (m_overriddenCategories.find(id) != m_overriddenCategories.end())
288 if (m_overriddenCategories.find(id) != m_overriddenCategories.end())
289+ {
238 return QVariant::fromValue(m_overriddenCategories[id]->rowCount());
290 return QVariant::fromValue(m_overriddenCategories[id]->rowCount());
291+ }
239 }
292 }
240− return QVariant::fromValue(getResults(index.row())->rowCount());
293+ return QVariant::fromValue(getResults(realRow)->rowCount());
241 default:
294 default:
242 return QVariant();
295 return QVariant();
243 }
296 }
plugins/Unity/categories.h+10−1
@@ -32,6 +32,9 @@
32#include <QSet>
32#include <QSet>
33#include <QTimer>
33#include <QTimer>
34
34
35+// local
36+#include "signalslist.h"
37+
35class Categories : public DeeListModel
38class Categories : public DeeListModel
36{
39{
37 Q_OBJECT
40 Q_OBJECT
@@ -71,6 +74,7 @@ private Q_SLOTS:
71
74
72private:
75private:
73 void onCategoriesModelChanged(unity::glib::Object<DeeModel> model);
76 void onCategoriesModelChanged(unity::glib::Object<DeeModel> model);
77+ void onCategoryOrderChanged(const std::vector<unsigned int>& cat_order);
74
78
75 DeeListModel* getResults(int index) const;
79 DeeListModel* getResults(int index) const;
76
80
@@ -80,7 +84,12 @@ private:
80 QHash<int, QByteArray> m_roles;
84 QHash<int, QByteArray> m_roles;
81 QMap<QString, QAbstractItemModel*> m_overriddenCategories;
85 QMap<QString, QAbstractItemModel*> m_overriddenCategories;
82 mutable QMap<int, DeeListModel*> m_results;
86 mutable QMap<int, DeeListModel*> m_results;
83− sigc::connection m_categoriesChangedConnection;
87+ SignalsList m_signals;
88+
89+ /* Category order array contains indices of actual categories in the underlying DeeListModel.
90+ It's used internally to reflect category order reported by scope.
91+ */
92+ mutable QList<unsigned int> m_categoryOrder;
84};
93};
85
94
86#endif // CATEGORIES_H
95#endif // CATEGORIES_H