Merge lp:~larryprice/libertine-scope/libertine-store-create-container into lp:~larryprice/libertine-scope/libertine-store-search

Proposed by Larry Price on 2016-10-05
Status: Needs review
Proposed branch: lp:~larryprice/libertine-scope/libertine-store-create-container
Merge into: lp:~larryprice/libertine-scope/libertine-store-search
Diff against target: 1588 lines (+882/-88)
32 files modified
CMakeLists.txt (+2/-0)
data/CMakeLists.txt (+4/-0)
lib/libertine-scope/CMakeLists.txt (+1/-0)
lib/libertine-scope/action.h (+1/-1)
lib/libertine-scope/container.cpp (+50/-0)
lib/libertine-scope/container.h (+44/-0)
lib/libertine-scope/preview.cpp (+2/-2)
lib/libertine-scope/service_manager.cpp (+23/-6)
lib/libertine-scope/service_manager.h (+3/-0)
scope/apps/action.cpp (+0/-1)
scope/apps/action.h (+0/-1)
scope/store/action.cpp (+43/-0)
scope/store/action.h (+48/-0)
scope/store/create_preview.cpp (+113/-0)
scope/store/create_preview.h (+65/-0)
scope/store/entry_point.cpp (+1/-1)
scope/store/query.cpp (+56/-12)
scope/store/query.h (+15/-13)
scope/store/scope.cpp (+13/-7)
scope/store/scope.h (+4/-7)
service/libertine_service/container.py (+14/-4)
service/libertine_service/dbus.py (+31/-10)
service/libertine_service/tasks.py (+23/-7)
tests/lib/libertine-scope/CMakeLists.txt (+3/-2)
tests/lib/libertine-scope/mock_service_manager.h (+2/-0)
tests/lib/libertine-scope/test_action.cpp (+3/-3)
tests/lib/libertine-scope/test_container.cpp (+53/-0)
tests/lib/libertine-scope/test_preview.cpp (+2/-2)
tests/scope/store/CMakeLists.txt (+2/-0)
tests/scope/store/test_action.cpp (+85/-0)
tests/scope/store/test_create_preview.cpp (+137/-0)
tests/scope/store/test_query.cpp (+39/-9)
To merge this branch: bzr merge lp:~larryprice/libertine-scope/libertine-store-create-container
Reviewer Review Type Date Requested Status
Libertine Developers 2016-10-05 Pending
Review via email: mp+307754@code.launchpad.net

Commit message

Warn user on data usage before container creation.

Description of the change

Warn user on data usage before container creation.

If the "palatine" container does not exist, present user with a special icon for creating the container. This takes the user to a special preview with a short warning message and the option to create the container.

I ended up changing some namespacing things here as I started running into collisions.

To post a comment you must log in.

Unmerged revisions

113. By Larry Price on 2016-10-05

further specify namespace for store scope

112. By Larry Price on 2016-10-05

Tests for new code

111. By Larry Price on 2016-10-05

Fix old tests

110. By Larry Price on 2016-10-05

Progress bar on create

109. By Larry Price on 2016-10-05

Special preview pane for creating the palatine container

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
1=== modified file 'CMakeLists.txt'
2--- CMakeLists.txt 2016-09-23 14:36:02 +0000
3+++ CMakeLists.txt 2016-10-05 19:26:10 +0000
4@@ -65,8 +65,10 @@
5 # Important project paths
6 if (CLICK_MODE)
7 set(SCOPE_INSTALL_DIR "/libertine-scope")
8+ set(STORE_INSTALL_DIR "/libertine-store")
9 else()
10 set(SCOPE_INSTALL_DIR ${CMAKE_INSTALL_FULL_LIBDIR}/unity-scopes/libertine-scope/)
11+ set(STORE_INSTALL_DIR ${CMAKE_INSTALL_FULL_LIBDIR}/unity-scopes/libertine-store/)
12 endif(CLICK_MODE)
13
14 set(SCOPE_NAME "libertine-scope")
15
16=== modified file 'data/CMakeLists.txt'
17--- data/CMakeLists.txt 2016-08-30 21:11:50 +0000
18+++ data/CMakeLists.txt 2016-10-05 19:26:10 +0000
19@@ -1,5 +1,6 @@
20 # Copy data files into apps scope dir for dev
21 file(COPY store.svg blacklist DESTINATION ${CMAKE_BINARY_DIR}/scope/apps/)
22+file(COPY store.svg DESTINATION ${CMAKE_BINARY_DIR}/scope/store/)
23
24 install(FILES apps.png apps.svg
25 DESTINATION ${APPS_DATA_DIR})
26@@ -7,5 +8,8 @@
27 install(FILES blacklist store.svg
28 DESTINATION ${SCOPE_INSTALL_DIR})
29
30+install(FILES store.svg
31+ DESTINATION ${STORE_INSTALL_DIR})
32+
33 install(FILES com.canonical.libertine.ContainerManager.service
34 DESTINATION ${CMAKE_INSTALL_DATADIR}/dbus-1/services)
35
36=== modified file 'lib/libertine-scope/CMakeLists.txt'
37--- lib/libertine-scope/CMakeLists.txt 2016-08-24 16:21:47 +0000
38+++ lib/libertine-scope/CMakeLists.txt 2016-10-05 19:26:10 +0000
39@@ -5,6 +5,7 @@
40 preview.cpp
41 service_manager.cpp
42 package.cpp
43+ container.cpp
44 action.cpp
45 )
46
47
48=== modified file 'lib/libertine-scope/action.h'
49--- lib/libertine-scope/action.h 2016-09-20 20:09:51 +0000
50+++ lib/libertine-scope/action.h 2016-10-05 19:26:10 +0000
51@@ -38,7 +38,7 @@
52
53 virtual unity::scopes::ActivationResponse activate() override;
54
55-private:
56+protected:
57 std::string action_id_;
58 std::shared_ptr<ServiceManager> service_;
59 };
60
61=== added file 'lib/libertine-scope/container.cpp'
62--- lib/libertine-scope/container.cpp 1970-01-01 00:00:00 +0000
63+++ lib/libertine-scope/container.cpp 2016-10-05 19:26:10 +0000
64@@ -0,0 +1,50 @@
65+/*
66+ * Copyright 2016 Canonical Ltd.
67+ *
68+ * This program is free software: you can redistribute it and/or modify it under
69+ * the terms of the GNU General Public License, version 3, as published by the
70+ * Free Software Foundation.
71+ *
72+ * This program is distributed in the hope that it will be useful,
73+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
74+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
75+ * GNU General Public License for more details.
76+ *
77+ * You should have received a copy of the GNU General Public License
78+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
79+ */
80+#include "libertine-scope/container.h"
81+
82+
83+namespace
84+{
85+libertine::scope::Container::ContainerStatus string_to_status(QString const& status)
86+{
87+ if (status == "ready")
88+ {
89+ return libertine::scope::Container::ContainerStatus::ready;
90+ }
91+ else if (status == "installing")
92+ {
93+ return libertine::scope::Container::ContainerStatus::installing;
94+ }
95+ else if (status == "removing")
96+ {
97+ return libertine::scope::Container::ContainerStatus::removing;
98+ }
99+
100+ return libertine::scope::Container::ContainerStatus::none;
101+}
102+}
103+
104+
105+libertine::scope::Container libertine::scope::Container::
106+from_map(QVariantMap const& pkgMap)
107+{
108+ Container container;
109+ container.id = pkgMap["id"].toString().toStdString();
110+ container.progress = pkgMap["progress_id"].toString().toStdString();
111+ container.status = string_to_status(pkgMap["status"].toString());
112+
113+ return container;
114+}
115
116=== added file 'lib/libertine-scope/container.h'
117--- lib/libertine-scope/container.h 1970-01-01 00:00:00 +0000
118+++ lib/libertine-scope/container.h 2016-10-05 19:26:10 +0000
119@@ -0,0 +1,44 @@
120+/*
121+ * Copyright 2016 Canonical Ltd.
122+ *
123+ * This program is free software: you can redistribute it and/or modify it under
124+ * the terms of the GNU General Public License, version 3, as published by the
125+ * Free Software Foundation.
126+ *
127+ * This program is distributed in the hope that it will be useful,
128+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
129+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
130+ * GNU General Public License for more details.
131+ *
132+ * You should have received a copy of the GNU General Public License
133+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
134+ */
135+#pragma once
136+
137+#include <QVariant>
138+
139+
140+namespace libertine
141+{
142+namespace scope
143+{
144+
145+
146+class Container
147+{
148+public:
149+ explicit Container() = default;
150+ virtual ~Container() = default;
151+
152+ static Container from_map(QVariantMap const&);
153+
154+ enum class ContainerStatus {ready, installing, removing, none};
155+
156+ std::string id;
157+ ContainerStatus status;
158+ std::string progress;
159+};
160+
161+
162+} // Store
163+} // Libertine
164
165=== modified file 'lib/libertine-scope/preview.cpp'
166--- lib/libertine-scope/preview.cpp 2016-09-23 14:19:44 +0000
167+++ lib/libertine-scope/preview.cpp 2016-10-05 19:26:10 +0000
168@@ -18,8 +18,8 @@
169
170 #include "libertine-scope/i18n.h"
171 #include "libertine-scope/service_manager.h"
172-#include <future>
173 #include <QDebug>
174+#include <thread>
175 #include <unity/UnityExceptions.h>
176 #include <unity/scopes/ColumnLayout.h>
177 #include <unity/scopes/PreviewReply.h>
178@@ -164,7 +164,7 @@
179 if (app.status == "installing" || app.status == "removing") {
180 thread_.reset(new std::thread([=](){
181 std::this_thread::sleep_for(update_progress_after);
182- service_->update_progress(QString::fromStdString(app.id));
183+ service_->update_progress(QString::fromStdString(app.progress));
184 }));
185 }
186 }
187
188=== modified file 'lib/libertine-scope/service_manager.cpp'
189--- lib/libertine-scope/service_manager.cpp 2016-09-20 17:56:18 +0000
190+++ lib/libertine-scope/service_manager.cpp 2016-10-05 19:26:10 +0000
191@@ -26,6 +26,9 @@
192 constexpr auto INSTALL_METHOD = "install";
193 constexpr auto REMOVE_METHOD = "remove";
194 constexpr auto UPDATE_PROGRESS_METHOD = "update_progress";
195+constexpr auto CONTAINER_INFO_METHOD = "container_info";
196+constexpr auto CONTAINER_PROGRESS_METHOD = "container_progress";
197+constexpr auto CREATE_METHOD = "create_container";
198 constexpr auto LIBERTINE_SERVICE_DESTINATION = "com.canonical.libertine.ContainerManager";
199 constexpr auto LIBERTINE_SERVICE_INTERFACE = "com.canonical.libertine.ContainerManager";
200 constexpr auto LIBERTINE_SERVICE_OBJECT = "/Manager";
201@@ -39,6 +42,20 @@
202 }
203
204
205+QList<libertine::scope::Package> libertine::scope::ServiceManager::
206+search_cache(const QString &query) const
207+{
208+ return Package::from_map(call<QList<QVariantMap > >(SEARCH_CACHE_METHOD, QVariant(query)));
209+}
210+
211+
212+libertine::scope::Package libertine::scope::ServiceManager::
213+app_info(const QString &app_id) const
214+{
215+ return Package::from_map(call<QVariantMap >(APP_INFO_METHOD, QVariant(app_id)));
216+}
217+
218+
219 void libertine::scope::ServiceManager::
220 install(QString const& package_name) const
221 {
222@@ -53,10 +70,10 @@
223 }
224
225
226-libertine::scope::Package libertine::scope::ServiceManager::
227-app_info(const QString &app_id) const
228+void libertine::scope::ServiceManager::
229+create(QString const& container_id) const
230 {
231- return Package::from_map(call<QVariantMap >(APP_INFO_METHOD, QVariant(app_id)));
232+ call<qlonglong>(CREATE_METHOD, QVariant(container_id));
233 }
234
235
236@@ -67,10 +84,10 @@
237 }
238
239
240-QList<libertine::scope::Package> libertine::scope::ServiceManager::
241-search_cache(const QString &query) const
242+libertine::scope::Container libertine::scope::ServiceManager::
243+container_info(const QString &container_id) const
244 {
245- return Package::from_map(call<QList<QVariantMap > >(SEARCH_CACHE_METHOD, QVariant(query)));
246+ return Container::from_map(call<QVariantMap >(CONTAINER_INFO_METHOD, QVariant(container_id)));
247 }
248
249
250
251=== modified file 'lib/libertine-scope/service_manager.h'
252--- lib/libertine-scope/service_manager.h 2016-09-20 17:56:18 +0000
253+++ lib/libertine-scope/service_manager.h 2016-10-05 19:26:10 +0000
254@@ -16,6 +16,7 @@
255 #pragma once
256
257 #include "libertine-scope/package.h"
258+#include "libertine-scope/container.h"
259
260 #include <QString>
261 #include <QVariant>
262@@ -38,6 +39,8 @@
263 virtual void install(QString const& package_name) const;
264 virtual void remove(QString const& package_name) const;
265 virtual void update_progress(QString const& package_name) const;
266+ virtual Container container_info(QString const& container_id) const;
267+ virtual void create(QString const& container_id) const;
268
269 private:
270 bool valid() const;
271
272=== modified file 'scope/apps/action.cpp'
273--- scope/apps/action.cpp 2016-09-20 20:09:51 +0000
274+++ scope/apps/action.cpp 2016-10-05 19:26:10 +0000
275@@ -46,7 +46,6 @@
276 std::shared_ptr<HiddenApps> const& hidden,
277 unity::scopes::FilterState const& filter_state)
278 : libertine::scope::Action(result, metadata, action_id, service)
279- , action_id_(action_id)
280 , hidden_(hidden)
281 , filter_state_(filter_state)
282 {
283
284=== modified file 'scope/apps/action.h'
285--- scope/apps/action.h 2016-09-20 20:09:51 +0000
286+++ scope/apps/action.h 2016-10-05 19:26:10 +0000
287@@ -43,7 +43,6 @@
288 virtual unity::scopes::ActivationResponse activate() override;
289
290 private:
291- std::string action_id_;
292 std::string cache_dir_;
293 std::shared_ptr<HiddenApps> hidden_;
294 unity::scopes::FilterState filter_state_;
295
296=== added file 'scope/store/action.cpp'
297--- scope/store/action.cpp 1970-01-01 00:00:00 +0000
298+++ scope/store/action.cpp 2016-10-05 19:26:10 +0000
299@@ -0,0 +1,43 @@
300+/*
301+ * Copyright (C) 2016 Canonical Ltd
302+ *
303+ * This program is free software: you can redistribute it and/or modify
304+ * it under the terms of the GNU General Public License version 3 as
305+ * published by the Free Software Foundation.
306+ *
307+ * This program is distributed in the hope that it will be useful,
308+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
309+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
310+ * GNU General Public License for more details.
311+ *
312+ * You should have received a copy of the GNU General Public License
313+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
314+ */
315+
316+#include "scope/store/action.h"
317+#include <libertine-scope/service_manager.h>
318+#include <unity/scopes/CannedQuery.h>
319+#include <QString>
320+
321+
322+libertine::scope::store::Action::
323+Action(unity::scopes::Result const& result,
324+ unity::scopes::ActionMetadata const& metadata,
325+ std::string const& action_id,
326+ std::shared_ptr<libertine::scope::ServiceManager> const& service)
327+ : ::libertine::scope::Action(result, metadata, action_id, service)
328+{
329+}
330+
331+
332+unity::scopes::ActivationResponse libertine::scope::store::Action::
333+activate()
334+{
335+ if (action_id_ == "create")
336+ {
337+ service_->create("palatine");
338+ return unity::scopes::ActivationResponse(unity::scopes::ActivationResponse::Status::ShowPreview);
339+ }
340+
341+ return ::libertine::scope::Action::activate();
342+}
343
344=== added file 'scope/store/action.h'
345--- scope/store/action.h 1970-01-01 00:00:00 +0000
346+++ scope/store/action.h 2016-10-05 19:26:10 +0000
347@@ -0,0 +1,48 @@
348+/*
349+ * Copyright (C) 2016 Canonical Ltd
350+ *
351+ * This program is free software: you can redistribute it and/or modify
352+ * it under the terms of the GNU General Public License version 3 as
353+ * published by the Free Software Foundation.
354+ *
355+ * This program is distributed in the hope that it will be useful,
356+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
357+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
358+ * GNU General Public License for more details.
359+ *
360+ * You should have received a copy of the GNU General Public License
361+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
362+ */
363+#pragma once
364+
365+
366+#include <libertine-scope/action.h>
367+#include <unity/scopes/ActionMetadata.h>
368+#include <unity/scopes/ActivationResponse.h>
369+#include <unity/scopes/Result.h>
370+
371+
372+namespace libertine
373+{
374+namespace scope
375+{
376+namespace store
377+{
378+class Action : public ::libertine::scope::Action
379+{
380+public:
381+ explicit
382+ Action(unity::scopes::Result const& result,
383+ unity::scopes::ActionMetadata const& metadata,
384+ std::string const& action_id,
385+ std::shared_ptr<libertine::scope::ServiceManager> const& service);
386+
387+ virtual
388+ ~Action() = default;
389+
390+ virtual
391+ unity::scopes::ActivationResponse activate() override;
392+};
393+} // namespace store
394+} // namespace scope
395+} // namespace libertine
396
397=== added file 'scope/store/create_preview.cpp'
398--- scope/store/create_preview.cpp 1970-01-01 00:00:00 +0000
399+++ scope/store/create_preview.cpp 2016-10-05 19:26:10 +0000
400@@ -0,0 +1,113 @@
401+/*
402+ * Copyright 2016 Canonical Ltd.
403+ *
404+ * This program is free software: you can redistribute it and/or modify it under
405+ * the terms of the GNU General Public License, version 3, as published by the
406+ * Free Software Foundation.
407+ *
408+ * This program is distributed in the hope that it will be useful,
409+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
410+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
411+ * GNU General Public License for more details.
412+ *
413+ * You should have received a copy of the GNU General Public License
414+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
415+ */
416+#include "scope/store/create_preview.h"
417+
418+#include "libertine-scope/i18n.h"
419+#include "libertine-scope/service_manager.h"
420+#include <thread>
421+#include <unity/scopes/PreviewReply.h>
422+#include <unity/scopes/PreviewWidget.h>
423+#include <unity/scopes/VariantBuilder.h>
424+
425+
426+namespace
427+{
428+static unity::scopes::PreviewWidget
429+warning()
430+{
431+ unity::scopes::PreviewWidget warning("warning", "text");
432+ warning.add_attribute_value("title", unity::scopes::Variant(_("Initializing this scope may consume up to 500MB of data and could take several minutes.")));
433+ return warning;
434+}
435+}
436+
437+
438+std::chrono::milliseconds libertine::scope::store::CreatePreview::
439+update_progress_after = std::chrono::milliseconds(500);
440+
441+
442+libertine::scope::store::CreatePreview::
443+CreatePreview(unity::scopes::Result const& result,
444+ unity::scopes::ActionMetadata const& metadata,
445+ std::shared_ptr<ServiceManager> const& service)
446+: PreviewQueryBase(result, metadata)
447+, service_(service)
448+, thread_()
449+{
450+}
451+
452+
453+libertine::scope::store::CreatePreview::
454+~CreatePreview()
455+{
456+ if (thread_ != nullptr)
457+ {
458+ thread_->join();
459+ }
460+}
461+
462+
463+void libertine::scope::store::CreatePreview::
464+cancelled()
465+{
466+}
467+
468+
469+void libertine::scope::store::CreatePreview::
470+run(unity::scopes::PreviewReplyProxy const& reply)
471+{
472+ auto info = service_->container_info("palatine");
473+
474+ unity::scopes::PreviewWidgetList widgets;
475+
476+ if (info.status == Container::ContainerStatus::none)
477+ {
478+ widgets.push_back(warning());
479+ unity::scopes::VariantBuilder builder;
480+ builder.add_tuple(
481+ {
482+ {"id", unity::scopes::Variant("create")},
483+ {"label", unity::scopes::Variant(_("Start"))},
484+ });
485+ unity::scopes::PreviewWidget start("actions", "actions");
486+ start.add_attribute_value("actions", builder.end());
487+ widgets.push_back(start);
488+ }
489+ else if (info.status != Container::ContainerStatus::ready)
490+ {
491+ widgets.push_back(warning());
492+ unity::scopes::PreviewWidget progress("actions", "progress");
493+ unity::scopes::VariantMap tuple;
494+ tuple["dbus-name"] = "com.canonical.libertine.ContainerManager";
495+ tuple["dbus-object"] = std::string("/Progress/") + info.progress;
496+ progress.add_attribute_value("source", unity::scopes::Variant(tuple));
497+ widgets.push_back(progress);
498+
499+ // update the progress bar asynchronously
500+ thread_.reset(new std::thread([=](){
501+ std::this_thread::sleep_for(update_progress_after);
502+ service_->update_progress(QString::fromStdString(info.progress));
503+ }));
504+ }
505+ else
506+ {
507+ unity::scopes::PreviewWidget info("info", "text");
508+ info.add_attribute_value("title", unity::scopes::Variant(_("Scope is ready.")));
509+ widgets.push_back(info);
510+ }
511+
512+ reply->push(widgets);
513+}
514
515=== added file 'scope/store/create_preview.h'
516--- scope/store/create_preview.h 1970-01-01 00:00:00 +0000
517+++ scope/store/create_preview.h 2016-10-05 19:26:10 +0000
518@@ -0,0 +1,65 @@
519+/*
520+ * Copyright 2016 Canonical Ltd.
521+ *
522+ * This program is free software: you can redistribute it and/or modify it under
523+ * the terms of the GNU General Public License, version 3, as published by the
524+ * Free Software Foundation.
525+ *
526+ * This program is distributed in the hope that it will be useful,
527+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
528+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
529+ * GNU General Public License for more details.
530+ *
531+ * You should have received a copy of the GNU General Public License
532+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
533+ */
534+#pragma once
535+
536+#include <chrono>
537+#include <unity/scopes/PreviewQueryBase.h>
538+
539+
540+namespace std
541+{
542+class thread;
543+}
544+
545+
546+namespace libertine
547+{
548+namespace scope
549+{
550+class ServiceManager;
551+
552+namespace store
553+{
554+
555+class CreatePreview
556+: public unity::scopes::PreviewQueryBase
557+{
558+public:
559+ explicit
560+ CreatePreview(unity::scopes::Result const& result,
561+ unity::scopes::ActionMetadata const& metadata,
562+ std::shared_ptr<ServiceManager> const& service);
563+
564+ virtual
565+ ~CreatePreview();
566+
567+ virtual void
568+ cancelled() override;
569+
570+ virtual void
571+ run(unity::scopes::PreviewReplyProxy const& reply) override;
572+
573+ static
574+ std::chrono::milliseconds update_progress_after;
575+
576+private:
577+ std::shared_ptr<ServiceManager> service_;
578+ std::unique_ptr<std::thread> thread_;
579+};
580+
581+} // namespace store
582+} // namespace scope
583+} // namespace libertine
584
585=== modified file 'scope/store/entry_point.cpp'
586--- scope/store/entry_point.cpp 2016-08-24 19:18:32 +0000
587+++ scope/store/entry_point.cpp 2016-10-05 19:26:10 +0000
588@@ -29,7 +29,7 @@
589 EXPORT unity::scopes::ScopeBase*
590 UNITY_SCOPE_CREATE_FUNCTION()
591 {
592- return new libertine::scope::Scope();
593+ return new libertine::scope::store::Scope();
594 }
595
596
597
598=== modified file 'scope/store/query.cpp'
599--- scope/store/query.cpp 2016-09-15 18:55:23 +0000
600+++ scope/store/query.cpp 2016-10-05 19:26:10 +0000
601@@ -65,33 +65,56 @@
602 )";
603
604
605+static const auto CATEGORY_CREATE = R"(
606+ {
607+ "schema-version": 1,
608+ "template": {
609+ "category-layout": "grid",
610+ "overlay": true,
611+ "card-background": "color:///#E95420"
612+ },
613+ "components": {
614+ "title": "title",
615+ "art": {
616+ "aspect-ratio": 0.55,
617+ "field": "art"
618+ },
619+ "overlay-color": "overlay-color"
620+ }
621+ }
622+)";
623+
624+
625 static auto const SINGLE_RESULT_FOUND = _("%1 result found");
626 static auto const MULTIPLE_RESULTS_FOUND = _("%1 results found");
627 static QString const APPID_URI_FORMAT = "appid://palatine/%1/0.0";
628 }
629
630
631-std::string const libertine::scope::Query::USE_SEARCH_HINT = _("Use the searchbar to find software.");
632-std::string const libertine::scope::Query::NO_SEARCH_RESULTS_HINT = _("No results found.");
633-
634-
635-libertine::scope::Query::
636-Query(usc::CannedQuery const& query,
637- usc::SearchMetadata const& metadata,
638- std::shared_ptr<ServiceManager> const& service)
639+std::string const libertine::scope::store::Query::USE_SEARCH_HINT = _("Use the searchbar to find software.");
640+std::string const libertine::scope::store::Query::NO_SEARCH_RESULTS_HINT = _("No results found.");
641+std::string const libertine::scope::store::Query::CREATE_CATEGORY_TITLE = _("Get started");
642+
643+
644+libertine::scope::store::Query::
645+Query(usc::CannedQuery const& query,
646+ usc::SearchMetadata const& metadata,
647+ std::shared_ptr<ServiceManager> const& service,
648+ std::string const & data_directory)
649 : usc::SearchQueryBase(query, metadata)
650 , service_(service)
651+ , data_directory_(data_directory)
652 {
653 }
654
655
656-void libertine::scope::Query::
657+void libertine::scope::store::Query::
658 cancelled()
659 {
660 }
661
662
663-void libertine::scope::Query::
664+void libertine::scope::store::Query::
665 show_hint(usc::SearchReplyProxy const& reply,
666 std::string const& reason) const
667 {
668@@ -103,7 +126,21 @@
669 }
670
671
672-void libertine::scope::Query::
673+void libertine::scope::store::Query::
674+add_create_category(usc::SearchReplyProxy const& reply) const
675+{
676+ auto cat = reply->register_category("create", "", "", usc::CategoryRenderer(CATEGORY_CREATE));
677+ usc::CategorisedResult res(cat);
678+ res.set_title(CREATE_CATEGORY_TITLE);
679+ res.set_art(data_directory_ + "/store.svg");
680+ res.set_uri("libertine-store://create");
681+ res["overlay-color"] = "transparent";
682+ res["show_create_preview"] = true;
683+ reply->push(res);
684+}
685+
686+
687+void libertine::scope::store::Query::
688 run_search(usc::SearchReplyProxy const& reply) const
689 {
690 auto results = service_->search_cache(QString::fromStdString(query().query_string()));
691@@ -136,9 +173,16 @@
692 }
693
694
695-void libertine::scope::Query::
696+void libertine::scope::store::Query::
697 run(usc::SearchReplyProxy const& reply)
698 {
699+ auto info = service_->container_info("palatine");
700+ if (info.status != Container::ContainerStatus::ready)
701+ {
702+ add_create_category(reply);
703+ return;
704+ }
705+
706 if (!query().query_string().empty())
707 {
708 run_search(reply);
709
710=== modified file 'scope/store/query.h'
711--- scope/store/query.h 2016-08-24 19:18:32 +0000
712+++ scope/store/query.h 2016-10-05 19:26:10 +0000
713@@ -13,23 +13,22 @@
714 * You should have received a copy of the GNU General Public License
715 * along with this program. If not, see <http://www.gnu.org/licenses/>.
716 */
717-#ifndef LIBERTINE_STORE_QUERY_H_
718-#define LIBERTINE_STORE_QUERY_H_
719-
720+#pragma once
721
722 #include <unity/scopes/ReplyProxyFwd.h>
723 #include <unity/scopes/SearchQueryBase.h>
724-
725-class QStringList;
726+#include <QString>
727
728
729 namespace libertine
730 {
731 namespace scope
732 {
733-
734 class ServiceManager;
735
736+namespace store
737+{
738+
739 /**
740 * Engine to run a specific store query.
741 */
742@@ -37,10 +36,12 @@
743 : public unity::scopes::SearchQueryBase
744 {
745 public:
746- explicit Query(unity::scopes::CannedQuery const& query,
747- unity::scopes::SearchMetadata const& metadata,
748- std::shared_ptr<ServiceManager> const& service);
749+ explicit Query(unity::scopes::CannedQuery const& query,
750+ unity::scopes::SearchMetadata const& metadata,
751+ std::shared_ptr<ServiceManager> const& service,
752+ std::string const& data_directory = "");
753
754+ virtual
755 ~Query() = default;
756
757 virtual void
758@@ -51,6 +52,7 @@
759
760 static std::string const USE_SEARCH_HINT;
761 static std::string const NO_SEARCH_RESULTS_HINT;
762+ static std::string const CREATE_CATEGORY_TITLE;
763
764 private:
765 void
766@@ -58,13 +60,13 @@
767 std::string const& reason) const;
768 void
769 run_search(unity::scopes::SearchReplyProxy const& reply) const;
770+ void
771+ add_create_category(unity::scopes::SearchReplyProxy const& reply) const;
772
773 std::shared_ptr<ServiceManager> service_;
774+ const std::string data_directory_;
775 };
776
777+} // namespace store
778 } // namespace scope
779 } // namespace libertine
780-
781-#endif // LIBERTINE_STORE_QUERY_H_
782-
783-
784
785=== modified file 'scope/store/scope.cpp'
786--- scope/store/scope.cpp 2016-09-20 17:56:18 +0000
787+++ scope/store/scope.cpp 2016-10-05 19:26:10 +0000
788@@ -19,6 +19,8 @@
789 */
790 #include "scope/store/scope.h"
791
792+#include "scope/store/action.h"
793+#include "scope/store/create_preview.h"
794 #include "scope/store/query.h"
795 #include <libertine-scope/action.h>
796 #include <libertine-scope/i18n.h>
797@@ -29,13 +31,13 @@
798 namespace usc = unity::scopes;
799
800
801-libertine::scope::Scope::
802+libertine::scope::store::Scope::
803 Scope()
804 : service_(std::make_shared<ServiceManager>())
805 { }
806
807
808-void libertine::scope::Scope::
809+void libertine::scope::store::Scope::
810 start(std::string const&)
811 {
812 setlocale(LC_ALL, "");
813@@ -45,23 +47,28 @@
814 }
815
816
817-usc::SearchQueryBase::UPtr libertine::scope::Scope::
818+usc::SearchQueryBase::UPtr libertine::scope::store::Scope::
819 search(usc::CannedQuery const& query,
820 usc::SearchMetadata const& metadata)
821 {
822- return usc::SearchQueryBase::UPtr(new Query(query, metadata, service_));
823+ return usc::SearchQueryBase::UPtr(new Query(query, metadata, service_, scope_directory()));
824 }
825
826
827-usc::PreviewQueryBase::UPtr libertine::scope::Scope::
828+usc::PreviewQueryBase::UPtr libertine::scope::store::Scope::
829 preview(usc::Result const& result,
830 usc::ActionMetadata const& metadata)
831 {
832+ if (result.contains("show_create_preview") && result["show_create_preview"].get_bool())
833+ {
834+ return usc::PreviewQueryBase::UPtr(new CreatePreview(result, metadata, service_));
835+ }
836+
837 return usc::PreviewQueryBase::UPtr(new Preview(result, metadata, service_));
838 }
839
840
841-usc::ActivationQueryBase::UPtr libertine::scope::Scope::
842+usc::ActivationQueryBase::UPtr libertine::scope::store::Scope::
843 perform_action(usc::Result const& result,
844 usc::ActionMetadata const& metadata,
845 std::string const& /* widget_id */,
846@@ -72,4 +79,3 @@
847 action_id,
848 service_));
849 }
850-
851
852=== modified file 'scope/store/scope.h'
853--- scope/store/scope.h 2016-09-20 17:56:18 +0000
854+++ scope/store/scope.h 2016-10-05 19:26:10 +0000
855@@ -17,8 +17,7 @@
856 * You should have received a copy of the GNU General Public License
857 * along with this program. If not, see <http://www.gnu.org/licenses/>.
858 */
859-#ifndef LIBERTINE_STORE_SCOPE_H_
860-#define LIBERTINE_STORE_SCOPE_H_
861+#pragma once
862
863 #include <unity/scopes/ScopeBase.h>
864
865@@ -26,10 +25,10 @@
866 {
867 namespace scope
868 {
869-
870 class ServiceManager;
871
872-
873+namespace store
874+{
875 class Scope
876 : public unity::scopes::ScopeBase
877 {
878@@ -70,8 +69,6 @@
879 std::shared_ptr<ServiceManager> service_;
880 };
881
882-
883+} // namespace store
884 } // namespace scope
885 } // namespace libertine
886-
887-#endif /* LIBERTINE_STORE_SCOPE_H_ */
888
889=== modified file 'service/libertine_service/container.py'
890--- service/libertine_service/container.py 2016-08-22 15:28:57 +0000
891+++ service/libertine_service/container.py 2016-10-05 19:26:10 +0000
892@@ -56,12 +56,22 @@
893 task = tasks.RemoveTask(package_name, container_id, self.libertine_config, progress, self.lock, self.log)
894 return task.start()
895
896- def status(self, package_name, container_id):
897- self.log.debug("Checking status of package '%s'" % package_name)
898+ def status(self, container, package=''):
899+ self.log.debug("Checking status of '%s':'%s'" % (container, package))
900 self.libertine_config.refresh_database()
901- if not self._container_exists(container_id):
902+ if not self._container_exists(container):
903 return ''
904- return self.libertine_config.get_package_install_status(container_id, package_name) or ''
905+ if package == '':
906+ return self.libertine_config._get_value_by_key(container, 'installStatus')
907+ return self.libertine_config.get_package_install_status(container, package) or ''
908+
909+ def create(self, container_id, progress):
910+ self.log.debug("Create container with ID '%s'" % container_id)
911+ self.libertine_config.refresh_database()
912+ if self._container_exists(container_id):
913+ return -1
914+ task = tasks.CreateTask(container_id, self.libertine_config, progress, self.lock, self.log)
915+ return task.start()
916
917 def _container_exists(self, container_id):
918 self.log.debug("Checking if container '%s' exists" % container_id)
919
920=== modified file 'service/libertine_service/dbus.py'
921--- service/libertine_service/dbus.py 2016-09-20 18:30:26 +0000
922+++ service/libertine_service/dbus.py 2016-10-05 19:26:10 +0000
923@@ -62,7 +62,6 @@
924
925
926 class Service(dbus.service.Object):
927-
928 def __init__(self, config):
929 log.debug("creating service")
930 DBusGMainLoop(set_as_default=True)
931@@ -117,16 +116,37 @@
932 log.debug("app_info('{}') called".format(app_id))
933 app = self.cache.app_info(app_id)
934 if 'package' in app:
935- app['status'] = self.container.status(app['package'], CONTAINER_ID)
936+ app['status'] = self.container.status(package=app['package'], container=CONTAINER_ID)
937 if app['id'] in self.progress:
938 app['progress_id'] = self.progress[app['id']].id
939
940 return app
941
942- @dbus.service.signal(LIBERTINE_STORE_INTERFACE,
943- signature='su')
944- def updating(self, target, percent):
945- log.debug("emit updating('{}', {})".format(target, percent))
946+ @dbus.service.method(LIBERTINE_STORE_INTERFACE,
947+ in_signature='s',
948+ out_signature='a{sv}')
949+ def container_info(self, container_id):
950+ log.debug("container_info('{}')".format(container_id))
951+ info = {"status": self.container.status(container=container_id)}
952+ if info['status'] != '':
953+ info['id'] = container_id
954+ cid = '_%s' % container_id
955+ if cid in self.progress:
956+ info['progress_id'] = self.progress[cid].id
957+
958+ return info
959+
960+ @dbus.service.method(LIBERTINE_STORE_INTERFACE,
961+ in_signature='s',
962+ out_signature='x')
963+ def create_container(self, container_id):
964+ log.debug("create_container('{}')".format(container_id))
965+ container_progress = Progress(self.connection)
966+ self.progress["_%s" % container_id] = container_progress
967+ retval = self.container.create(container_id, container_progress)
968+ if retval <= 0:
969+ container_progress.finished('')
970+ return retval
971
972 # Packaging
973
974@@ -155,11 +175,12 @@
975 @dbus.service.method(LIBERTINE_STORE_INTERFACE,
976 in_signature='s',
977 out_signature='b')
978- def update_progress(self, app_id):
979- log.debug("update_progress('%s')" % app_id)
980+ def update_progress(self, progress_id):
981+ log.debug("update_progress('%s')" % progress_id)
982 self.cleanup_progress()
983- if app_id in self.progress:
984- self.progress[app_id].emit_progress()
985+ progress = [v for k, v in self.progress.items() if v.id == progress_id]
986+ if len(progress) == 1:
987+ progress[0].emit_progress()
988 return True
989 return False
990
991
992=== modified file 'service/libertine_service/tasks.py'
993--- service/libertine_service/tasks.py 2016-09-16 21:35:57 +0000
994+++ service/libertine_service/tasks.py 2016-10-05 19:26:10 +0000
995@@ -12,13 +12,23 @@
996 # You should have received a copy of the GNU General Public License
997 # along with this program. If not, see <http://www.gnu.org/licenses/>.
998
999-from subprocess import Popen, PIPE
1000+import shlex
1001+from subprocess import Popen, DEVNULL
1002 from threading import Thread
1003 from abc import ABCMeta, abstractmethod
1004 from libertine import LibertineContainer, HostInfo, utils
1005 from dbus import UInt64
1006
1007
1008+def refresh_libertine_store_scope():
1009+ scopes_object_path = "/com/canonical/unity/scopes"
1010+ invalidate_signal = "com.canonical.unity.scopes.InvalidateResults"
1011+ libertine_scope_id = "libertine-scope.ubuntu_libertine-store"
1012+ gdbus_cmd = ("gdbus emit --session --object-path %s --signal %s %s" %
1013+ (scopes_object_path, invalidate_signal, libertine_scope_id))
1014+ Popen(shlex.split(gdbus_cmd), stdout=DEVNULL, stderr=DEVNULL)
1015+
1016+
1017 class LibertineTask(metaclass=ABCMeta):
1018 """
1019 Abstract class for performing long-running, synchronous operations on a
1020@@ -120,24 +130,29 @@
1021 self.log.debug("Package '%s' already exists, skipping install" % self.package)
1022 return False
1023
1024-
1025-class CreateTask(LibertineTask):
1026- def __init__(self, container_id, config, lock, log):
1027- super().__init__(lock, log)
1028- self.container = container_id
1029- self.config = config
1030+import time
1031+class CreateTask(ProgressTask):
1032+ def __init__(self, container_id, config, progress, lock, log):
1033+ super().__init__("", container_id, config, progress, lock, log)
1034
1035 def _run(self):
1036 self.log.debug("Creating container '%s'" % self.container)
1037+ self._progress()
1038+
1039 container = LibertineContainer(self.container, self.config)
1040 if not container.create_libertine_container(password=''):
1041 self.log.debug("Creating container '%s' failed" % self.container)
1042 self.config.delete_container(self.container)
1043 return
1044+ self._progress()
1045+
1046 self.config.update_container_install_status(self.container, "ready")
1047+ self.progress.finished(self.container)
1048+ refresh_libertine_store_scope()
1049
1050 def _before(self):
1051 self.log.debug("CreateTask::_before")
1052+ self._progress()
1053 if self.config.container_exists(self.container):
1054 return False
1055
1056@@ -146,4 +161,5 @@
1057 self.config.add_new_container(self.container, 'User Applications', info.select_container_type_by_kernel(),
1058 info.get_host_distro_release())
1059 self.config.update_container_install_status(self.container, 'installing')
1060+ self._progress()
1061 return True
1062
1063=== modified file 'tests/lib/libertine-scope/CMakeLists.txt'
1064--- tests/lib/libertine-scope/CMakeLists.txt 2016-08-24 16:21:47 +0000
1065+++ tests/lib/libertine-scope/CMakeLists.txt 2016-10-05 19:26:10 +0000
1066@@ -19,6 +19,7 @@
1067 add_test(${test_name} ${test_name}_exe)
1068 endfunction(create_test)
1069
1070+create_test(test_action)
1071+create_test(test_container)
1072+create_test(test_package)
1073 create_test(test_preview)
1074-create_test(test_package)
1075-create_test(test_action)
1076
1077=== modified file 'tests/lib/libertine-scope/mock_service_manager.h'
1078--- tests/lib/libertine-scope/mock_service_manager.h 2016-09-20 17:56:18 +0000
1079+++ tests/lib/libertine-scope/mock_service_manager.h 2016-10-05 19:26:10 +0000
1080@@ -40,6 +40,8 @@
1081 MOCK_CONST_METHOD1(update_progress, void(QString const&));
1082 MOCK_CONST_METHOD1(install, void(QString const&));
1083 MOCK_CONST_METHOD1(remove, void(QString const&));
1084+ MOCK_CONST_METHOD1(container_info, Container(QString const&));
1085+ MOCK_CONST_METHOD1(create, void(QString const&));
1086 };
1087
1088
1089
1090=== modified file 'tests/lib/libertine-scope/test_action.cpp'
1091--- tests/lib/libertine-scope/test_action.cpp 2016-08-25 12:59:32 +0000
1092+++ tests/lib/libertine-scope/test_action.cpp 2016-10-05 19:26:10 +0000
1093@@ -23,7 +23,7 @@
1094
1095 namespace
1096 {
1097-TEST(StoreActionTest, CallsInstallOnServiceManager)
1098+TEST(ActionTest, CallsInstallOnServiceManager)
1099 {
1100 unity::scopes::testing::Result result;
1101 result["id"] = "vim-common";
1102@@ -39,7 +39,7 @@
1103 }
1104
1105
1106-TEST(StoreActionTest, CallsRemoveOnServiceManager)
1107+TEST(ActionTest, CallsRemoveOnServiceManager)
1108 {
1109 unity::scopes::testing::Result result;
1110 result["id"] = "gedit";
1111@@ -55,7 +55,7 @@
1112 }
1113
1114
1115-TEST(StoreActionTest, OpenAllowsDefaultHandlerToRun)
1116+TEST(ActionTest, OpenAllowsDefaultHandlerToRun)
1117 {
1118 unity::scopes::testing::Result result;
1119 result["id"] = "gedit";
1120
1121=== added file 'tests/lib/libertine-scope/test_container.cpp'
1122--- tests/lib/libertine-scope/test_container.cpp 1970-01-01 00:00:00 +0000
1123+++ tests/lib/libertine-scope/test_container.cpp 2016-10-05 19:26:10 +0000
1124@@ -0,0 +1,53 @@
1125+/*
1126+ * Copyright 2016 Canonical Ltd.
1127+ *
1128+ * This program is free software: you can redistribute it and/or modify it under
1129+ * the terms of the GNU General Public License, version 3, as published by the
1130+ * Free Software Foundation.
1131+ *
1132+ * This program is distributed in the hope that it will be useful,
1133+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
1134+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
1135+ * GNU General Public License for more details.
1136+ *
1137+ * You should have received a copy of the GNU General Public License
1138+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
1139+ */
1140+#include "libertine-scope/container.h"
1141+
1142+#include <gmock/gmock.h>
1143+
1144+
1145+namespace
1146+{
1147+using namespace libertine::scope;
1148+
1149+
1150+TEST(PackageTest, FromMapCreatesPackage)
1151+{
1152+ QVariantMap attributes;
1153+ attributes["id"] = "foobar";
1154+ attributes["status"] = "ready";
1155+ attributes["progress_id"] = "1234321";
1156+
1157+ auto container = Container::from_map(attributes);
1158+ EXPECT_EQ("foobar", container.id);
1159+ EXPECT_EQ(Container::ContainerStatus::ready, container.status);
1160+ EXPECT_EQ("1234321", container.progress);
1161+}
1162+
1163+
1164+TEST(PackageTest, FromMapConvertsStatusStrings)
1165+{
1166+ QVariantMap attributes;
1167+
1168+ attributes["status"] = "ready";
1169+ EXPECT_EQ(Container::ContainerStatus::ready, Container::from_map(attributes).status);
1170+ attributes["status"] = "installing";
1171+ EXPECT_EQ(Container::ContainerStatus::installing, Container::from_map(attributes).status);
1172+ attributes["status"] = "removing";
1173+ EXPECT_EQ(Container::ContainerStatus::removing, Container::from_map(attributes).status);
1174+ attributes["status"] = "";
1175+ EXPECT_EQ(Container::ContainerStatus::none, Container::from_map(attributes).status);
1176+}
1177+}
1178
1179=== modified file 'tests/lib/libertine-scope/test_preview.cpp'
1180--- tests/lib/libertine-scope/test_preview.cpp 2016-09-20 17:56:18 +0000
1181+++ tests/lib/libertine-scope/test_preview.cpp 2016-10-05 19:26:10 +0000
1182@@ -249,7 +249,7 @@
1183 package.status = "removing";
1184 package.progress = "something";
1185 usePackage(package);
1186- EXPECT_CALL(*service, update_progress(QString::fromStdString(package.id)));
1187+ EXPECT_CALL(*service, update_progress(QString::fromStdString(package.progress)));
1188
1189 std::unique_ptr<Preview> preview(new Preview(result, metadata, service));
1190 preview->run(proxy);
1191@@ -273,7 +273,7 @@
1192 package.status = "installing";
1193 package.progress = "foobar";
1194 usePackage(package);
1195- EXPECT_CALL(*service, update_progress(QString::fromStdString(package.id)));
1196+ EXPECT_CALL(*service, update_progress(QString::fromStdString(package.progress)));
1197
1198 std::unique_ptr<Preview> preview(new Preview(result, metadata, service));
1199 preview->run(proxy);
1200
1201=== modified file 'tests/scope/store/CMakeLists.txt'
1202--- tests/scope/store/CMakeLists.txt 2016-08-24 16:21:47 +0000
1203+++ tests/scope/store/CMakeLists.txt 2016-10-05 19:26:10 +0000
1204@@ -20,4 +20,6 @@
1205 add_test(${full_test_name} ${full_test_name}_exe)
1206 endfunction(create_test)
1207
1208+create_test(test_action)
1209+create_test(test_create_preview)
1210 create_test(test_query)
1211
1212=== added file 'tests/scope/store/test_action.cpp'
1213--- tests/scope/store/test_action.cpp 1970-01-01 00:00:00 +0000
1214+++ tests/scope/store/test_action.cpp 2016-10-05 19:26:10 +0000
1215@@ -0,0 +1,85 @@
1216+/*
1217+ * Copyright 2016 Canonical Ltd.
1218+ *
1219+ * This program is free software: you can redistribute it and/or modify it under
1220+ * the terms of the GNU General Public License, version 3, as published by the
1221+ * Free Software Foundation.
1222+ *
1223+ * This program is distributed in the hope that it will be useful,
1224+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
1225+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
1226+ * GNU General Public License for more details.
1227+ *
1228+ * You should have received a copy of the GNU General Public License
1229+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
1230+ */
1231+#include "scope/store/action.h"
1232+
1233+#include <gmock/gmock.h>
1234+#include <tests/lib/libertine-scope/mock_service_manager.h>
1235+#include <unity/scopes/ActionMetadata.h>
1236+#include <unity/scopes/testing/Result.h>
1237+
1238+
1239+namespace
1240+{
1241+TEST(ActionTest, OpenAllowsDefaultHandlerToRun)
1242+{
1243+ unity::scopes::testing::Result result;
1244+ result.set_uri("app://this/is/my/app");
1245+ unity::scopes::ActionMetadata metadata("en_US", "phone");
1246+ auto service = std::make_shared<testing::NiceMock<libertine::scope::MockServiceManager> >();
1247+
1248+ libertine::scope::store::Action action(result, metadata, "open", service);
1249+
1250+ auto response = action.activate();
1251+ EXPECT_EQ(unity::scopes::ActivationResponse::Status::NotHandled, response.status());
1252+}
1253+
1254+
1255+TEST(ActionTest, CallsCreateOnServiceManager)
1256+{
1257+ unity::scopes::testing::Result result;
1258+ unity::scopes::ActionMetadata metadata("en_US", "phone");
1259+ auto service = std::make_shared<testing::NiceMock<libertine::scope::MockServiceManager> >();
1260+
1261+ libertine::scope::store::Action action(result, metadata, "create", service);
1262+
1263+ EXPECT_CALL(*service, create(QString("palatine")));
1264+
1265+ auto response = action.activate();
1266+ EXPECT_EQ(unity::scopes::ActivationResponse::Status::ShowPreview, response.status());
1267+}
1268+
1269+
1270+TEST(ActionTest, CallsInstallOnServiceManager)
1271+{
1272+ unity::scopes::testing::Result result;
1273+ result["id"] = "vim-common";
1274+ unity::scopes::ActionMetadata metadata("en_US", "phone");
1275+ auto service = std::make_shared<testing::NiceMock<libertine::scope::MockServiceManager> >();
1276+
1277+ libertine::scope::store::Action action(result, metadata, "install", service);
1278+
1279+ EXPECT_CALL(*service, install(QString("vim-common")));
1280+
1281+ auto response = action.activate();
1282+ EXPECT_EQ(unity::scopes::ActivationResponse::Status::ShowPreview, response.status());
1283+}
1284+
1285+
1286+TEST(ActionTest, CallsRemoveOnServiceManager)
1287+{
1288+ unity::scopes::testing::Result result;
1289+ result["id"] = "gedit";
1290+ unity::scopes::ActionMetadata metadata("en_US", "phone");
1291+ auto service = std::make_shared<testing::NiceMock<libertine::scope::MockServiceManager> >();
1292+
1293+ libertine::scope::store::Action action(result, metadata, "remove", service);
1294+
1295+ EXPECT_CALL(*service, remove(QString("gedit")));
1296+
1297+ auto response = action.activate();
1298+ EXPECT_EQ(unity::scopes::ActivationResponse::Status::ShowPreview, response.status());
1299+}
1300+}
1301
1302=== added file 'tests/scope/store/test_create_preview.cpp'
1303--- tests/scope/store/test_create_preview.cpp 1970-01-01 00:00:00 +0000
1304+++ tests/scope/store/test_create_preview.cpp 2016-10-05 19:26:10 +0000
1305@@ -0,0 +1,137 @@
1306+/*
1307+ * Copyright 2016 Canonical Ltd.
1308+ *
1309+ * This program is free software: you can redistribute it and/or modify it under
1310+ * the terms of the GNU General Public License, version 3, as published by the
1311+ * Free Software Foundation.
1312+ *
1313+ * This program is distributed in the hope that it will be useful,
1314+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
1315+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
1316+ * GNU General Public License for more details.
1317+ *
1318+ * You should have received a copy of the GNU General Public License
1319+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
1320+ */
1321+#include "scope/store/create_preview.h"
1322+
1323+#include <gtest/gtest.h>
1324+#include <memory>
1325+#include <unity/scopes/Variant.h>
1326+#include <unity/scopes/ActionMetadata.h>
1327+#include <unity/scopes/testing/Result.h>
1328+#include <unity/scopes/testing/MockPreviewReply.h>
1329+#include <unity/scopes/PreviewWidget.h>
1330+#include <tests/lib/libertine-scope/mock_service_manager.h>
1331+
1332+
1333+namespace
1334+{
1335+using namespace libertine::scope::store;
1336+
1337+
1338+class CreatePreviewTest : public testing::Test
1339+{
1340+protected:
1341+ CreatePreviewTest()
1342+ : testing::Test()
1343+ , result()
1344+ , metadata("en_US", "phone")
1345+ , list(new unity::scopes::PreviewWidgetList())
1346+ , reply()
1347+ , proxy(&reply, [](unity::scopes::PreviewReply*) {})
1348+ , service(new testing::NiceMock<libertine::scope::MockServiceManager>())
1349+ {
1350+ }
1351+
1352+ virtual void
1353+ SetUp()
1354+ {
1355+ EXPECT_CALL(reply, push(testing::_)).WillOnce(testing::SaveArg<0>(list.get()));
1356+ CreatePreview::update_progress_after = std::chrono::milliseconds(0);
1357+ }
1358+
1359+ unity::scopes::testing::Result result;
1360+ unity::scopes::ActionMetadata metadata;
1361+ std::unique_ptr<unity::scopes::PreviewWidgetList> list;
1362+ testing::NiceMock<unity::scopes::testing::MockPreviewReply> reply;
1363+ unity::scopes::PreviewReplyProxy proxy;
1364+ std::shared_ptr<testing::NiceMock<libertine::scope::MockServiceManager> > service;
1365+};
1366+
1367+
1368+TEST_F(CreatePreviewTest, ShowsCreateWarningWithInstallButton)
1369+{
1370+ ::libertine::scope::Container c;
1371+ c.status = ::libertine::scope::Container::ContainerStatus::none;
1372+ EXPECT_CALL(*service, container_info(QString("palatine"))).WillOnce(testing::Return(c));
1373+
1374+ CreatePreview preview(result, metadata, service);
1375+ preview.run(proxy);
1376+
1377+ ASSERT_NE(nullptr, list);
1378+ ASSERT_EQ(2, list->size());
1379+
1380+ auto description = list->front();
1381+ EXPECT_EQ("warning", description.id());
1382+ EXPECT_EQ("text", description.widget_type());
1383+ EXPECT_EQ("Initializing this scope may consume up to 500MB of data and could take several minutes.", description.attribute_values()["title"].get_string());
1384+ list->pop_front();
1385+
1386+ auto buttons = list->front();
1387+ EXPECT_EQ("actions", buttons.id());
1388+ EXPECT_EQ("actions", buttons.widget_type());
1389+ auto buttons_actions = buttons.attribute_values()["actions"].get_array();
1390+ ASSERT_EQ(1, buttons_actions.size());
1391+ EXPECT_EQ("create", buttons_actions[0].get_dict()["id"].get_string());
1392+ EXPECT_EQ("Start", buttons_actions[0].get_dict()["label"].get_string());
1393+}
1394+
1395+
1396+TEST_F(CreatePreviewTest, ShowsCreateWarningWithProgressBar)
1397+{
1398+ ::libertine::scope::Container c;
1399+ c.status = ::libertine::scope::Container::ContainerStatus::installing;
1400+ c.progress = "12321";
1401+ EXPECT_CALL(*service, container_info(QString("palatine"))).WillOnce(testing::Return(c));
1402+ EXPECT_CALL(*service, update_progress(QString::fromStdString(c.progress)));
1403+
1404+ CreatePreview preview(result, metadata, service);
1405+ preview.run(proxy);
1406+
1407+ ASSERT_NE(nullptr, list);
1408+ ASSERT_EQ(2, list->size());
1409+
1410+ auto description = list->front();
1411+ EXPECT_EQ("warning", description.id());
1412+ EXPECT_EQ("text", description.widget_type());
1413+ EXPECT_EQ("Initializing this scope may consume up to 500MB of data and could take several minutes.", description.attribute_values()["title"].get_string());
1414+
1415+ list->pop_front();
1416+ auto buttons = list->front();
1417+ EXPECT_EQ("actions", buttons.id());
1418+ EXPECT_EQ("progress", buttons.widget_type());
1419+ auto source = buttons.attribute_values()["source"].get_dict();
1420+ EXPECT_EQ("com.canonical.libertine.ContainerManager", source["dbus-name"].get_string());
1421+ EXPECT_EQ(std::string("/Progress/") + c.progress, source["dbus-object"].get_string());
1422+}
1423+
1424+
1425+TEST_F(CreatePreviewTest, ShowsScopeReadyMessage)
1426+{
1427+ ::libertine::scope::Container c;
1428+ c.status = ::libertine::scope::Container::ContainerStatus::ready;
1429+ EXPECT_CALL(*service, container_info(QString("palatine"))).WillOnce(testing::Return(c));
1430+
1431+ CreatePreview preview(result, metadata, service);
1432+ preview.run(proxy);
1433+
1434+ ASSERT_NE(nullptr, list);
1435+ ASSERT_EQ(1, list->size());
1436+
1437+ auto description = list->front();
1438+ EXPECT_EQ("info", description.id());
1439+ EXPECT_EQ("text", description.widget_type());
1440+ EXPECT_EQ("Scope is ready.", description.attribute_values()["title"].get_string());
1441+}
1442+}
1443
1444=== modified file 'tests/scope/store/test_query.cpp'
1445--- tests/scope/store/test_query.cpp 2016-08-26 14:22:41 +0000
1446+++ tests/scope/store/test_query.cpp 2016-10-05 19:26:10 +0000
1447@@ -28,7 +28,7 @@
1448
1449 namespace
1450 {
1451-using namespace libertine::scope;
1452+using namespace libertine::scope::store;
1453
1454
1455 class FakeCategory : public unity::scopes::Category
1456@@ -56,6 +56,13 @@
1457 }
1458
1459
1460+MATCHER(ResultCreateMatch, "")
1461+{
1462+ return arg.contains("title") && arg["title"] == unity::scopes::Variant(Query::CREATE_CATEGORY_TITLE) &&
1463+ arg.contains("show_create_preview") && arg["show_create_preview"].get_bool();
1464+}
1465+
1466+
1467 class TestStoreQuery : public ::testing::Test
1468 {
1469 protected:
1470@@ -65,13 +72,13 @@
1471 , reply_()
1472 , proxy_(&reply_, [](unity::scopes::SearchReply*) {})
1473 , category_(std::make_shared<FakeCategory>("fake-container", "fake-container", "Application", unity::scopes::CategoryRenderer()))
1474- , service_(new testing::NiceMock<MockServiceManager>())
1475+ , service_(new testing::NiceMock<::libertine::scope::MockServiceManager>())
1476 {
1477 }
1478
1479- Package create_package(std::string const& name, std::string const& summary, std::string const& id)
1480+ ::libertine::scope::Package create_package(std::string const& name, std::string const& summary, std::string const& id)
1481 {
1482- Package package;
1483+ ::libertine::scope::Package package;
1484 package.name = name;
1485 package.summary = summary;
1486 package.id = id;
1487@@ -84,17 +91,25 @@
1488 EXPECT_CALL(reply_, push(testing::Matcher<unity::scopes::CategorisedResult const&>(ResultPackageMatch(title, subtitle, id)))).WillOnce(testing::Return(result));
1489 }
1490
1491+ void set_container_ready(::libertine::scope::Container::ContainerStatus status = ::libertine::scope::Container::ContainerStatus::ready)
1492+ {
1493+ ::libertine::scope::Container info;
1494+ info.status = status;
1495+ EXPECT_CALL(*service_, container_info(QString("palatine"))).WillOnce(testing::Return(info));
1496+ }
1497+
1498 unity::scopes::SearchMetadata metadata_;
1499 unity::scopes::CannedQuery canned_query_;
1500 testing::NiceMock<unity::scopes::testing::MockSearchReply> reply_;
1501 unity::scopes::SearchReplyProxy proxy_;
1502 std::shared_ptr<FakeCategory> category_;
1503- std::shared_ptr<testing::NiceMock<MockServiceManager>> service_;
1504+ std::shared_ptr<testing::NiceMock<::libertine::scope::MockServiceManager>> service_;
1505 };
1506
1507
1508 TEST_F(TestStoreQuery, ShowsSearchHintOnEmptyQuery)
1509 {
1510+ set_container_ready();
1511 EXPECT_CALL(reply_, register_category("hint", "", "", testing::_)).WillOnce(testing::Return(category_));
1512 EXPECT_CALL(reply_, push(testing::Matcher<unity::scopes::CategorisedResult const&>(ResultTitleMatch(Query::USE_SEARCH_HINT)))).WillOnce(testing::Return(true));
1513
1514@@ -105,9 +120,10 @@
1515
1516 TEST_F(TestStoreQuery, ShowsNoResultsHintOnQueryWithNoResults)
1517 {
1518+ set_container_ready();
1519 EXPECT_CALL(reply_, register_category("hint", "", "", testing::_)).WillOnce(testing::Return(category_));
1520 EXPECT_CALL(reply_, push(testing::Matcher<unity::scopes::CategorisedResult const&>(ResultTitleMatch(Query::NO_SEARCH_RESULTS_HINT)))).WillOnce(testing::Return(true));
1521- EXPECT_CALL(*service_, search_cache(testing::_)).WillOnce(testing::Return(QList<Package>{}));
1522+ EXPECT_CALL(*service_, search_cache(testing::_)).WillOnce(testing::Return(QList<::libertine::scope::Package>{}));
1523 canned_query_.set_query_string("foobar");
1524
1525 Query q(canned_query_, metadata_, service_);
1526@@ -117,12 +133,13 @@
1527
1528 TEST_F(TestStoreQuery, ShowSingleSearchResult)
1529 {
1530+ set_container_ready();
1531 EXPECT_CALL(reply_, register_category("aptcache", "1 result found", "Application", testing::_)).WillOnce(testing::Return(category_));
1532
1533 auto package = create_package("vim", "Writin' stuff", "vim.desktop");
1534 expect_push("vim", "Writin' stuff", "vim.desktop");
1535
1536- EXPECT_CALL(*service_, search_cache(testing::_)).WillOnce(testing::Return(QList<Package>{package}));
1537+ EXPECT_CALL(*service_, search_cache(testing::_)).WillOnce(testing::Return(QList<::libertine::scope::Package>{package}));
1538 canned_query_.set_query_string("vim");
1539
1540 Query q(canned_query_, metadata_, service_);
1541@@ -132,6 +149,7 @@
1542
1543 TEST_F(TestStoreQuery, ShowMultipleSearchResults)
1544 {
1545+ set_container_ready();
1546 EXPECT_CALL(reply_, register_category("aptcache", "3 results found", "Application", testing::_)).WillOnce(testing::Return(category_));
1547
1548 auto vim = create_package("vim", "Writin' stuff", "vim.desktop");
1549@@ -142,7 +160,7 @@
1550 expect_push("gedit", "Writin' gui stuff", "gedit.desktop");
1551 expect_push("ed", "Writin' simple stuff", "ed.desktop");
1552
1553- EXPECT_CALL(*service_, search_cache(testing::_)).WillOnce(testing::Return(QList<Package>{vim, gedit, ed}));
1554+ EXPECT_CALL(*service_, search_cache(testing::_)).WillOnce(testing::Return(QList<::libertine::scope::Package>{vim, gedit, ed}));
1555 canned_query_.set_query_string("vim");
1556
1557 Query q(canned_query_, metadata_, service_);
1558@@ -152,6 +170,7 @@
1559
1560 TEST_F(TestStoreQuery, FailureToPushEndsQueryPrematurely)
1561 {
1562+ set_container_ready();
1563 EXPECT_CALL(reply_, register_category("aptcache", "3 results found", "Application", testing::_)).WillOnce(testing::Return(category_));
1564
1565 auto vim = create_package("vim", "Writin' stuff", "vim.desktop");
1566@@ -161,10 +180,21 @@
1567 expect_push("vim", "Writin' stuff", "vim.desktop");
1568 expect_push("gedit", "Writin' gui stuff", "gedit.desktop", false);
1569
1570- EXPECT_CALL(*service_, search_cache(testing::_)).WillOnce(testing::Return(QList<Package>{vim, gedit, ed}));
1571+ EXPECT_CALL(*service_, search_cache(testing::_)).WillOnce(testing::Return(QList<::libertine::scope::Package>{vim, gedit, ed}));
1572 canned_query_.set_query_string("vim");
1573
1574 Query q(canned_query_, metadata_, service_);
1575 q.run(proxy_);
1576 }
1577+
1578+
1579+TEST_F(TestStoreQuery, ShowsCreateCategoryWhenContainerDoesNotExist)
1580+{
1581+ set_container_ready(::libertine::scope::Container::ContainerStatus::none);
1582+ EXPECT_CALL(reply_, register_category("create", "", "", testing::_)).WillOnce(testing::Return(category_));
1583+ EXPECT_CALL(reply_, push(testing::Matcher<unity::scopes::CategorisedResult const&>(ResultCreateMatch()))).WillOnce(testing::Return(true));
1584+
1585+ Query q(canned_query_, metadata_, service_);
1586+ q.run(proxy_);
1587+}
1588 }

Subscribers

People subscribed via source and target branches

to all changes: