Merge lp:~unity-team/unity-scopes-shell/sort-order into lp:unity-scopes-shell

Proposed by Michal Hruby
Status: Merged
Approved by: Pete Woods
Approved revision: 153
Merged at revision: 123
Proposed branch: lp:~unity-team/unity-scopes-shell/sort-order
Merge into: lp:unity-scopes-shell
Diff against target: 1749 lines (+780/-169)
24 files modified
debian/changelog (+6/-0)
debian/control (+2/-3)
src/Unity/CMakeLists.txt (+2/-2)
src/Unity/collectors.cpp (+37/-3)
src/Unity/collectors.h (+9/-5)
src/Unity/department.cpp (+28/-13)
src/Unity/department.h (+12/-6)
src/Unity/departmentnode.cpp (+57/-1)
src/Unity/departmentnode.h (+8/-0)
src/Unity/overviewscope.cpp (+0/-5)
src/Unity/overviewscope.h (+0/-1)
src/Unity/plugin.cpp (+1/-1)
src/Unity/scope.cpp (+231/-80)
src/Unity/scope.h (+27/-8)
src/Unity/scopes.cpp (+6/-2)
src/Unity/scopes.h (+1/-0)
tests/data/CMakeLists.txt (+1/-0)
tests/data/mock-scope-double-nav/CMakeLists.txt (+16/-0)
tests/data/mock-scope-double-nav/mock-scope-double-nav.cpp (+214/-0)
tests/data/mock-scope-double-nav/mock-scope-double-nav.ini.in (+8/-0)
tests/departmentstest.cpp (+106/-29)
tests/previewtest.cpp (+3/-3)
tests/resultstest.cpp (+3/-5)
tests/settingsendtoendtest.cpp (+2/-2)
To merge this branch: bzr merge lp:~unity-team/unity-scopes-shell/sort-order
Reviewer Review Type Date Requested Status
Pete Woods (community) Approve
PS Jenkins bot (community) continuous-integration Needs Fixing
Review via email: mp+229190@code.launchpad.net

Commit message

Implemented alt navigation as per shell interface v4.

Description of the change

Implemented alt navigation as per shell interface v4.

To post a comment you must log in.
Revision history for this message
PS Jenkins bot (ps-jenkins) wrote :
review: Needs Fixing (continuous-integration)
145. By Michal Hruby

Drop support for impl-2 and 3, as the interfaces changed

146. By Michal Hruby

Compile with very latest unity-api

Revision history for this message
PS Jenkins bot (ps-jenkins) wrote :
review: Needs Fixing (continuous-integration)
147. By Michal Hruby

Update for the latest interface

Revision history for this message
PS Jenkins bot (ps-jenkins) wrote :
review: Needs Fixing (continuous-integration)
148. By Michal Hruby

Update tests

149. By Michal Hruby

Merge with drop-appid branch

Revision history for this message
PS Jenkins bot (ps-jenkins) wrote :
review: Needs Fixing (continuous-integration)
150. By Michal Hruby

Implement refresh method

Revision history for this message
PS Jenkins bot (ps-jenkins) wrote :
review: Needs Fixing (continuous-integration)
151. By Michal Hruby

Reset filter state on non-empty queries

152. By Michal Hruby

Merge trunk

Revision history for this message
PS Jenkins bot (ps-jenkins) wrote :
review: Needs Fixing (continuous-integration)
Revision history for this message
Pete Woods (pete-woods) wrote :

Conflicts with trunk

153. By Michal Hruby

Merge trunk

Revision history for this message
PS Jenkins bot (ps-jenkins) wrote :
review: Needs Fixing (continuous-integration)
Revision history for this message
Pete Woods (pete-woods) :
review: Needs Information
Revision history for this message
Michal Hruby (mhr3) :
Revision history for this message
Pete Woods (pete-woods) :
review: Approve

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
1=== modified file 'debian/changelog'
2--- debian/changelog 2014-08-05 16:42:48 +0000
3+++ debian/changelog 2014-08-06 08:35:31 +0000
4@@ -1,3 +1,9 @@
5+unity-scopes-shell (0.5.3-0ubuntu1) UNRELEASED; urgency=medium
6+
7+ * Implemented shell interface version 4
8+
9+ -- Michal Hruby <michal.hruby@canonical.com> Fri, 01 Aug 2014 11:08:43 +0100
10+
11 unity-scopes-shell (0.5.2+14.10.20140805.1-0ubuntu1) utopic; urgency=low
12
13 [ Pete Woods ]
14
15=== modified file 'debian/control'
16--- debian/control 2014-08-01 10:25:41 +0000
17+++ debian/control 2014-08-06 08:35:31 +0000
18@@ -3,7 +3,7 @@
19 Section: libs
20 Build-Depends: cmake,
21 debhelper (>= 9),
22- libunity-api-dev (>= 7.87),
23+ libunity-api-dev (>= 7.88),
24 libunity-scopes-dev (>= 0.6.0~),
25 libgsettings-qt-dev (>= 0.1),
26 libqtdbustest1-dev (>= 0.2),
27@@ -34,8 +34,7 @@
28 Provides: unity-scopes-impl,
29 unity-scopes-impl-0,
30 unity-scopes-impl-1,
31- unity-scopes-impl-2,
32- unity-scopes-impl-3,
33+ unity-scopes-impl-4,
34 Breaks: unity8-private (<< 7.84)
35 Replaces: unity8-private (<< 7.84)
36 Description: QML plugin for Scopes
37
38=== modified file 'src/Unity/CMakeLists.txt'
39--- src/Unity/CMakeLists.txt 2014-08-01 10:25:41 +0000
40+++ src/Unity/CMakeLists.txt 2014-08-06 08:35:31 +0000
41@@ -2,7 +2,7 @@
42 include(Plugins)
43
44 # Dependencies
45-pkg_check_modules(SCOPES_API REQUIRED unity-shell-scopes=3)
46+pkg_check_modules(SCOPES_API REQUIRED unity-shell-scopes=4)
47 pkg_check_modules(SCOPESLIB REQUIRED libunity-scopes>=0.6.0)
48 pkg_check_modules(GSETTINGSQT REQUIRED gsettings-qt)
49 pkg_check_modules(U1DB REQUIRED libu1db-qt5)
50@@ -41,7 +41,7 @@
51 # We need these headers here so moc runs and we get the moc-stuff
52 # compiled in, otherwise we miss some symbols
53 ${SCOPES_API_INCLUDEDIR}/unity/shell/scopes/CategoriesInterface.h
54- ${SCOPES_API_INCLUDEDIR}/unity/shell/scopes/DepartmentInterface.h
55+ ${SCOPES_API_INCLUDEDIR}/unity/shell/scopes/NavigationInterface.h
56 ${SCOPES_API_INCLUDEDIR}/unity/shell/scopes/PreviewModelInterface.h
57 ${SCOPES_API_INCLUDEDIR}/unity/shell/scopes/PreviewStackInterface.h
58 ${SCOPES_API_INCLUDEDIR}/unity/shell/scopes/PreviewWidgetModelInterface.h
59
60=== modified file 'src/Unity/collectors.cpp'
61--- src/Unity/collectors.cpp 2014-08-01 10:34:32 +0000
62+++ src/Unity/collectors.cpp 2014-08-06 08:35:31 +0000
63@@ -93,7 +93,19 @@
64 m_rootDepartment = department;
65 }
66
67- Status collect(QList<scopes::CategorisedResult::SPtr>& out_results, scopes::Department::SCPtr& out_rootDepartment)
68+ void setSortOrder(scopes::OptionSelectorFilter::SCPtr const& sortOrder)
69+ {
70+ QMutexLocker locker(&m_mutex);
71+ m_sortOrderFilter = sortOrder;
72+ }
73+
74+ void setFilterState(scopes::FilterState const& state)
75+ {
76+ QMutexLocker locker(&m_mutex);
77+ m_filterState = state;
78+ }
79+
80+ Status collect(QList<scopes::CategorisedResult::SPtr>& out_results, scopes::Department::SCPtr& out_rootDepartment, scopes::OptionSelectorFilter::SCPtr& out_sortOrder, scopes::FilterState& out_filterState)
81 {
82 Status status;
83
84@@ -106,12 +118,17 @@
85 m_results.swap(out_results);
86 out_rootDepartment = m_rootDepartment;
87
88+ out_sortOrder = m_sortOrderFilter;
89+ out_filterState = m_filterState;
90+
91 return status;
92 }
93
94 private:
95 QList<scopes::CategorisedResult::SPtr> m_results;
96 scopes::Department::SCPtr m_rootDepartment;
97+ scopes::OptionSelectorFilter::SCPtr m_sortOrderFilter;
98+ scopes::FilterState m_filterState;
99 };
100
101 class PreviewDataCollector: public CollectorBase
102@@ -222,10 +239,10 @@
103 return m_collector->msecsSinceStart();
104 }
105
106-CollectorBase::Status PushEvent::collectSearchResults(QList<scopes::CategorisedResult::SPtr>& out_results, scopes::Department::SCPtr& rootDepartment)
107+CollectorBase::Status PushEvent::collectSearchResults(QList<scopes::CategorisedResult::SPtr>& out_results, scopes::Department::SCPtr& rootDepartment, scopes::OptionSelectorFilter::SCPtr& sortOrder, scopes::FilterState& filterState)
108 {
109 auto collector = std::dynamic_pointer_cast<SearchDataCollector>(m_collector);
110- return collector->collect(out_results, rootDepartment);
111+ return collector->collect(out_results, rootDepartment, sortOrder, filterState);
112 }
113
114 CollectorBase::Status PushEvent::collectPreviewData(scopes::ColumnLayoutList& out_columns, scopes::PreviewWidgetList& out_widgets, QHash<QString, QVariant>& out_data)
115@@ -287,6 +304,23 @@
116 m_collector->setDepartment(department);
117 }
118
119+void SearchResultReceiver::push(scopes::Filters const& filters, scopes::FilterState const& state)
120+{
121+ for (auto it = filters.begin(); it != filters.end(); ++it) {
122+ scopes::FilterBase::SCPtr filter = *it;
123+ if (filter->display_hints() == scopes::FilterBase::DisplayHints::Primary) {
124+ scopes::OptionSelectorFilter::SCPtr option_filter = std::dynamic_pointer_cast<const scopes::OptionSelectorFilter>(filter);
125+ if (!option_filter) {
126+ continue;
127+ } else {
128+ m_collector->setSortOrder(option_filter);
129+ break;
130+ }
131+ }
132+ }
133+ m_collector->setFilterState(state);
134+}
135+
136 // this might be called from any thread (might be main, might be any other thread)
137 void SearchResultReceiver::finished(scopes::CompletionDetails const& details)
138 {
139
140=== modified file 'src/Unity/collectors.h'
141--- src/Unity/collectors.h 2014-08-01 10:34:32 +0000
142+++ src/Unity/collectors.h 2014-08-06 08:35:31 +0000
143@@ -27,12 +27,15 @@
144 #include <QElapsedTimer>
145
146 #include <unity/scopes/ActivationListenerBase.h>
147-#include <unity/scopes/SearchListenerBase.h>
148+#include <unity/scopes/ActivationResponse.h>
149+#include <unity/scopes/CategorisedResult.h>
150+#include <unity/scopes/FilterBase.h>
151+#include <unity/scopes/FilterState.h>
152+#include <unity/scopes/OptionSelectorFilter.h>
153 #include <unity/scopes/PreviewListenerBase.h>
154-#include <unity/scopes/CategorisedResult.h>
155+#include <unity/scopes/PreviewWidget.h>
156 #include <unity/scopes/QueryCtrl.h>
157-#include <unity/scopes/PreviewWidget.h>
158-#include <unity/scopes/ActivationResponse.h>
159+#include <unity/scopes/SearchListenerBase.h>
160
161 namespace scopes_ng
162 {
163@@ -73,7 +76,7 @@
164 PushEvent(Type event_type, std::shared_ptr<CollectorBase> collector);
165 Type type();
166
167- CollectorBase::Status collectSearchResults(QList<std::shared_ptr<unity::scopes::CategorisedResult>>& out_results, unity::scopes::Department::SCPtr& out_rootDepartment);
168+ CollectorBase::Status collectSearchResults(QList<std::shared_ptr<unity::scopes::CategorisedResult>>& out_results, unity::scopes::Department::SCPtr& out_rootDepartment, unity::scopes::OptionSelectorFilter::SCPtr& out_sortOrder, unity::scopes::FilterState& out_filterState);
169 CollectorBase::Status collectPreviewData(unity::scopes::ColumnLayoutList& out_columns, unity::scopes::PreviewWidgetList& out_widgets, QHash<QString, QVariant>& out_data);
170 CollectorBase::Status collectActivationResponse(std::shared_ptr<unity::scopes::ActivationResponse>& out_response, std::shared_ptr<unity::scopes::Result>& out_result);
171
172@@ -105,6 +108,7 @@
173 public:
174 virtual void push(unity::scopes::CategorisedResult result) override;
175 virtual void push(unity::scopes::Department::SCPtr const& department) override;
176+ virtual void push(unity::scopes::Filters const& filters, unity::scopes::FilterState const& state) override;
177 virtual void finished(unity::scopes::CompletionDetails const& details) override;
178
179 SearchResultReceiver(QObject* receiver);
180
181=== modified file 'src/Unity/department.cpp'
182--- src/Unity/department.cpp 2014-06-12 11:34:44 +0000
183+++ src/Unity/department.cpp 2014-08-06 08:35:31 +0000
184@@ -19,16 +19,22 @@
185
186 #include "department.h"
187
188+#include <unity/scopes/OptionSelectorFilter.h>
189+
190 namespace scopes_ng
191 {
192
193 using namespace unity;
194
195 Department::Department(QObject* parent) :
196- unity::shell::scopes::DepartmentInterface(parent),
197- m_loaded(false),
198- m_isRoot(false)
199-{
200+ unity::shell::scopes::NavigationInterface(parent),
201+ m_loaded(false), m_isRoot(false), m_hidden(false), m_isFilter(false)
202+{
203+}
204+
205+void Department::setScopeId(QString const& scopeId)
206+{
207+ m_scopeId = scopeId;
208 }
209
210 void Department::loadFromDepartmentNode(DepartmentNode* treeNode)
211@@ -37,14 +43,17 @@
212 qWarning("Tried to set null DepartmentNode!");
213 return;
214 }
215- m_departmentId = treeNode->id();
216+ m_navigationId = treeNode->id();
217+ m_filterId = treeNode->filterId();
218 m_label = treeNode->label();
219 m_allLabel = treeNode->allLabel();
220 m_loaded = !treeNode->isLeaf() && treeNode->childCount() > 0;
221 m_isRoot = treeNode->isRoot();
222+ m_hidden = treeNode->hidden();
223+ m_isFilter = treeNode->isFilter();
224
225 DepartmentNode* parentNode = treeNode->parent();
226- m_parentDepartmentId = parentNode ? parentNode->id() : "";
227+ m_parentNavigationId = parentNode ? parentNode->id() : "";
228 m_parentLabel = parentNode ? parentNode->label() : "";
229
230 beginResetModel();
231@@ -61,14 +70,15 @@
232
233 endResetModel();
234
235- Q_EMIT departmentIdChanged();
236+ Q_EMIT navigationIdChanged();
237 Q_EMIT labelChanged();
238 Q_EMIT allLabelChanged();
239- Q_EMIT parentDepartmentIdChanged();
240+ Q_EMIT parentNavigationIdChanged();
241 Q_EMIT parentLabelChanged();
242 Q_EMIT loadedChanged();
243 Q_EMIT countChanged();
244 Q_EMIT isRootChanged();
245+ Q_EMIT hiddenChanged();
246 }
247
248 void Department::markSubdepartmentActive(QString const& subdepartmentId)
249@@ -100,7 +110,7 @@
250 {
251 SubdepartmentData* data = m_subdepartments[index.row()].data();
252 switch (role) {
253- case RoleDepartmentId: return data->id;
254+ case RoleNavigationId: return data->id;
255 case RoleLabel: return data->label;
256 case RoleHasChildren: return data->hasChildren;
257 case RoleIsActive: return data->isActive;
258@@ -114,9 +124,9 @@
259 return m_subdepartments.size();
260 }
261
262-QString Department::departmentId() const
263+QString Department::navigationId() const
264 {
265- return m_departmentId;
266+ return m_navigationId;
267 }
268
269 QString Department::label() const
270@@ -129,9 +139,9 @@
271 return m_allLabel;
272 }
273
274-QString Department::parentDepartmentId() const
275+QString Department::parentNavigationId() const
276 {
277- return m_parentDepartmentId;
278+ return m_parentNavigationId;
279 }
280
281 QString Department::parentLabel() const
282@@ -149,6 +159,11 @@
283 return m_isRoot;
284 }
285
286+bool Department::hidden() const
287+{
288+ return m_hidden;
289+}
290+
291 int Department::count() const
292 {
293 return rowCount();
294
295=== modified file 'src/Unity/department.h'
296--- src/Unity/department.h 2014-06-12 11:34:44 +0000
297+++ src/Unity/department.h 2014-08-06 08:35:31 +0000
298@@ -21,7 +21,7 @@
299 #ifndef NG_DEPARTMENT_H
300 #define NG_DEPARTMENT_H
301
302-#include <unity/shell/scopes/DepartmentInterface.h>
303+#include <unity/shell/scopes/NavigationInterface.h>
304
305 #include <QString>
306 #include <QSharedPointer>
307@@ -44,37 +44,43 @@
308 bool isActive;
309 };
310
311-class Q_DECL_EXPORT Department : public unity::shell::scopes::DepartmentInterface
312+class Q_DECL_EXPORT Department : public unity::shell::scopes::NavigationInterface
313 {
314 Q_OBJECT
315
316 public:
317 explicit Department(QObject* parent = 0);
318+ void setScopeId(QString const& scopeId);
319 void loadFromDepartmentNode(DepartmentNode* treeNode);
320 void markSubdepartmentActive(QString const& subdepartmentId);
321
322 QVariant data(const QModelIndex& index, int role = Qt::DisplayRole) const override;
323 int rowCount(const QModelIndex& parent = QModelIndex()) const override;
324
325- QString departmentId() const override;
326+ QString navigationId() const override;
327 QString label() const override;
328 QString allLabel() const override;
329- QString parentDepartmentId() const override;
330+ QString parentNavigationId() const override;
331 QString parentLabel() const override;
332 bool loaded() const override;
333 bool isRoot() const override;
334+ bool hidden() const override;
335 int count() const override;
336
337 Q_SIGNALS:
338
339 private:
340- QString m_departmentId;
341+ QString m_navigationId;
342+ QString m_scopeId;
343+ QString m_filterId;
344 QString m_label;
345 QString m_allLabel;
346- QString m_parentDepartmentId;
347+ QString m_parentNavigationId;
348 QString m_parentLabel;
349 bool m_loaded;
350 bool m_isRoot;
351+ bool m_hidden;
352+ bool m_isFilter;
353
354 QList<QSharedPointer<SubdepartmentData>> m_subdepartments;
355 };
356
357=== modified file 'src/Unity/departmentnode.cpp'
358--- src/Unity/departmentnode.cpp 2014-05-28 07:04:50 +0000
359+++ src/Unity/departmentnode.cpp 2014-08-06 08:35:31 +0000
360@@ -24,7 +24,11 @@
361
362 using namespace unity;
363
364-DepartmentNode::DepartmentNode(DepartmentNode* parent) : m_parent(parent), m_isRoot(false)
365+DepartmentNode::DepartmentNode(DepartmentNode* parent)
366+ : m_parent(parent)
367+ , m_isRoot(false)
368+ , m_hidden(false)
369+ , m_isFilter(false)
370 {
371 }
372
373@@ -39,6 +43,8 @@
374 m_label = QString::fromStdString(dep->label());
375 m_allLabel = QString::fromStdString(dep->alternate_label());
376 m_hasSubdepartments = dep->has_subdepartments();
377+ m_hidden = false;
378+ m_isFilter = false;
379
380 clearChildren();
381
382@@ -50,6 +56,41 @@
383 }
384 }
385
386+void DepartmentNode::initializeForFilter(scopes::OptionSelectorFilter::SCPtr const& filter)
387+{
388+ auto children = filter->options();
389+ m_id = QString(""); // this is root (which we shouldn't show really)
390+ m_filterId = QString::fromStdString(filter->id());
391+ m_label = QString::fromStdString(filter->label());
392+ m_allLabel = QString();
393+ m_hasSubdepartments = !children.empty();
394+ m_isRoot = true;
395+ m_hidden = true;
396+ m_isFilter = true;
397+
398+ clearChildren();
399+
400+ for (auto it = children.begin(); it != children.end(); ++it) {
401+ DepartmentNode* subdep = new DepartmentNode(this);
402+ subdep->initializeForFilterOption(*it, m_filterId);
403+ this->appendChild(subdep);
404+ }
405+}
406+
407+void DepartmentNode::initializeForFilterOption(scopes::FilterOption::SCPtr const& option, QString const& filterId)
408+{
409+ m_id = QString::fromStdString(option->id());
410+ m_filterId = filterId;
411+ m_label = QString::fromStdString(option->label());
412+ m_allLabel = QString();
413+ m_hasSubdepartments = false;
414+ m_isRoot = false;
415+ m_hidden = false;
416+ m_isFilter = true;
417+
418+ clearChildren();
419+}
420+
421 void DepartmentNode::setIsRoot(bool isRoot)
422 {
423 m_isRoot = isRoot;
424@@ -60,6 +101,16 @@
425 return m_isRoot;
426 }
427
428+bool DepartmentNode::hidden() const
429+{
430+ return m_hidden;
431+}
432+
433+bool DepartmentNode::isFilter() const
434+{
435+ return m_isFilter;
436+}
437+
438 DepartmentNode* DepartmentNode::findNodeById(QString const& id)
439 {
440 if (id == m_id) return this;
441@@ -87,6 +138,11 @@
442 return m_allLabel;
443 }
444
445+QString DepartmentNode::filterId() const
446+{
447+ return m_filterId;
448+}
449+
450 bool DepartmentNode::hasSubdepartments() const
451 {
452 return m_hasSubdepartments;
453
454=== modified file 'src/Unity/departmentnode.h'
455--- src/Unity/departmentnode.h 2014-05-28 07:04:50 +0000
456+++ src/Unity/departmentnode.h 2014-08-06 08:35:31 +0000
457@@ -38,6 +38,7 @@
458 ~DepartmentNode();
459
460 void initializeForDepartment(unity::scopes::Department::SCPtr const& dep);
461+ void initializeForFilter(unity::scopes::OptionSelectorFilter::SCPtr const& filter);
462 DepartmentNode* findNodeById(QString const& id);
463
464 QString id() const;
465@@ -45,6 +46,8 @@
466 QString allLabel() const;
467 bool hasSubdepartments() const;
468 bool isRoot() const;
469+ bool hidden() const;
470+ bool isFilter() const;
471
472 void setIsRoot(bool isRoot);
473
474@@ -53,17 +56,22 @@
475 bool isLeaf() const;
476 QList<DepartmentNode*> childNodes() const;
477 DepartmentNode* parent() const;
478+ QString filterId() const;
479
480 private:
481 void clearChildren();
482+ void initializeForFilterOption(unity::scopes::FilterOption::SCPtr const&, QString const&);
483
484 DepartmentNode* m_parent;
485 QList<DepartmentNode*> m_children;
486 QString m_id;
487 QString m_label;
488 QString m_allLabel;
489+ QString m_filterId;
490 bool m_hasSubdepartments;
491 bool m_isRoot;
492+ bool m_hidden;
493+ bool m_isFilter;
494 };
495
496 } // namespace scopes_ng
497
498=== modified file 'src/Unity/overviewscope.cpp'
499--- src/Unity/overviewscope.cpp 2014-07-23 12:32:48 +0000
500+++ src/Unity/overviewscope.cpp 2014-08-06 08:35:31 +0000
501@@ -96,11 +96,6 @@
502 return QString("scopes");
503 }
504
505-bool OverviewScope::visible() const
506-{
507- return false;
508-}
509-
510 scopes::ScopeProxy OverviewScope::proxy_for_result(scopes::Result::SPtr const& result) const
511 {
512 try {
513
514=== modified file 'src/Unity/overviewscope.h'
515--- src/Unity/overviewscope.h 2014-07-18 17:10:39 +0000
516+++ src/Unity/overviewscope.h 2014-08-06 08:35:31 +0000
517@@ -35,7 +35,6 @@
518
519 /* getters */
520 QString id() const override;
521- bool visible() const override;
522
523 void dispatchSearch() override;
524
525
526=== modified file 'src/Unity/plugin.cpp'
527--- src/Unity/plugin.cpp 2014-06-11 17:08:34 +0000
528+++ src/Unity/plugin.cpp 2014-08-06 08:35:31 +0000
529@@ -41,7 +41,7 @@
530 // new Scopes classes
531 qmlRegisterType<scopes_ng::Scopes>(uri, 0, 2, "Scopes");
532 qmlRegisterUncreatableType<unity::shell::scopes::ScopeInterface>(uri, 0, 2, "Scope", "Can't create Scope object in QML. Get them from Scopes instance.");
533- qmlRegisterUncreatableType<unity::shell::scopes::DepartmentInterface>(uri, 0, 2, "Department", "Can't create Department object in QML. Get them from Scope instance.");
534+ qmlRegisterUncreatableType<unity::shell::scopes::NavigationInterface>(uri, 0, 2, "Navigation", "Can't create Navigation object in QML. Get them from Scope instance.");
535 qmlRegisterUncreatableType<unity::shell::scopes::CategoriesInterface>(uri, 0, 2, "Categories", "Can't create Categories object in QML. Get them from Scope instance.");
536 qmlRegisterUncreatableType<unity::shell::scopes::SettingsModelInterface>(uri, 0, 2, "Settings", "Can't create Settings object in QML. Get them from Scope instance.");
537 qmlRegisterUncreatableType<scopes_ng::ResultsModel>(uri, 0, 2, "ResultsModel", "Can't create new ResultsModel in QML. Get them from Categories instance.");
538
539=== modified file 'src/Unity/scope.cpp'
540--- src/Unity/scope.cpp 2014-08-05 16:24:32 +0000
541+++ src/Unity/scope.cpp 2014-08-06 08:35:31 +0000
542@@ -47,6 +47,8 @@
543 #include <libintl.h>
544
545 #include <unity/scopes/ListenerBase.h>
546+#include <unity/scopes/CannedQuery.h>
547+#include <unity/scopes/OptionSelectorFilter.h>
548 #include <unity/scopes/CategorisedResult.h>
549 #include <unity/scopes/QueryCtrl.h>
550 #include <unity/scopes/PreviewWidget.h>
551@@ -70,9 +72,11 @@
552 , m_searchInProgress(false)
553 , m_resultsDirty(false)
554 , m_delayedClear(false)
555- , m_hasDepartments(false)
556+ , m_hasNavigation(false)
557+ , m_hasAltNavigation(false)
558 , m_searchController(new CollectionController)
559 , m_activationController(new CollectionController)
560+ , m_status(Status::Okay)
561 {
562 m_categories.reset(new Categories(this));
563
564@@ -99,13 +103,17 @@
565 CollectorBase::Status status;
566 QList<std::shared_ptr<scopes::CategorisedResult>> results;
567 scopes::Department::SCPtr rootDepartment;
568+ scopes::OptionSelectorFilter::SCPtr sortOrderFilter;
569+ scopes::FilterState filterState;
570
571- status = pushEvent->collectSearchResults(results, rootDepartment);
572+ status = pushEvent->collectSearchResults(results, rootDepartment, sortOrderFilter, filterState);
573 if (status == CollectorBase::Status::CANCELLED) {
574 return;
575 }
576
577 m_rootDepartment = rootDepartment;
578+ m_sortOrderFilter = sortOrderFilter;
579+ m_receivedFilterState = filterState;
580
581 if (m_cachedResults.empty()) {
582 m_cachedResults.swap(results);
583@@ -126,6 +134,7 @@
584 flushUpdates();
585
586 setSearchInProgress(false);
587+ setStatus(status == CollectorBase::Status::FINISHED ? Status::Okay : Status::Unknown);
588
589 // Don't schedule a refresh if the query suffered an error
590 if (status == CollectorBase::Status::FINISHED) {
591@@ -226,9 +235,13 @@
592 }
593
594 if (scope != nullptr) {
595- // TODO: change filters?
596- scope->setCurrentDepartmentId(departmentId);
597+ scope->setCurrentNavigationId(departmentId);
598+ scope->setFilterState(query.filter_state());
599 scope->setSearchQuery(searchString);
600+ // FIXME: implement better way to do multiple changes to search props and dispatch single search
601+ if (!scope->searchInProgress()) {
602+ scope->invalidateResults();
603+ }
604 if (scope != this) Q_EMIT gotoScope(scopeId);
605 } else {
606 // create temp dash page
607@@ -237,7 +250,8 @@
608 scope = new scopes_ng::Scope(this);
609 scope->setScopeData(*meta_sptr);
610 scope->setScopesInstance(m_scopesInstance);
611- scope->setCurrentDepartmentId(departmentId);
612+ scope->setCurrentNavigationId(departmentId);
613+ scope->setFilterState(query.filter_state());
614 scope->setSearchQuery(searchString);
615 m_tempScopes.insert(scope);
616 Q_EMIT openScope(scope);
617@@ -263,6 +277,9 @@
618 m_clearTimer.stop();
619 }
620
621+ if (m_status != Status::Okay) {
622+ setStatus(Status::Okay);
623+ }
624 processResultSet(m_cachedResults); // clears the result list
625
626 // process departments
627@@ -289,25 +306,7 @@
628 m_departmentTree->setIsRoot(true);
629
630 // update corresponding models
631- QString activeDepartment(m_currentDepartmentId);
632- node = m_departmentTree->findNodeById(activeDepartment);
633- DepartmentNode* parentNode = nullptr;
634- if (node != nullptr) {
635- auto it = m_departmentModels.find(activeDepartment);
636- while (it != m_departmentModels.end() && it.key() == activeDepartment) {
637- it.value()->loadFromDepartmentNode(node);
638- ++it;
639- }
640- // if this node is a leaf, we need to update models for the parent
641- parentNode = node->isLeaf() ? node->parent() : nullptr;
642- }
643- if (parentNode != nullptr) {
644- auto it = m_departmentModels.find(parentNode->id());
645- while (it != m_departmentModels.end() && it.key() == parentNode->id()) {
646- it.value()->markSubdepartmentActive(activeDepartment);
647- ++it;
648- }
649- }
650+ updateNavigationModels(m_departmentTree.data(), m_departmentModels, m_currentNavigationId);
651 } else {
652 m_departmentTree.reset(new DepartmentNode);
653 m_departmentTree->initializeForDepartment(m_rootDepartment);
654@@ -320,17 +319,80 @@
655 m_lastRootDepartment = m_rootDepartment;
656
657 bool containsDepartments = m_rootDepartment.get() != nullptr;
658- // design decision - no departments when doing searches
659+ // design decision - no navigation when doing searches
660 containsDepartments &= m_searchQuery.isEmpty();
661
662- if (containsDepartments != m_hasDepartments) {
663- m_hasDepartments = containsDepartments;
664- Q_EMIT hasDepartmentsChanged();
665- }
666-
667- if (!containsDepartments && !m_currentDepartmentId.isEmpty()) {
668- m_currentDepartmentId = "";
669- Q_EMIT currentDepartmentIdChanged();
670+ if (containsDepartments != m_hasNavigation) {
671+ m_hasNavigation = containsDepartments;
672+ Q_EMIT hasNavigationChanged();
673+ }
674+
675+ if (!containsDepartments && !m_currentNavigationId.isEmpty()) {
676+ m_currentNavigationId = "";
677+ Q_EMIT currentNavigationIdChanged();
678+ }
679+
680+ // process the alt navigation (sort order filter)
681+ QString currentAltNav(m_currentAltNavigationId);
682+
683+ if (m_sortOrderFilter && m_sortOrderFilter != m_lastSortOrderFilter) {
684+ // build the nodes
685+ m_altNavTree.reset(new DepartmentNode);
686+ m_altNavTree->initializeForFilter(m_sortOrderFilter);
687+
688+ if (m_sortOrderFilter->has_active_option(m_receivedFilterState)) {
689+ auto active_options = m_sortOrderFilter->active_options(m_receivedFilterState);
690+ scopes::FilterOption::SCPtr active_option = *active_options.begin();
691+ if (active_option) {
692+ currentAltNav = QString::fromStdString(active_option->id());
693+ }
694+ }
695+ }
696+
697+ m_lastSortOrderFilter = m_sortOrderFilter;
698+
699+ bool containsAltNav = m_sortOrderFilter.get() != nullptr;
700+ // design decision - no navigation when doing searches
701+ containsAltNav &= m_searchQuery.isEmpty();
702+
703+ if (containsAltNav != m_hasAltNavigation) {
704+ m_hasAltNavigation = containsAltNav;
705+ Q_EMIT hasAltNavigationChanged();
706+ }
707+
708+ if (!containsAltNav && !m_currentAltNavigationId.isEmpty()) {
709+ m_currentAltNavigationId = "";
710+ Q_EMIT currentAltNavigationIdChanged();
711+ }
712+
713+ if (containsAltNav && currentAltNav != m_currentAltNavigationId) {
714+ m_currentAltNavigationId = currentAltNav;
715+ Q_EMIT currentAltNavigationIdChanged();
716+
717+ // update the alt navigation models
718+ updateNavigationModels(m_altNavTree.data(), m_altNavModels, m_currentAltNavigationId);
719+ }
720+}
721+
722+void Scope::updateNavigationModels(DepartmentNode* rootNode, QMultiMap<QString, Department*>& navigationModels, QString const& activeNavigation)
723+{
724+ DepartmentNode* parentNode = nullptr;
725+ DepartmentNode* node = rootNode->findNodeById(activeNavigation);
726+ if (node != nullptr) {
727+ auto it = navigationModels.find(activeNavigation);
728+ while (it != navigationModels.end() && it.key() == activeNavigation) {
729+ it.value()->loadFromDepartmentNode(node);
730+ ++it;
731+ }
732+ // if this node is a leaf, we need to update models for the parent
733+ parentNode = node->isLeaf() ? node->parent() : nullptr;
734+ }
735+ if (parentNode != nullptr) {
736+ auto it = navigationModels.find(parentNode->id());
737+ while (it != navigationModels.end() && it.key() == parentNode->id()) {
738+ it.value()->markSubdepartmentActive(activeNavigation);
739+ ++it;
740+ }
741 }
742 }
743
744@@ -494,12 +556,25 @@
745 }
746 }
747
748-void Scope::setCurrentDepartmentId(QString const& id)
749-{
750- if (m_currentDepartmentId != id) {
751- m_currentDepartmentId = id;
752- Q_EMIT currentDepartmentIdChanged();
753- }
754+void Scope::setStatus(shell::scopes::ScopeInterface::Status status)
755+{
756+ if (m_status != status) {
757+ m_status = status;
758+ Q_EMIT statusChanged();
759+ }
760+}
761+
762+void Scope::setCurrentNavigationId(QString const& id)
763+{
764+ if (m_currentNavigationId != id) {
765+ m_currentNavigationId = id;
766+ Q_EMIT currentNavigationIdChanged();
767+ }
768+}
769+
770+void Scope::setFilterState(scopes::FilterState const& filterState)
771+{
772+ m_filterState = filterState;
773 }
774
775 void Scope::dispatchSearch()
776@@ -554,7 +629,7 @@
777 scopes::SearchListenerBase::SPtr listener(new SearchResultReceiver(this));
778 m_searchController->setListener(listener);
779 try {
780- scopes::QueryCtrlProxy controller = m_proxy->search(m_searchQuery.toStdString(), m_currentDepartmentId.toStdString(), scopes::FilterState(), meta, listener);
781+ scopes::QueryCtrlProxy controller = m_proxy->search(m_searchQuery.toStdString(), m_currentNavigationId.toStdString(), m_filterState, meta, listener);
782 m_searchController->setController(controller);
783 } catch (std::exception& e) {
784 qWarning("Caught an error from create_query(): %s", e.what());
785@@ -652,9 +727,13 @@
786 return m_searchInProgress;
787 }
788
789-bool Scope::visible() const
790-{
791- // FIXME: get from scope config
792+unity::shell::scopes::ScopeInterface::Status Scope::status() const
793+{
794+ return m_status;
795+}
796+
797+bool Scope::favorite() const
798+{
799 return true;
800 }
801
802@@ -689,42 +768,86 @@
803 }
804 */
805
806-unity::shell::scopes::DepartmentInterface* Scope::getDepartment(QString const& departmentId)
807+unity::shell::scopes::NavigationInterface* Scope::getNavigation(QString const& navId)
808 {
809 if (!m_departmentTree) return nullptr;
810
811- DepartmentNode* node = m_departmentTree->findNodeById(departmentId);
812- if (!node) return nullptr;
813-
814- Department* departmentModel = new Department;
815- departmentModel->loadFromDepartmentNode(node);
816-
817- m_departmentModels.insert(departmentId, departmentModel);
818- m_inverseDepartments.insert(departmentModel, departmentId);
819- QObject::connect(departmentModel, &QObject::destroyed, this, &Scope::departmentModelDestroyed);
820-
821- return departmentModel;
822+ DepartmentNode* node = m_departmentTree->findNodeById(navId);
823+ if (!node) return nullptr;
824+
825+ Department* navModel = new Department;
826+ navModel->setScopeId(this->id());
827+ navModel->loadFromDepartmentNode(node);
828+ navModel->markSubdepartmentActive(m_currentNavigationId);
829+
830+ // sharing m_inverseDepartments with getAltNavigation
831+ m_departmentModels.insert(navId, navModel);
832+ m_inverseDepartments.insert(navModel, navId);
833+ QObject::connect(navModel, &QObject::destroyed, this, &Scope::departmentModelDestroyed);
834+
835+ return navModel;
836+}
837+
838+unity::shell::scopes::NavigationInterface* Scope::getAltNavigation(QString const& navId)
839+{
840+ if (!m_altNavTree) return nullptr;
841+
842+ DepartmentNode* node = m_altNavTree->findNodeById(navId);
843+ if (!node) return nullptr;
844+
845+ Department* navModel = new Department;
846+ navModel->setScopeId(this->id());
847+ navModel->loadFromDepartmentNode(node);
848+ navModel->markSubdepartmentActive(m_currentAltNavigationId);
849+
850+ // sharing m_inverseDepartments with getNavigation
851+ m_altNavModels.insert(navId, navModel);
852+ m_inverseDepartments.insert(navModel, navId);
853+ QObject::connect(navModel, &QObject::destroyed, this, &Scope::departmentModelDestroyed);
854+
855+ return navModel;
856+}
857+
858+QString Scope::buildQuery(QString const& scopeId, QString const& searchQuery, QString const& departmentId, QString const& primaryFilterId, QString const& primaryOptionId)
859+{
860+ scopes::CannedQuery q(scopeId.toStdString());
861+ q.set_query_string(searchQuery.toStdString());
862+ q.set_department_id(departmentId.toStdString());
863+
864+ if (!primaryFilterId.isEmpty() && !primaryOptionId.isEmpty()) {
865+ scopes::FilterState filter_state;
866+ scopes::OptionSelectorFilter::update_state(filter_state, primaryFilterId.toStdString(), primaryOptionId.toStdString(), true);
867+ q.set_filter_state(filter_state);
868+ }
869+
870+ return QString::fromStdString(q.to_uri());
871+}
872+
873+void Scope::setNavigationState(QString const& navId, bool altNavigation)
874+{
875+ QString primaryFilterId;
876+ if (m_sortOrderFilter) {
877+ primaryFilterId = QString::fromStdString(m_sortOrderFilter->id());
878+ }
879+ if (!altNavigation) {
880+ // switch current department id
881+ performQuery(buildQuery(id(), m_searchQuery, navId, primaryFilterId, m_currentAltNavigationId));
882+ } else {
883+ // switch current primary filter
884+ performQuery(buildQuery(id(), m_searchQuery, m_currentNavigationId, primaryFilterId, navId));
885+ }
886 }
887
888 void Scope::departmentModelDestroyed(QObject* obj)
889 {
890- scopes_ng::Department* department = reinterpret_cast<scopes_ng::Department*>(obj);
891-
892- auto it = m_inverseDepartments.find(department);
893- if (it == m_inverseDepartments.end()) return;
894-
895- m_departmentModels.remove(it.value(), department);
896- m_inverseDepartments.erase(it);
897-}
898-
899-void Scope::loadDepartment(QString const& departmentId)
900-{
901- if (departmentId != m_currentDepartmentId) {
902- m_currentDepartmentId = departmentId;
903- Q_EMIT currentDepartmentIdChanged();
904-
905- dispatchSearch();
906- }
907+ scopes_ng::Department* navigation = reinterpret_cast<scopes_ng::Department*>(obj);
908+
909+ auto it = m_inverseDepartments.find(navigation);
910+ if (it == m_inverseDepartments.end()) return;
911+
912+ m_departmentModels.remove(it.value(), navigation);
913+ m_altNavModels.remove(it.value(), navigation);
914+ m_inverseDepartments.erase(it);
915 }
916
917 void Scope::performQuery(QString const& cannedQuery)
918@@ -737,6 +860,12 @@
919 }
920 }
921
922+void Scope::refresh()
923+{
924+ // shell has to specifically call this, maybe we should ignore the active flag here and just call dispatchSearch
925+ invalidateResults();
926+}
927+
928 QString Scope::searchQuery() const
929 {
930 return m_searchQuery;
931@@ -757,14 +886,24 @@
932 return m_isActive;
933 }
934
935-QString Scope::currentDepartmentId() const
936-{
937- return m_currentDepartmentId;
938-}
939-
940-bool Scope::hasDepartments() const
941-{
942- return m_hasDepartments;
943+QString Scope::currentNavigationId() const
944+{
945+ return m_currentNavigationId;
946+}
947+
948+bool Scope::hasNavigation() const
949+{
950+ return m_hasNavigation;
951+}
952+
953+QString Scope::currentAltNavigationId() const
954+{
955+ return m_currentAltNavigationId;
956+}
957+
958+bool Scope::hasAltNavigation() const
959+{
960+ return m_hasAltNavigation;
961 }
962
963 QVariantMap Scope::customizations() const
964@@ -783,6 +922,11 @@
965 if (m_searchQuery.isNull() || search_query != m_searchQuery) {
966 m_searchQuery = search_query;
967
968+ // atm only empty query can have a filter state
969+ if (!m_searchQuery.isEmpty()) {
970+ m_filterState = scopes::FilterState();
971+ }
972+
973 // FIXME: use a timeout
974 invalidateResults();
975
976@@ -828,6 +972,13 @@
977 }
978 }
979
980+void Scope::setFavorite(const bool value)
981+{
982+ Q_UNUSED(value);
983+
984+ qWarning("Unimplemented: %s", __func__);
985+}
986+
987 void Scope::activate(QVariant const& result_var)
988 {
989 if (!result_var.canConvert<std::shared_ptr<scopes::Result>>()) {
990
991=== modified file 'src/Unity/scope.h'
992--- src/Unity/scope.h 2014-07-31 11:08:50 +0000
993+++ src/Unity/scope.h 2014-08-06 08:35:31 +0000
994@@ -116,17 +116,20 @@
995 QString iconHint() const override;
996 QString description() const override;
997 QString searchHint() const override;
998- bool visible() const override;
999+ bool favorite() const override;
1000 QString shortcut() const override;
1001 bool searchInProgress() const override;
1002+ unity::shell::scopes::ScopeInterface::Status status() const override;
1003 unity::shell::scopes::CategoriesInterface* categories() const override;
1004 unity::shell::scopes::SettingsModelInterface* settings() const override;
1005 QString searchQuery() const override;
1006 QString noResultsHint() const override;
1007 QString formFactor() const override;
1008 bool isActive() const override;
1009- QString currentDepartmentId() const override;
1010- bool hasDepartments() const override;
1011+ QString currentNavigationId() const override;
1012+ bool hasNavigation() const override;
1013+ QString currentAltNavigationId() const override;
1014+ bool hasAltNavigation() const override;
1015 QVariantMap customizations() const override;
1016
1017 /* setters */
1018@@ -134,14 +137,17 @@
1019 void setNoResultsHint(const QString& hint) override;
1020 void setFormFactor(const QString& form_factor) override;
1021 void setActive(const bool) override;
1022+ void setFavorite(const bool) override;
1023
1024 Q_INVOKABLE void activate(QVariant const& result) override;
1025 Q_INVOKABLE unity::shell::scopes::PreviewStackInterface* preview(QVariant const& result) override;
1026 Q_INVOKABLE void cancelActivation() override;
1027 Q_INVOKABLE void closeScope(unity::shell::scopes::ScopeInterface* scope) override;
1028- Q_INVOKABLE unity::shell::scopes::DepartmentInterface* getDepartment(QString const& id) override;
1029- Q_INVOKABLE void loadDepartment(QString const& id) override;
1030+ Q_INVOKABLE unity::shell::scopes::NavigationInterface* getNavigation(QString const& id) override;
1031+ Q_INVOKABLE unity::shell::scopes::NavigationInterface* getAltNavigation(QString const& id) override;
1032+ Q_INVOKABLE void setNavigationState(QString const& navId, bool altNavigation) override;
1033 Q_INVOKABLE void performQuery(QString const& cannedQuery) override;
1034+ Q_INVOKABLE void refresh() override;
1035
1036 void setScopeData(unity::scopes::ScopeMetadata const& data);
1037 void handleActivation(std::shared_ptr<unity::scopes::ActivationResponse> const&, unity::scopes::Result::SPtr const&);
1038@@ -164,6 +170,7 @@
1039
1040 protected:
1041 void setSearchInProgress(bool searchInProgress);
1042+ void setStatus(unity::shell::scopes::ScopeInterface::Status status);
1043 void invalidateLastSearch();
1044 virtual void dispatchSearch();
1045
1046@@ -173,9 +180,12 @@
1047 QPointer<Scopes> m_scopesInstance;
1048
1049 private:
1050+ static void updateNavigationModels(DepartmentNode* rootNode, QMultiMap<QString, Department*>& navigationModels, QString const& activeNavigation);
1051+ static QString buildQuery(QString const& scopeId, QString const& searchQuery, QString const& departmentId, QString const& primaryFilterId, QString const& primaryOptionId);
1052 void setScopesInstance(Scopes*);
1053 void startTtlTimer();
1054- void setCurrentDepartmentId(QString const& id);
1055+ void setCurrentNavigationId(QString const& id);
1056+ void setFilterState(unity::scopes::FilterState const& filterState);
1057 void processSearchChunk(PushEvent* pushEvent);
1058 void executeCannedQuery(unity::scopes::CannedQuery const& query, bool allowDelayedActivation);
1059
1060@@ -187,13 +197,15 @@
1061 QString m_searchQuery;
1062 QString m_noResultsHint;
1063 QString m_formFactor;
1064- QString m_currentDepartmentId;
1065+ QString m_currentNavigationId;
1066+ QString m_currentAltNavigationId;
1067 QVariantMap m_customizations;
1068 bool m_isActive;
1069 bool m_searchInProgress;
1070 bool m_resultsDirty;
1071 bool m_delayedClear;
1072- bool m_hasDepartments;
1073+ bool m_hasNavigation;
1074+ bool m_hasAltNavigation;
1075
1076 std::unique_ptr<CollectionController> m_searchController;
1077 std::unique_ptr<CollectionController> m_activationController;
1078@@ -202,15 +214,22 @@
1079 std::shared_ptr<unity::scopes::ActivationResponse> m_delayedActivation;
1080 unity::scopes::Department::SCPtr m_rootDepartment;
1081 unity::scopes::Department::SCPtr m_lastRootDepartment;
1082+ unity::scopes::OptionSelectorFilter::SCPtr m_sortOrderFilter;
1083+ unity::scopes::OptionSelectorFilter::SCPtr m_lastSortOrderFilter;
1084+ unity::scopes::FilterState m_filterState;
1085+ unity::scopes::FilterState m_receivedFilterState;
1086+ unity::shell::scopes::ScopeInterface::Status m_status;
1087 QGSettings* m_settings;
1088 QScopedPointer<SettingsModel> m_settingsModel;
1089 QSharedPointer<DepartmentNode> m_departmentTree;
1090+ QSharedPointer<DepartmentNode> m_altNavTree;
1091 QTimer m_aggregatorTimer;
1092 QTimer m_clearTimer;
1093 QTimer m_invalidateTimer;
1094 QList<std::shared_ptr<unity::scopes::CategorisedResult>> m_cachedResults;
1095 QSet<unity::shell::scopes::ScopeInterface*> m_tempScopes;
1096 QMultiMap<QString, Department*> m_departmentModels;
1097+ QMultiMap<QString, Department*> m_altNavModels;
1098 QMap<Department*, QString> m_inverseDepartments;
1099 QMetaObject::Connection m_metadataConnection;
1100 LocationService::Ptr m_locationService;
1101
1102=== modified file 'src/Unity/scopes.cpp'
1103--- src/Unity/scopes.cpp 2014-07-31 11:08:50 +0000
1104+++ src/Unity/scopes.cpp 2014-08-06 08:35:31 +0000
1105@@ -130,6 +130,11 @@
1106 return m_scopes.count();
1107 }
1108
1109+int Scopes::count() const
1110+{
1111+ return m_scopes.count();
1112+}
1113+
1114 void Scopes::populateScopes()
1115 {
1116 auto thread = new ScopeListWorker;
1117@@ -198,6 +203,7 @@
1118
1119 m_loaded = true;
1120 Q_EMIT loadedChanged();
1121+ Q_EMIT countChanged();
1122 Q_EMIT overviewScopeChanged();
1123 Q_EMIT metadataRefreshed();
1124
1125@@ -249,8 +255,6 @@
1126 return QVariant::fromValue(scope);
1127 case Scopes::RoleId:
1128 return QString(scope->id());
1129- case Scopes::RoleVisible:
1130- return QVariant::fromValue(scope->visible());
1131 case Scopes::RoleTitle:
1132 return QString(scope->name());
1133 default:
1134
1135=== modified file 'src/Unity/scopes.h'
1136--- src/Unity/scopes.h 2014-07-31 11:08:50 +0000
1137+++ src/Unity/scopes.h 2014-08-06 08:35:31 +0000
1138@@ -62,6 +62,7 @@
1139 void refreshScopeMetadata();
1140
1141 bool loaded() const override;
1142+ int count() const override;
1143 unity::shell::scopes::ScopeInterface* overviewScope() const override;
1144
1145 LocationService::Ptr locationService() const;
1146
1147=== modified file 'tests/data/CMakeLists.txt'
1148--- tests/data/CMakeLists.txt 2014-07-22 13:49:50 +0000
1149+++ tests/data/CMakeLists.txt 2014-08-06 08:35:31 +0000
1150@@ -1,5 +1,6 @@
1151 add_subdirectory(mock-scope)
1152 add_subdirectory(mock-scope-departments)
1153+add_subdirectory(mock-scope-double-nav)
1154 add_subdirectory(mock-scope-ttl)
1155 add_subdirectory(scopes)
1156
1157
1158=== added directory 'tests/data/mock-scope-double-nav'
1159=== added file 'tests/data/mock-scope-double-nav/CMakeLists.txt'
1160--- tests/data/mock-scope-double-nav/CMakeLists.txt 1970-01-01 00:00:00 +0000
1161+++ tests/data/mock-scope-double-nav/CMakeLists.txt 2014-08-06 08:35:31 +0000
1162@@ -0,0 +1,16 @@
1163+include(FindPkgConfig)
1164+pkg_check_modules(SCOPESLIB REQUIRED libunity-scopes>=0.4.0)
1165+
1166+set(SCOPES_BIN_DIR ${SCOPESLIB_LIBDIR})
1167+
1168+include_directories(${SCOPESLIB_INCLUDE_DIRS})
1169+include_directories(${CMAKE_CURRENT_BINARY_DIR})
1170+
1171+set(SCOPE_SOURCES
1172+ mock-scope-double-nav.cpp
1173+ )
1174+
1175+add_library(mock-scope-double-nav MODULE ${SCOPE_SOURCES})
1176+target_link_libraries(mock-scope-double-nav ${SCOPESLIB_LDFLAGS})
1177+
1178+configure_file(mock-scope-double-nav.ini.in mock-scope-double-nav.ini)
1179
1180=== added file 'tests/data/mock-scope-double-nav/mock-scope-double-nav.cpp'
1181--- tests/data/mock-scope-double-nav/mock-scope-double-nav.cpp 1970-01-01 00:00:00 +0000
1182+++ tests/data/mock-scope-double-nav/mock-scope-double-nav.cpp 2014-08-06 08:35:31 +0000
1183@@ -0,0 +1,214 @@
1184+/*
1185+ * Copyright (C) 2014 Canonical Ltd
1186+ *
1187+ * This program is free software: you can redistribute it and/or modify
1188+ * it under the terms of the GNU Lesser General Public License version 3 as
1189+ * published by the Free Software Foundation.
1190+ *
1191+ * This program is distributed in the hope that it will be useful,
1192+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
1193+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
1194+ * GNU Lesser General Public License for more details.
1195+ *
1196+ * You should have received a copy of the GNU Lesser General Public License
1197+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
1198+ *
1199+ * Authored by: Pete Woods <pete.woods@canonical.com>
1200+ */
1201+
1202+#include <unity/scopes/CategorisedResult.h>
1203+#include <unity/scopes/OptionSelectorFilter.h>
1204+#include <unity/scopes/ScopeBase.h>
1205+#include <unity/scopes/SearchReply.h>
1206+
1207+#include <iostream>
1208+#include <thread>
1209+#include <atomic>
1210+#include <sstream>
1211+
1212+#define EXPORT __attribute__ ((visibility ("default")))
1213+
1214+using namespace std;
1215+using namespace unity::scopes;
1216+
1217+class MyQuery : public SearchQueryBase
1218+{
1219+public:
1220+ MyQuery(CannedQuery const& query, SearchMetadata const& metadata) :
1221+ SearchQueryBase(query, metadata),
1222+ department_id_(query.department_id())
1223+ {
1224+ }
1225+
1226+ ~MyQuery()
1227+ {
1228+ }
1229+
1230+ virtual void cancelled() override
1231+ {
1232+ }
1233+
1234+ static Department::SPtr create_root_dep(CannedQuery const& query)
1235+ {
1236+ Department::SPtr child_dep;
1237+ Department::SPtr root_dep;
1238+ root_dep = Department::create("", query, "All departments");
1239+
1240+ child_dep = Department::create("books", query, "Books");
1241+ child_dep->set_has_subdepartments();
1242+ root_dep->add_subdepartment(child_dep);
1243+
1244+ child_dep = Department::create("movies", query, "Movies, TV, Music");
1245+ child_dep->set_has_subdepartments();
1246+ root_dep->add_subdepartment(child_dep);
1247+
1248+ child_dep = Department::create("electronics", query, "Electronics");
1249+ child_dep->set_has_subdepartments();
1250+ root_dep->add_subdepartment(child_dep);
1251+
1252+ child_dep = Department::create("home", query, "Home, Garden & DIY");
1253+ child_dep->set_has_subdepartments();
1254+ root_dep->add_subdepartment(child_dep);
1255+
1256+ child_dep = Department::create("toys", query, "Toys, Children & Baby");
1257+ child_dep->set_has_subdepartments();
1258+ root_dep->add_subdepartment(child_dep);
1259+
1260+ return root_dep;
1261+ }
1262+
1263+ static Department::SPtr get_department_by_id(Department::SPtr root_dep, std::string const& dep_id)
1264+ {
1265+ auto children = root_dep->subdepartments();
1266+ for (auto it = children.begin(); it != children.end(); ++it)
1267+ {
1268+ if ((*it)->id() == dep_id) return const_pointer_cast<Department>(*it);
1269+ }
1270+ return Department::SPtr();
1271+ }
1272+
1273+ virtual void run(SearchReplyProxy const& reply) override
1274+ {
1275+ Department::SPtr child_dep;
1276+ Department::SPtr root_dep;
1277+ Department::SPtr active_dep;
1278+
1279+ root_dep = create_root_dep(query());
1280+
1281+ if (department_id_.compare(0, 5, "books") == 0)
1282+ {
1283+ active_dep = get_department_by_id(root_dep, "books");
1284+ child_dep = Department::create("books-kindle", query(), "Kindle Books");
1285+ active_dep->add_subdepartment(child_dep);
1286+
1287+ child_dep = Department::create("books-study", query(), "Books for Study");
1288+ active_dep->add_subdepartment(child_dep);
1289+
1290+ child_dep = Department::create("books-audio", query(), "Audiobooks");
1291+ active_dep->add_subdepartment(child_dep);
1292+ }
1293+
1294+ if (department_id_.compare(0, 4, "home") == 0)
1295+ {
1296+ active_dep = get_department_by_id(root_dep, "home");
1297+ child_dep = Department::create("home-garden", query(), "Garden & Outdoors");
1298+ active_dep->add_subdepartment(child_dep);
1299+
1300+ child_dep = Department::create("home-furniture", query(), "Homeware & Furniture");
1301+ active_dep->add_subdepartment(child_dep);
1302+
1303+ child_dep = Department::create("home-kitchen", query(), "Kitchen & Dining");
1304+ active_dep->add_subdepartment(child_dep);
1305+ }
1306+
1307+ if (department_id_.compare(0, 4, "toys") == 0)
1308+ {
1309+ active_dep = get_department_by_id(root_dep, "toys");
1310+ child_dep = Department::create("toys-games", query(), "Toys & Games");
1311+ active_dep->add_subdepartment(child_dep);
1312+
1313+ child_dep = Department::create("toys-baby", query(), "Baby");
1314+ active_dep->add_subdepartment(child_dep);
1315+ }
1316+
1317+ // provide only partial tree for this leaf
1318+ if (department_id_ == "toys-games")
1319+ {
1320+ root_dep = Department::create("", query(), "All departments");
1321+ child_dep = Department::create("toys", query(), "Toys, Children & Baby");
1322+ root_dep->add_subdepartment(child_dep);
1323+ active_dep = Department::create("toys-games", query(), "Toys & Games");
1324+ child_dep->add_subdepartment(active_dep);
1325+ }
1326+
1327+ reply->register_departments(root_dep);
1328+
1329+ // add sort order filter
1330+ OptionSelectorFilter::UPtr sort_order_filter = OptionSelectorFilter::create("sort-order", "Sort Order");
1331+ sort_order_filter->set_display_hints(FilterBase::Primary);
1332+ sort_order_filter->add_option("featured", "Featured");
1333+ sort_order_filter->add_option("top", "Most popular");
1334+ sort_order_filter->add_option("best", "Best sellers");
1335+ Filters filters;
1336+ filters.push_back(std::move(sort_order_filter));
1337+
1338+ FilterState state;
1339+ FilterState initial_filter_state(query().filter_state());
1340+ if (initial_filter_state.has_filter("sort-order")) {
1341+ state = initial_filter_state;
1342+ } else {
1343+ // default option
1344+ OptionSelectorFilter::update_state(state, "sort-order", "featured", true);
1345+ }
1346+
1347+ reply->push(filters, state);
1348+
1349+ auto cat1 = reply->register_category("cat1", "Category 1", "");
1350+ CategorisedResult res1(cat1);
1351+ res1.set_uri("test:uri");
1352+ res1.set_title("result for: \"" + query().query_string() + "\"");
1353+ reply->push(res1);
1354+ }
1355+
1356+protected:
1357+ string department_id_;
1358+};
1359+
1360+class MyScope : public ScopeBase
1361+{
1362+public:
1363+ MyScope()
1364+ {
1365+ }
1366+
1367+ virtual SearchQueryBase::UPtr search(CannedQuery const& q, SearchMetadata const& metadata) override
1368+ {
1369+ return SearchQueryBase::UPtr(new MyQuery(q, metadata));
1370+ }
1371+
1372+ virtual PreviewQueryBase::UPtr preview(Result const&, ActionMetadata const&) override
1373+ {
1374+ return nullptr;
1375+ }
1376+};
1377+
1378+extern "C"
1379+{
1380+
1381+ EXPORT
1382+ unity::scopes::ScopeBase*
1383+ // cppcheck-suppress unusedFunction
1384+ UNITY_SCOPE_CREATE_FUNCTION()
1385+ {
1386+ return new MyScope;
1387+ }
1388+
1389+ EXPORT
1390+ void
1391+ // cppcheck-suppress unusedFunction
1392+ UNITY_SCOPE_DESTROY_FUNCTION(unity::scopes::ScopeBase* scope_base)
1393+ {
1394+ delete scope_base;
1395+ }
1396+
1397+}
1398
1399=== added file 'tests/data/mock-scope-double-nav/mock-scope-double-nav.ini.in'
1400--- tests/data/mock-scope-double-nav/mock-scope-double-nav.ini.in 1970-01-01 00:00:00 +0000
1401+++ tests/data/mock-scope-double-nav/mock-scope-double-nav.ini.in 2014-08-06 08:35:31 +0000
1402@@ -0,0 +1,8 @@
1403+[ScopeConfig]
1404+DisplayName = mock-double-nav.DisplayName
1405+Description = mock-double-nav.Description
1406+Art = /mock-double-nav.Art
1407+Icon = /mock-double-nav.Icon
1408+SearchHint = mock-double-nav.SearchHint
1409+HotKey = mock-double-nav.HotKey
1410+Author = mock-double-nav.Author
1411
1412=== modified file 'tests/departmentstest.cpp'
1413--- tests/departmentstest.cpp 2014-07-18 16:35:52 +0000
1414+++ tests/departmentstest.cpp 2014-08-06 08:35:31 +0000
1415@@ -48,6 +48,7 @@
1416 private:
1417 QScopedPointer<Scopes> m_scopes;
1418 Scope* m_scope;
1419+ Scope* m_scope_navs;
1420 QScopedPointer<RegistrySpawner> m_registry;
1421
1422 private Q_SLOTS:
1423@@ -78,6 +79,10 @@
1424 m_scope = qobject_cast<scopes_ng::Scope*>(m_scopes->getScope(QString("mock-scope-departments")));
1425 QVERIFY(m_scope != nullptr);
1426 m_scope->setActive(true);
1427+
1428+ m_scope_navs = qobject_cast<scopes_ng::Scope*>(m_scopes->getScope(QString("mock-scope-double-nav")));
1429+ QVERIFY(m_scope_navs != nullptr);
1430+ m_scope_navs->setActive(true);
1431 }
1432
1433 void cleanup()
1434@@ -90,37 +95,40 @@
1435 {
1436 performSearch(m_scope, QString("foo"));
1437
1438- QCOMPARE(m_scope->hasDepartments(), false);
1439+ QCOMPARE(m_scope->hasNavigation(), false);
1440+ QCOMPARE(m_scope->hasAltNavigation(), false);
1441 }
1442
1443 void testRootDepartment()
1444 {
1445 performSearch(m_scope, QString(""));
1446
1447- QCOMPARE(m_scope->hasDepartments(), true);
1448- QCOMPARE(m_scope->currentDepartmentId(), QString(""));
1449- QScopedPointer<DepartmentInterface> departmentModel(m_scope->getDepartment(m_scope->currentDepartmentId()));
1450+ QCOMPARE(m_scope->hasNavigation(), true);
1451+ QCOMPARE(m_scope->hasAltNavigation(), false);
1452+ QCOMPARE(m_scope->currentNavigationId(), QString(""));
1453+ QScopedPointer<NavigationInterface> departmentModel(m_scope->getNavigation(m_scope->currentNavigationId()));
1454 QVERIFY(departmentModel != nullptr);
1455
1456- QVERIFY(departmentModel->departmentId().isEmpty());
1457+ QVERIFY(departmentModel->navigationId().isEmpty());
1458 QCOMPARE(departmentModel->label(), QString("All departments"));
1459 QCOMPARE(departmentModel->allLabel(), QString(""));
1460- QCOMPARE(departmentModel->parentDepartmentId(), QString());
1461+ QCOMPARE(departmentModel->parentNavigationId(), QString());
1462 QCOMPARE(departmentModel->parentLabel(), QString());
1463 QCOMPARE(departmentModel->loaded(), true);
1464 QCOMPARE(departmentModel->isRoot(), true);
1465+ QCOMPARE(departmentModel->hidden(), false);
1466
1467 QCOMPARE(departmentModel->rowCount(), 5);
1468 QModelIndex idx;
1469
1470 idx = departmentModel->index(0);
1471- QCOMPARE(departmentModel->data(idx, Department::Roles::RoleDepartmentId), QVariant(QString("books")));
1472+ QCOMPARE(departmentModel->data(idx, Department::Roles::RoleNavigationId), QVariant(QString("books")));
1473 QCOMPARE(departmentModel->data(idx, Department::Roles::RoleLabel), QVariant(QString("Books")));
1474 QCOMPARE(departmentModel->data(idx, Department::Roles::RoleHasChildren), QVariant(true));
1475 QCOMPARE(departmentModel->data(idx, Department::Roles::RoleIsActive), QVariant(false));
1476
1477 idx = departmentModel->index(4);
1478- QCOMPARE(departmentModel->data(idx, Department::Roles::RoleDepartmentId), QVariant(QString("toys")));
1479+ QCOMPARE(departmentModel->data(idx, Department::Roles::RoleNavigationId), QVariant(QString("toys")));
1480 QCOMPARE(departmentModel->data(idx, Department::Roles::RoleLabel), QVariant(QString("Toys, Children & Baby")));
1481 QCOMPARE(departmentModel->data(idx, Department::Roles::RoleHasChildren), QVariant(true));
1482 QCOMPARE(departmentModel->data(idx, Department::Roles::RoleIsActive), QVariant(false));
1483@@ -130,23 +138,23 @@
1484 {
1485 performSearch(m_scope, QString(""));
1486
1487- QCOMPARE(m_scope->currentDepartmentId(), QString(""));
1488- QScopedPointer<DepartmentInterface> departmentModel(m_scope->getDepartment(QString("toys")));
1489+ QCOMPARE(m_scope->currentNavigationId(), QString(""));
1490+ QScopedPointer<NavigationInterface> departmentModel(m_scope->getNavigation(QString("toys")));
1491 QVERIFY(departmentModel != nullptr);
1492
1493 QSignalSpy spy(departmentModel.data(), SIGNAL(loadedChanged()));
1494
1495- QCOMPARE(departmentModel->departmentId(), QString("toys"));
1496+ QCOMPARE(departmentModel->navigationId(), QString("toys"));
1497 QCOMPARE(departmentModel->label(), QString("Toys, Children & Baby"));
1498 QCOMPARE(departmentModel->allLabel(), QString(""));
1499- QCOMPARE(departmentModel->parentDepartmentId(), QString(""));
1500+ QCOMPARE(departmentModel->parentNavigationId(), QString(""));
1501 QCOMPARE(departmentModel->parentLabel(), QString("All departments"));
1502 QCOMPARE(departmentModel->loaded(), false);
1503 QCOMPARE(departmentModel->isRoot(), false);
1504
1505 QCOMPARE(departmentModel->rowCount(), 0);
1506
1507- m_scope->loadDepartment(QString("toys"));
1508+ m_scope->setNavigationState(departmentModel->navigationId(), false);
1509 QVERIFY(spy.wait());
1510
1511 QCOMPARE(departmentModel->rowCount(), 2);
1512@@ -158,16 +166,18 @@
1513 {
1514 performSearch(m_scope, QString(""));
1515
1516- QCOMPARE(m_scope->currentDepartmentId(), QString(""));
1517+ QCOMPARE(m_scope->currentNavigationId(), QString(""));
1518 QSignalSpy spy(m_scope, SIGNAL(searchInProgressChanged()));
1519- m_scope->loadDepartment(QString("books"));
1520+ QScopedPointer<NavigationInterface> navModel(m_scope->getNavigation(QString("books")));
1521+ m_scope->setNavigationState(navModel->navigationId(), false);
1522 QVERIFY(spy.wait());
1523 QCOMPARE(m_scope->searchInProgress(), false);
1524- QScopedPointer<DepartmentInterface> departmentModel(m_scope->getDepartment(QString("books")));
1525+ QScopedPointer<NavigationInterface> departmentModel(m_scope->getNavigation(QString("books")));
1526 QCOMPARE(departmentModel->isRoot(), false);
1527
1528+ navModel.reset(m_scope->getNavigation(QString("books-audio")));
1529 // this is a leaf department, so activating it should update the parent model
1530- m_scope->loadDepartment(QString("books-audio"));
1531+ m_scope->setNavigationState(navModel->navigationId(), false);
1532 QVERIFY(spy.wait());
1533 QCOMPARE(m_scope->searchInProgress(), false);
1534 QCOMPARE(departmentModel->isRoot(), false);
1535@@ -175,7 +185,7 @@
1536 bool foundAudiobooks = false;
1537 for (int i = 0; i < departmentModel->rowCount(); i++) {
1538 QModelIndex idx(departmentModel->index(i));
1539- QVariant data = departmentModel->data(idx, Department::Roles::RoleDepartmentId);
1540+ QVariant data = departmentModel->data(idx, Department::Roles::RoleNavigationId);
1541 if (data.toString() == QString("books-audio")) {
1542 QCOMPARE(departmentModel->data(idx, Department::Roles::RoleIsActive).toBool(), true);
1543 foundAudiobooks = true;
1544@@ -188,16 +198,17 @@
1545 {
1546 performSearch(m_scope, QString(""));
1547
1548- QCOMPARE(m_scope->currentDepartmentId(), QString(""));
1549+ QCOMPARE(m_scope->currentNavigationId(), QString(""));
1550 QSignalSpy spy(m_scope, SIGNAL(searchInProgressChanged()));
1551- m_scope->loadDepartment(QString("books"));
1552+ QScopedPointer<NavigationInterface> navModel(m_scope->getNavigation(QString("books")));
1553+ m_scope->setNavigationState(navModel->navigationId(), false);
1554 QVERIFY(spy.wait());
1555 QCOMPARE(m_scope->searchInProgress(), false);
1556- QScopedPointer<DepartmentInterface> departmentModel(m_scope->getDepartment(QString("books")));
1557+ QScopedPointer<NavigationInterface> departmentModel(m_scope->getNavigation(QString("books")));
1558 QCOMPARE(departmentModel->isRoot(), false);
1559
1560 // get the root again without actually loading the department
1561- departmentModel.reset(m_scope->getDepartment(departmentModel->parentDepartmentId()));
1562+ departmentModel.reset(m_scope->getNavigation(departmentModel->parentNavigationId()));
1563 QCOMPARE(departmentModel->isRoot(), true);
1564 QEXPECT_FAIL("", "We have the department in cache, to it kind of is loaded", Continue);
1565 QCOMPARE(departmentModel->loaded(), false);
1566@@ -205,32 +216,98 @@
1567
1568 void testIncompleteTreeOnLeaf()
1569 {
1570- QScopedPointer<DepartmentInterface> departmentModel;
1571+ QScopedPointer<NavigationInterface> navModel;
1572+ QScopedPointer<NavigationInterface> departmentModel;
1573 performSearch(m_scope, QString(""));
1574
1575- QCOMPARE(m_scope->currentDepartmentId(), QString(""));
1576- QCOMPARE(m_scope->hasDepartments(), true);
1577+ QCOMPARE(m_scope->currentNavigationId(), QString(""));
1578+ QCOMPARE(m_scope->hasNavigation(), true);
1579
1580 QSignalSpy spy(m_scope, SIGNAL(searchInProgressChanged()));
1581- m_scope->loadDepartment(QString("toys"));
1582+ navModel.reset(m_scope->getNavigation(QString("toys")));
1583+ m_scope->setNavigationState(navModel->navigationId(), false);
1584 QVERIFY(spy.wait());
1585 QCOMPARE(m_scope->searchInProgress(), false);
1586
1587- departmentModel.reset(m_scope->getDepartment(QString("toys")));
1588+ departmentModel.reset(m_scope->getNavigation(QString("toys")));
1589 QCOMPARE(departmentModel->isRoot(), false);
1590 QCOMPARE(departmentModel->rowCount(), 2);
1591
1592- m_scope->loadDepartment(QString("toys-games"));
1593+ navModel.reset(m_scope->getNavigation(QString("toys-games")));
1594+ m_scope->setNavigationState(navModel->navigationId(), false);
1595 QVERIFY(spy.wait());
1596 QCOMPARE(m_scope->searchInProgress(), false);
1597
1598 // after getting the parent department model, it should still have
1599 // all the leaves, even though the leaf served just itself
1600- departmentModel.reset(m_scope->getDepartment(QString("toys")));
1601+ departmentModel.reset(m_scope->getNavigation(QString("toys")));
1602 QCOMPARE(departmentModel->isRoot(), false);
1603 QCOMPARE(departmentModel->rowCount(), 2);
1604 }
1605
1606+ void testDoubleNavigation()
1607+ {
1608+ performSearch(m_scope_navs, QString(""));
1609+
1610+ QCOMPARE(m_scope_navs->hasNavigation(), true);
1611+ QCOMPARE(m_scope_navs->hasAltNavigation(), true);
1612+ QCOMPARE(m_scope_navs->currentNavigationId(), QString(""));
1613+ QCOMPARE(m_scope_navs->currentAltNavigationId(), QString("featured"));
1614+ QScopedPointer<NavigationInterface> departmentModel(m_scope_navs->getNavigation(m_scope_navs->currentNavigationId()));
1615+ QVERIFY(departmentModel != nullptr);
1616+
1617+ QVERIFY(!m_scope_navs->currentAltNavigationId().isEmpty());
1618+ QScopedPointer<NavigationInterface> sortOrderModel(m_scope_navs->getAltNavigation(""));
1619+ QVERIFY(sortOrderModel != nullptr);
1620+
1621+ QCOMPARE(sortOrderModel->navigationId(), QString(""));
1622+ QCOMPARE(sortOrderModel->label(), QString("Sort Order"));
1623+ QCOMPARE(sortOrderModel->allLabel(), QString(""));
1624+ QCOMPARE(sortOrderModel->parentNavigationId(), QString());
1625+ QCOMPARE(sortOrderModel->parentLabel(), QString());
1626+ QCOMPARE(sortOrderModel->loaded(), true);
1627+ QCOMPARE(sortOrderModel->isRoot(), true);
1628+ QCOMPARE(sortOrderModel->hidden(), true);
1629+
1630+ QCOMPARE(sortOrderModel->rowCount(), 3);
1631+ QModelIndex idx;
1632+
1633+ idx = sortOrderModel->index(0);
1634+ QCOMPARE(sortOrderModel->data(idx, Department::Roles::RoleNavigationId), QVariant(QString("featured")));
1635+ QCOMPARE(sortOrderModel->data(idx, Department::Roles::RoleLabel), QVariant(QString("Featured")));
1636+ QCOMPARE(sortOrderModel->data(idx, Department::Roles::RoleHasChildren), QVariant(false));
1637+ QCOMPARE(sortOrderModel->data(idx, Department::Roles::RoleIsActive), QVariant(true));
1638+
1639+ idx = sortOrderModel->index(2);
1640+ QCOMPARE(sortOrderModel->data(idx, Department::Roles::RoleNavigationId), QVariant(QString("best")));
1641+ QCOMPARE(sortOrderModel->data(idx, Department::Roles::RoleLabel), QVariant(QString("Best sellers")));
1642+ QCOMPARE(sortOrderModel->data(idx, Department::Roles::RoleHasChildren), QVariant(false));
1643+ QCOMPARE(sortOrderModel->data(idx, Department::Roles::RoleIsActive), QVariant(false));
1644+ }
1645+
1646+ void testDoubleNavChangeActive()
1647+ {
1648+ performSearch(m_scope_navs, QString(""));
1649+
1650+ QCOMPARE(m_scope_navs->currentAltNavigationId(), QString("featured"));
1651+ QScopedPointer<NavigationInterface> sortOrderModel(m_scope_navs->getAltNavigation(""));
1652+ QVERIFY(sortOrderModel != nullptr);
1653+ QCOMPARE(sortOrderModel->loaded(), true);
1654+ QCOMPARE(sortOrderModel->rowCount(), 3);
1655+
1656+ QModelIndex idx(sortOrderModel->index(1));
1657+ QCOMPARE(sortOrderModel->data(idx, Department::Roles::RoleNavigationId), QVariant(QString("top")));
1658+ QCOMPARE(sortOrderModel->data(idx, Department::Roles::RoleIsActive), QVariant(false));
1659+
1660+ // perform a query for the other navigation
1661+ QSignalSpy spy(m_scope_navs, SIGNAL(searchInProgressChanged()));
1662+ m_scope_navs->setNavigationState("top", true);
1663+ QVERIFY(spy.wait());
1664+
1665+ // the model should be updated
1666+ QCOMPARE(sortOrderModel->data(idx, Department::Roles::RoleNavigationId), QVariant(QString("top")));
1667+ QCOMPARE(sortOrderModel->data(idx, Department::Roles::RoleIsActive), QVariant(true));
1668+ }
1669 };
1670
1671 QTEST_GUILESS_MAIN(DepartmentsTest)
1672
1673=== modified file 'tests/previewtest.cpp'
1674--- tests/previewtest.cpp 2014-08-05 12:10:41 +0000
1675+++ tests/previewtest.cpp 2014-08-06 08:35:31 +0000
1676@@ -67,14 +67,14 @@
1677 QVERIFY(spy.wait());
1678 QCOMPARE(m_scopes->loaded(), true);
1679 // should have at least one scope now
1680- QCOMPARE(m_scopes->rowCount(), 4);
1681+ QVERIFY(m_scopes->rowCount() > 1);
1682
1683 QVariant scope_var = m_scopes->data(m_scopes->index(0), Scopes::Roles::RoleScope);
1684 QVERIFY(scope_var.canConvert<Scope*>());
1685
1686 // get scope proxy
1687- m_scope = scope_var.value<Scope*>();
1688- QCOMPARE(m_scope->id(), QString("mock-scope"));
1689+ m_scope = m_scopes->getScopeById("mock-scope");
1690+ QVERIFY(m_scope != nullptr);
1691 m_scope->setActive(true);
1692 }
1693
1694
1695=== modified file 'tests/resultstest.cpp'
1696--- tests/resultstest.cpp 2014-07-31 13:04:20 +0000
1697+++ tests/resultstest.cpp 2014-08-06 08:35:31 +0000
1698@@ -112,15 +112,15 @@
1699 QVERIFY(spy.wait());
1700 QCOMPARE(m_scopes->loaded(), true);
1701 // should have at least one scope now
1702- QCOMPARE(m_scopes->rowCount(), 4);
1703+ QVERIFY(m_scopes->rowCount() > 1);
1704
1705 // get scope proxy
1706- m_scope = qobject_cast<scopes_ng::Scope*>(m_scopes->getScope(QString("mock-scope")));
1707+ m_scope = qobject_cast<scopes_ng::Scope*>(m_scopes->getScopeById(QString("mock-scope")));
1708 QVERIFY(m_scope != nullptr);
1709 m_scope->setActive(true);
1710
1711 // get scope proxy for TTL scope
1712- m_scope_ttl = qobject_cast<scopes_ng::Scope*>(m_scopes->getScope(QString("mock-scope-ttl")));
1713+ m_scope_ttl = qobject_cast<scopes_ng::Scope*>(m_scopes->getScopeById(QString("mock-scope-ttl")));
1714 QVERIFY(m_scope != nullptr);
1715 m_scope_ttl->setActive(true);
1716 }
1717@@ -177,7 +177,6 @@
1718 QCOMPARE(m_scope->description(), QString("mock.Description"));
1719 QCOMPARE(m_scope->searchHint(), QString("mock.SearchHint"));
1720 QCOMPARE(m_scope->shortcut(), QString("mock.HotKey"));
1721- QCOMPARE(m_scope->visible(), true);
1722 QCOMPARE(m_scope->searchQuery(), QString());
1723
1724 QVariantMap customizations(m_scope->customizations());
1725@@ -199,7 +198,6 @@
1726 QCOMPARE(m_scope_ttl->description(), QString("mock-ttl.Description"));
1727 QCOMPARE(m_scope_ttl->searchHint(), QString());
1728 QCOMPARE(m_scope_ttl->shortcut(), QString());
1729- QCOMPARE(m_scope_ttl->visible(), true);
1730 QCOMPARE(m_scope_ttl->searchQuery(), QString());
1731 }
1732
1733
1734=== modified file 'tests/settingsendtoendtest.cpp'
1735--- tests/settingsendtoendtest.cpp 2014-08-05 16:41:02 +0000
1736+++ tests/settingsendtoendtest.cpp 2014-08-06 08:35:31 +0000
1737@@ -61,10 +61,10 @@
1738 QVERIFY(spy.wait());
1739 QCOMPARE(m_scopes->loaded(), true);
1740 // should have at least one scope now
1741- QCOMPARE(m_scopes->rowCount(), 4);
1742+ QVERIFY(m_scopes->rowCount() > 1);
1743
1744 // get scope proxy
1745- m_scope = qobject_cast<scopes_ng::Scope*>(m_scopes->getScope(QString("mock-scope")));
1746+ m_scope = m_scopes->getScopeById("mock-scope");
1747 QVERIFY(m_scope != nullptr);
1748 m_scope->setActive(true);
1749 }

Subscribers

People subscribed via source and target branches

to all changes: