Merge lp:~stolowski/unity-scopes-shell/favoriting-fixes into lp:unity-scopes-shell
- favoriting-fixes
- Merge into trunk
Proposed by
Paweł Stołowski
Status: | Merged | ||||||||
---|---|---|---|---|---|---|---|---|---|
Approved by: | Marcus Tomlinson | ||||||||
Approved revision: | 341 | ||||||||
Merged at revision: | 346 | ||||||||
Proposed branch: | lp:~stolowski/unity-scopes-shell/favoriting-fixes | ||||||||
Merge into: | lp:unity-scopes-shell | ||||||||
Diff against target: |
626 lines (+309/-126) 7 files modified
src/Unity/CMakeLists.txt (+1/-0) src/Unity/favorites.cpp (+160/-0) src/Unity/favorites.h (+63/-0) src/Unity/scope.cpp (+4/-4) src/Unity/scope.h (+2/-2) src/Unity/scopes.cpp (+76/-118) src/Unity/scopes.h (+3/-2) |
||||||||
To merge this branch: | bzr merge lp:~stolowski/unity-scopes-shell/favoriting-fixes | ||||||||
Related bugs: |
|
Reviewer | Review Type | Date Requested | Status |
---|---|---|---|
Marcus Tomlinson (community) | Approve | ||
Review via email: mp+302253@code.launchpad.net |
Commit message
Optimize scope favoriting. Make sure click scope is favorited back if reinstalled.
Description of the change
Optimize and refactor scope favoriting. Make sure click scope is favorited back if reinstalled.
The optimization is mostly achieved by temporarily disabling gesttings signals when storing an updated list of favorites.
To post a comment you must log in.
Preview Diff
[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
1 | === modified file 'src/Unity/CMakeLists.txt' |
2 | --- src/Unity/CMakeLists.txt 2016-06-02 08:49:55 +0000 |
3 | +++ src/Unity/CMakeLists.txt 2016-08-10 07:21:23 +0000 |
4 | @@ -20,6 +20,7 @@ |
5 | collectors.cpp |
6 | department.cpp |
7 | departmentnode.cpp |
8 | + favorites.cpp |
9 | filters.cpp |
10 | filtergroupwidget.cpp |
11 | optionselectorfilter.cpp |
12 | |
13 | === added file 'src/Unity/favorites.cpp' |
14 | --- src/Unity/favorites.cpp 1970-01-01 00:00:00 +0000 |
15 | +++ src/Unity/favorites.cpp 2016-08-10 07:21:23 +0000 |
16 | @@ -0,0 +1,160 @@ |
17 | +/* |
18 | + * Copyright (C) 2016 Canonical, Ltd. |
19 | + * |
20 | + * Authors: |
21 | + * Pawel Stolowski <pawel.stolowski@canonical.com> |
22 | + * |
23 | + * This program is free software; you can redistribute it and/or modify |
24 | + * it under the terms of the GNU General Public License as published by |
25 | + * the Free Software Foundation; version 3. |
26 | + * |
27 | + * This program is distributed in the hope that it will be useful, |
28 | + * but WITHOUT ANY WARRANTY; without even the implied warranty of |
29 | + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
30 | + * GNU General Public License for more details. |
31 | + * |
32 | + * You should have received a copy of the GNU General Public License |
33 | + * along with this program. If not, see <http://www.gnu.org/licenses/>. |
34 | + */ |
35 | + |
36 | +#include <QGSettings> |
37 | +#include <QVariant> |
38 | +#include <QDebug> |
39 | +#include <unity/scopes/CannedQuery.h> |
40 | +#include <unity/UnityExceptions.h> |
41 | +#include <algorithm> |
42 | +#include "favorites.h" |
43 | + |
44 | +namespace scopes_ng |
45 | +{ |
46 | + |
47 | +Favorites::Favorites(QObject *parent, QGSettings *dashSettings) |
48 | + : QObject(parent), |
49 | + m_dashSettings(dashSettings) |
50 | +{ |
51 | + if (m_dashSettings) { |
52 | + readFavoritesFromGSettings(); |
53 | + QObject::connect(m_dashSettings, &QGSettings::changed, this, &Favorites::dashSettingsChanged); |
54 | + } |
55 | +} |
56 | + |
57 | +void Favorites::readFavoritesFromGSettings() |
58 | +{ |
59 | + m_favoriteScopes.clear(); |
60 | + m_positionLookup.clear(); |
61 | + |
62 | + int pos = 0 ; |
63 | + auto const favs = m_dashSettings->get(QStringLiteral("favoriteScopes")).toList(); |
64 | + for (auto const fv: favs) { |
65 | + try |
66 | + { |
67 | + auto const query = unity::scopes::CannedQuery::from_uri(fv.toString().toStdString()); |
68 | + auto scopeId = QString::fromStdString(query.scope_id()); |
69 | + m_favoriteScopes.append(scopeId); |
70 | + m_positionLookup[scopeId] = pos++; |
71 | + } |
72 | + catch (const unity::InvalidArgumentException &e) |
73 | + { |
74 | + qWarning() << "Invalid canned query '" << fv.toString() << "'" << QString::fromStdString(e.what()); |
75 | + } |
76 | + } |
77 | +} |
78 | + |
79 | +Favorites::~Favorites() |
80 | +{ |
81 | +} |
82 | + |
83 | +int Favorites::setFavorite(QString const& scopeId, bool value) |
84 | +{ |
85 | + if (!value) { |
86 | + int pos = position(scopeId); |
87 | + if (pos >= 0) { |
88 | + m_favoriteScopes.removeAt(pos); |
89 | + m_positionLookup.remove(scopeId); |
90 | + for (int i = pos; i<m_favoriteScopes.size(); i++) { |
91 | + m_positionLookup[m_favoriteScopes[i]] = i; |
92 | + } |
93 | + Q_ASSERT(m_favoriteScopes.size() == m_positionLookup.size()); |
94 | + storeFavorites(); |
95 | + return pos; |
96 | + } |
97 | + } else { |
98 | + int pos = position(scopeId); |
99 | + if (pos < 0) { |
100 | + m_favoriteScopes.push_back(scopeId); |
101 | + pos = m_favoriteScopes.size() - 1; |
102 | + m_positionLookup[scopeId] = pos; |
103 | + } |
104 | + Q_ASSERT(m_favoriteScopes.size() == m_positionLookup.size()); |
105 | + storeFavorites(); |
106 | + return pos; |
107 | + } |
108 | + |
109 | + return -1; |
110 | +} |
111 | + |
112 | +void Favorites::moveFavoriteTo(QString const& scopeId, int pos) |
113 | +{ |
114 | + int oldPos = position(scopeId); |
115 | + if (oldPos >= 0) { |
116 | + m_favoriteScopes.move(oldPos, pos); |
117 | + auto const range = std::minmax(oldPos, pos); |
118 | + for (int i = range.first; i<=range.second; i++) { |
119 | + m_positionLookup[m_favoriteScopes[i]] = i; |
120 | + } |
121 | + } else { |
122 | + qWarning() << "Favorites::moveFavoriteTo: no such scope" << scopeId; |
123 | + } |
124 | + |
125 | + storeFavorites(); |
126 | + |
127 | + Q_ASSERT(m_favoriteScopes.size() == m_positionLookup.size()); |
128 | +} |
129 | + |
130 | +QStringList Favorites::getFavorites() |
131 | +{ |
132 | + return m_favoriteScopes; |
133 | +} |
134 | + |
135 | +bool Favorites::hasScope(QString const& scopeId) const |
136 | +{ |
137 | + return m_positionLookup.find(scopeId) != m_positionLookup.end(); |
138 | +} |
139 | + |
140 | +int Favorites::position(QString const& scopeId) const |
141 | +{ |
142 | + auto it = m_positionLookup.find(scopeId); |
143 | + if (it != m_positionLookup.end()) { |
144 | + return it.value(); |
145 | + } |
146 | + return -1; |
147 | +} |
148 | + |
149 | +void Favorites::dashSettingsChanged(QString const &key) |
150 | +{ |
151 | + if (key != QLatin1String("favoriteScopes")) { |
152 | + return; |
153 | + } |
154 | + readFavoritesFromGSettings(); |
155 | + Q_EMIT favoritesChanged(); |
156 | +} |
157 | + |
158 | +void Favorites::storeFavorites() |
159 | +{ |
160 | + if (m_dashSettings) { |
161 | + QStringList cannedQueries; |
162 | + for (auto const& fav: m_favoriteScopes) |
163 | + { |
164 | + const QString query = "scope://" + fav; |
165 | + cannedQueries.push_back(query); |
166 | + } |
167 | + |
168 | + QObject::disconnect(m_dashSettings, &QGSettings::changed, this, &Favorites::dashSettingsChanged); |
169 | + m_dashSettings->set(QStringLiteral("favoriteScopes"), QVariant(cannedQueries)); |
170 | + QObject::connect(m_dashSettings, &QGSettings::changed, this, &Favorites::dashSettingsChanged); |
171 | + } |
172 | +} |
173 | + |
174 | +} // namespace scopes_ng |
175 | + |
176 | +#include <favorites.moc> |
177 | |
178 | === added file 'src/Unity/favorites.h' |
179 | --- src/Unity/favorites.h 1970-01-01 00:00:00 +0000 |
180 | +++ src/Unity/favorites.h 2016-08-10 07:21:23 +0000 |
181 | @@ -0,0 +1,63 @@ |
182 | +/* |
183 | + * Copyright (C) 2016 Canonical, Ltd. |
184 | + * |
185 | + * Authors: |
186 | + * Pawel Stolowski <pawel.stolowski@canonical.com> |
187 | + * |
188 | + * This program is free software; you can redistribute it and/or modify |
189 | + * it under the terms of the GNU General Public License as published by |
190 | + * the Free Software Foundation; version 3. |
191 | + * |
192 | + * This program is distributed in the hope that it will be useful, |
193 | + * but WITHOUT ANY WARRANTY; without even the implied warranty of |
194 | + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
195 | + * GNU General Public License for more details. |
196 | + * |
197 | + * You should have received a copy of the GNU General Public License |
198 | + * along with this program. If not, see <http://www.gnu.org/licenses/>. |
199 | + */ |
200 | + |
201 | +#ifndef NG_FAVORITES_H |
202 | +#define NG_FAVORITES_H |
203 | + |
204 | +#include <QStringList> |
205 | +#include <QObject> |
206 | +#include <QPointer> |
207 | +#include <QMap> |
208 | + |
209 | +class QGSettings; |
210 | + |
211 | +namespace scopes_ng |
212 | +{ |
213 | + |
214 | +class Q_DECL_EXPORT Favorites : public QObject |
215 | +{ |
216 | + Q_OBJECT |
217 | +public: |
218 | + Favorites(QObject *parent, QGSettings *dashSettings); |
219 | + ~Favorites(); |
220 | + |
221 | + int setFavorite(QString const& scopeId, bool value); |
222 | + void moveFavoriteTo(QString const& scopeId, int pos); |
223 | + bool hasScope(QString const& scopeId) const; |
224 | + int position(QString const& scopeId) const; |
225 | + QStringList getFavorites(); |
226 | + void storeFavorites(); |
227 | + |
228 | +Q_SIGNALS: |
229 | + void favoritesChanged(); |
230 | + |
231 | +private Q_SLOTS: |
232 | + void dashSettingsChanged(QString const &key); |
233 | + |
234 | +private: |
235 | + void readFavoritesFromGSettings(); |
236 | + |
237 | + QPointer<QGSettings> m_dashSettings; |
238 | + QStringList m_favoriteScopes; |
239 | + QMap<QString, int> m_positionLookup; |
240 | +}; |
241 | + |
242 | +} // namespace scopes_ng |
243 | + |
244 | +#endif // NG_SCOPES_H |
245 | |
246 | === modified file 'src/Unity/scope.cpp' |
247 | --- src/Unity/scope.cpp 2016-06-24 14:03:59 +0000 |
248 | +++ src/Unity/scope.cpp 2016-08-10 07:21:23 +0000 |
249 | @@ -75,13 +75,13 @@ |
250 | const int RESULTS_TTL_LARGE = 3600000; // 1 hour |
251 | const int SEARCH_CARDINALITY = 300; // maximum number of results accepted from a single scope |
252 | |
253 | -Scope::Ptr Scope::newInstance(scopes_ng::Scopes* parent) |
254 | +Scope::Ptr Scope::newInstance(scopes_ng::Scopes* parent, bool favorite) |
255 | { |
256 | - auto scope = Scope::Ptr(new Scope(parent), &QObject::deleteLater); |
257 | + auto scope = Scope::Ptr(new Scope(parent, favorite), &QObject::deleteLater); |
258 | return scope; |
259 | } |
260 | |
261 | -Scope::Scope(scopes_ng::Scopes* parent) : |
262 | +Scope::Scope(scopes_ng::Scopes* parent, bool favorite) : |
263 | m_query_id(0) |
264 | , m_formFactor(QStringLiteral("phone")) |
265 | , m_activeFiltersCount(0) |
266 | @@ -91,7 +91,7 @@ |
267 | , m_resultsDirty(false) |
268 | , m_delayedSearchProcessing(false) |
269 | , m_hasNavigation(false) |
270 | - , m_favorite(false) |
271 | + , m_favorite(favorite) |
272 | , m_initialQueryDone(false) |
273 | , m_childScopesDirty(true) |
274 | , m_searchController(new CollectionController) |
275 | |
276 | === modified file 'src/Unity/scope.h' |
277 | --- src/Unity/scope.h 2016-06-23 09:27:45 +0000 |
278 | +++ src/Unity/scope.h 2016-08-10 07:21:23 +0000 |
279 | @@ -110,7 +110,7 @@ |
280 | public: |
281 | typedef QSharedPointer<Scope> Ptr; |
282 | |
283 | - static Scope::Ptr newInstance(scopes_ng::Scopes* parent); |
284 | + static Scope::Ptr newInstance(scopes_ng::Scopes* parent, bool favorite = false); |
285 | |
286 | virtual ~Scope(); |
287 | |
288 | @@ -205,7 +205,7 @@ |
289 | void previewModelDestroyed(QObject *obj); |
290 | |
291 | protected: |
292 | - explicit Scope(scopes_ng::Scopes* parent); |
293 | + explicit Scope(scopes_ng::Scopes* parent, bool favorite = false); |
294 | |
295 | void setStatus(unity::shell::scopes::ScopeInterface::Status status); |
296 | void invalidateLastSearch(); |
297 | |
298 | === modified file 'src/Unity/scopes.cpp' |
299 | --- src/Unity/scopes.cpp 2016-06-23 12:53:21 +0000 |
300 | +++ src/Unity/scopes.cpp 2016-08-10 07:21:23 +0000 |
301 | @@ -24,6 +24,7 @@ |
302 | #include "scope.h" |
303 | #include "overviewscope.h" |
304 | #include "ubuntulocationservice.h" |
305 | +#include "favorites.h" |
306 | |
307 | // Qt |
308 | #include <QDebug> |
309 | @@ -126,10 +127,8 @@ |
310 | QDBusConnection::sessionBus().connect(QString(), QStringLiteral("/com/canonical/unity/scopes"), QStringLiteral("com.canonical.unity.scopes"), QStringLiteral("InvalidateResults"), this, SLOT(invalidateScopeResults(QString))); |
311 | |
312 | m_dashSettings = QGSettings::isSchemaInstalled("com.canonical.Unity.Dash") ? new QGSettings("com.canonical.Unity.Dash", QByteArray(), this) : nullptr; |
313 | - if (m_dashSettings) |
314 | - { |
315 | - QObject::connect(m_dashSettings, &QGSettings::changed, this, &Scopes::dashSettingsChanged); |
316 | - } |
317 | + m_favoriteScopes = new Favorites(this, m_dashSettings); |
318 | + QObject::connect(m_favoriteScopes, &Favorites::favoritesChanged, this, &Scopes::favoritesChanged); |
319 | |
320 | m_overviewScope = OverviewScope::newInstance(this); |
321 | |
322 | @@ -427,57 +426,41 @@ |
323 | |
324 | void Scopes::processFavoriteScopes() |
325 | { |
326 | + qDebug() << "Scopes::processFavoriteScopes()"; |
327 | + |
328 | if (m_noFavorites) { |
329 | return; |
330 | } |
331 | |
332 | // |
333 | - // read the favoriteScopes array value from gsettings. |
334 | - // process it and turn its values into scope ids. |
335 | // create new Scope objects or remove existing according to the list of favorities. |
336 | // notify about scopes model changes accordingly. |
337 | if (m_dashSettings) { |
338 | - QStringList newFavorites; |
339 | - QMap<QString, int> favScopesLut; |
340 | - for (auto const& fv: m_dashSettings->get(QStringLiteral("favoriteScopes")).toList()) |
341 | + for (auto const& fv: m_favoriteScopes->getFavorites()) |
342 | { |
343 | - int pos = 0; |
344 | - try |
345 | - { |
346 | - auto const query = unity::scopes::CannedQuery::from_uri(fv.toString().toStdString()); |
347 | - const QString id = QString::fromStdString(query.scope_id()); |
348 | - |
349 | - if (m_cachedMetadata.find(id) != m_cachedMetadata.end()) |
350 | - { |
351 | - newFavorites.push_back(id); |
352 | - pos = newFavorites.size() - 1; |
353 | - favScopesLut[id] = pos; |
354 | - } |
355 | - else |
356 | - { |
357 | - // If a scope that was favorited no longer exists, unfavorite it in m_dashSettings |
358 | - setFavorite(id, false); |
359 | - } |
360 | - } |
361 | - catch (const InvalidArgumentException &e) |
362 | - { |
363 | - qWarning() << "Invalid canned query '" << fv.toString() << "'" << QString::fromStdString(e.what()); |
364 | - } |
365 | - } |
366 | - |
367 | - // this prevents further processing if we get called back when calling scope->setFavorite() below |
368 | - if (m_favoriteScopes == newFavorites) |
369 | - return; |
370 | - |
371 | - m_favoriteScopes = newFavorites; |
372 | - |
373 | - QSet<QString> oldScopes; |
374 | + // favorited scope not installed? |
375 | + if (m_cachedMetadata.find(fv) == m_cachedMetadata.end()) |
376 | + { |
377 | + qDebug() << "Favorited scope" << fv << "is no longer available, un-favoriting"; |
378 | + m_favoriteScopes->setFavorite(fv, false); |
379 | + } |
380 | + } |
381 | + |
382 | + // special-case clickscope; append it to favorites if it was uninstalled (and in consequence removed from favorites) - see LP: #1603186 |
383 | + if (m_cachedMetadata.contains(CLICK_SCOPE_ID) && !m_favoriteScopes->hasScope(CLICK_SCOPE_ID)) { |
384 | + qDebug() << "Favoriting" << CLICK_SCOPE_ID; |
385 | + m_favoriteScopes->setFavorite(CLICK_SCOPE_ID, true); |
386 | + } |
387 | + |
388 | + QSet<QString> scopesInTheModel; |
389 | int row = 0; |
390 | // remove un-favorited scopes |
391 | for (auto it = m_scopes.begin(); it != m_scopes.end();) |
392 | { |
393 | - if (!favScopesLut.contains((*it)->id())) |
394 | + if (!m_favoriteScopes->hasScope((*it)->id())) |
395 | { |
396 | + qDebug() << "Scope" << (*it)->id() << "is no longer favorited, removing"; |
397 | + |
398 | beginRemoveRows(QModelIndex(), row, row); |
399 | Scope::Ptr toDelete = *it; |
400 | toDelete->setFavorite(false); |
401 | @@ -490,7 +473,7 @@ |
402 | } |
403 | else |
404 | { |
405 | - oldScopes.insert((*it)->id()); |
406 | + scopesInTheModel.insert((*it)->id()); |
407 | ++it; |
408 | ++row; |
409 | } |
410 | @@ -498,41 +481,35 @@ |
411 | |
412 | // add new favorites |
413 | row = 0; |
414 | - for (auto favIt = m_favoriteScopes.begin(); favIt != m_favoriteScopes.end(); ) |
415 | + for (auto const& fv: m_favoriteScopes->getFavorites()) |
416 | { |
417 | - auto const fav = *favIt; |
418 | - if (!oldScopes.contains(fav)) |
419 | + if (!scopesInTheModel.contains(fv)) |
420 | { |
421 | - auto it = m_cachedMetadata.find(fav); |
422 | + auto it = m_cachedMetadata.find(fv); |
423 | if (it != m_cachedMetadata.end()) |
424 | { |
425 | - Scope::Ptr scope = Scope::newInstance(this); |
426 | + qDebug() << "Scope" << fv << "is favorited, adding to scopes model"; |
427 | + |
428 | + Scope::Ptr scope = Scope::newInstance(this, true); |
429 | connect(scope.data(), SIGNAL(isActiveChanged()), this, SLOT(prepopulateNextScopes())); |
430 | scope->setScopeData(*(it.value())); |
431 | - scope->setFavorite(true); |
432 | beginInsertRows(QModelIndex(), row, row); |
433 | m_scopes.insert(row, scope); |
434 | endInsertRows(); |
435 | } |
436 | - else |
437 | - { |
438 | - qWarning() << "No such scope:" << fav; |
439 | - favIt = m_favoriteScopes.erase(favIt); |
440 | - continue; |
441 | - } |
442 | } |
443 | ++row; |
444 | - ++favIt; |
445 | } |
446 | |
447 | - // iterate over results, move rows if positions changes |
448 | + // iterate over results, move rows if positions changed |
449 | for (int i = 0; i<m_scopes.size(); ) |
450 | { |
451 | auto scope = m_scopes.at(i); |
452 | const QString id = scope->id(); |
453 | - if (favScopesLut.contains(id)) { |
454 | - int pos = favScopesLut[id]; |
455 | + int pos = m_favoriteScopes->position(id); |
456 | + if (pos >= 0) { |
457 | if (pos != i) { |
458 | + qDebug() << "Moving scope" << id << "to row" << pos << "to match position in favorites"; |
459 | beginMoveRows(QModelIndex(), i, i, QModelIndex(), pos + (pos > i ? 1 : 0)); |
460 | m_scopes.move(i, pos); |
461 | endMoveRows(); |
462 | @@ -544,17 +521,13 @@ |
463 | } |
464 | } |
465 | |
466 | -void Scopes::dashSettingsChanged(QString const& key) |
467 | +void Scopes::favoritesChanged() |
468 | { |
469 | - if (key != QLatin1String("favoriteScopes")) { |
470 | - return; |
471 | - } |
472 | - |
473 | processFavoriteScopes(); |
474 | |
475 | if (m_overviewScope) |
476 | { |
477 | - m_overviewScope->updateFavorites(m_favoriteScopes); |
478 | + m_overviewScope->updateFavorites(m_favoriteScopes->getFavorites()); |
479 | } |
480 | } |
481 | |
482 | @@ -675,7 +648,7 @@ |
483 | |
484 | QStringList Scopes::getFavoriteIds() const |
485 | { |
486 | - return m_favoriteScopes; |
487 | + return m_favoriteScopes->getFavorites(); |
488 | } |
489 | |
490 | void Scopes::setFavorite(QString const& scopeId, bool value) |
491 | @@ -685,32 +658,39 @@ |
492 | qWarning() << "Cannot unfavorite" << scopeId; |
493 | return; |
494 | } |
495 | - if (m_dashSettings) |
496 | + |
497 | + int row = m_favoriteScopes->setFavorite(scopeId, value); |
498 | + if (row >= 0) |
499 | { |
500 | - QStringList cannedQueries; |
501 | - bool changed = false; |
502 | - |
503 | - for (auto const& fav: m_favoriteScopes) |
504 | - { |
505 | - if (value == false && fav == scopeId) { |
506 | - changed = true; |
507 | - continue; // skip it |
508 | - } |
509 | - // TODO: use CannedQuery::to_uri() when we really support them |
510 | - const QString query = "scope://" + fav; |
511 | - cannedQueries.push_back(query); |
512 | - } |
513 | - |
514 | - if (value && !m_favoriteScopes.contains(scopeId)) { |
515 | - const QString query = "scope://" + scopeId; |
516 | - cannedQueries.push_back(query); |
517 | - changed = true; |
518 | - } |
519 | - |
520 | - if (changed) { |
521 | - // update gsettings entry |
522 | - // note: this will trigger notification, so that new favorites are processed by processFavoriteScopes |
523 | - m_dashSettings->set(QStringLiteral("favoriteScopes"), QVariant(cannedQueries)); |
524 | + if (value) { |
525 | + auto it = m_cachedMetadata.find(scopeId); |
526 | + if (it != m_cachedMetadata.end()) |
527 | + { |
528 | + Scope::Ptr scope = Scope::newInstance(this, true); |
529 | + connect(scope.data(), SIGNAL(isActiveChanged()), this, SLOT(prepopulateNextScopes())); |
530 | + scope->setScopeData(*(it.value())); |
531 | + beginInsertRows(QModelIndex(), row, row); |
532 | + m_scopes.insert(row, scope); |
533 | + endInsertRows(); |
534 | + } else { |
535 | + qWarning() << "setFavorite: unknown scope" << scopeId; |
536 | + } |
537 | + } else { |
538 | + for (auto it = m_scopes.begin(); it != m_scopes.end(); it++) |
539 | + { |
540 | + if ((*it)->id() == scopeId) { |
541 | + beginRemoveRows(QModelIndex(), row, row); |
542 | + Scope::Ptr toDelete = *it; |
543 | + toDelete->setFavorite(false); |
544 | + // we need to delay actual deletion of Scope object so that shell can animate it |
545 | + m_scopesToDelete.push_back(toDelete); |
546 | + // if the timer is already active, we just wait a bit longer, which is no problem |
547 | + m_scopesToDeleteTimer.start(); |
548 | + it = m_scopes.erase(it); |
549 | + endRemoveRows(); |
550 | + break; |
551 | + } |
552 | + } |
553 | } |
554 | } |
555 | } |
556 | @@ -737,34 +717,12 @@ |
557 | |
558 | void Scopes::moveFavoriteTo(QString const& scopeId, int index) |
559 | { |
560 | - if (m_dashSettings) |
561 | - { |
562 | - QStringList cannedQueries; |
563 | - bool found = false; |
564 | - |
565 | - int i = 0; |
566 | - for (auto const& fav: m_favoriteScopes) |
567 | - { |
568 | - if (fav == scopeId) { |
569 | - if (index == i) |
570 | - return; // same position |
571 | - found = true; |
572 | - } else { |
573 | - const QString query = "scope://" + fav; |
574 | - cannedQueries.push_back(query); |
575 | - } |
576 | - |
577 | - ++i; |
578 | - } |
579 | - |
580 | - if (found) { |
581 | - // insert scopeId at new position |
582 | - const QString query = "scope://" + scopeId; |
583 | - cannedQueries.insert(index, query); |
584 | - // update gsettings entry |
585 | - // note: this will trigger notification, so that new favorites are processed by processFavoriteScopes |
586 | - m_dashSettings->set(QStringLiteral("favoriteScopes"), QVariant(cannedQueries)); |
587 | - } |
588 | + int oldPos = m_favoriteScopes->position(scopeId); |
589 | + if (oldPos != index) { |
590 | + m_favoriteScopes->moveFavoriteTo(scopeId, index); |
591 | + beginMoveRows(QModelIndex(), oldPos, oldPos, QModelIndex(), index + (index > oldPos ? 1 : 0)); |
592 | + m_scopes.move(oldPos, index); |
593 | + endMoveRows(); |
594 | } |
595 | } |
596 | |
597 | |
598 | === modified file 'src/Unity/scopes.h' |
599 | --- src/Unity/scopes.h 2016-06-10 13:41:37 +0000 |
600 | +++ src/Unity/scopes.h 2016-08-10 07:21:23 +0000 |
601 | @@ -47,6 +47,7 @@ |
602 | class UbuntuLocationService; |
603 | class LocationAccessHelper; |
604 | class Scope; |
605 | +class Favorites; |
606 | class OverviewScope; |
607 | |
608 | class Q_DECL_EXPORT Scopes : public unity::shell::scopes::ScopesInterface |
609 | @@ -92,7 +93,7 @@ |
610 | virtual QString readPartnerId(); |
611 | |
612 | private Q_SLOTS: |
613 | - void dashSettingsChanged(QString const &key); |
614 | + void favoritesChanged(); |
615 | void processFavoriteScopes(); |
616 | void populateScopes(); |
617 | void discoveryFinished(); |
618 | @@ -117,7 +118,7 @@ |
619 | QList<QSharedPointer<Scope>> m_scopes; |
620 | QList<QSharedPointer<Scope>> m_scopesToDelete; |
621 | bool m_noFavorites; |
622 | - QStringList m_favoriteScopes; |
623 | + Favorites* m_favoriteScopes; |
624 | QGSettings* m_dashSettings; |
625 | QMap<QString, unity::scopes::ScopeMetadata::SPtr> m_cachedMetadata; |
626 | QSharedPointer<OverviewScope> m_overviewScope; |
Outstanding work Pawel. +1