Merge lp:unity-scope-click/devel into lp:unity-scope-click

Proposed by Alejandro J. Cura
Status: Merged
Approved by: dobey
Approved revision: 232
Merged at revision: 217
Proposed branch: lp:unity-scope-click/devel
Merge into: lp:unity-scope-click
Diff against target: 6601 lines (+3909/-1140)
61 files modified
.bzrignore (+0/-1)
autopilot/unityclickscope/test_click_scope.py (+60/-61)
data/CMakeLists.txt (+13/-4)
data/clickscope.ini.in.in (+7/-7)
debian/control (+2/-3)
po/CMakeLists.txt (+2/-1)
po/POTFILES.in (+2/-0)
po/ar.po (+92/-0)
po/ca.po (+90/-0)
po/de.po (+90/-0)
po/es.po (+92/-0)
po/eu.po (+92/-0)
po/fi.po (+92/-0)
po/gd.po (+94/-0)
po/gl.po (+90/-0)
po/he.po (+90/-0)
po/id.po (+90/-0)
po/it.po (+92/-0)
po/lv.po (+90/-0)
po/nb.po (+92/-0)
po/ru.po (+90/-0)
po/sl.po (+90/-0)
po/uk.po (+94/-0)
po/unity-scope-click.pot (+90/-0)
po/zh_CN.po (+90/-0)
scope/click/CMakeLists.txt (+3/-1)
scope/click/configuration.cpp (+124/-0)
scope/click/configuration.h (+62/-0)
scope/click/download-manager.cpp (+1/-1)
scope/click/index.cpp (+37/-206)
scope/click/index.h (+14/-101)
scope/click/interface.cpp (+72/-89)
scope/click/interface.h (+10/-15)
scope/click/package.cpp (+237/-0)
scope/click/package.h (+137/-0)
scope/click/preview.cpp (+232/-51)
scope/click/preview.h (+47/-13)
scope/click/qtbridge.cpp (+7/-28)
scope/click/qtbridge.h (+4/-132)
scope/click/query.cpp (+94/-202)
scope/click/query.h (+21/-2)
scope/click/reviews.cpp (+44/-2)
scope/click/reviews.h (+3/-1)
scope/click/scope.cpp (+24/-91)
scope/click/scope.h (+2/-2)
scope/click/scope_activation.cpp (+48/-0)
scope/click/scope_activation.h (+53/-0)
scope/click/webclient.cpp (+39/-25)
scope/click/webclient.h (+10/-4)
scope/tests/CMakeLists.txt (+2/-0)
scope/tests/applications/user/semi-broken.desktop (+1/-0)
scope/tests/fake_json.h (+29/-0)
scope/tests/integration/webclient_integration.cpp (+3/-10)
scope/tests/mock_webclient.h (+5/-10)
scope/tests/test_configuration.cpp (+174/-0)
scope/tests/test_data.h (+5/-0)
scope/tests/test_index.cpp (+97/-8)
scope/tests/test_interface.cpp (+148/-51)
scope/tests/test_query.cpp (+257/-0)
scope/tests/test_reviews.cpp (+70/-3)
scope/tests/test_webclient.cpp (+67/-15)
To merge this branch: bzr merge lp:unity-scope-click/devel
Reviewer Review Type Date Requested Status
dobey (community) Approve
PS Jenkins bot continuous-integration Needs Fixing
Review via email: mp+217604@code.launchpad.net

Commit message

- Clean up query.cpp by using the unit tested search code.
- Updated the autopilot tests to work with the new scopes.
- Removed the dependency on url-dispatcher.
- Use direct activation of Open/Go to Accounts actions on the shell side by setting 'uri' attribute of preview actions.
- Moved ScopeActivation to separate file.
- Add support for getting search index URL from environment.
- Fix the naming of the environment variable for reviews base URL.
- Move the Package and PackageDetails classes and related code to separate files.
- Only show the Uninstall button for apps with _removable flag set to true.
- Move Configuration tests to their own file.
- Refactor QProcess usage in Interface to a separate method.
- Add tests for get_manifest_for_app and get_manifests.
- Add methods to get language in use (en_US) and its base (en).
- Remove unused code in the qtbridge.
- Add a backend method to submit a review to the server.
- Build the preview using the strategy pattern.
- Display the publisher in the header, not the first line of description.
- Check for valid .desktop files.
- Add initial support for submitting ratings and reviews of apps.
- Improvements to support for translations.
- Use some local data to present a preview when offline or for unknown apps.
- Create a valid string for the Accept-Language HTTP header.
- Add the Accept-Language header by default to all HTTP requests.

Description of the change

Merging several branches from the /devel tree to trunk

To post a comment you must log in.
Revision history for this message
PS Jenkins bot (ps-jenkins) wrote :
review: Approve (continuous-integration)
lp:unity-scope-click/devel updated
224. By Alejandro J. Cura

Check for valid .desktop files. Fixes: https://bugs.launchpad.net/bugs/1313878.

Approved by Rodney Dawes, PS Jenkins bot.

Revision history for this message
PS Jenkins bot (ps-jenkins) wrote :
review: Approve (continuous-integration)
lp:unity-scope-click/devel updated
225. By dobey

Display the publisher in the header, not the first line of description. Fixes: https://bugs.launchpad.net/bugs/1313843.

Approved by Alejandro J. Cura, PS Jenkins bot.

Revision history for this message
PS Jenkins bot (ps-jenkins) wrote :
review: Approve (continuous-integration)
lp:unity-scope-click/devel updated
226. By dobey

Enable translation of the clickscope.ini data file.
Add missing query.cpp to POTFILES.in. Fixes: https://bugs.launchpad.net/bugs/1314353.

Approved by Alejandro J. Cura, PS Jenkins bot.

227. By dobey

Don't build the pot file automatically.
Include the pot file in the tree.

Approved by Alejandro J. Cura, PS Jenkins bot.

Revision history for this message
PS Jenkins bot (ps-jenkins) wrote :
review: Approve (continuous-integration)
lp:unity-scope-click/devel updated
228. By dobey

Add the language to the review.
Add a test to ensure the language is correctly added to the review.
Handle LANGUAGE being unset, in get_language(), falling back to "C".
Add tests to verify LANGUAGE being unset.
Integrate the rating-input widget to the InstalledPreview.
Submit the review when the user presses "Send" on the widget.

Approved by PS Jenkins bot, Alejandro J. Cura, Pawel Stolowski.

Revision history for this message
PS Jenkins bot (ps-jenkins) wrote :
review: Approve (continuous-integration)
Revision history for this message
PS Jenkins bot (ps-jenkins) wrote :
review: Approve (continuous-integration)
lp:unity-scope-click/devel updated
229. By Launchpad Translations on behalf of unity-team

Launchpad automatic translations update.

Revision history for this message
PS Jenkins bot (ps-jenkins) wrote :
review: Approve (continuous-integration)
lp:unity-scope-click/devel updated
230. By Alejandro J. Cura

Restore ubuntu-download-manager client mocks.

Approved by PS Jenkins bot, Rodney Dawes.

Revision history for this message
PS Jenkins bot (ps-jenkins) wrote :
review: Needs Fixing (continuous-integration)
lp:unity-scope-click/devel updated
231. By Launchpad Translations on behalf of unity-team

Launchpad automatic translations update.

Revision history for this message
PS Jenkins bot (ps-jenkins) wrote :
review: Needs Fixing (continuous-integration)
Revision history for this message
dobey (dobey) :
review: Approve
Revision history for this message
dobey (dobey) wrote :

There seems to be an issue with performing a search by typing into the search entry at the top of the screen, where the spinner that shows up in the entry during the search, never goes away, despite the results having been pushed to the dash. This is related to the switch to using Index::search() in query.cpp. Attempting to add a call to searchReply->finished() when the search was finished, seems to cause a crash. It seems like the pointer is being held somewhere, but I'm not sure where.

review: Needs Fixing
Revision history for this message
Alejandro J. Cura (alecu) wrote :
lp:unity-scope-click/devel updated
232. By Alejandro J. Cura

Force calling .finished() when the last search result is pushed.

Approved by Rodney Dawes, PS Jenkins bot.

Revision history for this message
dobey (dobey) :
review: Approve
lp:unity-scope-click/devel updated
233. By Launchpad Translations on behalf of unity-team

Launchpad automatic translations update.

234. By dobey

Use some local data to present a preview when offline or for unknown apps. Fixes: https://bugs.launchpad.net/bugs/1297436.

Approved by Pawel Stolowski, PS Jenkins bot.

235. By dobey

Create a valid string for the Accept-Language HTTP header.
Add the Accept-Language header by default to all HTTP requests. Fixes: https://bugs.launchpad.net/bugs/1314781.

Approved by Pawel Stolowski, PS Jenkins bot.

236. By dobey

Hide the rating widget until #1314117 is fixed.

Approved by PS Jenkins bot, Michal Hruby.

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
1=== modified file '.bzrignore'
2--- .bzrignore 2014-01-20 13:10:02 +0000
3+++ .bzrignore 2014-05-02 16:27:07 +0000
4@@ -25,7 +25,6 @@
5 *.la
6 *.lo
7 *.o
8-*.pot
9 *.service
10 *.tar.*
11 *.typelib
12
13=== modified file 'autopilot/unityclickscope/test_click_scope.py'
14--- autopilot/unityclickscope/test_click_scope.py 2014-02-03 15:42:51 +0000
15+++ autopilot/unityclickscope/test_click_scope.py 2014-05-02 16:27:07 +0000
16@@ -22,13 +22,11 @@
17 import fixtures
18 from autopilot.introspection import dbus as autopilot_dbus
19 from autopilot.matchers import Eventually
20-from testtools.matchers import Equals
21-from ubuntuuitoolkit import emulators as toolkit_emulators
22+from testtools.matchers import Equals, MatchesAny
23 from unity8 import process_helpers
24-from unity8.shell import (
25- emulators as unity_emulators,
26- tests as unity_tests
27-)
28+from unity8.shell import tests as unity_tests
29+from unity8.shell.emulators import dash
30+
31
32 from unityclickscope import credentials, fake_services, fixture_setup
33
34@@ -36,6 +34,10 @@
35 logger = logging.getLogger(__name__)
36
37
38+class ClickScopeException(Exception):
39+ """Exception raised when there's a problem with the scope."""
40+
41+
42 class BaseClickScopeTestCase(dbusmock.DBusTestCase, unity_tests.UnityTestCase):
43
44 scenarios = [
45@@ -57,7 +59,7 @@
46 unity_proxy = self.launch_unity()
47 process_helpers.unlock_unity(unity_proxy)
48 self.dash = self.main_window.get_dash()
49- self.scope = self.dash.get_scope('applications')
50+ self.scope = self.dash.get_scope('clickscope')
51
52 def _use_fake_server(self):
53 fake_search_server = fixture_setup.FakeSearchServerRunning()
54@@ -103,64 +105,76 @@
55
56 def _restart_scope(self):
57 logging.info('Restarting click scope.')
58- os.system('pkill click-scope')
59+ os.system('pkill -f -9 clickscope.ini')
60+ lib_path = '/usr/lib/$DEB_HOST_MULTIARCH/'
61+ scoperunner_path = os.path.join(lib_path, 'scoperunner/scoperunner')
62+ clickscope_config_ini_path = os.path.join(
63+ lib_path, 'unity-scopes/clickscope/clickscope.ini')
64 os.system(
65 "dpkg-architecture -c "
66- "'/usr/lib/$DEB_HOST_MULTIARCH//unity-scope-click/click-scope' &")
67+ "'{scoperunner} \"\" {clickscope}' &".format(
68+ scoperunner=scoperunner_path,
69+ clickscope=clickscope_config_ini_path))
70
71 def _unlock_screen(self):
72 self.main_window.get_greeter().swipe()
73
74 def open_scope(self):
75- self.dash.open_scope('applications')
76- self.scope.isCurrent.wait_for(True)
77-
78- def open_app_preview(self, name):
79- self.search(name)
80- icon = self.scope.wait_select_single('Tile', text=name)
81- pointing_device = toolkit_emulators.get_pointing_device()
82- pointing_device.click_object(icon)
83- preview = self.dash.wait_select_single(AppPreview)
84- preview.showProcessingAction.wait_for(False)
85- return preview
86+ scope = self.dash.open_scope('clickscope')
87+ scope.isCurrent.wait_for(True)
88+ return scope
89
90 def search(self, query):
91 # TODO move this to the unity8 main view emulator.
92 # --elopio - 2013-12-27
93- search_box = self._proxy.select_single("SearchIndicator")
94- self.touch.tap_object(search_box)
95+ search_indicator = self._proxy.select_single(
96+ 'SearchIndicator', objectName='search')
97+ self.touch.tap_object(search_indicator)
98+ page_header = self._proxy.select_single(
99+ 'PageHeader', objectName='pageHeader')
100+ search_container = page_header.select_single(
101+ 'QQuickItem', objectName='searchContainer')
102+ search_container.state.wait_for(
103+ MatchesAny(Equals('narrowActive'), Equals('active')))
104 self.keyboard.type(query)
105
106+ def open_app_preview(self, category, name):
107+ self.search(name)
108+ preview = self.scope.open_preview(category, name)
109+ preview.get_parent().ready.wait_for(True)
110+ return preview
111+
112
113 class TestCaseWithHomeScopeOpen(BaseClickScopeTestCase):
114
115 def test_open_scope_scrolling(self):
116- self.assertFalse(self.scope.isCurrent)
117- self.dash.open_scope('applications')
118- self.assertThat(self.scope.isCurrent, Eventually(Equals(True)))
119+ scope = self.dash.open_scope('clickscope')
120+ self.assertThat(scope.isCurrent, Equals(True))
121
122
123 class TestCaseWithClickScopeOpen(BaseClickScopeTestCase):
124
125 def setUp(self):
126 super(TestCaseWithClickScopeOpen, self).setUp()
127- self.open_scope()
128+ self.scope = self.open_scope()
129
130 def test_search_available_app(self):
131 self.search('Shorts')
132- self.scope.wait_select_single('Tile', text='Shorts')
133+ applications = self.scope.get_applications('appstore')
134+ self.assertThat(applications[0].title, Equals('Shorts'))
135
136 def test_open_app_preview(self):
137 expected_details = dict(
138- title='Shorts', publisher='Ubuntu Click Loader')
139- preview = self.open_app_preview('Shorts')
140+ title='Shorts', subtitle='Shorts is an rssreader application')
141+ preview = self.open_app_preview('appstore', 'Shorts')
142 details = preview.get_details()
143 self.assertEqual(details, expected_details)
144
145 def test_install_without_credentials(self):
146- preview = self.open_app_preview('Shorts')
147+ preview = self.open_app_preview('appstore', 'Shorts')
148 preview.install()
149- error = self.dash.wait_select_single(DashPreview)
150+ error = self.dash.wait_select_single(Preview)
151+
152 details = error.get_details()
153 self.assertEqual('Login Error', details.get('title'))
154
155@@ -168,12 +182,14 @@
156 class ClickScopeTestCaseWithCredentials(BaseClickScopeTestCase):
157
158 def setUp(self):
159+ self.skipTest('segfaults. TODO in following branches.')
160 self.add_u1_credentials()
161 super(ClickScopeTestCaseWithCredentials, self).setUp()
162- self.open_scope()
163- self.preview = self.open_app_preview('Shorts')
164+ self.scope = self.open_scope()
165+ self.preview = self.open_app_preview('appstore', 'Shorts')
166
167 def add_u1_credentials(self):
168+ import pdb; pdb.set_trace()
169 account_manager = credentials.AccountManager()
170 account = account_manager.add_u1_credentials(
171 'dummy@example.com', 'dummy')
172@@ -187,43 +203,26 @@
173 self.preview.is_progress_bar_visible, Eventually(Equals(True)))
174
175
176-class Preview(object):
177-
178- def get_details(self):
179- """Return the details of the open preview."""
180- title = self.select_single('Label', objectName='titleLabel').text
181- subtitle = self.select_single(
182- 'Label', objectName='subtitleLabel').text
183- # The description label doesn't have an object name. Reported as bug
184- # http://pad.lv/1269114 -- elopio - 2014-1-14
185- # description = self.select_single(
186- # 'Label', objectName='descriptionLabel').text
187- # TODO check screenshots, icon, rating and reviews.
188- return dict(title=title, subtitle=subtitle)
189-
190-
191-# TODO move this to unity. --elopio - 2014-1-22
192-class DashPreview(unity_emulators.UnityEmulatorBase, Preview):
193- """Autopilot emulator for the generic preview."""
194-
195-
196-# TODO move this to unity. --elopio - 2014-1-14
197-class AppPreview(unity_emulators.UnityEmulatorBase, Preview):
198+class DashApps(dash.DashApps):
199+ """Autopilot emulator for the applicatios scope."""
200+
201+
202+class Preview(dash.Preview):
203 """Autopilot emulator for the application preview."""
204
205 def get_details(self):
206 """Return the details of the application whose preview is open."""
207- details = super(AppPreview, self).get_details()
208+ card_header = self.select_single('CardHeader', objectName='cardHeader')
209 return dict(
210- title=details.get('title'), publisher=details.get('subtitle'))
211+ title=card_header.title, subtitle=card_header.subtitle)
212
213 def install(self):
214- install_button = self.select_single('Button', objectName='button0')
215- if install_button.text != 'Install':
216- raise unity_emulators.UnityEmulatorException(
217- 'Install button not found.')
218+ parent = self.get_parent()
219+ install_button = self.select_single(
220+ 'PreviewActionButton', objectName='buttoninstall_click')
221 self.pointing_device.click_object(install_button)
222 self.implicitHeight.wait_for(0)
223+ parent.ready.wait_for(True)
224
225 def is_progress_bar_visible(self):
226 try:
227
228=== modified file 'data/CMakeLists.txt'
229--- data/CMakeLists.txt 2014-03-06 15:38:35 +0000
230+++ data/CMakeLists.txt 2014-05-02 16:27:07 +0000
231@@ -1,12 +1,21 @@
232+find_program(INTLTOOL_MERGE intltool-merge)
233+set(SCOPE_INI_TARGET clickscope.ini)
234+
235 configure_file(
236- clickscope.ini.in
237- clickscope.ini
238-)
239+ ${SCOPE_INI_TARGET}.in.in
240+ ${SCOPE_INI_TARGET}.in
241+)
242+
243+add_custom_target(${SCOPE_INI_TARGET} ALL
244+ COMMENT "Merging translations into ${SCOPE_INI_TARGET}"
245+ COMMAND LC_ALL=C ${INTLTOOL_MERGE} -d -u ${CMAKE_SOURCE_DIR}/po ${SCOPE_INI_TARGET}.in ${SCOPE_INI_TARGET} >/dev/null
246+)
247+
248 install(
249 FILES clickscope-screenshot.jpg apps-scope.svg
250 DESTINATION "${SCOPE_DATA_DIR}"
251 )
252 install(
253- FILES "${CMAKE_CURRENT_BINARY_DIR}/clickscope.ini"
254+ FILES "${CMAKE_CURRENT_BINARY_DIR}/${SCOPE_INI_TARGET}"
255 DESTINATION "${SCOPE_LIB_DIR}"
256 )
257
258=== renamed file 'data/clickscope.ini.in' => 'data/clickscope.ini.in.in'
259--- data/clickscope.ini.in 2014-02-24 13:36:22 +0000
260+++ data/clickscope.ini.in.in 2014-05-02 16:27:07 +0000
261@@ -1,8 +1,8 @@
262 [ScopeConfig]
263-DisplayName = Apps
264-Description = Scope for searching the click app store
265-Author = Canonical Ltd.
266-Art = @SCOPE_DATA_DIR@/clickscope-screenshot.jpg
267-Icon = @SCOPE_DATA_DIR@/apps-scope.svg
268-SearchHint = clickscope.SearchHint
269-HotKey = clickscope.HotKey
270+_DisplayName=Apps
271+_Description=Scope for searching the click app store
272+Author=Canonical Ltd.
273+Art=@SCOPE_DATA_DIR@/clickscope-screenshot.jpg
274+Icon=@SCOPE_DATA_DIR@/apps-scope.svg
275+SearchHint=clickscope.SearchHint
276+HotKey=clickscope.HotKey
277
278=== modified file 'debian/control'
279--- debian/control 2014-04-10 18:19:33 +0000
280+++ debian/control 2014-05-02 16:27:07 +0000
281@@ -8,11 +8,10 @@
282 intltool,
283 libglib2.0-dev (>= 2.32),
284 libjsoncpp-dev,
285- libubuntu-download-manager-client-dev,
286- libubuntu-download-manager-common-dev,
287+ libubuntu-download-manager-client-dev (>= 0.3+14.10.20140430-0ubuntu1),
288+ libubuntu-download-manager-common-dev (>= 0.3+14.10.20140430-0ubuntu1),
289 libubuntuoneauth-2.0-dev,
290 libunity-scopes-dev (>= 0.4.0),
291- liburl-dispatcher1-dev,
292 pkg-config,
293 Maintainer: Ubuntu Developers <ubuntu-devel-discuss@lists.ubuntu.com>
294 Standards-Version: 3.9.5
295
296=== modified file 'po/CMakeLists.txt'
297--- po/CMakeLists.txt 2014-04-03 16:06:05 +0000
298+++ po/CMakeLists.txt 2014-05-02 16:27:07 +0000
299@@ -17,9 +17,10 @@
300 )
301
302 # Creates the .pot file containing the translations template
303-add_custom_target(${POT_FILE} ALL
304+add_custom_target(${POT_FILE}
305 COMMENT "Generating translation template"
306 COMMAND XGETTEXT="${GETTEXT_XGETTEXT_EXECUTABLE}" srcdir="${CMAKE_CURRENT_SOURCE_DIR}" ${INTLTOOL_UPDATE} --gettext-package ${GETTEXT_PACKAGE} --pot
307+ COMMAND cp -f ${POT_FILE} ${CMAKE_CURRENT_SOURCE_DIR}/
308 DEPENDS POTFILES
309 )
310
311
312=== modified file 'po/POTFILES.in'
313--- po/POTFILES.in 2014-04-03 16:06:05 +0000
314+++ po/POTFILES.in 2014-05-02 16:27:07 +0000
315@@ -1,1 +1,3 @@
316+[type: gettext/ini] data/clickscope.ini.in.in
317 scope/click/preview.cpp
318+scope/click/query.cpp
319
320=== added file 'po/ar.po'
321--- po/ar.po 1970-01-01 00:00:00 +0000
322+++ po/ar.po 2014-05-02 16:27:07 +0000
323@@ -0,0 +1,92 @@
324+# Arabic translation for unity-scope-click
325+# Copyright (c) 2014 Rosetta Contributors and Canonical Ltd 2014
326+# This file is distributed under the same license as the unity-scope-click package.
327+# FIRST AUTHOR <EMAIL@ADDRESS>, 2014.
328+#
329+msgid ""
330+msgstr ""
331+"Project-Id-Version: unity-scope-click\n"
332+"Report-Msgid-Bugs-To: FULL NAME <EMAIL@ADDRESS>\n"
333+"POT-Creation-Date: 2014-04-29 15:20-0400\n"
334+"PO-Revision-Date: 2014-05-01 19:32+0000\n"
335+"Last-Translator: Ibrahim Saed <ibraheem5000@gmail.com>\n"
336+"Language-Team: Arabic <ar@li.org>\n"
337+"MIME-Version: 1.0\n"
338+"Content-Type: text/plain; charset=UTF-8\n"
339+"Content-Transfer-Encoding: 8bit\n"
340+"X-Launchpad-Export-Date: 2014-05-02 07:39+0000\n"
341+"X-Generator: Launchpad (build 16985)\n"
342+
343+#: ../data/clickscope.ini.in.in.h:1
344+msgid "Apps"
345+msgstr "التطبيقات"
346+
347+#: ../data/clickscope.ini.in.in.h:2
348+msgid "Scope for searching the click app store"
349+msgstr ""
350+
351+#: /home/dobey/Projects/canonical/unity-scope-click/no-auto-pot/po/../scope/click/preview.cpp:199
352+msgid "Download Error"
353+msgstr "خطأ في التنزيل"
354+
355+#: /home/dobey/Projects/canonical/unity-scope-click/no-auto-pot/po/../scope/click/preview.cpp:200
356+msgid "Download or install failed. Please try again."
357+msgstr "فشل في التنزيل أو التثبيت. يرجى المحاولة مجددًا."
358+
359+#. TODO see bug LP: #1289434
360+#: /home/dobey/Projects/canonical/unity-scope-click/no-auto-pot/po/../scope/click/preview.cpp:202
361+msgid "Close"
362+msgstr "إغلاق"
363+
364+#: /home/dobey/Projects/canonical/unity-scope-click/no-auto-pot/po/../scope/click/preview.cpp:207
365+msgid "Login Error"
366+msgstr "خطأ في الولوج"
367+
368+#: /home/dobey/Projects/canonical/unity-scope-click/no-auto-pot/po/../scope/click/preview.cpp:208
369+msgid "Please log in to your Ubuntu One account."
370+msgstr "يرجى الولوج إلى حساب أوبونتو ون خاصتك."
371+
372+#: /home/dobey/Projects/canonical/unity-scope-click/no-auto-pot/po/../scope/click/preview.cpp:210
373+msgid "Go to Accounts"
374+msgstr "انتقل إلى الحسابات"
375+
376+#: /home/dobey/Projects/canonical/unity-scope-click/no-auto-pot/po/../scope/click/preview.cpp:391
377+msgid "Open"
378+msgstr "فتح"
379+
380+#: /home/dobey/Projects/canonical/unity-scope-click/no-auto-pot/po/../scope/click/preview.cpp:399
381+msgid "Uninstall"
382+msgstr "إزالة التثبيت"
383+
384+#: /home/dobey/Projects/canonical/unity-scope-click/no-auto-pot/po/../scope/click/preview.cpp:484
385+msgid "Confirmation"
386+msgstr "التأكيد"
387+
388+#: /home/dobey/Projects/canonical/unity-scope-click/no-auto-pot/po/../scope/click/preview.cpp:486
389+msgid ""
390+"Uninstalling this app will delete all the related information. Are you sure "
391+"you want to uninstall?"
392+msgstr ""
393+"إزالة تثبيت هذا التطبيق ستؤدي لحذف جميع المعلومات المتعلقة به. هل أنت متأكد "
394+"من رغبتك بإزالة التثبيت؟"
395+
396+#. TODO: see bug LP: #1289434
397+#: /home/dobey/Projects/canonical/unity-scope-click/no-auto-pot/po/../scope/click/preview.cpp:493
398+msgid "Not anymore"
399+msgstr "ليس بعد الآن"
400+
401+#: /home/dobey/Projects/canonical/unity-scope-click/no-auto-pot/po/../scope/click/preview.cpp:497
402+msgid "Yes Uninstall"
403+msgstr "نعم أزِل التثبيت"
404+
405+#: /home/dobey/Projects/canonical/unity-scope-click/no-auto-pot/po/../scope/click/preview.cpp:545
406+msgid "Install"
407+msgstr "تثبيت"
408+
409+#: /home/dobey/Projects/canonical/unity-scope-click/no-auto-pot/po/../scope/click/query.cpp:95
410+msgid "My apps"
411+msgstr "تطبيقاتي"
412+
413+#: /home/dobey/Projects/canonical/unity-scope-click/no-auto-pot/po/../scope/click/query.cpp:184
414+msgid "Available"
415+msgstr "متوفر"
416
417=== added file 'po/ca.po'
418--- po/ca.po 1970-01-01 00:00:00 +0000
419+++ po/ca.po 2014-05-02 16:27:07 +0000
420@@ -0,0 +1,90 @@
421+# Catalan translation for unity-scope-click
422+# Copyright (c) 2014 Rosetta Contributors and Canonical Ltd 2014
423+# This file is distributed under the same license as the unity-scope-click package.
424+# FIRST AUTHOR <EMAIL@ADDRESS>, 2014.
425+#
426+msgid ""
427+msgstr ""
428+"Project-Id-Version: unity-scope-click\n"
429+"Report-Msgid-Bugs-To: FULL NAME <EMAIL@ADDRESS>\n"
430+"POT-Creation-Date: 2014-04-29 15:20-0400\n"
431+"PO-Revision-Date: 2014-04-29 21:24+0000\n"
432+"Last-Translator: David Planella <david.planella@ubuntu.com>\n"
433+"Language-Team: Catalan <ca@li.org>\n"
434+"MIME-Version: 1.0\n"
435+"Content-Type: text/plain; charset=UTF-8\n"
436+"Content-Transfer-Encoding: 8bit\n"
437+"X-Launchpad-Export-Date: 2014-04-30 07:36+0000\n"
438+"X-Generator: Launchpad (build 16985)\n"
439+
440+#: ../data/clickscope.ini.in.in.h:1
441+msgid "Apps"
442+msgstr "Aplicacions"
443+
444+#: ../data/clickscope.ini.in.in.h:2
445+msgid "Scope for searching the click app store"
446+msgstr ""
447+
448+#: /home/dobey/Projects/canonical/unity-scope-click/no-auto-pot/po/../scope/click/preview.cpp:199
449+msgid "Download Error"
450+msgstr ""
451+
452+#: /home/dobey/Projects/canonical/unity-scope-click/no-auto-pot/po/../scope/click/preview.cpp:200
453+msgid "Download or install failed. Please try again."
454+msgstr ""
455+
456+#. TODO see bug LP: #1289434
457+#: /home/dobey/Projects/canonical/unity-scope-click/no-auto-pot/po/../scope/click/preview.cpp:202
458+msgid "Close"
459+msgstr "Tanca"
460+
461+#: /home/dobey/Projects/canonical/unity-scope-click/no-auto-pot/po/../scope/click/preview.cpp:207
462+msgid "Login Error"
463+msgstr ""
464+
465+#: /home/dobey/Projects/canonical/unity-scope-click/no-auto-pot/po/../scope/click/preview.cpp:208
466+msgid "Please log in to your Ubuntu One account."
467+msgstr ""
468+
469+#: /home/dobey/Projects/canonical/unity-scope-click/no-auto-pot/po/../scope/click/preview.cpp:210
470+msgid "Go to Accounts"
471+msgstr ""
472+
473+#: /home/dobey/Projects/canonical/unity-scope-click/no-auto-pot/po/../scope/click/preview.cpp:391
474+msgid "Open"
475+msgstr ""
476+
477+#: /home/dobey/Projects/canonical/unity-scope-click/no-auto-pot/po/../scope/click/preview.cpp:399
478+msgid "Uninstall"
479+msgstr ""
480+
481+#: /home/dobey/Projects/canonical/unity-scope-click/no-auto-pot/po/../scope/click/preview.cpp:484
482+msgid "Confirmation"
483+msgstr ""
484+
485+#: /home/dobey/Projects/canonical/unity-scope-click/no-auto-pot/po/../scope/click/preview.cpp:486
486+msgid ""
487+"Uninstalling this app will delete all the related information. Are you sure "
488+"you want to uninstall?"
489+msgstr ""
490+
491+#. TODO: see bug LP: #1289434
492+#: /home/dobey/Projects/canonical/unity-scope-click/no-auto-pot/po/../scope/click/preview.cpp:493
493+msgid "Not anymore"
494+msgstr ""
495+
496+#: /home/dobey/Projects/canonical/unity-scope-click/no-auto-pot/po/../scope/click/preview.cpp:497
497+msgid "Yes Uninstall"
498+msgstr ""
499+
500+#: /home/dobey/Projects/canonical/unity-scope-click/no-auto-pot/po/../scope/click/preview.cpp:545
501+msgid "Install"
502+msgstr ""
503+
504+#: /home/dobey/Projects/canonical/unity-scope-click/no-auto-pot/po/../scope/click/query.cpp:95
505+msgid "My apps"
506+msgstr ""
507+
508+#: /home/dobey/Projects/canonical/unity-scope-click/no-auto-pot/po/../scope/click/query.cpp:184
509+msgid "Available"
510+msgstr ""
511
512=== added file 'po/de.po'
513--- po/de.po 1970-01-01 00:00:00 +0000
514+++ po/de.po 2014-05-02 16:27:07 +0000
515@@ -0,0 +1,90 @@
516+# German translation for unity-scope-click
517+# Copyright (c) 2014 Rosetta Contributors and Canonical Ltd 2014
518+# This file is distributed under the same license as the unity-scope-click package.
519+# FIRST AUTHOR <EMAIL@ADDRESS>, 2014.
520+#
521+msgid ""
522+msgstr ""
523+"Project-Id-Version: unity-scope-click\n"
524+"Report-Msgid-Bugs-To: FULL NAME <EMAIL@ADDRESS>\n"
525+"POT-Creation-Date: 2014-04-29 15:20-0400\n"
526+"PO-Revision-Date: 2014-04-29 21:45+0000\n"
527+"Last-Translator: Phillip Sz <Unknown>\n"
528+"Language-Team: German <de@li.org>\n"
529+"MIME-Version: 1.0\n"
530+"Content-Type: text/plain; charset=UTF-8\n"
531+"Content-Transfer-Encoding: 8bit\n"
532+"X-Launchpad-Export-Date: 2014-04-30 07:36+0000\n"
533+"X-Generator: Launchpad (build 16985)\n"
534+
535+#: ../data/clickscope.ini.in.in.h:1
536+msgid "Apps"
537+msgstr "Anwendungen"
538+
539+#: ../data/clickscope.ini.in.in.h:2
540+msgid "Scope for searching the click app store"
541+msgstr ""
542+
543+#: /home/dobey/Projects/canonical/unity-scope-click/no-auto-pot/po/../scope/click/preview.cpp:199
544+msgid "Download Error"
545+msgstr "Fehler beim Herunterladen"
546+
547+#: /home/dobey/Projects/canonical/unity-scope-click/no-auto-pot/po/../scope/click/preview.cpp:200
548+msgid "Download or install failed. Please try again."
549+msgstr ""
550+
551+#. TODO see bug LP: #1289434
552+#: /home/dobey/Projects/canonical/unity-scope-click/no-auto-pot/po/../scope/click/preview.cpp:202
553+msgid "Close"
554+msgstr "Schließen"
555+
556+#: /home/dobey/Projects/canonical/unity-scope-click/no-auto-pot/po/../scope/click/preview.cpp:207
557+msgid "Login Error"
558+msgstr "Anmeldefehler"
559+
560+#: /home/dobey/Projects/canonical/unity-scope-click/no-auto-pot/po/../scope/click/preview.cpp:208
561+msgid "Please log in to your Ubuntu One account."
562+msgstr ""
563+
564+#: /home/dobey/Projects/canonical/unity-scope-click/no-auto-pot/po/../scope/click/preview.cpp:210
565+msgid "Go to Accounts"
566+msgstr ""
567+
568+#: /home/dobey/Projects/canonical/unity-scope-click/no-auto-pot/po/../scope/click/preview.cpp:391
569+msgid "Open"
570+msgstr "Öffnen"
571+
572+#: /home/dobey/Projects/canonical/unity-scope-click/no-auto-pot/po/../scope/click/preview.cpp:399
573+msgid "Uninstall"
574+msgstr "Entfernen"
575+
576+#: /home/dobey/Projects/canonical/unity-scope-click/no-auto-pot/po/../scope/click/preview.cpp:484
577+msgid "Confirmation"
578+msgstr "Bestätigung"
579+
580+#: /home/dobey/Projects/canonical/unity-scope-click/no-auto-pot/po/../scope/click/preview.cpp:486
581+msgid ""
582+"Uninstalling this app will delete all the related information. Are you sure "
583+"you want to uninstall?"
584+msgstr ""
585+
586+#. TODO: see bug LP: #1289434
587+#: /home/dobey/Projects/canonical/unity-scope-click/no-auto-pot/po/../scope/click/preview.cpp:493
588+msgid "Not anymore"
589+msgstr ""
590+
591+#: /home/dobey/Projects/canonical/unity-scope-click/no-auto-pot/po/../scope/click/preview.cpp:497
592+msgid "Yes Uninstall"
593+msgstr ""
594+
595+#: /home/dobey/Projects/canonical/unity-scope-click/no-auto-pot/po/../scope/click/preview.cpp:545
596+msgid "Install"
597+msgstr "Installieren"
598+
599+#: /home/dobey/Projects/canonical/unity-scope-click/no-auto-pot/po/../scope/click/query.cpp:95
600+msgid "My apps"
601+msgstr "Meine Anwendungen"
602+
603+#: /home/dobey/Projects/canonical/unity-scope-click/no-auto-pot/po/../scope/click/query.cpp:184
604+msgid "Available"
605+msgstr "Verfügbar"
606
607=== added file 'po/es.po'
608--- po/es.po 1970-01-01 00:00:00 +0000
609+++ po/es.po 2014-05-02 16:27:07 +0000
610@@ -0,0 +1,92 @@
611+# Spanish translation for unity-scope-click
612+# Copyright (c) 2014 Rosetta Contributors and Canonical Ltd 2014
613+# This file is distributed under the same license as the unity-scope-click package.
614+# FIRST AUTHOR <EMAIL@ADDRESS>, 2014.
615+#
616+msgid ""
617+msgstr ""
618+"Project-Id-Version: unity-scope-click\n"
619+"Report-Msgid-Bugs-To: FULL NAME <EMAIL@ADDRESS>\n"
620+"POT-Creation-Date: 2014-04-29 15:20-0400\n"
621+"PO-Revision-Date: 2014-05-01 06:54+0000\n"
622+"Last-Translator: Paco Molinero <paco@byasl.com>\n"
623+"Language-Team: Spanish <es@li.org>\n"
624+"MIME-Version: 1.0\n"
625+"Content-Type: text/plain; charset=UTF-8\n"
626+"Content-Transfer-Encoding: 8bit\n"
627+"X-Launchpad-Export-Date: 2014-05-02 07:39+0000\n"
628+"X-Generator: Launchpad (build 16985)\n"
629+
630+#: ../data/clickscope.ini.in.in.h:1
631+msgid "Apps"
632+msgstr "Aplicaciones"
633+
634+#: ../data/clickscope.ini.in.in.h:2
635+msgid "Scope for searching the click app store"
636+msgstr "Scope para buscar en la tienda de aplicaciones"
637+
638+#: /home/dobey/Projects/canonical/unity-scope-click/no-auto-pot/po/../scope/click/preview.cpp:199
639+msgid "Download Error"
640+msgstr "Error en la descarga"
641+
642+#: /home/dobey/Projects/canonical/unity-scope-click/no-auto-pot/po/../scope/click/preview.cpp:200
643+msgid "Download or install failed. Please try again."
644+msgstr "La descarga o la instalación han fallado. Inténtelo nuevamente."
645+
646+#. TODO see bug LP: #1289434
647+#: /home/dobey/Projects/canonical/unity-scope-click/no-auto-pot/po/../scope/click/preview.cpp:202
648+msgid "Close"
649+msgstr "Cerrar"
650+
651+#: /home/dobey/Projects/canonical/unity-scope-click/no-auto-pot/po/../scope/click/preview.cpp:207
652+msgid "Login Error"
653+msgstr "Error de autenticación"
654+
655+#: /home/dobey/Projects/canonical/unity-scope-click/no-auto-pot/po/../scope/click/preview.cpp:208
656+msgid "Please log in to your Ubuntu One account."
657+msgstr "Acceda a su cuenta de Ubuntu One."
658+
659+#: /home/dobey/Projects/canonical/unity-scope-click/no-auto-pot/po/../scope/click/preview.cpp:210
660+msgid "Go to Accounts"
661+msgstr "Ir a Cuentas"
662+
663+#: /home/dobey/Projects/canonical/unity-scope-click/no-auto-pot/po/../scope/click/preview.cpp:391
664+msgid "Open"
665+msgstr "Abrir"
666+
667+#: /home/dobey/Projects/canonical/unity-scope-click/no-auto-pot/po/../scope/click/preview.cpp:399
668+msgid "Uninstall"
669+msgstr "Desinstalar"
670+
671+#: /home/dobey/Projects/canonical/unity-scope-click/no-auto-pot/po/../scope/click/preview.cpp:484
672+msgid "Confirmation"
673+msgstr "Confirmación"
674+
675+#: /home/dobey/Projects/canonical/unity-scope-click/no-auto-pot/po/../scope/click/preview.cpp:486
676+msgid ""
677+"Uninstalling this app will delete all the related information. Are you sure "
678+"you want to uninstall?"
679+msgstr ""
680+"Desinstalar esta aplicación borrará toda la información asociada. ¿Quiere "
681+"desinstalar?"
682+
683+#. TODO: see bug LP: #1289434
684+#: /home/dobey/Projects/canonical/unity-scope-click/no-auto-pot/po/../scope/click/preview.cpp:493
685+msgid "Not anymore"
686+msgstr "Cancelar"
687+
688+#: /home/dobey/Projects/canonical/unity-scope-click/no-auto-pot/po/../scope/click/preview.cpp:497
689+msgid "Yes Uninstall"
690+msgstr "Desinstalar"
691+
692+#: /home/dobey/Projects/canonical/unity-scope-click/no-auto-pot/po/../scope/click/preview.cpp:545
693+msgid "Install"
694+msgstr "Instalar"
695+
696+#: /home/dobey/Projects/canonical/unity-scope-click/no-auto-pot/po/../scope/click/query.cpp:95
697+msgid "My apps"
698+msgstr "Mis aplicaciones"
699+
700+#: /home/dobey/Projects/canonical/unity-scope-click/no-auto-pot/po/../scope/click/query.cpp:184
701+msgid "Available"
702+msgstr "Disponibles"
703
704=== added file 'po/eu.po'
705--- po/eu.po 1970-01-01 00:00:00 +0000
706+++ po/eu.po 2014-05-02 16:27:07 +0000
707@@ -0,0 +1,92 @@
708+# Basque translation for unity-scope-click
709+# Copyright (c) 2014 Rosetta Contributors and Canonical Ltd 2014
710+# This file is distributed under the same license as the unity-scope-click package.
711+# FIRST AUTHOR <EMAIL@ADDRESS>, 2014.
712+#
713+msgid ""
714+msgstr ""
715+"Project-Id-Version: unity-scope-click\n"
716+"Report-Msgid-Bugs-To: FULL NAME <EMAIL@ADDRESS>\n"
717+"POT-Creation-Date: 2014-04-29 15:20-0400\n"
718+"PO-Revision-Date: 2014-04-29 21:40+0000\n"
719+"Last-Translator: Ibai Oihanguren Sala <Unknown>\n"
720+"Language-Team: Basque <eu@li.org>\n"
721+"MIME-Version: 1.0\n"
722+"Content-Type: text/plain; charset=UTF-8\n"
723+"Content-Transfer-Encoding: 8bit\n"
724+"X-Launchpad-Export-Date: 2014-04-30 07:36+0000\n"
725+"X-Generator: Launchpad (build 16985)\n"
726+
727+#: ../data/clickscope.ini.in.in.h:1
728+msgid "Apps"
729+msgstr "Aplikazioak"
730+
731+#: ../data/clickscope.ini.in.in.h:2
732+msgid "Scope for searching the click app store"
733+msgstr ""
734+
735+#: /home/dobey/Projects/canonical/unity-scope-click/no-auto-pot/po/../scope/click/preview.cpp:199
736+msgid "Download Error"
737+msgstr "Deskarga-errorea"
738+
739+#: /home/dobey/Projects/canonical/unity-scope-click/no-auto-pot/po/../scope/click/preview.cpp:200
740+msgid "Download or install failed. Please try again."
741+msgstr "Deskarga edo instalazioak huts egin du. Saiatu berriro."
742+
743+#. TODO see bug LP: #1289434
744+#: /home/dobey/Projects/canonical/unity-scope-click/no-auto-pot/po/../scope/click/preview.cpp:202
745+msgid "Close"
746+msgstr "Itxi"
747+
748+#: /home/dobey/Projects/canonical/unity-scope-click/no-auto-pot/po/../scope/click/preview.cpp:207
749+msgid "Login Error"
750+msgstr "Errorea saioa hastean"
751+
752+#: /home/dobey/Projects/canonical/unity-scope-click/no-auto-pot/po/../scope/click/preview.cpp:208
753+msgid "Please log in to your Ubuntu One account."
754+msgstr "Hasi saioa zure Ubuntu One kontuan."
755+
756+#: /home/dobey/Projects/canonical/unity-scope-click/no-auto-pot/po/../scope/click/preview.cpp:210
757+msgid "Go to Accounts"
758+msgstr "Joan Kontuak-era"
759+
760+#: /home/dobey/Projects/canonical/unity-scope-click/no-auto-pot/po/../scope/click/preview.cpp:391
761+msgid "Open"
762+msgstr "Ireki"
763+
764+#: /home/dobey/Projects/canonical/unity-scope-click/no-auto-pot/po/../scope/click/preview.cpp:399
765+msgid "Uninstall"
766+msgstr "Desinstalatu"
767+
768+#: /home/dobey/Projects/canonical/unity-scope-click/no-auto-pot/po/../scope/click/preview.cpp:484
769+msgid "Confirmation"
770+msgstr "Berrespena"
771+
772+#: /home/dobey/Projects/canonical/unity-scope-click/no-auto-pot/po/../scope/click/preview.cpp:486
773+msgid ""
774+"Uninstalling this app will delete all the related information. Are you sure "
775+"you want to uninstall?"
776+msgstr ""
777+"Aplikazio hau desinstalatuz erlazionatutako informazio guztia ezabatuko da. "
778+"Ziur desinstalatu nahi duzula?"
779+
780+#. TODO: see bug LP: #1289434
781+#: /home/dobey/Projects/canonical/unity-scope-click/no-auto-pot/po/../scope/click/preview.cpp:493
782+msgid "Not anymore"
783+msgstr ""
784+
785+#: /home/dobey/Projects/canonical/unity-scope-click/no-auto-pot/po/../scope/click/preview.cpp:497
786+msgid "Yes Uninstall"
787+msgstr "Bai, desinstalatu"
788+
789+#: /home/dobey/Projects/canonical/unity-scope-click/no-auto-pot/po/../scope/click/preview.cpp:545
790+msgid "Install"
791+msgstr "Instalatu"
792+
793+#: /home/dobey/Projects/canonical/unity-scope-click/no-auto-pot/po/../scope/click/query.cpp:95
794+msgid "My apps"
795+msgstr "Nire aplikazioak"
796+
797+#: /home/dobey/Projects/canonical/unity-scope-click/no-auto-pot/po/../scope/click/query.cpp:184
798+msgid "Available"
799+msgstr "Eskuragarri"
800
801=== added file 'po/fi.po'
802--- po/fi.po 1970-01-01 00:00:00 +0000
803+++ po/fi.po 2014-05-02 16:27:07 +0000
804@@ -0,0 +1,92 @@
805+# Finnish translation for unity-scope-click
806+# Copyright (c) 2014 Rosetta Contributors and Canonical Ltd 2014
807+# This file is distributed under the same license as the unity-scope-click package.
808+# FIRST AUTHOR <EMAIL@ADDRESS>, 2014.
809+#
810+msgid ""
811+msgstr ""
812+"Project-Id-Version: unity-scope-click\n"
813+"Report-Msgid-Bugs-To: FULL NAME <EMAIL@ADDRESS>\n"
814+"POT-Creation-Date: 2014-04-29 15:20-0400\n"
815+"PO-Revision-Date: 2014-04-30 08:18+0000\n"
816+"Last-Translator: Jiri Grönroos <Unknown>\n"
817+"Language-Team: Finnish <fi@li.org>\n"
818+"MIME-Version: 1.0\n"
819+"Content-Type: text/plain; charset=UTF-8\n"
820+"Content-Transfer-Encoding: 8bit\n"
821+"X-Launchpad-Export-Date: 2014-05-01 07:02+0000\n"
822+"X-Generator: Launchpad (build 16985)\n"
823+
824+#: ../data/clickscope.ini.in.in.h:1
825+msgid "Apps"
826+msgstr "Sovellukset"
827+
828+#: ../data/clickscope.ini.in.in.h:2
829+msgid "Scope for searching the click app store"
830+msgstr "Näkymä Click-sovelluskaupasta etsintää varten"
831+
832+#: /home/dobey/Projects/canonical/unity-scope-click/no-auto-pot/po/../scope/click/preview.cpp:199
833+msgid "Download Error"
834+msgstr "Latausvirhe"
835+
836+#: /home/dobey/Projects/canonical/unity-scope-click/no-auto-pot/po/../scope/click/preview.cpp:200
837+msgid "Download or install failed. Please try again."
838+msgstr "Lataus tai asennus epäonnistui. Yritä uudelleen."
839+
840+#. TODO see bug LP: #1289434
841+#: /home/dobey/Projects/canonical/unity-scope-click/no-auto-pot/po/../scope/click/preview.cpp:202
842+msgid "Close"
843+msgstr "Sulje"
844+
845+#: /home/dobey/Projects/canonical/unity-scope-click/no-auto-pot/po/../scope/click/preview.cpp:207
846+msgid "Login Error"
847+msgstr "Kirjautumisvirhe"
848+
849+#: /home/dobey/Projects/canonical/unity-scope-click/no-auto-pot/po/../scope/click/preview.cpp:208
850+msgid "Please log in to your Ubuntu One account."
851+msgstr "Kirjaudu Ubuntu One -tilillesi."
852+
853+#: /home/dobey/Projects/canonical/unity-scope-click/no-auto-pot/po/../scope/click/preview.cpp:210
854+msgid "Go to Accounts"
855+msgstr "Siirry tileihin"
856+
857+#: /home/dobey/Projects/canonical/unity-scope-click/no-auto-pot/po/../scope/click/preview.cpp:391
858+msgid "Open"
859+msgstr "Avaa"
860+
861+#: /home/dobey/Projects/canonical/unity-scope-click/no-auto-pot/po/../scope/click/preview.cpp:399
862+msgid "Uninstall"
863+msgstr "Poista"
864+
865+#: /home/dobey/Projects/canonical/unity-scope-click/no-auto-pot/po/../scope/click/preview.cpp:484
866+msgid "Confirmation"
867+msgstr "Vahvistus"
868+
869+#: /home/dobey/Projects/canonical/unity-scope-click/no-auto-pot/po/../scope/click/preview.cpp:486
870+msgid ""
871+"Uninstalling this app will delete all the related information. Are you sure "
872+"you want to uninstall?"
873+msgstr ""
874+"Tämän sovelluksen poistaminen poistaa kaikki siihen liittyvät tiedot. "
875+"Haluatko varmasti poistaa sovelluksen?"
876+
877+#. TODO: see bug LP: #1289434
878+#: /home/dobey/Projects/canonical/unity-scope-click/no-auto-pot/po/../scope/click/preview.cpp:493
879+msgid "Not anymore"
880+msgstr "Ei enää"
881+
882+#: /home/dobey/Projects/canonical/unity-scope-click/no-auto-pot/po/../scope/click/preview.cpp:497
883+msgid "Yes Uninstall"
884+msgstr "Kyllä, poista"
885+
886+#: /home/dobey/Projects/canonical/unity-scope-click/no-auto-pot/po/../scope/click/preview.cpp:545
887+msgid "Install"
888+msgstr "Asenna"
889+
890+#: /home/dobey/Projects/canonical/unity-scope-click/no-auto-pot/po/../scope/click/query.cpp:95
891+msgid "My apps"
892+msgstr "Omat sovellukset"
893+
894+#: /home/dobey/Projects/canonical/unity-scope-click/no-auto-pot/po/../scope/click/query.cpp:184
895+msgid "Available"
896+msgstr "Saatavilla"
897
898=== added file 'po/gd.po'
899--- po/gd.po 1970-01-01 00:00:00 +0000
900+++ po/gd.po 2014-05-02 16:27:07 +0000
901@@ -0,0 +1,94 @@
902+# Gaelic; Scottish translation for unity-scope-click
903+# Copyright (c) 2014 Rosetta Contributors and Canonical Ltd 2014
904+# This file is distributed under the same license as the unity-scope-click package.
905+# FIRST AUTHOR <EMAIL@ADDRESS>, 2014.
906+#
907+msgid ""
908+msgstr ""
909+"Project-Id-Version: unity-scope-click\n"
910+"Report-Msgid-Bugs-To: FULL NAME <EMAIL@ADDRESS>\n"
911+"POT-Creation-Date: 2014-04-29 15:20-0400\n"
912+"PO-Revision-Date: 2014-05-01 13:41+0000\n"
913+"Last-Translator: GunChleoc <Unknown>\n"
914+"Language-Team: Gaelic; Scottish <gd@li.org>\n"
915+"MIME-Version: 1.0\n"
916+"Content-Type: text/plain; charset=UTF-8\n"
917+"Content-Transfer-Encoding: 8bit\n"
918+"X-Launchpad-Export-Date: 2014-05-02 07:39+0000\n"
919+"X-Generator: Launchpad (build 16985)\n"
920+
921+#: ../data/clickscope.ini.in.in.h:1
922+msgid "Apps"
923+msgstr "Aplacaidean"
924+
925+#: ../data/clickscope.ini.in.in.h:2
926+msgid "Scope for searching the click app store"
927+msgstr "Sgòp airson lorg sa bhùth click app"
928+
929+#: /home/dobey/Projects/canonical/unity-scope-click/no-auto-pot/po/../scope/click/preview.cpp:199
930+msgid "Download Error"
931+msgstr "Mearachd leis an luchdadh a-nuas"
932+
933+#: /home/dobey/Projects/canonical/unity-scope-click/no-auto-pot/po/../scope/click/preview.cpp:200
934+msgid "Download or install failed. Please try again."
935+msgstr ""
936+"Dh'fhàillig leis an luchdadh a-nuas no an stàladh. Am feuch thu ris a-"
937+"rithist?"
938+
939+#. TODO see bug LP: #1289434
940+#: /home/dobey/Projects/canonical/unity-scope-click/no-auto-pot/po/../scope/click/preview.cpp:202
941+msgid "Close"
942+msgstr "Dùin"
943+
944+#: /home/dobey/Projects/canonical/unity-scope-click/no-auto-pot/po/../scope/click/preview.cpp:207
945+msgid "Login Error"
946+msgstr "Mearachd leis an logadh a-steach"
947+
948+#: /home/dobey/Projects/canonical/unity-scope-click/no-auto-pot/po/../scope/click/preview.cpp:208
949+msgid "Please log in to your Ubuntu One account."
950+msgstr "Logh a-steach dhan chunntas Ubuntu One agad."
951+
952+#: /home/dobey/Projects/canonical/unity-scope-click/no-auto-pot/po/../scope/click/preview.cpp:210
953+msgid "Go to Accounts"
954+msgstr "Rach dha na cunntasan"
955+
956+#: /home/dobey/Projects/canonical/unity-scope-click/no-auto-pot/po/../scope/click/preview.cpp:391
957+msgid "Open"
958+msgstr "Fosgail"
959+
960+#: /home/dobey/Projects/canonical/unity-scope-click/no-auto-pot/po/../scope/click/preview.cpp:399
961+msgid "Uninstall"
962+msgstr "Dì-stàlaich"
963+
964+#: /home/dobey/Projects/canonical/unity-scope-click/no-auto-pot/po/../scope/click/preview.cpp:484
965+msgid "Confirmation"
966+msgstr "Dearbhadh"
967+
968+#: /home/dobey/Projects/canonical/unity-scope-click/no-auto-pot/po/../scope/click/preview.cpp:486
969+msgid ""
970+"Uninstalling this app will delete all the related information. Are you sure "
971+"you want to uninstall?"
972+msgstr ""
973+"Ma dhì-stàlaicheas tu an aplacaid seo, thèid a h-uile fiosrachadh ceangailte "
974+"rithe a sguabadh às. A bheil thu cinnteach gu bheil thu airson a dì-stàladh?"
975+
976+#. TODO: see bug LP: #1289434
977+#: /home/dobey/Projects/canonical/unity-scope-click/no-auto-pot/po/../scope/click/preview.cpp:493
978+msgid "Not anymore"
979+msgstr "Chan eil tuilleadh"
980+
981+#: /home/dobey/Projects/canonical/unity-scope-click/no-auto-pot/po/../scope/click/preview.cpp:497
982+msgid "Yes Uninstall"
983+msgstr "Tha, dì-stàlaich i"
984+
985+#: /home/dobey/Projects/canonical/unity-scope-click/no-auto-pot/po/../scope/click/preview.cpp:545
986+msgid "Install"
987+msgstr "Stàlaich"
988+
989+#: /home/dobey/Projects/canonical/unity-scope-click/no-auto-pot/po/../scope/click/query.cpp:95
990+msgid "My apps"
991+msgstr "Na h-aplacaidean agam"
992+
993+#: /home/dobey/Projects/canonical/unity-scope-click/no-auto-pot/po/../scope/click/query.cpp:184
994+msgid "Available"
995+msgstr "Ri fhaighinn"
996
997=== added file 'po/gl.po'
998--- po/gl.po 1970-01-01 00:00:00 +0000
999+++ po/gl.po 2014-05-02 16:27:07 +0000
1000@@ -0,0 +1,90 @@
1001+# Galician translation for unity-scope-click
1002+# Copyright (c) 2014 Rosetta Contributors and Canonical Ltd 2014
1003+# This file is distributed under the same license as the unity-scope-click package.
1004+# FIRST AUTHOR <EMAIL@ADDRESS>, 2014.
1005+#
1006+msgid ""
1007+msgstr ""
1008+"Project-Id-Version: unity-scope-click\n"
1009+"Report-Msgid-Bugs-To: FULL NAME <EMAIL@ADDRESS>\n"
1010+"POT-Creation-Date: 2014-04-29 15:20-0400\n"
1011+"PO-Revision-Date: 2014-04-30 09:08+0000\n"
1012+"Last-Translator: Marcos Lans <Unknown>\n"
1013+"Language-Team: Galician <gl@li.org>\n"
1014+"MIME-Version: 1.0\n"
1015+"Content-Type: text/plain; charset=UTF-8\n"
1016+"Content-Transfer-Encoding: 8bit\n"
1017+"X-Launchpad-Export-Date: 2014-05-01 07:02+0000\n"
1018+"X-Generator: Launchpad (build 16985)\n"
1019+
1020+#: ../data/clickscope.ini.in.in.h:1
1021+msgid "Apps"
1022+msgstr "Aplicativos"
1023+
1024+#: ../data/clickscope.ini.in.in.h:2
1025+msgid "Scope for searching the click app store"
1026+msgstr ""
1027+
1028+#: /home/dobey/Projects/canonical/unity-scope-click/no-auto-pot/po/../scope/click/preview.cpp:199
1029+msgid "Download Error"
1030+msgstr "Erro de descarga"
1031+
1032+#: /home/dobey/Projects/canonical/unity-scope-click/no-auto-pot/po/../scope/click/preview.cpp:200
1033+msgid "Download or install failed. Please try again."
1034+msgstr ""
1035+
1036+#. TODO see bug LP: #1289434
1037+#: /home/dobey/Projects/canonical/unity-scope-click/no-auto-pot/po/../scope/click/preview.cpp:202
1038+msgid "Close"
1039+msgstr "Pechar"
1040+
1041+#: /home/dobey/Projects/canonical/unity-scope-click/no-auto-pot/po/../scope/click/preview.cpp:207
1042+msgid "Login Error"
1043+msgstr "Erro de acceso"
1044+
1045+#: /home/dobey/Projects/canonical/unity-scope-click/no-auto-pot/po/../scope/click/preview.cpp:208
1046+msgid "Please log in to your Ubuntu One account."
1047+msgstr ""
1048+
1049+#: /home/dobey/Projects/canonical/unity-scope-click/no-auto-pot/po/../scope/click/preview.cpp:210
1050+msgid "Go to Accounts"
1051+msgstr ""
1052+
1053+#: /home/dobey/Projects/canonical/unity-scope-click/no-auto-pot/po/../scope/click/preview.cpp:391
1054+msgid "Open"
1055+msgstr "Abrir"
1056+
1057+#: /home/dobey/Projects/canonical/unity-scope-click/no-auto-pot/po/../scope/click/preview.cpp:399
1058+msgid "Uninstall"
1059+msgstr "Desinstalar"
1060+
1061+#: /home/dobey/Projects/canonical/unity-scope-click/no-auto-pot/po/../scope/click/preview.cpp:484
1062+msgid "Confirmation"
1063+msgstr "Confirmación"
1064+
1065+#: /home/dobey/Projects/canonical/unity-scope-click/no-auto-pot/po/../scope/click/preview.cpp:486
1066+msgid ""
1067+"Uninstalling this app will delete all the related information. Are you sure "
1068+"you want to uninstall?"
1069+msgstr ""
1070+
1071+#. TODO: see bug LP: #1289434
1072+#: /home/dobey/Projects/canonical/unity-scope-click/no-auto-pot/po/../scope/click/preview.cpp:493
1073+msgid "Not anymore"
1074+msgstr ""
1075+
1076+#: /home/dobey/Projects/canonical/unity-scope-click/no-auto-pot/po/../scope/click/preview.cpp:497
1077+msgid "Yes Uninstall"
1078+msgstr ""
1079+
1080+#: /home/dobey/Projects/canonical/unity-scope-click/no-auto-pot/po/../scope/click/preview.cpp:545
1081+msgid "Install"
1082+msgstr "Instalar"
1083+
1084+#: /home/dobey/Projects/canonical/unity-scope-click/no-auto-pot/po/../scope/click/query.cpp:95
1085+msgid "My apps"
1086+msgstr ""
1087+
1088+#: /home/dobey/Projects/canonical/unity-scope-click/no-auto-pot/po/../scope/click/query.cpp:184
1089+msgid "Available"
1090+msgstr "Dispoñíbel"
1091
1092=== added file 'po/he.po'
1093--- po/he.po 1970-01-01 00:00:00 +0000
1094+++ po/he.po 2014-05-02 16:27:07 +0000
1095@@ -0,0 +1,90 @@
1096+# Hebrew translation for unity-scope-click
1097+# Copyright (c) 2014 Rosetta Contributors and Canonical Ltd 2014
1098+# This file is distributed under the same license as the unity-scope-click package.
1099+# FIRST AUTHOR <EMAIL@ADDRESS>, 2014.
1100+#
1101+msgid ""
1102+msgstr ""
1103+"Project-Id-Version: unity-scope-click\n"
1104+"Report-Msgid-Bugs-To: FULL NAME <EMAIL@ADDRESS>\n"
1105+"POT-Creation-Date: 2014-04-29 15:20-0400\n"
1106+"PO-Revision-Date: 2014-05-01 14:52+0000\n"
1107+"Last-Translator: Yaron <sh.yaron@gmail.com>\n"
1108+"Language-Team: Hebrew <he@li.org>\n"
1109+"MIME-Version: 1.0\n"
1110+"Content-Type: text/plain; charset=UTF-8\n"
1111+"Content-Transfer-Encoding: 8bit\n"
1112+"X-Launchpad-Export-Date: 2014-05-02 07:39+0000\n"
1113+"X-Generator: Launchpad (build 16985)\n"
1114+
1115+#: ../data/clickscope.ini.in.in.h:1
1116+msgid "Apps"
1117+msgstr "יישומים"
1118+
1119+#: ../data/clickscope.ini.in.in.h:2
1120+msgid "Scope for searching the click app store"
1121+msgstr "מתחם לחיפוש בחנות היישומים בלחיצה"
1122+
1123+#: /home/dobey/Projects/canonical/unity-scope-click/no-auto-pot/po/../scope/click/preview.cpp:199
1124+msgid "Download Error"
1125+msgstr "שגיאת הורדה"
1126+
1127+#: /home/dobey/Projects/canonical/unity-scope-click/no-auto-pot/po/../scope/click/preview.cpp:200
1128+msgid "Download or install failed. Please try again."
1129+msgstr "ההורדה או ההתקנה נכשלו. נא לנסות שוב."
1130+
1131+#. TODO see bug LP: #1289434
1132+#: /home/dobey/Projects/canonical/unity-scope-click/no-auto-pot/po/../scope/click/preview.cpp:202
1133+msgid "Close"
1134+msgstr "סגירה"
1135+
1136+#: /home/dobey/Projects/canonical/unity-scope-click/no-auto-pot/po/../scope/click/preview.cpp:207
1137+msgid "Login Error"
1138+msgstr "שגיאת כניסה"
1139+
1140+#: /home/dobey/Projects/canonical/unity-scope-click/no-auto-pot/po/../scope/click/preview.cpp:208
1141+msgid "Please log in to your Ubuntu One account."
1142+msgstr "נא להיכנס לחשבונך ב־Ubuntu One"
1143+
1144+#: /home/dobey/Projects/canonical/unity-scope-click/no-auto-pot/po/../scope/click/preview.cpp:210
1145+msgid "Go to Accounts"
1146+msgstr "מעבר לחשבונות"
1147+
1148+#: /home/dobey/Projects/canonical/unity-scope-click/no-auto-pot/po/../scope/click/preview.cpp:391
1149+msgid "Open"
1150+msgstr "פתיחה"
1151+
1152+#: /home/dobey/Projects/canonical/unity-scope-click/no-auto-pot/po/../scope/click/preview.cpp:399
1153+msgid "Uninstall"
1154+msgstr "הסרה"
1155+
1156+#: /home/dobey/Projects/canonical/unity-scope-click/no-auto-pot/po/../scope/click/preview.cpp:484
1157+msgid "Confirmation"
1158+msgstr ""
1159+
1160+#: /home/dobey/Projects/canonical/unity-scope-click/no-auto-pot/po/../scope/click/preview.cpp:486
1161+msgid ""
1162+"Uninstalling this app will delete all the related information. Are you sure "
1163+"you want to uninstall?"
1164+msgstr ""
1165+
1166+#. TODO: see bug LP: #1289434
1167+#: /home/dobey/Projects/canonical/unity-scope-click/no-auto-pot/po/../scope/click/preview.cpp:493
1168+msgid "Not anymore"
1169+msgstr ""
1170+
1171+#: /home/dobey/Projects/canonical/unity-scope-click/no-auto-pot/po/../scope/click/preview.cpp:497
1172+msgid "Yes Uninstall"
1173+msgstr ""
1174+
1175+#: /home/dobey/Projects/canonical/unity-scope-click/no-auto-pot/po/../scope/click/preview.cpp:545
1176+msgid "Install"
1177+msgstr ""
1178+
1179+#: /home/dobey/Projects/canonical/unity-scope-click/no-auto-pot/po/../scope/click/query.cpp:95
1180+msgid "My apps"
1181+msgstr ""
1182+
1183+#: /home/dobey/Projects/canonical/unity-scope-click/no-auto-pot/po/../scope/click/query.cpp:184
1184+msgid "Available"
1185+msgstr ""
1186
1187=== added file 'po/id.po'
1188--- po/id.po 1970-01-01 00:00:00 +0000
1189+++ po/id.po 2014-05-02 16:27:07 +0000
1190@@ -0,0 +1,90 @@
1191+# Indonesian translation for unity-scope-click
1192+# Copyright (c) 2014 Rosetta Contributors and Canonical Ltd 2014
1193+# This file is distributed under the same license as the unity-scope-click package.
1194+# FIRST AUTHOR <EMAIL@ADDRESS>, 2014.
1195+#
1196+msgid ""
1197+msgstr ""
1198+"Project-Id-Version: unity-scope-click\n"
1199+"Report-Msgid-Bugs-To: FULL NAME <EMAIL@ADDRESS>\n"
1200+"POT-Creation-Date: 2014-04-29 15:20-0400\n"
1201+"PO-Revision-Date: 2014-04-30 02:36+0000\n"
1202+"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
1203+"Language-Team: Indonesian <id@li.org>\n"
1204+"MIME-Version: 1.0\n"
1205+"Content-Type: text/plain; charset=UTF-8\n"
1206+"Content-Transfer-Encoding: 8bit\n"
1207+"X-Launchpad-Export-Date: 2014-05-01 07:02+0000\n"
1208+"X-Generator: Launchpad (build 16985)\n"
1209+
1210+#: ../data/clickscope.ini.in.in.h:1
1211+msgid "Apps"
1212+msgstr ""
1213+
1214+#: ../data/clickscope.ini.in.in.h:2
1215+msgid "Scope for searching the click app store"
1216+msgstr ""
1217+
1218+#: /home/dobey/Projects/canonical/unity-scope-click/no-auto-pot/po/../scope/click/preview.cpp:199
1219+msgid "Download Error"
1220+msgstr ""
1221+
1222+#: /home/dobey/Projects/canonical/unity-scope-click/no-auto-pot/po/../scope/click/preview.cpp:200
1223+msgid "Download or install failed. Please try again."
1224+msgstr ""
1225+
1226+#. TODO see bug LP: #1289434
1227+#: /home/dobey/Projects/canonical/unity-scope-click/no-auto-pot/po/../scope/click/preview.cpp:202
1228+msgid "Close"
1229+msgstr ""
1230+
1231+#: /home/dobey/Projects/canonical/unity-scope-click/no-auto-pot/po/../scope/click/preview.cpp:207
1232+msgid "Login Error"
1233+msgstr ""
1234+
1235+#: /home/dobey/Projects/canonical/unity-scope-click/no-auto-pot/po/../scope/click/preview.cpp:208
1236+msgid "Please log in to your Ubuntu One account."
1237+msgstr ""
1238+
1239+#: /home/dobey/Projects/canonical/unity-scope-click/no-auto-pot/po/../scope/click/preview.cpp:210
1240+msgid "Go to Accounts"
1241+msgstr ""
1242+
1243+#: /home/dobey/Projects/canonical/unity-scope-click/no-auto-pot/po/../scope/click/preview.cpp:391
1244+msgid "Open"
1245+msgstr ""
1246+
1247+#: /home/dobey/Projects/canonical/unity-scope-click/no-auto-pot/po/../scope/click/preview.cpp:399
1248+msgid "Uninstall"
1249+msgstr ""
1250+
1251+#: /home/dobey/Projects/canonical/unity-scope-click/no-auto-pot/po/../scope/click/preview.cpp:484
1252+msgid "Confirmation"
1253+msgstr ""
1254+
1255+#: /home/dobey/Projects/canonical/unity-scope-click/no-auto-pot/po/../scope/click/preview.cpp:486
1256+msgid ""
1257+"Uninstalling this app will delete all the related information. Are you sure "
1258+"you want to uninstall?"
1259+msgstr ""
1260+
1261+#. TODO: see bug LP: #1289434
1262+#: /home/dobey/Projects/canonical/unity-scope-click/no-auto-pot/po/../scope/click/preview.cpp:493
1263+msgid "Not anymore"
1264+msgstr ""
1265+
1266+#: /home/dobey/Projects/canonical/unity-scope-click/no-auto-pot/po/../scope/click/preview.cpp:497
1267+msgid "Yes Uninstall"
1268+msgstr ""
1269+
1270+#: /home/dobey/Projects/canonical/unity-scope-click/no-auto-pot/po/../scope/click/preview.cpp:545
1271+msgid "Install"
1272+msgstr ""
1273+
1274+#: /home/dobey/Projects/canonical/unity-scope-click/no-auto-pot/po/../scope/click/query.cpp:95
1275+msgid "My apps"
1276+msgstr ""
1277+
1278+#: /home/dobey/Projects/canonical/unity-scope-click/no-auto-pot/po/../scope/click/query.cpp:184
1279+msgid "Available"
1280+msgstr ""
1281
1282=== added file 'po/it.po'
1283--- po/it.po 1970-01-01 00:00:00 +0000
1284+++ po/it.po 2014-05-02 16:27:07 +0000
1285@@ -0,0 +1,92 @@
1286+# Italian translation for unity-scope-click
1287+# Copyright (c) 2014 Rosetta Contributors and Canonical Ltd 2014
1288+# This file is distributed under the same license as the unity-scope-click package.
1289+# FIRST AUTHOR <EMAIL@ADDRESS>, 2014.
1290+#
1291+msgid ""
1292+msgstr ""
1293+"Project-Id-Version: unity-scope-click\n"
1294+"Report-Msgid-Bugs-To: FULL NAME <EMAIL@ADDRESS>\n"
1295+"POT-Creation-Date: 2014-04-29 15:20-0400\n"
1296+"PO-Revision-Date: 2014-04-30 12:04+0000\n"
1297+"Last-Translator: Claudio Arseni <claudio.arseni@gmail.com>\n"
1298+"Language-Team: Italian <it@li.org>\n"
1299+"MIME-Version: 1.0\n"
1300+"Content-Type: text/plain; charset=UTF-8\n"
1301+"Content-Transfer-Encoding: 8bit\n"
1302+"X-Launchpad-Export-Date: 2014-05-01 07:02+0000\n"
1303+"X-Generator: Launchpad (build 16985)\n"
1304+
1305+#: ../data/clickscope.ini.in.in.h:1
1306+msgid "Apps"
1307+msgstr "App"
1308+
1309+#: ../data/clickscope.ini.in.in.h:2
1310+msgid "Scope for searching the click app store"
1311+msgstr "Scope per la ricerca nel «click app store»"
1312+
1313+#: /home/dobey/Projects/canonical/unity-scope-click/no-auto-pot/po/../scope/click/preview.cpp:199
1314+msgid "Download Error"
1315+msgstr "Errore nello scaricamento"
1316+
1317+#: /home/dobey/Projects/canonical/unity-scope-click/no-auto-pot/po/../scope/click/preview.cpp:200
1318+msgid "Download or install failed. Please try again."
1319+msgstr "Scaricamento o installazione non riusciti. Riprovare."
1320+
1321+#. TODO see bug LP: #1289434
1322+#: /home/dobey/Projects/canonical/unity-scope-click/no-auto-pot/po/../scope/click/preview.cpp:202
1323+msgid "Close"
1324+msgstr "Chiudi"
1325+
1326+#: /home/dobey/Projects/canonical/unity-scope-click/no-auto-pot/po/../scope/click/preview.cpp:207
1327+msgid "Login Error"
1328+msgstr "Errore di accesso"
1329+
1330+#: /home/dobey/Projects/canonical/unity-scope-click/no-auto-pot/po/../scope/click/preview.cpp:208
1331+msgid "Please log in to your Ubuntu One account."
1332+msgstr "Accedere al proprio account Ubuntu One."
1333+
1334+#: /home/dobey/Projects/canonical/unity-scope-click/no-auto-pot/po/../scope/click/preview.cpp:210
1335+msgid "Go to Accounts"
1336+msgstr "Vai agli account"
1337+
1338+#: /home/dobey/Projects/canonical/unity-scope-click/no-auto-pot/po/../scope/click/preview.cpp:391
1339+msgid "Open"
1340+msgstr "Apri"
1341+
1342+#: /home/dobey/Projects/canonical/unity-scope-click/no-auto-pot/po/../scope/click/preview.cpp:399
1343+msgid "Uninstall"
1344+msgstr "Rimuovi"
1345+
1346+#: /home/dobey/Projects/canonical/unity-scope-click/no-auto-pot/po/../scope/click/preview.cpp:484
1347+msgid "Confirmation"
1348+msgstr "Conferma"
1349+
1350+#: /home/dobey/Projects/canonical/unity-scope-click/no-auto-pot/po/../scope/click/preview.cpp:486
1351+msgid ""
1352+"Uninstalling this app will delete all the related information. Are you sure "
1353+"you want to uninstall?"
1354+msgstr ""
1355+"Rimuovendo questa applicazione verranno eliminate anche tutte le relative "
1356+"informazioni. Rimuovere veramente?"
1357+
1358+#. TODO: see bug LP: #1289434
1359+#: /home/dobey/Projects/canonical/unity-scope-click/no-auto-pot/po/../scope/click/preview.cpp:493
1360+msgid "Not anymore"
1361+msgstr "Non ora"
1362+
1363+#: /home/dobey/Projects/canonical/unity-scope-click/no-auto-pot/po/../scope/click/preview.cpp:497
1364+msgid "Yes Uninstall"
1365+msgstr "Sì, rimuovi"
1366+
1367+#: /home/dobey/Projects/canonical/unity-scope-click/no-auto-pot/po/../scope/click/preview.cpp:545
1368+msgid "Install"
1369+msgstr "Installa"
1370+
1371+#: /home/dobey/Projects/canonical/unity-scope-click/no-auto-pot/po/../scope/click/query.cpp:95
1372+msgid "My apps"
1373+msgstr "Le mia app"
1374+
1375+#: /home/dobey/Projects/canonical/unity-scope-click/no-auto-pot/po/../scope/click/query.cpp:184
1376+msgid "Available"
1377+msgstr "Disponibile"
1378
1379=== added file 'po/lv.po'
1380--- po/lv.po 1970-01-01 00:00:00 +0000
1381+++ po/lv.po 2014-05-02 16:27:07 +0000
1382@@ -0,0 +1,90 @@
1383+# Latvian translation for unity-scope-click
1384+# Copyright (c) 2014 Rosetta Contributors and Canonical Ltd 2014
1385+# This file is distributed under the same license as the unity-scope-click package.
1386+# FIRST AUTHOR <EMAIL@ADDRESS>, 2014.
1387+#
1388+msgid ""
1389+msgstr ""
1390+"Project-Id-Version: unity-scope-click\n"
1391+"Report-Msgid-Bugs-To: FULL NAME <EMAIL@ADDRESS>\n"
1392+"POT-Creation-Date: 2014-04-29 15:20-0400\n"
1393+"PO-Revision-Date: 2014-04-30 06:16+0000\n"
1394+"Last-Translator: Jānis-Marks Gailis <jeanmarc.gailis@gmail.com>\n"
1395+"Language-Team: Latvian <lv@li.org>\n"
1396+"MIME-Version: 1.0\n"
1397+"Content-Type: text/plain; charset=UTF-8\n"
1398+"Content-Transfer-Encoding: 8bit\n"
1399+"X-Launchpad-Export-Date: 2014-05-01 07:02+0000\n"
1400+"X-Generator: Launchpad (build 16985)\n"
1401+
1402+#: ../data/clickscope.ini.in.in.h:1
1403+msgid "Apps"
1404+msgstr "Lietotnes"
1405+
1406+#: ../data/clickscope.ini.in.in.h:2
1407+msgid "Scope for searching the click app store"
1408+msgstr ""
1409+
1410+#: /home/dobey/Projects/canonical/unity-scope-click/no-auto-pot/po/../scope/click/preview.cpp:199
1411+msgid "Download Error"
1412+msgstr "Lejupielādes kļūda"
1413+
1414+#: /home/dobey/Projects/canonical/unity-scope-click/no-auto-pot/po/../scope/click/preview.cpp:200
1415+msgid "Download or install failed. Please try again."
1416+msgstr ""
1417+
1418+#. TODO see bug LP: #1289434
1419+#: /home/dobey/Projects/canonical/unity-scope-click/no-auto-pot/po/../scope/click/preview.cpp:202
1420+msgid "Close"
1421+msgstr "Aizvērt"
1422+
1423+#: /home/dobey/Projects/canonical/unity-scope-click/no-auto-pot/po/../scope/click/preview.cpp:207
1424+msgid "Login Error"
1425+msgstr "Pieteikšanās kļūda"
1426+
1427+#: /home/dobey/Projects/canonical/unity-scope-click/no-auto-pot/po/../scope/click/preview.cpp:208
1428+msgid "Please log in to your Ubuntu One account."
1429+msgstr ""
1430+
1431+#: /home/dobey/Projects/canonical/unity-scope-click/no-auto-pot/po/../scope/click/preview.cpp:210
1432+msgid "Go to Accounts"
1433+msgstr ""
1434+
1435+#: /home/dobey/Projects/canonical/unity-scope-click/no-auto-pot/po/../scope/click/preview.cpp:391
1436+msgid "Open"
1437+msgstr "Atvērt"
1438+
1439+#: /home/dobey/Projects/canonical/unity-scope-click/no-auto-pot/po/../scope/click/preview.cpp:399
1440+msgid "Uninstall"
1441+msgstr "Noņemt"
1442+
1443+#: /home/dobey/Projects/canonical/unity-scope-click/no-auto-pot/po/../scope/click/preview.cpp:484
1444+msgid "Confirmation"
1445+msgstr "Apstiprināt"
1446+
1447+#: /home/dobey/Projects/canonical/unity-scope-click/no-auto-pot/po/../scope/click/preview.cpp:486
1448+msgid ""
1449+"Uninstalling this app will delete all the related information. Are you sure "
1450+"you want to uninstall?"
1451+msgstr ""
1452+
1453+#. TODO: see bug LP: #1289434
1454+#: /home/dobey/Projects/canonical/unity-scope-click/no-auto-pot/po/../scope/click/preview.cpp:493
1455+msgid "Not anymore"
1456+msgstr ""
1457+
1458+#: /home/dobey/Projects/canonical/unity-scope-click/no-auto-pot/po/../scope/click/preview.cpp:497
1459+msgid "Yes Uninstall"
1460+msgstr ""
1461+
1462+#: /home/dobey/Projects/canonical/unity-scope-click/no-auto-pot/po/../scope/click/preview.cpp:545
1463+msgid "Install"
1464+msgstr "Instalēt"
1465+
1466+#: /home/dobey/Projects/canonical/unity-scope-click/no-auto-pot/po/../scope/click/query.cpp:95
1467+msgid "My apps"
1468+msgstr ""
1469+
1470+#: /home/dobey/Projects/canonical/unity-scope-click/no-auto-pot/po/../scope/click/query.cpp:184
1471+msgid "Available"
1472+msgstr "Pieejams"
1473
1474=== added file 'po/nb.po'
1475--- po/nb.po 1970-01-01 00:00:00 +0000
1476+++ po/nb.po 2014-05-02 16:27:07 +0000
1477@@ -0,0 +1,92 @@
1478+# Norwegian Bokmal translation for unity-scope-click
1479+# Copyright (c) 2014 Rosetta Contributors and Canonical Ltd 2014
1480+# This file is distributed under the same license as the unity-scope-click package.
1481+# FIRST AUTHOR <EMAIL@ADDRESS>, 2014.
1482+#
1483+msgid ""
1484+msgstr ""
1485+"Project-Id-Version: unity-scope-click\n"
1486+"Report-Msgid-Bugs-To: FULL NAME <EMAIL@ADDRESS>\n"
1487+"POT-Creation-Date: 2014-04-29 15:20-0400\n"
1488+"PO-Revision-Date: 2014-05-01 11:24+0000\n"
1489+"Last-Translator: Åka Sikrom <Unknown>\n"
1490+"Language-Team: Norwegian Bokmal <nb@li.org>\n"
1491+"MIME-Version: 1.0\n"
1492+"Content-Type: text/plain; charset=UTF-8\n"
1493+"Content-Transfer-Encoding: 8bit\n"
1494+"X-Launchpad-Export-Date: 2014-05-02 07:39+0000\n"
1495+"X-Generator: Launchpad (build 16985)\n"
1496+
1497+#: ../data/clickscope.ini.in.in.h:1
1498+msgid "Apps"
1499+msgstr "Programmer"
1500+
1501+#: ../data/clickscope.ini.in.in.h:2
1502+msgid "Scope for searching the click app store"
1503+msgstr "Ramme som søker gjennom klikk-programvarebutikken"
1504+
1505+#: /home/dobey/Projects/canonical/unity-scope-click/no-auto-pot/po/../scope/click/preview.cpp:199
1506+msgid "Download Error"
1507+msgstr "Feil ved nedlastning"
1508+
1509+#: /home/dobey/Projects/canonical/unity-scope-click/no-auto-pot/po/../scope/click/preview.cpp:200
1510+msgid "Download or install failed. Please try again."
1511+msgstr "Feil ved nedlastning eller installasjon. Prøv igjen."
1512+
1513+#. TODO see bug LP: #1289434
1514+#: /home/dobey/Projects/canonical/unity-scope-click/no-auto-pot/po/../scope/click/preview.cpp:202
1515+msgid "Close"
1516+msgstr "Lukk"
1517+
1518+#: /home/dobey/Projects/canonical/unity-scope-click/no-auto-pot/po/../scope/click/preview.cpp:207
1519+msgid "Login Error"
1520+msgstr "Påloggingsfeil"
1521+
1522+#: /home/dobey/Projects/canonical/unity-scope-click/no-auto-pot/po/../scope/click/preview.cpp:208
1523+msgid "Please log in to your Ubuntu One account."
1524+msgstr "Logg på Ubuntu One-kontoen din."
1525+
1526+#: /home/dobey/Projects/canonical/unity-scope-click/no-auto-pot/po/../scope/click/preview.cpp:210
1527+msgid "Go to Accounts"
1528+msgstr "Gå til Kontoer"
1529+
1530+#: /home/dobey/Projects/canonical/unity-scope-click/no-auto-pot/po/../scope/click/preview.cpp:391
1531+msgid "Open"
1532+msgstr "Åpne"
1533+
1534+#: /home/dobey/Projects/canonical/unity-scope-click/no-auto-pot/po/../scope/click/preview.cpp:399
1535+msgid "Uninstall"
1536+msgstr "Avinstaller"
1537+
1538+#: /home/dobey/Projects/canonical/unity-scope-click/no-auto-pot/po/../scope/click/preview.cpp:484
1539+msgid "Confirmation"
1540+msgstr "Bekreftelse"
1541+
1542+#: /home/dobey/Projects/canonical/unity-scope-click/no-auto-pot/po/../scope/click/preview.cpp:486
1543+msgid ""
1544+"Uninstalling this app will delete all the related information. Are you sure "
1545+"you want to uninstall?"
1546+msgstr ""
1547+"All relatert informasjon blir slettet hvis du avinstallerer dette "
1548+"programmet. Er du sikker på at du vil avinstallere?"
1549+
1550+#. TODO: see bug LP: #1289434
1551+#: /home/dobey/Projects/canonical/unity-scope-click/no-auto-pot/po/../scope/click/preview.cpp:493
1552+msgid "Not anymore"
1553+msgstr "Ikke nå lenger"
1554+
1555+#: /home/dobey/Projects/canonical/unity-scope-click/no-auto-pot/po/../scope/click/preview.cpp:497
1556+msgid "Yes Uninstall"
1557+msgstr "Ja, avinstaller"
1558+
1559+#: /home/dobey/Projects/canonical/unity-scope-click/no-auto-pot/po/../scope/click/preview.cpp:545
1560+msgid "Install"
1561+msgstr "Installer"
1562+
1563+#: /home/dobey/Projects/canonical/unity-scope-click/no-auto-pot/po/../scope/click/query.cpp:95
1564+msgid "My apps"
1565+msgstr "Mine programmer"
1566+
1567+#: /home/dobey/Projects/canonical/unity-scope-click/no-auto-pot/po/../scope/click/query.cpp:184
1568+msgid "Available"
1569+msgstr "Tilgjengelig"
1570
1571=== added file 'po/ru.po'
1572--- po/ru.po 1970-01-01 00:00:00 +0000
1573+++ po/ru.po 2014-05-02 16:27:07 +0000
1574@@ -0,0 +1,90 @@
1575+# Russian translation for unity-scope-click
1576+# Copyright (c) 2014 Rosetta Contributors and Canonical Ltd 2014
1577+# This file is distributed under the same license as the unity-scope-click package.
1578+# FIRST AUTHOR <EMAIL@ADDRESS>, 2014.
1579+#
1580+msgid ""
1581+msgstr ""
1582+"Project-Id-Version: unity-scope-click\n"
1583+"Report-Msgid-Bugs-To: FULL NAME <EMAIL@ADDRESS>\n"
1584+"POT-Creation-Date: 2014-04-29 15:20-0400\n"
1585+"PO-Revision-Date: 2014-05-01 05:40+0000\n"
1586+"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
1587+"Language-Team: Russian <ru@li.org>\n"
1588+"MIME-Version: 1.0\n"
1589+"Content-Type: text/plain; charset=UTF-8\n"
1590+"Content-Transfer-Encoding: 8bit\n"
1591+"X-Launchpad-Export-Date: 2014-05-02 07:39+0000\n"
1592+"X-Generator: Launchpad (build 16985)\n"
1593+
1594+#: ../data/clickscope.ini.in.in.h:1
1595+msgid "Apps"
1596+msgstr ""
1597+
1598+#: ../data/clickscope.ini.in.in.h:2
1599+msgid "Scope for searching the click app store"
1600+msgstr ""
1601+
1602+#: /home/dobey/Projects/canonical/unity-scope-click/no-auto-pot/po/../scope/click/preview.cpp:199
1603+msgid "Download Error"
1604+msgstr ""
1605+
1606+#: /home/dobey/Projects/canonical/unity-scope-click/no-auto-pot/po/../scope/click/preview.cpp:200
1607+msgid "Download or install failed. Please try again."
1608+msgstr ""
1609+
1610+#. TODO see bug LP: #1289434
1611+#: /home/dobey/Projects/canonical/unity-scope-click/no-auto-pot/po/../scope/click/preview.cpp:202
1612+msgid "Close"
1613+msgstr ""
1614+
1615+#: /home/dobey/Projects/canonical/unity-scope-click/no-auto-pot/po/../scope/click/preview.cpp:207
1616+msgid "Login Error"
1617+msgstr ""
1618+
1619+#: /home/dobey/Projects/canonical/unity-scope-click/no-auto-pot/po/../scope/click/preview.cpp:208
1620+msgid "Please log in to your Ubuntu One account."
1621+msgstr ""
1622+
1623+#: /home/dobey/Projects/canonical/unity-scope-click/no-auto-pot/po/../scope/click/preview.cpp:210
1624+msgid "Go to Accounts"
1625+msgstr ""
1626+
1627+#: /home/dobey/Projects/canonical/unity-scope-click/no-auto-pot/po/../scope/click/preview.cpp:391
1628+msgid "Open"
1629+msgstr ""
1630+
1631+#: /home/dobey/Projects/canonical/unity-scope-click/no-auto-pot/po/../scope/click/preview.cpp:399
1632+msgid "Uninstall"
1633+msgstr ""
1634+
1635+#: /home/dobey/Projects/canonical/unity-scope-click/no-auto-pot/po/../scope/click/preview.cpp:484
1636+msgid "Confirmation"
1637+msgstr ""
1638+
1639+#: /home/dobey/Projects/canonical/unity-scope-click/no-auto-pot/po/../scope/click/preview.cpp:486
1640+msgid ""
1641+"Uninstalling this app will delete all the related information. Are you sure "
1642+"you want to uninstall?"
1643+msgstr ""
1644+
1645+#. TODO: see bug LP: #1289434
1646+#: /home/dobey/Projects/canonical/unity-scope-click/no-auto-pot/po/../scope/click/preview.cpp:493
1647+msgid "Not anymore"
1648+msgstr ""
1649+
1650+#: /home/dobey/Projects/canonical/unity-scope-click/no-auto-pot/po/../scope/click/preview.cpp:497
1651+msgid "Yes Uninstall"
1652+msgstr ""
1653+
1654+#: /home/dobey/Projects/canonical/unity-scope-click/no-auto-pot/po/../scope/click/preview.cpp:545
1655+msgid "Install"
1656+msgstr ""
1657+
1658+#: /home/dobey/Projects/canonical/unity-scope-click/no-auto-pot/po/../scope/click/query.cpp:95
1659+msgid "My apps"
1660+msgstr ""
1661+
1662+#: /home/dobey/Projects/canonical/unity-scope-click/no-auto-pot/po/../scope/click/query.cpp:184
1663+msgid "Available"
1664+msgstr ""
1665
1666=== added file 'po/sl.po'
1667--- po/sl.po 1970-01-01 00:00:00 +0000
1668+++ po/sl.po 2014-05-02 16:27:07 +0000
1669@@ -0,0 +1,90 @@
1670+# Slovenian translation for unity-scope-click
1671+# Copyright (c) 2014 Rosetta Contributors and Canonical Ltd 2014
1672+# This file is distributed under the same license as the unity-scope-click package.
1673+# FIRST AUTHOR <EMAIL@ADDRESS>, 2014.
1674+#
1675+msgid ""
1676+msgstr ""
1677+"Project-Id-Version: unity-scope-click\n"
1678+"Report-Msgid-Bugs-To: FULL NAME <EMAIL@ADDRESS>\n"
1679+"POT-Creation-Date: 2014-04-29 15:20-0400\n"
1680+"PO-Revision-Date: 2014-04-30 15:46+0000\n"
1681+"Last-Translator: Damir Jerovšek <Unknown>\n"
1682+"Language-Team: Slovenian <sl@li.org>\n"
1683+"MIME-Version: 1.0\n"
1684+"Content-Type: text/plain; charset=UTF-8\n"
1685+"Content-Transfer-Encoding: 8bit\n"
1686+"X-Launchpad-Export-Date: 2014-05-01 07:03+0000\n"
1687+"X-Generator: Launchpad (build 16985)\n"
1688+
1689+#: ../data/clickscope.ini.in.in.h:1
1690+msgid "Apps"
1691+msgstr "Programi"
1692+
1693+#: ../data/clickscope.ini.in.in.h:2
1694+msgid "Scope for searching the click app store"
1695+msgstr ""
1696+
1697+#: /home/dobey/Projects/canonical/unity-scope-click/no-auto-pot/po/../scope/click/preview.cpp:199
1698+msgid "Download Error"
1699+msgstr "Napaka med prenosom"
1700+
1701+#: /home/dobey/Projects/canonical/unity-scope-click/no-auto-pot/po/../scope/click/preview.cpp:200
1702+msgid "Download or install failed. Please try again."
1703+msgstr "Prejem ali namestitev je spodletela. Poskusite znova."
1704+
1705+#. TODO see bug LP: #1289434
1706+#: /home/dobey/Projects/canonical/unity-scope-click/no-auto-pot/po/../scope/click/preview.cpp:202
1707+msgid "Close"
1708+msgstr "Zapri"
1709+
1710+#: /home/dobey/Projects/canonical/unity-scope-click/no-auto-pot/po/../scope/click/preview.cpp:207
1711+msgid "Login Error"
1712+msgstr "Napaka med prijavo"
1713+
1714+#: /home/dobey/Projects/canonical/unity-scope-click/no-auto-pot/po/../scope/click/preview.cpp:208
1715+msgid "Please log in to your Ubuntu One account."
1716+msgstr ""
1717+
1718+#: /home/dobey/Projects/canonical/unity-scope-click/no-auto-pot/po/../scope/click/preview.cpp:210
1719+msgid "Go to Accounts"
1720+msgstr ""
1721+
1722+#: /home/dobey/Projects/canonical/unity-scope-click/no-auto-pot/po/../scope/click/preview.cpp:391
1723+msgid "Open"
1724+msgstr "Odpri"
1725+
1726+#: /home/dobey/Projects/canonical/unity-scope-click/no-auto-pot/po/../scope/click/preview.cpp:399
1727+msgid "Uninstall"
1728+msgstr "Odstrani"
1729+
1730+#: /home/dobey/Projects/canonical/unity-scope-click/no-auto-pot/po/../scope/click/preview.cpp:484
1731+msgid "Confirmation"
1732+msgstr "Potrditev"
1733+
1734+#: /home/dobey/Projects/canonical/unity-scope-click/no-auto-pot/po/../scope/click/preview.cpp:486
1735+msgid ""
1736+"Uninstalling this app will delete all the related information. Are you sure "
1737+"you want to uninstall?"
1738+msgstr ""
1739+
1740+#. TODO: see bug LP: #1289434
1741+#: /home/dobey/Projects/canonical/unity-scope-click/no-auto-pot/po/../scope/click/preview.cpp:493
1742+msgid "Not anymore"
1743+msgstr ""
1744+
1745+#: /home/dobey/Projects/canonical/unity-scope-click/no-auto-pot/po/../scope/click/preview.cpp:497
1746+msgid "Yes Uninstall"
1747+msgstr "Da, odstrani"
1748+
1749+#: /home/dobey/Projects/canonical/unity-scope-click/no-auto-pot/po/../scope/click/preview.cpp:545
1750+msgid "Install"
1751+msgstr "Namesti"
1752+
1753+#: /home/dobey/Projects/canonical/unity-scope-click/no-auto-pot/po/../scope/click/query.cpp:95
1754+msgid "My apps"
1755+msgstr "Moji programi"
1756+
1757+#: /home/dobey/Projects/canonical/unity-scope-click/no-auto-pot/po/../scope/click/query.cpp:184
1758+msgid "Available"
1759+msgstr "Na voljo"
1760
1761=== added file 'po/uk.po'
1762--- po/uk.po 1970-01-01 00:00:00 +0000
1763+++ po/uk.po 2014-05-02 16:27:07 +0000
1764@@ -0,0 +1,94 @@
1765+# Ukrainian translation for unity-scope-click
1766+# Copyright (c) 2014 Rosetta Contributors and Canonical Ltd 2014
1767+# This file is distributed under the same license as the unity-scope-click package.
1768+# FIRST AUTHOR <EMAIL@ADDRESS>, 2014.
1769+#
1770+msgid ""
1771+msgstr ""
1772+"Project-Id-Version: unity-scope-click\n"
1773+"Report-Msgid-Bugs-To: FULL NAME <EMAIL@ADDRESS>\n"
1774+"POT-Creation-Date: 2014-04-29 15:20-0400\n"
1775+"PO-Revision-Date: 2014-04-30 04:14+0000\n"
1776+"Last-Translator: Yuri Chornoivan <yurchor@gmail.com>\n"
1777+"Language-Team: Ukrainian <uk@li.org>\n"
1778+"MIME-Version: 1.0\n"
1779+"Content-Type: text/plain; charset=UTF-8\n"
1780+"Content-Transfer-Encoding: 8bit\n"
1781+"X-Launchpad-Export-Date: 2014-05-01 07:03+0000\n"
1782+"X-Generator: Launchpad (build 16985)\n"
1783+
1784+#: ../data/clickscope.ini.in.in.h:1
1785+msgid "Apps"
1786+msgstr "Програми"
1787+
1788+#: ../data/clickscope.ini.in.in.h:2
1789+msgid "Scope for searching the click app store"
1790+msgstr "Область для пошуку у збірці програм click"
1791+
1792+#: /home/dobey/Projects/canonical/unity-scope-click/no-auto-pot/po/../scope/click/preview.cpp:199
1793+msgid "Download Error"
1794+msgstr "Помилка під час отримання даних"
1795+
1796+#: /home/dobey/Projects/canonical/unity-scope-click/no-auto-pot/po/../scope/click/preview.cpp:200
1797+msgid "Download or install failed. Please try again."
1798+msgstr ""
1799+"Спроба отримання даних або встановлення пакунка зазнала невдачі. Будь ласка, "
1800+"повторіть її."
1801+
1802+#. TODO see bug LP: #1289434
1803+#: /home/dobey/Projects/canonical/unity-scope-click/no-auto-pot/po/../scope/click/preview.cpp:202
1804+msgid "Close"
1805+msgstr "Закрити"
1806+
1807+#: /home/dobey/Projects/canonical/unity-scope-click/no-auto-pot/po/../scope/click/preview.cpp:207
1808+msgid "Login Error"
1809+msgstr "Помилка входу"
1810+
1811+#: /home/dobey/Projects/canonical/unity-scope-click/no-auto-pot/po/../scope/click/preview.cpp:208
1812+msgid "Please log in to your Ubuntu One account."
1813+msgstr "Будь ласка, увійдіть до вашого облікового запису Ubuntu One."
1814+
1815+#: /home/dobey/Projects/canonical/unity-scope-click/no-auto-pot/po/../scope/click/preview.cpp:210
1816+msgid "Go to Accounts"
1817+msgstr "Перейти до облікових записів"
1818+
1819+#: /home/dobey/Projects/canonical/unity-scope-click/no-auto-pot/po/../scope/click/preview.cpp:391
1820+msgid "Open"
1821+msgstr "Відкрити"
1822+
1823+#: /home/dobey/Projects/canonical/unity-scope-click/no-auto-pot/po/../scope/click/preview.cpp:399
1824+msgid "Uninstall"
1825+msgstr "Вилучити"
1826+
1827+#: /home/dobey/Projects/canonical/unity-scope-click/no-auto-pot/po/../scope/click/preview.cpp:484
1828+msgid "Confirmation"
1829+msgstr "Підтвердждення"
1830+
1831+#: /home/dobey/Projects/canonical/unity-scope-click/no-auto-pot/po/../scope/click/preview.cpp:486
1832+msgid ""
1833+"Uninstalling this app will delete all the related information. Are you sure "
1834+"you want to uninstall?"
1835+msgstr ""
1836+"Вилучення цієї програми призведе до вилучення усіх пов’язаних з нею даних. "
1837+"Ви справді хочете вилучити програму?"
1838+
1839+#. TODO: see bug LP: #1289434
1840+#: /home/dobey/Projects/canonical/unity-scope-click/no-auto-pot/po/../scope/click/preview.cpp:493
1841+msgid "Not anymore"
1842+msgstr "Ні"
1843+
1844+#: /home/dobey/Projects/canonical/unity-scope-click/no-auto-pot/po/../scope/click/preview.cpp:497
1845+msgid "Yes Uninstall"
1846+msgstr "Так, вилучити"
1847+
1848+#: /home/dobey/Projects/canonical/unity-scope-click/no-auto-pot/po/../scope/click/preview.cpp:545
1849+msgid "Install"
1850+msgstr "Встановити"
1851+
1852+#: /home/dobey/Projects/canonical/unity-scope-click/no-auto-pot/po/../scope/click/query.cpp:95
1853+msgid "My apps"
1854+msgstr "Мої програми"
1855+
1856+#: /home/dobey/Projects/canonical/unity-scope-click/no-auto-pot/po/../scope/click/query.cpp:184
1857+msgid "Available"
1858+msgstr "Доступно"
1859
1860=== added file 'po/unity-scope-click.pot'
1861--- po/unity-scope-click.pot 1970-01-01 00:00:00 +0000
1862+++ po/unity-scope-click.pot 2014-05-02 16:27:07 +0000
1863@@ -0,0 +1,90 @@
1864+# SOME DESCRIPTIVE TITLE.
1865+# Copyright (C) YEAR THE PACKAGE'S COPYRIGHT HOLDER
1866+# This file is distributed under the same license as the PACKAGE package.
1867+# FIRST AUTHOR <EMAIL@ADDRESS>, YEAR.
1868+#
1869+#, fuzzy
1870+msgid ""
1871+msgstr ""
1872+"Project-Id-Version: PACKAGE VERSION\n"
1873+"Report-Msgid-Bugs-To: \n"
1874+"POT-Creation-Date: 2014-04-29 15:20-0400\n"
1875+"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
1876+"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
1877+"Language-Team: LANGUAGE <LL@li.org>\n"
1878+"Language: \n"
1879+"MIME-Version: 1.0\n"
1880+"Content-Type: text/plain; charset=CHARSET\n"
1881+"Content-Transfer-Encoding: 8bit\n"
1882+
1883+#: ../data/clickscope.ini.in.in.h:1
1884+msgid "Apps"
1885+msgstr ""
1886+
1887+#: ../data/clickscope.ini.in.in.h:2
1888+msgid "Scope for searching the click app store"
1889+msgstr ""
1890+
1891+#: /home/dobey/Projects/canonical/unity-scope-click/no-auto-pot/po/../scope/click/preview.cpp:199
1892+msgid "Download Error"
1893+msgstr ""
1894+
1895+#: /home/dobey/Projects/canonical/unity-scope-click/no-auto-pot/po/../scope/click/preview.cpp:200
1896+msgid "Download or install failed. Please try again."
1897+msgstr ""
1898+
1899+#. TODO see bug LP: #1289434
1900+#: /home/dobey/Projects/canonical/unity-scope-click/no-auto-pot/po/../scope/click/preview.cpp:202
1901+msgid "Close"
1902+msgstr ""
1903+
1904+#: /home/dobey/Projects/canonical/unity-scope-click/no-auto-pot/po/../scope/click/preview.cpp:207
1905+msgid "Login Error"
1906+msgstr ""
1907+
1908+#: /home/dobey/Projects/canonical/unity-scope-click/no-auto-pot/po/../scope/click/preview.cpp:208
1909+msgid "Please log in to your Ubuntu One account."
1910+msgstr ""
1911+
1912+#: /home/dobey/Projects/canonical/unity-scope-click/no-auto-pot/po/../scope/click/preview.cpp:210
1913+msgid "Go to Accounts"
1914+msgstr ""
1915+
1916+#: /home/dobey/Projects/canonical/unity-scope-click/no-auto-pot/po/../scope/click/preview.cpp:391
1917+msgid "Open"
1918+msgstr ""
1919+
1920+#: /home/dobey/Projects/canonical/unity-scope-click/no-auto-pot/po/../scope/click/preview.cpp:399
1921+msgid "Uninstall"
1922+msgstr ""
1923+
1924+#: /home/dobey/Projects/canonical/unity-scope-click/no-auto-pot/po/../scope/click/preview.cpp:484
1925+msgid "Confirmation"
1926+msgstr ""
1927+
1928+#: /home/dobey/Projects/canonical/unity-scope-click/no-auto-pot/po/../scope/click/preview.cpp:486
1929+msgid ""
1930+"Uninstalling this app will delete all the related information. Are you sure "
1931+"you want to uninstall?"
1932+msgstr ""
1933+
1934+#. TODO: see bug LP: #1289434
1935+#: /home/dobey/Projects/canonical/unity-scope-click/no-auto-pot/po/../scope/click/preview.cpp:493
1936+msgid "Not anymore"
1937+msgstr ""
1938+
1939+#: /home/dobey/Projects/canonical/unity-scope-click/no-auto-pot/po/../scope/click/preview.cpp:497
1940+msgid "Yes Uninstall"
1941+msgstr ""
1942+
1943+#: /home/dobey/Projects/canonical/unity-scope-click/no-auto-pot/po/../scope/click/preview.cpp:545
1944+msgid "Install"
1945+msgstr ""
1946+
1947+#: /home/dobey/Projects/canonical/unity-scope-click/no-auto-pot/po/../scope/click/query.cpp:95
1948+msgid "My apps"
1949+msgstr ""
1950+
1951+#: /home/dobey/Projects/canonical/unity-scope-click/no-auto-pot/po/../scope/click/query.cpp:184
1952+msgid "Available"
1953+msgstr ""
1954
1955=== added file 'po/zh_CN.po'
1956--- po/zh_CN.po 1970-01-01 00:00:00 +0000
1957+++ po/zh_CN.po 2014-05-02 16:27:07 +0000
1958@@ -0,0 +1,90 @@
1959+# Chinese (Simplified) translation for unity-scope-click
1960+# Copyright (c) 2014 Rosetta Contributors and Canonical Ltd 2014
1961+# This file is distributed under the same license as the unity-scope-click package.
1962+# FIRST AUTHOR <EMAIL@ADDRESS>, 2014.
1963+#
1964+msgid ""
1965+msgstr ""
1966+"Project-Id-Version: unity-scope-click\n"
1967+"Report-Msgid-Bugs-To: FULL NAME <EMAIL@ADDRESS>\n"
1968+"POT-Creation-Date: 2014-04-29 15:20-0400\n"
1969+"PO-Revision-Date: 2014-04-30 07:29+0000\n"
1970+"Last-Translator: Aron Xu <Unknown>\n"
1971+"Language-Team: Chinese (Simplified) <zh_CN@li.org>\n"
1972+"MIME-Version: 1.0\n"
1973+"Content-Type: text/plain; charset=UTF-8\n"
1974+"Content-Transfer-Encoding: 8bit\n"
1975+"X-Launchpad-Export-Date: 2014-05-01 07:03+0000\n"
1976+"X-Generator: Launchpad (build 16985)\n"
1977+
1978+#: ../data/clickscope.ini.in.in.h:1
1979+msgid "Apps"
1980+msgstr "应用"
1981+
1982+#: ../data/clickscope.ini.in.in.h:2
1983+msgid "Scope for searching the click app store"
1984+msgstr "用以搜索 Click 应用商店的 Scope"
1985+
1986+#: /home/dobey/Projects/canonical/unity-scope-click/no-auto-pot/po/../scope/click/preview.cpp:199
1987+msgid "Download Error"
1988+msgstr "下载出错"
1989+
1990+#: /home/dobey/Projects/canonical/unity-scope-click/no-auto-pot/po/../scope/click/preview.cpp:200
1991+msgid "Download or install failed. Please try again."
1992+msgstr "下载或安装失败。请再试一次。"
1993+
1994+#. TODO see bug LP: #1289434
1995+#: /home/dobey/Projects/canonical/unity-scope-click/no-auto-pot/po/../scope/click/preview.cpp:202
1996+msgid "Close"
1997+msgstr "关闭"
1998+
1999+#: /home/dobey/Projects/canonical/unity-scope-click/no-auto-pot/po/../scope/click/preview.cpp:207
2000+msgid "Login Error"
2001+msgstr "登录出错"
2002+
2003+#: /home/dobey/Projects/canonical/unity-scope-click/no-auto-pot/po/../scope/click/preview.cpp:208
2004+msgid "Please log in to your Ubuntu One account."
2005+msgstr "请用您的 Ubuntu One 账号登录"
2006+
2007+#: /home/dobey/Projects/canonical/unity-scope-click/no-auto-pot/po/../scope/click/preview.cpp:210
2008+msgid "Go to Accounts"
2009+msgstr "跳转到帐号"
2010+
2011+#: /home/dobey/Projects/canonical/unity-scope-click/no-auto-pot/po/../scope/click/preview.cpp:391
2012+msgid "Open"
2013+msgstr "打开"
2014+
2015+#: /home/dobey/Projects/canonical/unity-scope-click/no-auto-pot/po/../scope/click/preview.cpp:399
2016+msgid "Uninstall"
2017+msgstr "卸载"
2018+
2019+#: /home/dobey/Projects/canonical/unity-scope-click/no-auto-pot/po/../scope/click/preview.cpp:484
2020+msgid "Confirmation"
2021+msgstr "确认"
2022+
2023+#: /home/dobey/Projects/canonical/unity-scope-click/no-auto-pot/po/../scope/click/preview.cpp:486
2024+msgid ""
2025+"Uninstalling this app will delete all the related information. Are you sure "
2026+"you want to uninstall?"
2027+msgstr "卸载这个应用将删除所有相关信息。您确定要卸载吗?"
2028+
2029+#. TODO: see bug LP: #1289434
2030+#: /home/dobey/Projects/canonical/unity-scope-click/no-auto-pot/po/../scope/click/preview.cpp:493
2031+msgid "Not anymore"
2032+msgstr ""
2033+
2034+#: /home/dobey/Projects/canonical/unity-scope-click/no-auto-pot/po/../scope/click/preview.cpp:497
2035+msgid "Yes Uninstall"
2036+msgstr "卸载"
2037+
2038+#: /home/dobey/Projects/canonical/unity-scope-click/no-auto-pot/po/../scope/click/preview.cpp:545
2039+msgid "Install"
2040+msgstr "安装"
2041+
2042+#: /home/dobey/Projects/canonical/unity-scope-click/no-auto-pot/po/../scope/click/query.cpp:95
2043+msgid "My apps"
2044+msgstr "我的应用"
2045+
2046+#: /home/dobey/Projects/canonical/unity-scope-click/no-auto-pot/po/../scope/click/query.cpp:184
2047+msgid "Available"
2048+msgstr "可用"
2049
2050=== modified file 'scope/click/CMakeLists.txt'
2051--- scope/click/CMakeLists.txt 2014-04-10 18:19:33 +0000
2052+++ scope/click/CMakeLists.txt 2014-05-02 16:27:07 +0000
2053@@ -2,7 +2,6 @@
2054 SET (CMAKE_AUTOMOC ON)
2055 find_package (Qt5Core REQUIRED)
2056 pkg_check_modules(JSON_CPP REQUIRED jsoncpp)
2057-pkg_check_modules(LIBURL_DISPATCHER REQUIRED url-dispatcher-1)
2058
2059 add_definitions(
2060 -DGETTEXT_PACKAGE=\"${PROJECT_NAME}\"
2061@@ -10,6 +9,7 @@
2062 )
2063
2064 add_library(${SCOPE_LIB_UNVERSIONED} SHARED
2065+ configuration.cpp
2066 download-manager.cpp
2067 index.cpp
2068 interface.cpp
2069@@ -18,7 +18,9 @@
2070 query.cpp
2071 reviews.cpp
2072 scope.cpp
2073+ scope_activation.cpp
2074 smartconnect.cpp
2075+ package.cpp
2076 preview.cpp
2077 ubuntuone_credentials.cpp
2078 webclient.cpp
2079
2080=== added file 'scope/click/configuration.cpp'
2081--- scope/click/configuration.cpp 1970-01-01 00:00:00 +0000
2082+++ scope/click/configuration.cpp 2014-05-02 16:27:07 +0000
2083@@ -0,0 +1,124 @@
2084+/*
2085+ * Copyright (C) 2014 Canonical Ltd.
2086+ *
2087+ * This program is free software: you can redistribute it and/or modify it
2088+ * under the terms of the GNU General Public License version 3, as published
2089+ * by the Free Software Foundation.
2090+ *
2091+ * This program is distributed in the hope that it will be useful, but
2092+ * WITHOUT ANY WARRANTY; without even the implied warranties of
2093+ * MERCHANTABILITY, SATISFACTORY QUALITY, or FITNESS FOR A PARTICULAR
2094+ * PURPOSE. See the GNU General Public License for more details.
2095+ *
2096+ * You should have received a copy of the GNU General Public License along
2097+ * with this program. If not, see <http://www.gnu.org/licenses/>.
2098+ *
2099+ * In addition, as a special exception, the copyright holders give
2100+ * permission to link the code of portions of this program with the
2101+ * OpenSSL library under certain conditions as described in each
2102+ * individual source file, and distribute linked combinations
2103+ * including the two.
2104+ * You must obey the GNU General Public License in all respects
2105+ * for all of the code used other than OpenSSL. If you modify
2106+ * file(s) with this exception, you may extend this exception to your
2107+ * version of the file(s), but you are not obligated to do so. If you
2108+ * do not wish to do so, delete this exception statement from your
2109+ * version. If you delete this exception statement from all source
2110+ * files in the program, then also delete it here.
2111+ */
2112+
2113+#include <string>
2114+#include <vector>
2115+
2116+#include <QDir>
2117+#include <QProcess>
2118+
2119+#include <boost/algorithm/string.hpp>
2120+#include <boost/algorithm/string/replace.hpp>
2121+
2122+#include "configuration.h"
2123+
2124+namespace click {
2125+
2126+std::vector<std::string> Configuration::list_folder(const std::string& folder, const std::string& pattern)
2127+{
2128+ std::vector<std::string> result;
2129+
2130+ QDir dir(QString::fromStdString(folder), QString::fromStdString(pattern),
2131+ QDir::Unsorted, QDir::Readable | QDir::Files);
2132+ QStringList entries = dir.entryList();
2133+ for (int i = 0; i < entries.size(); ++i) {
2134+ QString filename = entries.at(i);
2135+ result.push_back(filename.toStdString());
2136+ }
2137+
2138+ return result;
2139+}
2140+
2141+std::vector<std::string> Configuration::get_available_frameworks()
2142+{
2143+ std::vector<std::string> result;
2144+ for (auto f: list_folder(FRAMEWORKS_FOLDER, FRAMEWORKS_PATTERN)) {
2145+ result.push_back(f.substr(0, f.size()-FRAMEWORKS_EXTENSION_LENGTH));
2146+ }
2147+ return result;
2148+}
2149+
2150+std::string Configuration::architectureFromDpkg()
2151+{
2152+ QString program("dpkg");
2153+ QStringList arguments;
2154+ arguments << "--print-architecture";
2155+ QProcess archDetector;
2156+ archDetector.start(program, arguments);
2157+ if(!archDetector.waitForFinished()) {
2158+ throw std::runtime_error("Architecture detection failed.");
2159+ }
2160+ auto output = archDetector.readAllStandardOutput();
2161+ auto ostr = QString::fromUtf8(output);
2162+ ostr.remove('\n');
2163+
2164+ return ostr.toStdString();
2165+}
2166+
2167+std::string Configuration::get_architecture()
2168+{
2169+ static const std::string arch{architectureFromDpkg()};
2170+ return arch;
2171+}
2172+
2173+std::string Configuration::get_language_base()
2174+{
2175+ std::string language = get_language();
2176+ std::vector<std::string> lang_parts;
2177+ boost::split(lang_parts, language, boost::is_any_of("_"));
2178+ return lang_parts[0];
2179+}
2180+
2181+std::string Configuration::get_language()
2182+{
2183+ const char* language = getenv(LANGUAGE_ENVVAR);
2184+ if (language == NULL) {
2185+ language = "C";
2186+ }
2187+ std::vector<std::string> lang_parts;
2188+ boost::split(lang_parts, language, boost::is_any_of("."));
2189+ return lang_parts[0];
2190+}
2191+
2192+std::string Configuration::get_accept_languages()
2193+{
2194+ std::string language = get_language();
2195+ std::vector<std::string> lang_parts;
2196+ boost::split(lang_parts, language, boost::is_any_of("_"));
2197+ std::string result;
2198+ if (lang_parts.size() > 1) {
2199+ boost::replace_first(language, "_", "-");
2200+ result = language + ", " + get_language_base();
2201+ } else {
2202+ result = language;
2203+ }
2204+ return result;
2205+}
2206+
2207+} // namespace click
2208
2209=== added file 'scope/click/configuration.h'
2210--- scope/click/configuration.h 1970-01-01 00:00:00 +0000
2211+++ scope/click/configuration.h 2014-05-02 16:27:07 +0000
2212@@ -0,0 +1,62 @@
2213+/*
2214+ * Copyright (C) 2014 Canonical Ltd.
2215+ *
2216+ * This program is free software: you can redistribute it and/or modify it
2217+ * under the terms of the GNU General Public License version 3, as published
2218+ * by the Free Software Foundation.
2219+ *
2220+ * This program is distributed in the hope that it will be useful, but
2221+ * WITHOUT ANY WARRANTY; without even the implied warranties of
2222+ * MERCHANTABILITY, SATISFACTORY QUALITY, or FITNESS FOR A PARTICULAR
2223+ * PURPOSE. See the GNU General Public License for more details.
2224+ *
2225+ * You should have received a copy of the GNU General Public License along
2226+ * with this program. If not, see <http://www.gnu.org/licenses/>.
2227+ *
2228+ * In addition, as a special exception, the copyright holders give
2229+ * permission to link the code of portions of this program with the
2230+ * OpenSSL library under certain conditions as described in each
2231+ * individual source file, and distribute linked combinations
2232+ * including the two.
2233+ * You must obey the GNU General Public License in all respects
2234+ * for all of the code used other than OpenSSL. If you modify
2235+ * file(s) with this exception, you may extend this exception to your
2236+ * version of the file(s), but you are not obligated to do so. If you
2237+ * do not wish to do so, delete this exception statement from your
2238+ * version. If you delete this exception statement from all source
2239+ * files in the program, then also delete it here.
2240+ */
2241+
2242+#ifndef CONFIGURATION_H
2243+#define CONFIGURATION_H
2244+
2245+#include <string>
2246+#include <vector>
2247+
2248+namespace click
2249+{
2250+
2251+class Configuration
2252+{
2253+public:
2254+ constexpr static const char* FRAMEWORKS_FOLDER {"/usr/share/click/frameworks/"};
2255+ constexpr static const char* FRAMEWORKS_PATTERN {"*.framework"};
2256+ constexpr static const int FRAMEWORKS_EXTENSION_LENGTH = 10; // strlen(".framework")
2257+ constexpr static const char* LANGUAGE_ENVVAR {"LANGUAGE"};
2258+
2259+ virtual std::vector<std::string> get_available_frameworks();
2260+ virtual std::string get_architecture();
2261+
2262+ virtual std::string get_language_base();
2263+ virtual std::string get_language();
2264+ virtual std::string get_accept_languages();
2265+
2266+ virtual ~Configuration() {}
2267+protected:
2268+ virtual std::vector<std::string> list_folder(const std::string &folder, const std::string &pattern);
2269+ virtual std::string architectureFromDpkg();
2270+};
2271+
2272+} // namespace click
2273+
2274+#endif // CONFIGURATION_H
2275
2276=== modified file 'scope/click/download-manager.cpp'
2277--- scope/click/download-manager.cpp 2014-03-22 00:08:31 +0000
2278+++ scope/click/download-manager.cpp 2014-05-02 16:27:07 +0000
2279@@ -335,7 +335,7 @@
2280 void click::Downloader::startDownload(std::string url, std::string package_name,
2281 const std::function<void (std::pair<std::string, click::InstallError >)>& callback)
2282 {
2283- qt::core::world::enter_with_task([this, callback, url, package_name] (qt::core::world::Environment& /*env*/)
2284+ qt::core::world::enter_with_task([this, callback, url, package_name] ()
2285 {
2286 auto& dm = downloadManagerInstance(networkAccessManager);
2287
2288
2289=== modified file 'scope/click/index.cpp'
2290--- scope/click/index.cpp 2014-04-04 10:11:11 +0000
2291+++ scope/click/index.cpp 2014-05-02 16:27:07 +0000
2292@@ -31,57 +31,20 @@
2293 #include <QObject>
2294 #include <QProcess>
2295
2296-#include <json/json.h>
2297+#include <cstdlib>
2298 #include <sstream>
2299
2300 #include "download-manager.h"
2301 #include "index.h"
2302+#include "interface.h"
2303 #include "application.h"
2304+#include "smartconnect.h"
2305
2306 namespace json = Json;
2307
2308 namespace click
2309 {
2310
2311-bool operator==(const Package& lhs, const Package& rhs) {
2312- return lhs.name == rhs.name &&
2313- lhs.title == rhs.title &&
2314- lhs.price == rhs.price &&
2315- lhs.icon_url == rhs.icon_url;
2316-}
2317-
2318-bool operator==(const PackageDetails& lhs, const PackageDetails& rhs) {
2319- return lhs.package == rhs.package &&
2320- lhs.description == rhs.description &&
2321- lhs.download_url == rhs.download_url &&
2322- lhs.rating == rhs.rating &&
2323- // TODO: keywords should be a list of strings
2324- lhs.keywords == rhs.keywords &&
2325- lhs.terms_of_service == rhs.terms_of_service &&
2326- lhs.license == rhs.license &&
2327- lhs.publisher == rhs.publisher &&
2328- lhs.main_screenshot_url == rhs.main_screenshot_url &&
2329- // TODO: more_screenshots_urls should be a list of strings
2330- lhs.more_screenshots_urls == rhs.more_screenshots_urls &&
2331- // TODO: binary_filesize should be a int/long
2332- lhs.binary_filesize == rhs.binary_filesize &&
2333- lhs.version == rhs.version &&
2334- lhs.framework == rhs.framework;
2335-}
2336-
2337-QDebug operator<< (QDebug d, const std::string &s) {
2338- d << QString::fromStdString(s);
2339- return d;
2340-}
2341-
2342-bool operator==(const Application& lhs, const Application& rhs) {
2343- return lhs.name == rhs.name &&
2344- lhs.title == rhs.title &&
2345- lhs.description == rhs.description &&
2346- lhs.main_screenshot == rhs.main_screenshot &&
2347- lhs.icon_url == rhs.icon_url;
2348-}
2349-
2350 void PackageManager::uninstall(const Package& package,
2351 std::function<void(int, std::string)> callback)
2352 {
2353@@ -117,186 +80,45 @@
2354 process.data()->start(command.c_str());
2355 }
2356
2357-PackageList package_list_from_json(const std::string& json)
2358-{
2359- std::istringstream is(json);
2360-
2361- PackageList pl;
2362-
2363- json::Reader reader;
2364- json::Value root;
2365-
2366- if (!reader.parse(json, root)) {
2367- throw std::runtime_error(reader.getFormattedErrorMessages());
2368- }
2369-
2370- for (uint i = 0; i < root.size(); i++)
2371- {
2372- Package p;
2373- json::Value item = root[i];
2374- p.name = item[Package::JsonKeys::name].asString();
2375- p.title = item[Package::JsonKeys::title].asString();
2376- p.price = item[Package::JsonKeys::price].asDouble();
2377- p.icon_url = item[Package::JsonKeys::icon_url].asString();
2378- p.url = item[Package::JsonKeys::resource_url].asString();
2379- pl.push_back(p);
2380- }
2381- return pl;
2382-}
2383-
2384-PackageDetails PackageDetails::from_json(const std::string &json)
2385-{
2386- PackageDetails details;
2387- try
2388- {
2389- json::Reader reader;
2390- json::Value root;
2391-
2392- if (!reader.parse(json, root))
2393- throw std::runtime_error(reader.getFormattedErrorMessages());
2394-
2395- // Mandatory details go here. That is, asString() will throw as we
2396- // do not provide a default value if a value with the given key does not exist.
2397- details.package.name = root[Package::JsonKeys::name].asString();
2398- details.package.title = root[Package::JsonKeys::title].asString();
2399- details.package.icon_url = root[Package::JsonKeys::icon_url].asString();
2400- details.package.price = root[Package::JsonKeys::price].asDouble();
2401- details.description = root[JsonKeys::description].asString();
2402- details.download_url = root[JsonKeys::download_url].asString();
2403- details.license = root[JsonKeys::license].asString();
2404-
2405- // Optional details go here.
2406- if (root[JsonKeys::version].isString())
2407- details.version = root[JsonKeys::version].asString();
2408-
2409- if (root[JsonKeys::rating].isNumeric())
2410- details.rating = root[JsonKeys::rating].asDouble();
2411-
2412- if (root[JsonKeys::keywords].isString())
2413- details.keywords = root[JsonKeys::keywords].asString();
2414-
2415- if (root[JsonKeys::terms_of_service].isString())
2416- details.terms_of_service = root[JsonKeys::terms_of_service].asString();
2417-
2418- if (root[JsonKeys::publisher].isString())
2419- details.publisher = root[JsonKeys::publisher].asString();
2420-
2421- if (root[JsonKeys::main_screenshot_url].isString())
2422- details.main_screenshot_url = root[JsonKeys::main_screenshot_url].asString();
2423-
2424- auto screenshots = root[JsonKeys::more_screenshot_urls];
2425-
2426- for (uint i = 0; i < screenshots.size(); i++)
2427- {
2428- auto scr = screenshots[i].asString();
2429- // more_screenshot_urls may contain main_screenshot_url, if so, skip it
2430- if (scr != details.main_screenshot_url)
2431- {
2432- details.more_screenshots_urls.push_back(scr);
2433- }
2434- }
2435-
2436- if (root[JsonKeys::binary_filesize].isIntegral())
2437- details.binary_filesize = root[JsonKeys::binary_filesize].asUInt64();
2438-
2439- if (root[JsonKeys::framework].isString())
2440- details.framework = root[JsonKeys::framework].asString();
2441-
2442- } catch(const std::exception& e)
2443- {
2444- std::cerr << "PackageDetails::loadJson: Exception thrown while decoding JSON: " << e.what() << std::endl;
2445- } catch(...)
2446- {
2447- std::cerr << "PackageDetails::loadJson: Exception thrown while decoding JSON." << std::endl;
2448- }
2449-
2450- return details;
2451-}
2452-
2453-std::string print_string_if_not_empty(const std::string& s)
2454-{
2455-
2456- return s.empty() ? "n/a" : s;
2457-}
2458-
2459-std::string print_list_if_not_empty(const std::list<std::string>& li)
2460-{
2461- std::stringstream s;
2462- s << "[";
2463- if (!li.empty())
2464- {
2465- auto it = li.begin();
2466- s << print_string_if_not_empty(*it);
2467- ++it;
2468- while (it != li.end())
2469- {
2470- s << ", " << print_string_if_not_empty(*it);
2471- ++it;
2472- }
2473- }
2474- s << "]";
2475- return s.str();
2476-}
2477-
2478-std::ostream& operator<<(std::ostream& out, const click::PackageDetails& details)
2479-{
2480- out << "("
2481- << print_string_if_not_empty(details.package.name) << ", "
2482- << print_string_if_not_empty(details.package.title) << ", "
2483- << print_string_if_not_empty(details.package.icon_url) << ", "
2484- << print_string_if_not_empty(details.description) << ", "
2485- << print_string_if_not_empty(details.download_url) << ", "
2486- << details.rating << ", "
2487- << print_string_if_not_empty(details.keywords) << ", "
2488- << print_string_if_not_empty(details.terms_of_service) << ", "
2489- << print_string_if_not_empty(details.license) << ", "
2490- << print_string_if_not_empty(details.publisher) << ", "
2491- << print_string_if_not_empty(details.main_screenshot_url) << ", "
2492- << print_list_if_not_empty(details.more_screenshots_urls) << ", "
2493- << details.binary_filesize << ", "
2494- << print_string_if_not_empty(details.version) << ", "
2495- << print_string_if_not_empty(details.framework)
2496- << ")";
2497-
2498- return out;
2499-}
2500-
2501-std::ostream& operator<<(std::ostream& out, const click::Application& app)
2502-{
2503- out << "("
2504- << print_string_if_not_empty(app.name) << ", "
2505- << print_string_if_not_empty(app.title) << ", "
2506- << app.price << ", "
2507- << print_string_if_not_empty(app.icon_url) << ", "
2508- << print_string_if_not_empty(app.url) << ", "
2509- << print_string_if_not_empty(app.version) << ", "
2510- << print_string_if_not_empty(app.description) << ", "
2511- << print_string_if_not_empty(app.main_screenshot)
2512- << ")";
2513-
2514- return out;
2515-}
2516-
2517-Index::Index(const QSharedPointer<click::web::Client>& client) : client(client)
2518-{
2519-
2520+Index::Index(const QSharedPointer<click::web::Client>& client,
2521+ const QSharedPointer<Configuration> configuration) :
2522+ client(client), configuration(configuration)
2523+{
2524+
2525+}
2526+
2527+std::string Index::build_index_query(std::string query)
2528+{
2529+ std::stringstream result;
2530+
2531+ result << query;
2532+ for (auto f: configuration->get_available_frameworks()) {
2533+ result << ",framework:" << f;
2534+ }
2535+ result << ",architecture:" << configuration->get_architecture();
2536+
2537+ return result.str();
2538 }
2539
2540 click::web::Cancellable Index::search (const std::string& query, std::function<void(click::PackageList)> callback)
2541 {
2542 click::web::CallParams params;
2543- params.add(click::QUERY_ARGNAME, query.c_str());
2544+ std::string built_query(build_index_query(query));
2545+ params.add(click::QUERY_ARGNAME, built_query.c_str());
2546 QSharedPointer<click::web::Response> response(client->call(
2547- click::SEARCH_BASE_URL + click::SEARCH_PATH, params));
2548+ get_base_url() + click::SEARCH_PATH, params));
2549
2550 QObject::connect(response.data(), &click::web::Response::finished, [=](QString reply) {
2551 click::PackageList pl = click::package_list_from_json(reply.toUtf8().constData());
2552+ qDebug() << "found packages:" << pl.size();
2553 callback(pl);
2554 });
2555 QObject::connect(response.data(), &click::web::Response::error, [=](QString /*description*/) {
2556 qDebug() << "No packages found due to network error";
2557 click::PackageList pl;
2558+ qDebug() << "calling callback";
2559 callback(pl);
2560+ qDebug() << " ...Done!";
2561 });
2562 return click::web::Cancellable(response);
2563 }
2564@@ -304,7 +126,7 @@
2565 click::web::Cancellable Index::get_details (const std::string& package_name, std::function<void(PackageDetails, click::Index::Error)> callback)
2566 {
2567 QSharedPointer<click::web::Response> response = client->call
2568- (click::SEARCH_BASE_URL + click::DETAILS_PATH + package_name);
2569+ (get_base_url() + click::DETAILS_PATH + package_name);
2570 qDebug() << "getting details for" << package_name.c_str();
2571
2572 QObject::connect(response.data(), &click::web::Response::finished, [=](const QByteArray reply) {
2573@@ -321,6 +143,15 @@
2574 return click::web::Cancellable(response);
2575 }
2576
2577+std::string Index::get_base_url ()
2578+{
2579+ const char *env_url = getenv(SEARCH_BASE_URL_ENVVAR.c_str());
2580+ if (env_url != NULL) {
2581+ return env_url;
2582+ }
2583+ return click::SEARCH_BASE_URL;
2584+}
2585+
2586 Index::~Index()
2587 {
2588 }
2589
2590=== modified file 'scope/click/index.h'
2591--- scope/click/index.h 2014-04-01 17:28:41 +0000
2592+++ scope/click/index.h 2014-05-02 16:27:07 +0000
2593@@ -32,18 +32,18 @@
2594
2595
2596 #include <string>
2597-#include <list>
2598-#include <iosfwd>
2599 #include <functional>
2600
2601-#include <json/json.h>
2602-
2603+#include "configuration.h"
2604+#include "package.h"
2605 #include "webclient.h"
2606
2607-namespace json = Json;
2608
2609 namespace click {
2610
2611+class Configuration;
2612+
2613+const std::string SEARCH_BASE_URL_ENVVAR = "U1_SEARCH_BASE_URL";
2614 const std::string SEARCH_BASE_URL = "https://search.apps.ubuntu.com/";
2615 const std::string SEARCH_PATH = "api/v1/search";
2616 const std::string SUPPORTED_FRAMEWORKS = "framework:ubuntu-sdk-13.10";
2617@@ -51,48 +51,6 @@
2618 const std::string ARCHITECTURE = "architecture:";
2619 const std::string DETAILS_PATH = "api/v1/package/";
2620
2621-struct Package
2622-{
2623- struct JsonKeys
2624- {
2625- JsonKeys() = delete;
2626-
2627- constexpr static const char* name{"name"};
2628- constexpr static const char* title{"title"};
2629- constexpr static const char* price{"price"};
2630- constexpr static const char* icon_url{"icon_url"};
2631- constexpr static const char* resource_url{"resource_url"};
2632- };
2633-
2634- Package() = default;
2635- Package(std::string name, std::string title, double price, std::string icon_url, std::string url) :
2636- name(name),
2637- title(title),
2638- price(price),
2639- icon_url(icon_url),
2640- url(url)
2641- {
2642- }
2643- Package(std::string name, std::string title, double price, std::string icon_url, std::string url, std::string version) :
2644- name(name),
2645- title(title),
2646- price(price),
2647- icon_url(icon_url),
2648- url(url),
2649- version(version)
2650- {
2651- }
2652- virtual ~Package() = default;
2653-
2654- std::string name; // formerly app_id
2655- std::string title;
2656- double price;
2657- std::string icon_url;
2658- std::string url;
2659- std::string version;
2660- void matches (std::string query, std::function<bool> callback);
2661-};
2662-
2663 class PackageManager
2664 {
2665 public:
2666@@ -100,68 +58,23 @@
2667 virtual void execute_uninstall_command (const std::string& command, std::function<void(int, std::string)>);
2668 };
2669
2670-typedef std::list<Package> PackageList;
2671-
2672-PackageList package_list_from_json(const std::string& json);
2673-
2674-struct PackageDetails
2675-{
2676- struct JsonKeys
2677- {
2678- JsonKeys() = delete;
2679-
2680- constexpr static const char* name{"name"};
2681- constexpr static const char* title{"title"};
2682- constexpr static const char* icon_url{"icon_url"};
2683- constexpr static const char* description{"description"};
2684- constexpr static const char* download_url{"download_url"};
2685- constexpr static const char* rating{"rating"};
2686- constexpr static const char* keywords{"keywords"};
2687- constexpr static const char* terms_of_service{"terms_of_service"};
2688- constexpr static const char* license{"license"};
2689- constexpr static const char* publisher{"publisher"};
2690- constexpr static const char* main_screenshot_url{"screenshot_url"};
2691- constexpr static const char* more_screenshot_urls{"screenshot_urls"};
2692- constexpr static const char* binary_filesize{"binary_filesize"};
2693- constexpr static const char* version{"version"};
2694- constexpr static const char* framework{"framework"};
2695- };
2696-
2697- static PackageDetails from_json(const std::string &json);
2698-
2699- Package package;
2700-
2701- std::string description;
2702- std::string download_url;
2703- double rating;
2704- std::string keywords;
2705- std::string terms_of_service;
2706- std::string license;
2707- std::string publisher;
2708- std::string main_screenshot_url;
2709- std::list<std::string> more_screenshots_urls;
2710- json::Value::UInt64 binary_filesize;
2711- std::string version;
2712- std::string framework;
2713-};
2714-
2715-std::ostream& operator<<(std::ostream& out, const PackageDetails& details);
2716-
2717 class Index
2718 {
2719 protected:
2720 QSharedPointer<web::Client> client;
2721+ QSharedPointer<Configuration> configuration;
2722+ virtual std::string build_index_query(std::string query);
2723 public:
2724 enum class Error {NoError, CredentialsError, NetworkError};
2725- Index(const QSharedPointer<click::web::Client>& client);
2726- click::web::Cancellable search (const std::string& query, std::function<void(PackageList)> callback);
2727- click::web::Cancellable get_details(const std::string& package_name, std::function<void(PackageDetails, Error)> callback);
2728- ~Index();
2729+ Index(const QSharedPointer<click::web::Client>& client,
2730+ const QSharedPointer<Configuration> configuration=QSharedPointer<Configuration>(new Configuration()));
2731+ virtual click::web::Cancellable search (const std::string& query, std::function<void(PackageList)> callback);
2732+ virtual click::web::Cancellable get_details(const std::string& package_name, std::function<void(PackageDetails, Error)> callback);
2733+ virtual ~Index();
2734+
2735+ static std::string get_base_url ();
2736 };
2737
2738-bool operator==(const Package& lhs, const Package& rhs);
2739-bool operator==(const PackageDetails& lhs, const PackageDetails& rhs);
2740-
2741 } // namespace click
2742
2743 #endif // CLICKINDEX_H
2744
2745=== modified file 'scope/click/interface.cpp'
2746--- scope/click/interface.cpp 2014-04-10 17:29:49 +0000
2747+++ scope/click/interface.cpp 2014-05-02 16:27:07 +0000
2748@@ -136,6 +136,10 @@
2749 auto enumerator = [&result, &installTimes, this, search_query, include_desktop_results]
2750 (const unity::util::IniParser& keyFile, const std::string& filename)
2751 {
2752+ if (keyFile.has_group(DESKTOP_FILE_GROUP) == false) {
2753+ qWarning() << "Broken desktop file:" << QString::fromStdString(filename);
2754+ return;
2755+ }
2756 if (is_visible_app(keyFile) == false) {
2757 return; // from the enumerator lambda
2758 }
2759@@ -226,30 +230,6 @@
2760 return icon_id;
2761 }
2762
2763-std::vector<std::string> FrameworkLocator::list_folder(const std::string& folder, const std::string& pattern)
2764-{
2765- std::vector<std::string> result;
2766-
2767- QDir dir(QString::fromStdString(folder), QString::fromStdString(pattern),
2768- QDir::Unsorted, QDir::Readable | QDir::Files);
2769- QStringList entries = dir.entryList();
2770- for (int i = 0; i < entries.size(); ++i) {
2771- QString filename = entries.at(i);
2772- result.push_back(filename.toStdString());
2773- }
2774-
2775- return result;
2776-}
2777-
2778-std::vector<std::string> FrameworkLocator::get_available_frameworks()
2779-{
2780- std::vector<std::string> result;
2781- for (auto f: list_folder(FRAMEWORKS_FOLDER, FRAMEWORKS_PATTERN)) {
2782- result.push_back(f.substr(0, f.size()-FRAMEWORKS_EXTENSION_LENGTH));
2783- }
2784- return result;
2785-}
2786-
2787 ManifestList manifest_list_from_json(const std::string& json)
2788 {
2789 using namespace boost::property_tree;
2790@@ -265,20 +245,22 @@
2791 {
2792 assert(v.first.empty()); // array elements have no names
2793 auto node = v.second;
2794- std::string name = node.get<std::string>("name");
2795- std::string version = node.get<std::string>("version");
2796- std::string first_app_name;
2797+ Manifest manifest;
2798+
2799+ manifest.name = node.get<std::string>("name");
2800+ manifest.version = node.get<std::string>("version");
2801+ manifest.removable = node.get<bool>("_removable");
2802
2803 BOOST_FOREACH(ptree::value_type &sv, node.get_child("hooks"))
2804 {
2805 // FIXME: "primary app" for a package is not defined, we just
2806 // use first one here:
2807- first_app_name = sv.first;
2808+ manifest.first_app_name = sv.first;
2809 break;
2810 }
2811- qDebug() << "adding manifest: " << name.c_str() << version.c_str() << first_app_name.c_str();
2812+ qDebug() << "adding manifest: " << manifest.name.c_str() << manifest.version.c_str() << manifest.first_app_name.c_str();
2813
2814- manifests.push_back(Manifest(name, version, first_app_name));
2815+ manifests.push_back(manifest);
2816 }
2817
2818 return manifests;
2819@@ -293,87 +275,59 @@
2820 ptree pt;
2821 read_json(is, pt);
2822
2823- std::string name = pt.get<std::string>("name");
2824- std::string version = pt.get<std::string>("version");
2825- std::string first_app_name;
2826+ Manifest manifest;
2827+
2828+ manifest.name = pt.get<std::string>("name");
2829+ manifest.version = pt.get<std::string>("version");
2830+ manifest.removable = pt.get<bool>("_removable");
2831
2832 BOOST_FOREACH(ptree::value_type &sv, pt.get_child("hooks"))
2833 {
2834 // FIXME: "primary app" for a package is not defined, we just
2835 // use first one here:
2836- first_app_name = sv.first;
2837+ manifest.first_app_name = sv.first;
2838 break;
2839 }
2840- qDebug() << "adding manifest: " << name.c_str() << version.c_str() << first_app_name.c_str();
2841-
2842- Manifest manifest(name, version, first_app_name);
2843+ qDebug() << "adding manifest: " << manifest.name.c_str() << manifest.version.c_str() << manifest.first_app_name.c_str();
2844
2845 return manifest;
2846 }
2847
2848 void Interface::get_manifests(std::function<void(ManifestList, ManifestError)> callback)
2849 {
2850- QSharedPointer<QProcess> process(new QProcess());
2851- typedef void(QProcess::*QProcessFinished)(int, QProcess::ExitStatus);
2852- typedef void(QProcess::*QProcessError)(QProcess::ProcessError);
2853- QObject::connect(process.data(),
2854- static_cast<QProcessFinished>(&QProcess::finished),
2855- [callback, process](int code, QProcess::ExitStatus /*status*/) {
2856- qDebug() << "manifest command finished with exit code:" << code;
2857- try {
2858- auto data = process.data()->readAllStandardOutput().data();
2859- ManifestList manifests = manifest_list_from_json(data);
2860- qDebug() << "calling back ";
2861- callback(manifests, ManifestError::NoError);
2862- }
2863- catch ( ... ) {
2864- callback(ManifestList(), ManifestError::ParseError);
2865- }
2866- } );
2867-
2868- QObject::connect(process.data(),
2869- static_cast<QProcessError>(&QProcess::error),
2870- [callback, process](QProcess::ProcessError error) {
2871- qCritical() << "error running command:" << error;
2872- callback(ManifestList(), ManifestError::CallError);
2873- } );
2874-
2875 std::string command = "click list --manifest";
2876 qDebug() << "Running command:" << command.c_str();
2877- process->start(command.c_str());
2878+ run_process(command, [callback](int code, const std::string& stdout_data, const std::string&) {
2879+ if (code == 0) {
2880+ try {
2881+ ManifestList manifests = manifest_list_from_json(stdout_data);
2882+ callback(manifests, ManifestError::NoError);
2883+ } catch (...) {
2884+ callback(ManifestList(), ManifestError::ParseError);
2885+ }
2886+ } else {
2887+ callback(ManifestList(), ManifestError::CallError);
2888+ }
2889+ });
2890 }
2891
2892 void Interface::get_manifest_for_app(const std::string &app_id,
2893 std::function<void(Manifest, ManifestError)> callback)
2894 {
2895- QSharedPointer<QProcess> process(new QProcess());
2896- typedef void(QProcess::*QProcessFinished)(int, QProcess::ExitStatus);
2897- typedef void(QProcess::*QProcessError)(QProcess::ProcessError);
2898- QObject::connect(process.data(),
2899- static_cast<QProcessFinished>(&QProcess::finished),
2900- [callback, process](int code, QProcess::ExitStatus /*status*/) {
2901- qDebug() << "manifest command finished with exit code:" << code;
2902- try {
2903- auto data = process.data()->readAllStandardOutput().data();
2904- Manifest manifest = manifest_from_json(data);
2905- qDebug() << "calling back ";
2906- callback(manifest, ManifestError::NoError);
2907- }
2908- catch ( ... ) {
2909- callback(Manifest(), ManifestError::ParseError);
2910- }
2911- } );
2912-
2913- QObject::connect(process.data(),
2914- static_cast<QProcessError>(&QProcess::error),
2915- [callback, process](QProcess::ProcessError error) {
2916- qCritical() << "error running command:" << error;
2917- callback(Manifest(), ManifestError::CallError);
2918- } );
2919-
2920 std::string command = "click info " + app_id;
2921 qDebug() << "Running command:" << command.c_str();
2922- process->start(command.c_str());
2923+ run_process(command, [callback](int code, const std::string& stdout_data, const std::string&) {
2924+ if (code == 0) {
2925+ try {
2926+ Manifest manifest = manifest_from_json(stdout_data);
2927+ callback(manifest, ManifestError::NoError);
2928+ } catch (...) {
2929+ callback(Manifest(), ManifestError::ParseError);
2930+ }
2931+ } else {
2932+ callback(Manifest(), ManifestError::CallError);
2933+ }
2934+ });
2935 }
2936
2937 void Interface::get_dotdesktop_filename(const std::string &app_id,
2938@@ -398,4 +352,33 @@
2939 });
2940 }
2941
2942+void Interface::run_process(const std::string& command,
2943+ std::function<void(int code,
2944+ const std::string& stdout_data,
2945+ const std::string& stderr_data)> callback)
2946+{
2947+ QSharedPointer<QProcess> process(new QProcess());
2948+ typedef void(QProcess::*QProcessFinished)(int, QProcess::ExitStatus);
2949+ typedef void(QProcess::*QProcessError)(QProcess::ProcessError);
2950+ QObject::connect(process.data(),
2951+ static_cast<QProcessFinished>(&QProcess::finished),
2952+ [callback, process](int code, QProcess::ExitStatus /*status*/) {
2953+ qDebug() << "command finished with exit code:" << code;
2954+ auto data = process.data()->readAllStandardOutput().data();
2955+ auto errors = process.data()->readAllStandardError().data();
2956+ callback(code, data, errors);
2957+ } );
2958+
2959+ QObject::connect(process.data(),
2960+ static_cast<QProcessError>(&QProcess::error),
2961+ [callback, process](QProcess::ProcessError error) {
2962+ qCritical() << "error running command:" << error;
2963+ auto data = process.data()->readAllStandardOutput().data();
2964+ auto errors = process.data()->readAllStandardError().data();
2965+ callback(process.data()->exitCode(), data, errors);
2966+ } );
2967+
2968+ process->start(command.c_str());
2969+}
2970+
2971 } // namespace click
2972
2973=== modified file 'scope/click/interface.h'
2974--- scope/click/interface.h 2014-04-08 20:04:45 +0000
2975+++ scope/click/interface.h 2014-05-02 16:27:07 +0000
2976@@ -59,6 +59,7 @@
2977 std::string name;
2978 std::string version;
2979 std::string first_app_name;
2980+ bool removable = false;
2981 };
2982
2983 enum class ManifestError {NoError, CallError, ParseError};
2984@@ -71,6 +72,7 @@
2985 {
2986 public:
2987 Interface(const QSharedPointer<KeyFileLocator>& keyFileLocator);
2988+ Interface() = default;
2989 virtual ~Interface();
2990
2991 virtual std::vector<Application> find_installed_apps(const QString& search_query);
2992@@ -79,29 +81,22 @@
2993
2994 static bool is_icon_identifier(const std::string &icon_id);
2995 static std::string add_theme_scheme(const std::string &filename);
2996- static void get_manifests(std::function<void(ManifestList, ManifestError)> callback);
2997- static void get_manifest_for_app(const std::string &app_id, std::function<void(Manifest, ManifestError)> callback);
2998- static void get_dotdesktop_filename(const std::string &app_id,
2999+ virtual void get_manifests(std::function<void(ManifestList, ManifestError)> callback);
3000+ virtual void get_manifest_for_app(const std::string &app_id, std::function<void(Manifest, ManifestError)> callback);
3001+ virtual void get_dotdesktop_filename(const std::string &app_id,
3002 std::function<void(std::string filename, ManifestError)> callback);
3003 constexpr static const char* ENV_SHOW_DESKTOP_APPS {"CLICK_SCOPE_SHOW_DESKTOP_APPS"};
3004 virtual bool is_visible_app(const unity::util::IniParser& keyFile);
3005 virtual bool show_desktop_apps();
3006+
3007+ virtual void run_process(const std::string& command,
3008+ std::function<void(int code,
3009+ const std::string& stdout_data,
3010+ const std::string& stderr_data)> callback);
3011 private:
3012 QSharedPointer<KeyFileLocator> keyFileLocator;
3013 };
3014
3015-class FrameworkLocator
3016-{
3017-public:
3018- constexpr static const char* FRAMEWORKS_FOLDER {"/usr/share/click/frameworks/"};
3019- constexpr static const char* FRAMEWORKS_PATTERN {"*.framework"};
3020- constexpr static const int FRAMEWORKS_EXTENSION_LENGTH = 10; // strlen(".framework")
3021-
3022- virtual std::vector<std::string> get_available_frameworks();
3023-protected:
3024- virtual std::vector<std::string> list_folder(const std::string &folder, const std::string &pattern);
3025-};
3026-
3027 } // namespace click
3028
3029 #endif // CLICK_INTERFACE_H
3030
3031=== added file 'scope/click/package.cpp'
3032--- scope/click/package.cpp 1970-01-01 00:00:00 +0000
3033+++ scope/click/package.cpp 2014-05-02 16:27:07 +0000
3034@@ -0,0 +1,237 @@
3035+/*
3036+ * Copyright (C) 2014 Canonical Ltd.
3037+ *
3038+ * This program is free software: you can redistribute it and/or modify it
3039+ * under the terms of the GNU General Public License version 3, as published
3040+ * by the Free Software Foundation.
3041+ *
3042+ * This program is distributed in the hope that it will be useful, but
3043+ * WITHOUT ANY WARRANTY; without even the implied warranties of
3044+ * MERCHANTABILITY, SATISFACTORY QUALITY, or FITNESS FOR A PARTICULAR
3045+ * PURPOSE. See the GNU General Public License for more details.
3046+ *
3047+ * You should have received a copy of the GNU General Public License along
3048+ * with this program. If not, see <http://www.gnu.org/licenses/>.
3049+ *
3050+ * In addition, as a special exception, the copyright holders give
3051+ * permission to link the code of portions of this program with the
3052+ * OpenSSL library under certain conditions as described in each
3053+ * individual source file, and distribute linked combinations
3054+ * including the two.
3055+ * You must obey the GNU General Public License in all respects
3056+ * for all of the code used other than OpenSSL. If you modify
3057+ * file(s) with this exception, you may extend this exception to your
3058+ * version of the file(s), but you are not obligated to do so. If you
3059+ * do not wish to do so, delete this exception statement from your
3060+ * version. If you delete this exception statement from all source
3061+ * files in the program, then also delete it here.
3062+ */
3063+
3064+#include <sstream>
3065+
3066+#include "application.h"
3067+#include "package.h"
3068+
3069+namespace click
3070+{
3071+
3072+QDebug operator<< (QDebug d, const std::string &s) {
3073+ d << QString::fromStdString(s);
3074+ return d;
3075+}
3076+
3077+bool operator==(const Package& lhs, const Package& rhs) {
3078+ return lhs.name == rhs.name &&
3079+ lhs.title == rhs.title &&
3080+ lhs.price == rhs.price &&
3081+ lhs.icon_url == rhs.icon_url;
3082+}
3083+
3084+bool operator==(const PackageDetails& lhs, const PackageDetails& rhs) {
3085+ return lhs.package == rhs.package &&
3086+ lhs.description == rhs.description &&
3087+ lhs.download_url == rhs.download_url &&
3088+ lhs.rating == rhs.rating &&
3089+ // TODO: keywords should be a list of strings
3090+ lhs.keywords == rhs.keywords &&
3091+ lhs.terms_of_service == rhs.terms_of_service &&
3092+ lhs.license == rhs.license &&
3093+ lhs.publisher == rhs.publisher &&
3094+ lhs.main_screenshot_url == rhs.main_screenshot_url &&
3095+ // TODO: more_screenshots_urls should be a list of strings
3096+ lhs.more_screenshots_urls == rhs.more_screenshots_urls &&
3097+ // TODO: binary_filesize should be a int/long
3098+ lhs.binary_filesize == rhs.binary_filesize &&
3099+ lhs.version == rhs.version &&
3100+ lhs.framework == rhs.framework;
3101+}
3102+
3103+PackageList package_list_from_json(const std::string& json)
3104+{
3105+ std::istringstream is(json);
3106+
3107+ PackageList pl;
3108+
3109+ json::Reader reader;
3110+ json::Value root;
3111+
3112+ if (!reader.parse(json, root)) {
3113+ throw std::runtime_error(reader.getFormattedErrorMessages());
3114+ }
3115+
3116+ for (uint i = 0; i < root.size(); i++)
3117+ {
3118+ Package p;
3119+ json::Value item = root[i];
3120+ p.name = item[Package::JsonKeys::name].asString();
3121+ p.title = item[Package::JsonKeys::title].asString();
3122+ p.price = item[Package::JsonKeys::price].asDouble();
3123+ p.icon_url = item[Package::JsonKeys::icon_url].asString();
3124+ p.url = item[Package::JsonKeys::resource_url].asString();
3125+ pl.push_back(p);
3126+ }
3127+ return pl;
3128+}
3129+
3130+PackageDetails PackageDetails::from_json(const std::string &json)
3131+{
3132+ PackageDetails details;
3133+ try
3134+ {
3135+ json::Reader reader;
3136+ json::Value root;
3137+
3138+ if (!reader.parse(json, root))
3139+ throw std::runtime_error(reader.getFormattedErrorMessages());
3140+
3141+ // Mandatory details go here. That is, asString() will throw as we
3142+ // do not provide a default value if a value with the given key does not exist.
3143+ details.package.name = root[Package::JsonKeys::name].asString();
3144+ details.package.title = root[Package::JsonKeys::title].asString();
3145+ details.package.icon_url = root[Package::JsonKeys::icon_url].asString();
3146+ details.package.price = root[Package::JsonKeys::price].asDouble();
3147+ details.description = root[JsonKeys::description].asString();
3148+ details.download_url = root[JsonKeys::download_url].asString();
3149+ details.license = root[JsonKeys::license].asString();
3150+
3151+ // Optional details go here.
3152+ if (root[JsonKeys::version].isString())
3153+ details.version = root[JsonKeys::version].asString();
3154+
3155+ if (root[JsonKeys::rating].isNumeric())
3156+ details.rating = root[JsonKeys::rating].asDouble();
3157+
3158+ if (root[JsonKeys::keywords].isString())
3159+ details.keywords = root[JsonKeys::keywords].asString();
3160+
3161+ if (root[JsonKeys::terms_of_service].isString())
3162+ details.terms_of_service = root[JsonKeys::terms_of_service].asString();
3163+
3164+ if (root[JsonKeys::publisher].isString())
3165+ details.publisher = root[JsonKeys::publisher].asString();
3166+
3167+ if (root[JsonKeys::main_screenshot_url].isString())
3168+ details.main_screenshot_url = root[JsonKeys::main_screenshot_url].asString();
3169+
3170+ auto screenshots = root[JsonKeys::more_screenshot_urls];
3171+
3172+ for (uint i = 0; i < screenshots.size(); i++)
3173+ {
3174+ auto scr = screenshots[i].asString();
3175+ // more_screenshot_urls may contain main_screenshot_url, if so, skip it
3176+ if (scr != details.main_screenshot_url)
3177+ {
3178+ details.more_screenshots_urls.push_back(scr);
3179+ }
3180+ }
3181+
3182+ if (root[JsonKeys::binary_filesize].isIntegral())
3183+ details.binary_filesize = root[JsonKeys::binary_filesize].asUInt64();
3184+
3185+ if (root[JsonKeys::framework].isString())
3186+ details.framework = root[JsonKeys::framework].asString();
3187+
3188+ } catch(const std::exception& e)
3189+ {
3190+ std::cerr << "PackageDetails::loadJson: Exception thrown while decoding JSON: " << e.what() << std::endl;
3191+ } catch(...)
3192+ {
3193+ std::cerr << "PackageDetails::loadJson: Exception thrown while decoding JSON." << std::endl;
3194+ }
3195+
3196+ return details;
3197+}
3198+
3199+std::string print_string_if_not_empty(const std::string& s)
3200+{
3201+
3202+ return s.empty() ? "n/a" : s;
3203+}
3204+
3205+std::string print_list_if_not_empty(const std::list<std::string>& li)
3206+{
3207+ std::stringstream s;
3208+ s << "[";
3209+ if (!li.empty())
3210+ {
3211+ auto it = li.begin();
3212+ s << print_string_if_not_empty(*it);
3213+ ++it;
3214+ while (it != li.end())
3215+ {
3216+ s << ", " << print_string_if_not_empty(*it);
3217+ ++it;
3218+ }
3219+ }
3220+ s << "]";
3221+ return s.str();
3222+}
3223+
3224+std::ostream& operator<<(std::ostream& out, const click::PackageDetails& details)
3225+{
3226+ out << "("
3227+ << print_string_if_not_empty(details.package.name) << ", "
3228+ << print_string_if_not_empty(details.package.title) << ", "
3229+ << print_string_if_not_empty(details.package.icon_url) << ", "
3230+ << print_string_if_not_empty(details.description) << ", "
3231+ << print_string_if_not_empty(details.download_url) << ", "
3232+ << details.rating << ", "
3233+ << print_string_if_not_empty(details.keywords) << ", "
3234+ << print_string_if_not_empty(details.terms_of_service) << ", "
3235+ << print_string_if_not_empty(details.license) << ", "
3236+ << print_string_if_not_empty(details.publisher) << ", "
3237+ << print_string_if_not_empty(details.main_screenshot_url) << ", "
3238+ << print_list_if_not_empty(details.more_screenshots_urls) << ", "
3239+ << details.binary_filesize << ", "
3240+ << print_string_if_not_empty(details.version) << ", "
3241+ << print_string_if_not_empty(details.framework)
3242+ << ")";
3243+
3244+ return out;
3245+}
3246+
3247+bool operator==(const Application& lhs, const Application& rhs) {
3248+ return lhs.name == rhs.name &&
3249+ lhs.title == rhs.title &&
3250+ lhs.description == rhs.description &&
3251+ lhs.main_screenshot == rhs.main_screenshot &&
3252+ lhs.icon_url == rhs.icon_url;
3253+}
3254+
3255+std::ostream& operator<<(std::ostream& out, const click::Application& app)
3256+{
3257+ out << "("
3258+ << print_string_if_not_empty(app.name) << ", "
3259+ << print_string_if_not_empty(app.title) << ", "
3260+ << app.price << ", "
3261+ << print_string_if_not_empty(app.icon_url) << ", "
3262+ << print_string_if_not_empty(app.url) << ", "
3263+ << print_string_if_not_empty(app.version) << ", "
3264+ << print_string_if_not_empty(app.description) << ", "
3265+ << print_string_if_not_empty(app.main_screenshot)
3266+ << ")";
3267+
3268+ return out;
3269+}
3270+
3271+} // namespace click
3272
3273=== added file 'scope/click/package.h'
3274--- scope/click/package.h 1970-01-01 00:00:00 +0000
3275+++ scope/click/package.h 2014-05-02 16:27:07 +0000
3276@@ -0,0 +1,137 @@
3277+/*
3278+ * Copyright (C) 2014 Canonical Ltd.
3279+ *
3280+ * This program is free software: you can redistribute it and/or modify it
3281+ * under the terms of the GNU General Public License version 3, as published
3282+ * by the Free Software Foundation.
3283+ *
3284+ * This program is distributed in the hope that it will be useful, but
3285+ * WITHOUT ANY WARRANTY; without even the implied warranties of
3286+ * MERCHANTABILITY, SATISFACTORY QUALITY, or FITNESS FOR A PARTICULAR
3287+ * PURPOSE. See the GNU General Public License for more details.
3288+ *
3289+ * You should have received a copy of the GNU General Public License along
3290+ * with this program. If not, see <http://www.gnu.org/licenses/>.
3291+ *
3292+ * In addition, as a special exception, the copyright holders give
3293+ * permission to link the code of portions of this program with the
3294+ * OpenSSL library under certain conditions as described in each
3295+ * individual source file, and distribute linked combinations
3296+ * including the two.
3297+ * You must obey the GNU General Public License in all respects
3298+ * for all of the code used other than OpenSSL. If you modify
3299+ * file(s) with this exception, you may extend this exception to your
3300+ * version of the file(s), but you are not obligated to do so. If you
3301+ * do not wish to do so, delete this exception statement from your
3302+ * version. If you delete this exception statement from all source
3303+ * files in the program, then also delete it here.
3304+ */
3305+
3306+#ifndef CLICK_PACKAGE_H
3307+#define CLICK_PACKAGE_H
3308+
3309+#include <string>
3310+#include <list>
3311+
3312+#include <json/json.h>
3313+
3314+
3315+namespace json = Json;
3316+
3317+namespace click {
3318+
3319+struct Package
3320+{
3321+ struct JsonKeys
3322+ {
3323+ JsonKeys() = delete;
3324+
3325+ constexpr static const char* name{"name"};
3326+ constexpr static const char* title{"title"};
3327+ constexpr static const char* price{"price"};
3328+ constexpr static const char* icon_url{"icon_url"};
3329+ constexpr static const char* resource_url{"resource_url"};
3330+ };
3331+
3332+ Package() = default;
3333+ Package(std::string name, std::string title, double price, std::string icon_url, std::string url) :
3334+ name(name),
3335+ title(title),
3336+ price(price),
3337+ icon_url(icon_url),
3338+ url(url)
3339+ {
3340+ }
3341+ Package(std::string name, std::string title, double price, std::string icon_url, std::string url, std::string version) :
3342+ name(name),
3343+ title(title),
3344+ price(price),
3345+ icon_url(icon_url),
3346+ url(url),
3347+ version(version)
3348+ {
3349+ }
3350+ virtual ~Package() = default;
3351+
3352+ std::string name; // formerly app_id
3353+ std::string title;
3354+ double price;
3355+ std::string icon_url;
3356+ std::string url;
3357+ std::string version;
3358+ void matches (std::string query, std::function<bool> callback);
3359+};
3360+
3361+typedef std::list<Package> PackageList;
3362+
3363+PackageList package_list_from_json(const std::string& json);
3364+
3365+struct PackageDetails
3366+{
3367+ struct JsonKeys
3368+ {
3369+ JsonKeys() = delete;
3370+
3371+ constexpr static const char* name{"name"};
3372+ constexpr static const char* title{"title"};
3373+ constexpr static const char* icon_url{"icon_url"};
3374+ constexpr static const char* description{"description"};
3375+ constexpr static const char* download_url{"download_url"};
3376+ constexpr static const char* rating{"rating"};
3377+ constexpr static const char* keywords{"keywords"};
3378+ constexpr static const char* terms_of_service{"terms_of_service"};
3379+ constexpr static const char* license{"license"};
3380+ constexpr static const char* publisher{"publisher"};
3381+ constexpr static const char* main_screenshot_url{"screenshot_url"};
3382+ constexpr static const char* more_screenshot_urls{"screenshot_urls"};
3383+ constexpr static const char* binary_filesize{"binary_filesize"};
3384+ constexpr static const char* version{"version"};
3385+ constexpr static const char* framework{"framework"};
3386+ };
3387+
3388+ static PackageDetails from_json(const std::string &json);
3389+
3390+ Package package;
3391+
3392+ std::string description;
3393+ std::string download_url;
3394+ double rating;
3395+ std::string keywords;
3396+ std::string terms_of_service;
3397+ std::string license;
3398+ std::string publisher;
3399+ std::string main_screenshot_url;
3400+ std::list<std::string> more_screenshots_urls;
3401+ json::Value::UInt64 binary_filesize;
3402+ std::string version;
3403+ std::string framework;
3404+};
3405+
3406+std::ostream& operator<<(std::ostream& out, const PackageDetails& details);
3407+
3408+bool operator==(const Package& lhs, const Package& rhs);
3409+bool operator==(const PackageDetails& lhs, const PackageDetails& rhs);
3410+
3411+} // namespace click
3412+
3413+#endif // CLICK_PACKAGE_H
3414
3415=== modified file 'scope/click/preview.cpp'
3416--- scope/click/preview.cpp 2014-04-10 18:19:33 +0000
3417+++ scope/click/preview.cpp 2014-05-02 16:27:07 +0000
3418@@ -27,6 +27,8 @@
3419 * files in the program, then also delete it here.
3420 */
3421
3422+#include "application.h"
3423+#include "interface.h"
3424 #include "preview.h"
3425 #include "qtbridge.h"
3426 #include "download-manager.h"
3427@@ -42,40 +44,110 @@
3428 #include <iostream>
3429 #include <sstream>
3430
3431+#include "interface.h"
3432 #include "click-i18n.h"
3433
3434 namespace click {
3435
3436 // Preview base class
3437
3438-Preview::Preview(const unity::scopes::Result& result)
3439+Preview::Preview(const unity::scopes::Result& result,
3440+ const unity::scopes::ActionMetadata& metadata,
3441+ const QSharedPointer<click::web::Client>& client,
3442+ const QSharedPointer<click::network::AccessManager>& nam)
3443+{
3444+ strategy.reset(choose_strategy(result, metadata, client, nam));
3445+}
3446+
3447+PreviewStrategy* Preview::choose_strategy(const unity::scopes::Result &result,
3448+ const unity::scopes::ActionMetadata &metadata,
3449+ const QSharedPointer<web::Client> &client,
3450+ const QSharedPointer<click::network::AccessManager>& nam)
3451+{
3452+ if (metadata.scope_data().which() != scopes::Variant::Type::Null) {
3453+ auto metadict = metadata.scope_data().get_dict();
3454+
3455+ if (metadict.count(click::Preview::Actions::DOWNLOAD_FAILED) != 0) {
3456+ return new DownloadErrorPreview(result);
3457+ } else if (metadict.count(click::Preview::Actions::DOWNLOAD_COMPLETED) != 0 ||
3458+ metadict.count(click::Preview::Actions::CLOSE_PREVIEW) != 0) {
3459+ qDebug() << "in Scope::preview(), metadata has download_completed="
3460+ << metadict.count(click::Preview::Actions::DOWNLOAD_COMPLETED)
3461+ << " and close_preview="
3462+ << metadict.count(click::Preview::Actions::CLOSE_PREVIEW);
3463+
3464+ return new InstalledPreview(result, metadata, client);
3465+ } else if (metadict.count("action_id") != 0 && metadict.count("download_url") != 0) {
3466+ std::string action_id = metadict["action_id"].get_string();
3467+ std::string download_url = metadict["download_url"].get_string();
3468+ if (action_id == click::Preview::Actions::INSTALL_CLICK) {
3469+ return new InstallingPreview(download_url, result, client, nam);
3470+ } else {
3471+ qWarning() << "unexpected action id " << QString::fromStdString(action_id)
3472+ << " given with download_url" << QString::fromStdString(download_url);
3473+ return new UninstalledPreview(result, client);
3474+ }
3475+ } else if (metadict.count(click::Preview::Actions::UNINSTALL_CLICK) != 0) {
3476+ return new UninstallConfirmationPreview(result);
3477+ } else if (metadict.count(click::Preview::Actions::CONFIRM_UNINSTALL) != 0) {
3478+ return new UninstallingPreview(result, client);
3479+ } else if (metadict.count(click::Preview::Actions::RATED) != 0) {
3480+ return new InstalledPreview(result, metadata, client);
3481+ } else {
3482+ qWarning() << "preview() called with unexpected metadata. returning uninstalled preview";
3483+ return new UninstalledPreview(result, client);
3484+ }
3485+ } else {
3486+ // metadata.scope_data() is Null, so we return an appropriate "default" preview:
3487+ if (result["installed"].get_bool() == true) {
3488+ return new InstalledPreview(result, metadata, client);
3489+ } else {
3490+ return new UninstalledPreview(result, client);
3491+ }
3492+ }
3493+
3494+}
3495+
3496+void Preview::cancelled()
3497+{
3498+ strategy->cancelled();
3499+}
3500+
3501+void Preview::run(const unity::scopes::PreviewReplyProxy &reply)
3502+{
3503+ strategy->run(reply);
3504+}
3505+
3506+PreviewStrategy::PreviewStrategy(const unity::scopes::Result& result)
3507 : result(result)
3508 {
3509 }
3510
3511-Preview::Preview(const unity::scopes::Result& result,
3512+PreviewStrategy::PreviewStrategy(const unity::scopes::Result& result,
3513 const QSharedPointer<click::web::Client>& client) :
3514 result(result),
3515+ client(client),
3516 index(new click::Index(client)),
3517 reviews(new click::Reviews(client))
3518 {
3519 }
3520
3521-Preview::~Preview()
3522+PreviewStrategy::~PreviewStrategy()
3523 {
3524 }
3525
3526-void Preview::cancelled()
3527+void PreviewStrategy::cancelled()
3528 {
3529 index_operation.cancel();
3530 reviews_operation.cancel();
3531+ submit_operation.cancel();
3532 }
3533
3534
3535 // TODO: error handling - once get_details provides errors, we can
3536 // return them from populateDetails and check them in the calling code
3537 // to decide whether to show error widgets. see bug LP: #1289541
3538-void Preview::populateDetails(std::function<void(const click::PackageDetails& details)> details_callback,
3539+void PreviewStrategy::populateDetails(std::function<void(const click::PackageDetails& details)> details_callback,
3540 std::function<void(const click::ReviewList&,
3541 click::Reviews::Error)> reviews_callback)
3542 {
3543@@ -96,7 +168,7 @@
3544 // I think this should not be required when we switch the click::Index over
3545 // to using the Qt bridge. With that, the qt dependency becomes an implementation detail
3546 // and code using it does not need to worry about threading/event loop topics.
3547- qt::core::world::enter_with_task([this, details_callback, reviews_callback, app_name](qt::core::world::Environment&)
3548+ qt::core::world::enter_with_task([this, details_callback, reviews_callback, app_name]()
3549 {
3550 index_operation = index->get_details(app_name, [this, app_name, details_callback, reviews_callback](PackageDetails details, click::Index::Error error){
3551 if(error == click::Index::Error::NoError) {
3552@@ -104,7 +176,12 @@
3553 details_callback(details);
3554 } else {
3555 qDebug() << "Error getting details for:" << app_name.c_str();
3556- // TODO: handle error getting details
3557+ click::PackageDetails details;
3558+ details.package.title = result.title();
3559+ details.package.icon_url = result.art();
3560+ details.description = result["description"].get_string();
3561+ details.main_screenshot_url = result["main_screenshot"].get_string();
3562+ details_callback(details);
3563 }
3564 reviews_operation = reviews->fetch_reviews(app_name,
3565 reviews_callback);
3566@@ -113,7 +190,7 @@
3567 }
3568 }
3569
3570-scopes::PreviewWidgetList Preview::headerWidgets(const click::PackageDetails& details)
3571+scopes::PreviewWidgetList PreviewStrategy::headerWidgets(const click::PackageDetails& details)
3572 {
3573 scopes::PreviewWidgetList widgets;
3574
3575@@ -140,12 +217,9 @@
3576
3577 scopes::PreviewWidget header("hdr", "header");
3578 header.add_attribute_value("title", scopes::Variant(details.package.title));
3579- if (!details.description.empty())
3580+ if (!details.publisher.empty())
3581 {
3582- std::stringstream ss(details.description);
3583- std::string first_line;
3584- if (std::getline(ss, first_line))
3585- header.add_attribute_value("subtitle", scopes::Variant(first_line));
3586+ header.add_attribute_value("subtitle", scopes::Variant(details.publisher));
3587 }
3588 if (!details.package.icon_url.empty())
3589 header.add_attribute_value("mascot", scopes::Variant(details.package.icon_url));
3590@@ -154,7 +228,7 @@
3591 return widgets;
3592 }
3593
3594-scopes::PreviewWidgetList Preview::descriptionWidgets(const click::PackageDetails& details)
3595+scopes::PreviewWidgetList PreviewStrategy::descriptionWidgets(const click::PackageDetails& details)
3596 {
3597 scopes::PreviewWidgetList widgets;
3598 if (details.description.empty())
3599@@ -169,7 +243,7 @@
3600 return widgets;
3601 }
3602
3603-scopes::PreviewWidgetList Preview::reviewsWidgets(const click::ReviewList& reviewlist)
3604+scopes::PreviewWidgetList PreviewStrategy::reviewsWidgets(const click::ReviewList& reviewlist)
3605 {
3606 scopes::PreviewWidgetList widgets;
3607
3608@@ -191,7 +265,7 @@
3609 return widgets;
3610 }
3611
3612-scopes::PreviewWidgetList Preview::downloadErrorWidgets()
3613+scopes::PreviewWidgetList PreviewStrategy::downloadErrorWidgets()
3614 {
3615 return errorWidgets(scopes::Variant(_("Download Error")),
3616 scopes::Variant(_("Download or install failed. Please try again.")),
3617@@ -199,18 +273,20 @@
3618 scopes::Variant(_("Close")));
3619 }
3620
3621-scopes::PreviewWidgetList Preview::loginErrorWidgets()
3622+scopes::PreviewWidgetList PreviewStrategy::loginErrorWidgets()
3623 {
3624 return errorWidgets(scopes::Variant(_("Login Error")),
3625 scopes::Variant(_("Please log in to your Ubuntu One account.")),
3626 scopes::Variant(click::Preview::Actions::OPEN_ACCOUNTS),
3627- scopes::Variant(_("Go to Accounts")));
3628+ scopes::Variant(_("Go to Accounts")),
3629+ scopes::Variant("settings:///system/online-accounts"));
3630 }
3631
3632-scopes::PreviewWidgetList Preview::errorWidgets(const scopes::Variant& title,
3633+scopes::PreviewWidgetList PreviewStrategy::errorWidgets(const scopes::Variant& title,
3634 const scopes::Variant& subtitle,
3635 const scopes::Variant& action_id,
3636- const scopes::Variant& action_label)
3637+ const scopes::Variant& action_label,
3638+ const scopes::Variant& uri)
3639 {
3640 scopes::PreviewWidgetList widgets;
3641
3642@@ -221,7 +297,14 @@
3643
3644 scopes::PreviewWidget buttons("buttons", "actions");
3645 scopes::VariantBuilder builder;
3646- builder.add_tuple({ {"id", action_id}, {"label", action_label} });
3647+ if (uri.is_null())
3648+ {
3649+ builder.add_tuple({ {"id", action_id}, {"label", action_label} });
3650+ }
3651+ else
3652+ {
3653+ builder.add_tuple({ {"id", action_id}, {"label", action_label}, {"uri", uri} });
3654+ }
3655 buttons.add_attribute_value("actions", builder.end());
3656 widgets.push_back(buttons);
3657
3658@@ -232,7 +315,7 @@
3659 // class DownloadErrorPreview
3660
3661 DownloadErrorPreview::DownloadErrorPreview(const unity::scopes::Result &result)
3662- : Preview(result)
3663+ : PreviewStrategy(result)
3664 {
3665 }
3666
3667@@ -255,7 +338,7 @@
3668 const unity::scopes::Result &result,
3669 const QSharedPointer<click::web::Client>& client,
3670 const QSharedPointer<click::network::AccessManager> &nam)
3671- : Preview(result, client), download_url(download_url),
3672+ : PreviewStrategy(result, client), download_url(download_url),
3673 downloader(new click::Downloader(nam))
3674 {
3675 }
3676@@ -317,8 +400,10 @@
3677 // class InstalledPreview
3678
3679 InstalledPreview::InstalledPreview(const unity::scopes::Result& result,
3680+ const unity::scopes::ActionMetadata& metadata,
3681 const QSharedPointer<click::web::Client>& client)
3682- : Preview(result, client)
3683+ : PreviewStrategy(result, client),
3684+ metadata(metadata)
3685 {
3686 }
3687
3688@@ -328,50 +413,146 @@
3689
3690 void InstalledPreview::run(unity::scopes::PreviewReplyProxy const& reply)
3691 {
3692- populateDetails([this, reply](const PackageDetails &details){
3693- reply->push(headerWidgets(details));
3694- reply->push(installedActionButtonWidgets());
3695- reply->push(descriptionWidgets(details));
3696- },
3697- [this, reply](const ReviewList& reviewlist,
3698- click::Reviews::Error error) {
3699- if (error == click::Reviews::Error::NoError) {
3700- reply->push(reviewsWidgets(reviewlist));
3701- } else {
3702- qDebug() << "There was an error getting reviews for:" << result["name"].get_string().c_str();
3703- }
3704- reply->finished();
3705- });
3706+ // Check if the user is submitting a rating, so we can submit it.
3707+ Review review;
3708+ review.rating = 0;
3709+ // We use a try/catch here, as scope_data() can be a dict, but not have
3710+ // the values we need, which will result in an exception thrown.
3711+ try {
3712+ auto metadict = metadata.scope_data().get_dict();
3713+ review.rating = metadict["rating"].get_int();
3714+ review.review_text = metadict["review"].get_string();
3715+ } catch(...) {
3716+ // Do nothing as we are not submitting a review.
3717+ }
3718+
3719+ // Get the removable flag from the click manifest.
3720+ bool removable = false;
3721+ std::promise<bool> manifest_promise;
3722+ std::future<bool> manifest_future = manifest_promise.get_future();
3723+ std::string app_name = result["name"].get_string();
3724+ if (!app_name.empty()) {
3725+ qt::core::world::enter_with_task([&]() {
3726+ click::Interface().get_manifest_for_app(app_name,
3727+ [&](Manifest manifest, ManifestError error) {
3728+ qDebug() << "Got manifest for:" << app_name.c_str();
3729+ removable = manifest.removable;
3730+
3731+ // Fill in required data about the package being reviewed.
3732+ review.package_name = manifest.name;
3733+ review.package_version = manifest.version;
3734+
3735+ if (error != click::ManifestError::NoError) {
3736+ qDebug() << "There was an error getting the manifest for:" << app_name.c_str();
3737+ }
3738+ manifest_promise.set_value(true);
3739+ });
3740+ });
3741+ manifest_future.get();
3742+ if (review.rating > 0) {
3743+ std::promise<bool> submit_promise;
3744+ std::future<bool> submit_future = submit_promise.get_future();
3745+ qt::core::world::enter_with_task([this, review, &submit_promise]() {
3746+ QSharedPointer<click::CredentialsService> sso(new click::CredentialsService());
3747+ client->setCredentialsService(sso);
3748+ submit_operation = reviews->submit_review(review,
3749+ [&submit_promise](click::Reviews::Error){
3750+ // TODO: Need to handle errors properly.
3751+ submit_promise.set_value(true);
3752+ });
3753+ });
3754+ submit_future.get();
3755+ }
3756+ }
3757+ getApplicationUri([this, reply, removable, app_name, &review](const std::string& uri) {
3758+ populateDetails([this, reply, uri, removable, app_name, &review](const PackageDetails &details){
3759+ reply->push(headerWidgets(details));
3760+ reply->push(createButtons(uri, removable));
3761+ reply->push(descriptionWidgets(details));
3762+
3763+ // Hide the rating widget until #1314117 is fixed.
3764+ if (false && review.rating == 0 && removable) {
3765+ scopes::PreviewWidgetList review_input;
3766+ scopes::PreviewWidget rating("rating", "rating-input");
3767+ rating.add_attribute_value("required", scopes::Variant("rating"));
3768+ review_input.push_back(rating);
3769+ reply->push(review_input);
3770+ }
3771+ },
3772+ [this, reply](const ReviewList& reviewlist,
3773+ click::Reviews::Error error) {
3774+ if (error == click::Reviews::Error::NoError) {
3775+ reply->push(reviewsWidgets(reviewlist));
3776+ } else {
3777+ qDebug() << "There was an error getting reviews for:" << result["name"].get_string().c_str();
3778+ }
3779+ reply->finished();
3780+ });
3781+ });
3782 }
3783
3784-scopes::PreviewWidgetList InstalledPreview::installedActionButtonWidgets()
3785+scopes::PreviewWidgetList InstalledPreview::createButtons(const std::string& uri,
3786+ bool removable)
3787 {
3788 scopes::PreviewWidgetList widgets;
3789-
3790 scopes::PreviewWidget buttons("buttons", "actions");
3791 scopes::VariantBuilder builder;
3792- builder.add_tuple(
3793+ if (!uri.empty())
3794+ {
3795+ builder.add_tuple(
3796 {
3797 {"id", scopes::Variant(click::Preview::Actions::OPEN_CLICK)},
3798- {"label", scopes::Variant(_("Open"))}
3799+ {"label", scopes::Variant(_("Open"))},
3800+ {"uri", scopes::Variant(uri)}
3801 });
3802- builder.add_tuple(
3803- {
3804+ }
3805+ if (removable)
3806+ {
3807+ builder.add_tuple({
3808 {"id", scopes::Variant(click::Preview::Actions::UNINSTALL_CLICK)},
3809 {"label", scopes::Variant(_("Uninstall"))}
3810 });
3811- buttons.add_attribute_value("actions", builder.end());
3812- widgets.push_back(buttons);
3813-
3814+ }
3815+ if (!uri.empty() || removable) {
3816+ buttons.add_attribute_value("actions", builder.end());
3817+ widgets.push_back(buttons);
3818+ }
3819 return widgets;
3820 }
3821
3822+void InstalledPreview::getApplicationUri(std::function<void(const std::string&)> callback)
3823+{
3824+ std::string uri;
3825+ QString app_url = QString::fromStdString(result.uri());
3826+
3827+ // asynchronously get application uri based on app name, if the uri is not application://.
3828+ // this can happen if the app was just installed and we have its http uri from the Result.
3829+ if (!app_url.startsWith("application:///")) {
3830+ const std::string name = result["name"].get_string();
3831+ auto ft = qt::core::world::enter_with_task([this, name, callback] ()
3832+ {
3833+ click::Interface().get_dotdesktop_filename(name,
3834+ [callback] (std::string val, click::ManifestError error) {
3835+ std::string uri;
3836+ if (error == click::ManifestError::NoError) {
3837+ uri = "application:///" + val;
3838+ }
3839+ callback(uri);
3840+ }
3841+ );
3842+ });
3843+ } else {
3844+ uri = app_url.toStdString();
3845+ callback(uri);
3846+ }
3847+}
3848+
3849
3850 // class PurchasingPreview
3851
3852 PurchasingPreview::PurchasingPreview(const unity::scopes::Result& result,
3853 const QSharedPointer<click::web::Client>& client)
3854- : Preview(result, client)
3855+ : PreviewStrategy(result, client)
3856 {
3857 }
3858
3859@@ -400,7 +581,7 @@
3860 // class UninstallConfirmationPreview
3861
3862 UninstallConfirmationPreview::UninstallConfirmationPreview(const unity::scopes::Result& result)
3863- : Preview(result)
3864+ : PreviewStrategy(result)
3865 {
3866 }
3867
3868@@ -439,7 +620,7 @@
3869
3870 UninstalledPreview::UninstalledPreview(const unity::scopes::Result& result,
3871 const QSharedPointer<click::web::Client>& client)
3872- : Preview(result, client)
3873+ : PreviewStrategy(result, client)
3874 {
3875 }
3876
3877@@ -510,7 +691,7 @@
3878 package.title = result.title();
3879 package.name = result["name"].get_string();
3880 package.version = result["version"].get_string();
3881- qt::core::world::enter_with_task([this, package] (qt::core::world::Environment& /*env*/)
3882+ qt::core::world::enter_with_task([this, package] ()
3883 {
3884 click::PackageManager manager;
3885 manager.uninstall(package, [&](int code, std::string stderr_content) {
3886
3887=== modified file 'scope/click/preview.h'
3888--- scope/click/preview.h 2014-04-02 09:29:38 +0000
3889+++ scope/click/preview.h 2014-05-02 16:27:07 +0000
3890@@ -36,16 +36,26 @@
3891 #include "qtbridge.h"
3892 #include "reviews.h"
3893
3894+#include <unity/scopes/ActionMetadata.h>
3895 #include <unity/scopes/PreviewQueryBase.h>
3896 #include <unity/scopes/PreviewWidget.h>
3897 #include <unity/scopes/Result.h>
3898+#include <unity/scopes/ScopeBase.h>
3899
3900 namespace scopes = unity::scopes;
3901
3902 namespace click {
3903
3904+class PreviewStrategy;
3905+
3906 class Preview : public unity::scopes::PreviewQueryBase
3907 {
3908+protected:
3909+ std::unique_ptr<PreviewStrategy> strategy;
3910+ PreviewStrategy* choose_strategy(const unity::scopes::Result& result,
3911+ const unity::scopes::ActionMetadata& metadata,
3912+ const QSharedPointer<web::Client> &client,
3913+ const QSharedPointer<click::network::AccessManager>& nam);
3914 public:
3915 struct Actions
3916 {
3917@@ -63,17 +73,31 @@
3918 constexpr static const char* CONFIRM_UNINSTALL{"confirm_uninstall"};
3919 constexpr static const char* CLOSE_PREVIEW{"close_preview"};
3920 constexpr static const char* OPEN_ACCOUNTS{"open_accounts"};
3921+ constexpr static const char* RATED{"rated"};
3922 };
3923
3924 Preview(const unity::scopes::Result& result);
3925 Preview(const unity::scopes::Result& result,
3926- const QSharedPointer<click::web::Client>& client);
3927-
3928- virtual ~Preview();
3929-
3930+ const unity::scopes::ActionMetadata& metadata,
3931+ const QSharedPointer<click::web::Client>& client,
3932+ const QSharedPointer<click::network::AccessManager>& nam);
3933 // From unity::scopes::PreviewQuery
3934 void cancelled() override;
3935- virtual void run(unity::scopes::PreviewReplyProxy const& reply) override = 0;
3936+ virtual void run(unity::scopes::PreviewReplyProxy const& reply) override;
3937+};
3938+
3939+class PreviewStrategy
3940+{
3941+public:
3942+
3943+ PreviewStrategy(const unity::scopes::Result& result);
3944+ PreviewStrategy(const unity::scopes::Result& result,
3945+ const QSharedPointer<click::web::Client>& client);
3946+
3947+ virtual ~PreviewStrategy();
3948+
3949+ virtual void cancelled();
3950+ virtual void run(unity::scopes::PreviewReplyProxy const& reply) = 0;
3951
3952 protected:
3953 virtual void populateDetails(std::function<void(const PackageDetails &)> details_callback,
3954@@ -87,15 +111,18 @@
3955 virtual scopes::PreviewWidgetList errorWidgets(const scopes::Variant& title,
3956 const scopes::Variant& subtitle,
3957 const scopes::Variant& action_id,
3958- const scopes::Variant& action_label);
3959+ const scopes::Variant& action_label,
3960+ const scopes::Variant& action_uri = scopes::Variant::null());
3961 scopes::Result result;
3962+ QSharedPointer<click::web::Client> client;
3963 QSharedPointer<click::Index> index;
3964 click::web::Cancellable index_operation;
3965 QSharedPointer<click::Reviews> reviews;
3966 click::web::Cancellable reviews_operation;
3967+ click::web::Cancellable submit_operation;
3968 };
3969
3970-class DownloadErrorPreview : public Preview
3971+class DownloadErrorPreview : public PreviewStrategy
3972 {
3973 public:
3974 DownloadErrorPreview(const unity::scopes::Result& result);
3975@@ -105,7 +132,7 @@
3976 void run(unity::scopes::PreviewReplyProxy const& reply) override;
3977 };
3978
3979-class InstallingPreview : public Preview
3980+class InstallingPreview : public PreviewStrategy
3981 {
3982 public:
3983 InstallingPreview(std::string const& download_url,
3984@@ -124,20 +151,27 @@
3985
3986 };
3987
3988-class InstalledPreview : public Preview
3989+class InstalledPreview : public PreviewStrategy
3990 {
3991 public:
3992 InstalledPreview(const unity::scopes::Result& result,
3993+ const unity::scopes::ActionMetadata& metadata,
3994 const QSharedPointer<click::web::Client>& client);
3995
3996 virtual ~InstalledPreview();
3997
3998 void run(unity::scopes::PreviewReplyProxy const& reply) override;
3999+
4000 protected:
4001- virtual scopes::PreviewWidgetList installedActionButtonWidgets();
4002+ void getApplicationUri(std::function<void(const std::string&)> callback);
4003+
4004+private:
4005+ static scopes::PreviewWidgetList createButtons(const std::string& uri,
4006+ bool removable);
4007+ scopes::ActionMetadata metadata;
4008 };
4009
4010-class PurchasingPreview : public Preview
4011+class PurchasingPreview : public PreviewStrategy
4012 {
4013 public:
4014 PurchasingPreview(const unity::scopes::Result& result,
4015@@ -150,7 +184,7 @@
4016 virtual scopes::PreviewWidgetList purchasingWidgets(const PackageDetails &);
4017 };
4018
4019-class UninstallConfirmationPreview : public Preview
4020+class UninstallConfirmationPreview : public PreviewStrategy
4021 {
4022 public:
4023 UninstallConfirmationPreview(const unity::scopes::Result& result);
4024@@ -161,7 +195,7 @@
4025
4026 };
4027
4028-class UninstalledPreview : public Preview
4029+class UninstalledPreview : public PreviewStrategy
4030 {
4031 public:
4032 UninstalledPreview(const unity::scopes::Result& result,
4033
4034=== modified file 'scope/click/qtbridge.cpp'
4035--- scope/click/qtbridge.cpp 2014-02-07 11:14:48 +0000
4036+++ scope/click/qtbridge.cpp 2014-05-02 16:27:07 +0000
4037@@ -39,10 +39,6 @@
4038 {
4039 namespace world
4040 {
4041-Environment::Environment(QObject *parent) : QObject(parent)
4042-{
4043-}
4044-
4045 namespace detail
4046 {
4047 QEvent::Type qt_core_world_task_event_type()
4048@@ -51,28 +47,20 @@
4049 return event_type;
4050 }
4051
4052-class Environment : public qt::core::world::Environment
4053-{
4054-public:
4055- Environment(QObject* parent) : qt::core::world::Environment(parent)
4056- {
4057- }
4058-};
4059-
4060 class TaskEvent : public QEvent
4061 {
4062 public:
4063- TaskEvent(const std::function<void(qt::core::world::Environment&)>& task)
4064+ TaskEvent(const std::function<void()>& task)
4065 : QEvent(qt_core_world_task_event_type()),
4066 task(task)
4067 {
4068 }
4069
4070- void run(qt::core::world::Environment& env)
4071+ void run()
4072 {
4073 try
4074 {
4075- task(env);
4076+ task();
4077 promise.set_value();
4078 } catch(...)
4079 {
4080@@ -86,7 +74,7 @@
4081 }
4082
4083 private:
4084- std::function<void(qt::core::world::Environment&)> task;
4085+ std::function<void()> task;
4086 std::promise<void> promise;
4087 };
4088
4089@@ -125,12 +113,6 @@
4090 return instance;
4091 }
4092
4093-qt::core::world::Environment* environment()
4094-{
4095- static detail::Environment* env = new detail::Environment(coreApplicationInstance());
4096- return env;
4097-}
4098-
4099 bool TaskHandler::event(QEvent *e)
4100 {
4101 if (e->type() != qt_core_world_task_event_type())
4102@@ -139,7 +121,7 @@
4103 auto te = dynamic_cast<TaskEvent*>(e);
4104 if (te)
4105 {
4106- te->run(*environment());
4107+ te->run();
4108 return true;
4109 }
4110
4111@@ -160,9 +142,6 @@
4112 detail::task_handler()->moveToThread(
4113 detail::coreApplicationInstance()->thread());
4114
4115- detail::environment()->moveToThread(
4116- detail::coreApplicationInstance()->thread());
4117-
4118 // Signal to other worlds that we are good to go.
4119 ready();
4120
4121@@ -174,14 +153,14 @@
4122
4123 void destroy()
4124 {
4125- enter_with_task([](qt::core::world::Environment&)
4126+ enter_with_task([]()
4127 {
4128 // We make sure that all tasks have completed before quitting the app.
4129 QEventLoopLocker locker;
4130 }).wait_for(std::chrono::seconds{1});
4131 }
4132
4133-std::future<void> enter_with_task(const std::function<void(qt::core::world::Environment&)>& task)
4134+std::future<void> enter_with_task(const std::function<void()>& task)
4135 {
4136 QCoreApplication* instance = QCoreApplication::instance();
4137
4138
4139=== modified file 'scope/click/qtbridge.h'
4140--- scope/click/qtbridge.h 2014-04-17 13:03:18 +0000
4141+++ scope/click/qtbridge.h 2014-05-02 16:27:07 +0000
4142@@ -32,134 +32,6 @@
4143 {
4144 namespace world
4145 {
4146-// Forward declaration to allow for friend declaration in HeapAllocatedObject.
4147-class Environment;
4148-}
4149-}
4150-
4151-/**
4152- * @brief Models an object allocated on the heap in qt world, but pulled over
4153- * to this world to be passed on to tasks. Please note that compilation will
4154- * abort if QObject is not a base of T.
4155- *
4156- * One other important thing to note: The destrucotor will throw a std::runtime_error
4157- * if a HeapAllocatedObject has not been free'd in Qt world and does _not_ have a parent
4158- * assigned. In that case, the object would be leaked.
4159- *
4160- */
4161-template<typename T>
4162-class HeapAllocatedObject
4163-{
4164-public:
4165- static_assert(
4166- std::is_base_of<QObject, T>::value,
4167- "HeapAllocatedObject<T> is only required to transport QObject"
4168- " subclasses over the world boundary.");
4169-
4170- /** Constructs an empty, invalid instance. */
4171- HeapAllocatedObject() = default;
4172-
4173- /** HeapAllocatedObjects, i.e., their shared state, can be copied. */
4174- HeapAllocatedObject(const HeapAllocatedObject<T>& rhs) = default;
4175-
4176- /** HeapAllocatedObjects, i.e., their shared state can be assigned. */
4177- HeapAllocatedObject& operator=(const HeapAllocatedObject<T>& rhs) = default;
4178-
4179- /** HeapAllocatedObjects, i.e., their shared state can be compared for equality. */
4180- inline bool operator==(const HeapAllocatedObject<T>& rhs) const
4181- {
4182- return state == rhs.state || state->instance == rhs.state->instance;
4183- }
4184-
4185- /** Check if this object contains a valid instance. */
4186- inline operator bool() const
4187- {
4188- return state && (state->instance != nullptr);
4189- }
4190-
4191-private:
4192- friend class qt::core::world::Environment;
4193-
4194- struct Private
4195- {
4196- Private(T* instance) : instance(instance)
4197- {
4198- }
4199-
4200- ~Private()
4201- {
4202- if (instance != nullptr && instance->parent() == nullptr)
4203- {
4204- std::cerr << "MEMORY LEAK: HeapAllocatedObject::Private::~Private: "
4205- "Giving up ownership on a QObject instance without a parent: "
4206- << std::string(qPrintable(instance->metaObject()->className()))
4207- << std::endl;
4208- // We allow leaking a bit of memory here instead of crashing the scope
4209- }
4210- }
4211-
4212- T* instance{nullptr};
4213- };
4214-
4215- HeapAllocatedObject(T* instance) : state(std::make_shared<Private>(instance))
4216- {
4217- }
4218-
4219- std::shared_ptr<Private> state;
4220-};
4221-
4222-namespace core
4223-{
4224-namespace world
4225-{
4226-/**
4227- * @brief The Environment class models the environment in the Qt world
4228- * that tasks operate under.
4229- */
4230-class Environment : public QObject
4231-{
4232- Q_OBJECT
4233-
4234-public:
4235- /**
4236- * @brief Allocates subclasses of a QObject in the Qt world to make sure
4237- * thread assumptions are satisfied.
4238- *
4239- * @tparam Args Construction argument types to be passed to the class's c'tor.
4240- * @param args Construction arguments to be passed to the class's c'tor.
4241- */
4242- template<typename T, typename... Args>
4243- qt::HeapAllocatedObject<T> allocate(Args... args)
4244- {
4245- return qt::HeapAllocatedObject<T>{new T(args...)};
4246- }
4247-
4248- /**
4249- * @brief Frees a previously allocated object in the Qt world.
4250- * @param object The object to be freed.
4251- */
4252- template<typename T>
4253- void free(const qt::HeapAllocatedObject<T>& object)
4254- {
4255- delete object.state->instance;
4256- object.state->instance = nullptr;
4257- }
4258-
4259- /**
4260- * @brief Provides access to the instance contained in the object handle.
4261- * @param object The object containing the instance to be accessed.
4262- * @return A pointer to an instance of T, or nullptr.
4263- */
4264- template<typename T>
4265- T* resolve(const HeapAllocatedObject<T>& object)
4266- {
4267- return object.state->instance;
4268- }
4269-
4270-protected:
4271- Environment(QObject* parent);
4272-};
4273-
4274 /**
4275 * @brief Sets up the Qt core world and executes its event loop. Blocks until destroy() is called.
4276 * @param argc Number of arguments in argv.
4277@@ -179,7 +51,7 @@
4278 * @param task The task to be executed in the Qt core world.
4279 * @return A std::future that can be waited for to synchronize to the world's internal event loop.
4280 */
4281-std::future<void> enter_with_task(const std::function<void(Environment&)>& task);
4282+std::future<void> enter_with_task(const std::function<void()>& task);
4283
4284
4285 /**
4286@@ -188,16 +60,16 @@
4287 * @return A std::future that can be waited for to get hold of the result of the task.
4288 */
4289 template<typename T>
4290-inline std::future<T> enter_with_task_and_expect_result(const std::function<T(Environment&)>& task)
4291+inline std::future<T> enter_with_task_and_expect_result(const std::function<T()>& task)
4292 {
4293 std::shared_ptr<std::promise<T>> promise = std::make_shared<std::promise<T>>();
4294 std::future<T> future = promise->get_future();
4295
4296- auto t = [promise, task](Environment& env)
4297+ auto t = [promise, task]()
4298 {
4299 try
4300 {
4301- promise->set_value(task(env));
4302+ promise->set_value(task());
4303 } catch(...)
4304 {
4305 promise->set_exception(std::current_exception());
4306
4307=== modified file 'scope/click/query.cpp'
4308--- scope/click/query.cpp 2014-04-10 18:19:33 +0000
4309+++ scope/click/query.cpp 2014-05-02 16:27:07 +0000
4310@@ -27,6 +27,7 @@
4311 * files in the program, then also delete it here.
4312 */
4313
4314+#include "application.h"
4315 #include "query.h"
4316 #include "qtbridge.h"
4317 #include "key_file_locator.h"
4318@@ -39,14 +40,6 @@
4319 #include <unity/scopes/SearchReply.h>
4320 #include <unity/scopes/SearchMetadata.h>
4321
4322-#include<QJsonDocument>
4323-#include<QJsonArray>
4324-#include<QJsonObject>
4325-#include<QNetworkReply>
4326-#include<QNetworkRequest>
4327-#include<QProcess>
4328-#include<QStringList>
4329-#include<QUrl>
4330 #include<vector>
4331 #include<set>
4332 #include<sstream>
4333@@ -56,8 +49,6 @@
4334 namespace
4335 {
4336
4337-
4338-
4339 std::string CATEGORY_APPS_DISPLAY = R"(
4340 {
4341 "schema-version" : 1,
4342@@ -94,159 +85,11 @@
4343 }
4344 )";
4345
4346-QNetworkAccessManager* getNetworkAccessManager(qt::core::world::Environment& env)
4347-{
4348- static qt::HeapAllocatedObject<QNetworkAccessManager> nam = env.allocate<QNetworkAccessManager>(&env);
4349- return env.resolve(nam);
4350-}
4351-
4352-QString architectureFromDpkg()
4353-{
4354- QString program("dpkg");
4355- QStringList arguments;
4356- arguments << "--print-architecture";
4357- QProcess archDetector;
4358- archDetector.start(program, arguments);
4359- if(!archDetector.waitForFinished()) {
4360- throw std::runtime_error("Architecture detection failed.");
4361- }
4362- auto output = archDetector.readAllStandardOutput();
4363- auto ostr = QString::fromUtf8(output);
4364- ostr.remove('\n');
4365-
4366- return ostr;
4367-}
4368-
4369-const QString& architecture()
4370-{
4371- static const QString arch{architectureFromDpkg()};
4372- return arch;
4373-}
4374-
4375-class ReplyWrapper : public QObject
4376-{
4377- Q_OBJECT
4378-
4379-public:
4380- ReplyWrapper(QNetworkReply* reply,
4381- const scopes::SearchReplyProxy& replyProxy,
4382- const std::set<std::string>& installedApplications,
4383- const std::string& categoryTemplate,
4384- const QString& queryUri,
4385- QObject* parent)
4386- : QObject(parent),
4387- reply(reply),
4388- replyProxy(replyProxy),
4389- installedApplications(installedApplications),
4390- renderer(categoryTemplate),
4391- category(replyProxy->register_category("appstore", _("Available"), "", renderer)),
4392- queryUrl(queryUri) {
4393- }
4394-
4395- void cancel()
4396- {
4397- reply->abort();
4398- }
4399-
4400-public slots:
4401- void downloadFinished(QNetworkReply *reply) {
4402- // If the user types a search term, multiple queries are kicked off
4403- // and we have to make sure that we only consider results from the query
4404- // that this reply corresponds to.
4405- if (reply->url() != queryUrl)
4406- return;
4407-
4408- // category might be null if the query got cancelled before the ReplyWrapper got created
4409- // unlikely, but still possible.
4410- if (!category)
4411- return;
4412-
4413- struct Scope
4414- {
4415- Scope(QNetworkReply* reply, ReplyWrapper* wrapper)
4416- : reply(reply),
4417- wrapper(wrapper)
4418- {
4419- }
4420-
4421- ~Scope()
4422- {
4423- reply->deleteLater();
4424- wrapper->deleteLater();
4425- }
4426-
4427- QNetworkReply* reply;
4428- ReplyWrapper* wrapper;
4429- } scope(reply, this);
4430-
4431- if (reply->error() != QNetworkReply::NoError)
4432- {
4433- std::cerr << __PRETTY_FUNCTION__ << ": Received network reply with error: "
4434- << reply->errorString().toStdString() << std::endl;
4435- return;
4436- }
4437-
4438- try
4439- {
4440- QByteArray msg = reply->readAll();
4441- QJsonParseError jsonParseError;
4442- QJsonDocument doc = QJsonDocument::fromJson(msg, &jsonParseError);
4443-
4444- if (jsonParseError.error != QJsonParseError::NoError)
4445- throw std::runtime_error(
4446- "ReplyWrapper::onDownloadFinished: Cannot parse JSON from server response with " +
4447- jsonParseError.errorString().toStdString());
4448-
4449- QJsonArray results = doc.array();
4450-
4451- for(const auto &entry : results) {
4452- if(not entry.isObject()) {
4453- // FIXME: write message about invalid JSON here.
4454- continue;
4455- }
4456- scopes::CategorisedResult res(category);
4457- QJsonObject obj = entry.toObject();
4458- std::string resourceUrl = obj[click::Query::JsonKeys::RESOURCE_URL].toString().toUtf8().data();
4459- std::string title = obj[click::Query::JsonKeys::TITLE].toString().toUtf8().data();
4460- std::string iconUrl = obj[click::Query::JsonKeys::ICON_URL].toString().toUtf8().data();
4461- std::string name = obj[click::Query::JsonKeys::NAME].toString().toUtf8().data();
4462-
4463- if (installedApplications.count(name) > 0)
4464- continue;
4465-
4466- res.set_uri(queryUrl.toString().toUtf8().data());
4467- res.set_title(title);
4468- res.set_art(iconUrl);
4469- res.set_dnd_uri(queryUrl.toString().toUtf8().data());
4470- res[click::Query::ResultKeys::NAME] = name;
4471- res[click::Query::ResultKeys::INSTALLED] = false;
4472- res[click::Query::ResultKeys::DOWNLOAD_URL] = resourceUrl;
4473- // FIXME at this point we should go through the rest of the fields
4474- // and convert them.
4475- replyProxy->push(res);
4476- }
4477- } catch(const std::exception& e)
4478- {
4479- std::cerr << __PRETTY_FUNCTION__ << ": Caught std::exception with: " << e.what() << std::endl;
4480- } catch(...)
4481- {
4482- std::cerr << __PRETTY_FUNCTION__ << ": Caught exception" << std::endl;
4483- }
4484- }
4485-
4486-private:
4487- QNetworkReply* reply;
4488- scopes::SearchReplyProxy replyProxy;
4489- std::set<std::string> installedApplications;
4490- scopes::CategoryRenderer renderer;
4491- scopes::Category::SCPtr category;
4492- QUrl queryUrl;
4493-};
4494-}
4495-
4496-static void push_local_results(scopes::SearchReplyProxy const &replyProxy,
4497- std::vector<click::Application> const &apps,
4498- std::string categoryTemplate)
4499+}
4500+
4501+void click::Query::push_local_results(scopes::SearchReplyProxy const &replyProxy,
4502+ std::vector<click::Application> const &apps,
4503+ std::string &categoryTemplate)
4504 {
4505 scopes::CategoryRenderer rdr(categoryTemplate);
4506 auto cat = replyProxy->register_category("local", _("My apps"), "", rdr);
4507@@ -272,32 +115,32 @@
4508
4509 struct click::Query::Private
4510 {
4511- Private(const std::string& query, const scopes::SearchMetadata& metadata)
4512+ Private(const std::string& query, click::Index& index, const scopes::SearchMetadata& metadata)
4513 : query(query),
4514+ index(index),
4515 meta(metadata)
4516 {
4517 }
4518 std::string query;
4519+ click::Index& index;
4520 scopes::SearchMetadata meta;
4521- qt::HeapAllocatedObject<ReplyWrapper> replyWrapper;
4522+ click::web::Cancellable search_operation;
4523 };
4524
4525-click::Query::Query(std::string const& query, scopes::SearchMetadata const& metadata)
4526- : impl(new Private(query, metadata))
4527+click::Query::Query(std::string const& query, click::Index& index, scopes::SearchMetadata const& metadata)
4528+ : impl(new Private(query, index, metadata))
4529 {
4530 }
4531
4532 click::Query::~Query()
4533 {
4534+ qDebug() << "destroying search";
4535 }
4536
4537 void click::Query::cancelled()
4538 {
4539- qt::core::world::enter_with_task([=](qt::core::world::Environment& env)
4540- {
4541- if (impl->replyWrapper)
4542- env.resolve(impl->replyWrapper)->cancel();
4543- });
4544+ qDebug() << "cancelling search of" << QString::fromStdString(impl->query);
4545+ impl->search_operation.cancel();
4546 }
4547
4548 namespace
4549@@ -310,16 +153,81 @@
4550 return iface;
4551 }
4552
4553-QString frameworks_arg()
4554-{
4555- std::stringstream frameworks;
4556- for (auto f: click::FrameworkLocator().get_available_frameworks()) {
4557- frameworks << ",framework:" << f;
4558+}
4559+
4560+bool click::Query::push_result(scopes::SearchReplyProxy const& searchReply, const scopes::CategorisedResult &res)
4561+{
4562+ return searchReply->push(res);
4563+}
4564+
4565+void click::Query::finished(const scopes::SearchReplyProxy &searchReply)
4566+{
4567+ searchReply->finished();
4568+}
4569+
4570+scopes::Category::SCPtr click::Query::register_category(const scopes::SearchReplyProxy &searchReply,
4571+ const std::string &id,
4572+ const std::string &title,
4573+ const std::string &icon,
4574+ const scopes::CategoryRenderer &renderer_template)
4575+{
4576+ return searchReply->register_category(id, title, icon, renderer_template);
4577+}
4578+
4579+void click::Query::run_under_qt(const std::function<void ()> &task)
4580+{
4581+ qt::core::world::enter_with_task([task]() {
4582+ task();
4583+ });
4584+}
4585+
4586+void click::Query::add_available_apps(scopes::SearchReplyProxy const& searchReply,
4587+ const std::set<std::string>& locallyInstalledApps,
4588+ const std::string& categoryTemplate)
4589+{
4590+ scopes::CategoryRenderer categoryRenderer(categoryTemplate);
4591+ auto category = register_category(searchReply, "appstore", _("Available"), "", categoryRenderer);
4592+ if (!category) {
4593+ // category might be null when the underlying query got cancelled.
4594+ qDebug() << "category is null";
4595+ return;
4596 }
4597- return QString::fromStdString(frameworks.str());
4598-}
4599-
4600-}
4601+
4602+ run_under_qt([=]()
4603+ {
4604+ qDebug() << "starting search of" << QString::fromStdString(impl->query);
4605+
4606+ impl->search_operation = impl->index.search(impl->query, [=](PackageList packages){
4607+ qDebug("callback here");
4608+ foreach (auto p, packages) {
4609+ qDebug() << "pushing result" << QString::fromStdString(p.name);
4610+ try {
4611+ scopes::CategorisedResult res(category);
4612+ if (locallyInstalledApps.count(p.name) > 0) {
4613+ qDebug() << "already installed" << QString::fromStdString(p.name);
4614+ continue;
4615+ }
4616+ res.set_title(p.title);
4617+ res.set_art(p.icon_url);
4618+ res.set_uri(p.url);
4619+ res[click::Query::ResultKeys::NAME] = p.name;
4620+ res[click::Query::ResultKeys::INSTALLED] = false;
4621+
4622+ this->push_result(searchReply, res);
4623+ } catch(const std::exception& e){
4624+ qDebug() << "PackageDetails::loadJson: Exception thrown while decoding JSON: " << e.what() ;
4625+ } catch(...){
4626+ qDebug() << "no reason to catch";
4627+ }
4628+ }
4629+ qDebug() << "search completed";
4630+ this->finished(searchReply);
4631+ });
4632+
4633+ });
4634+
4635+}
4636+
4637 void click::Query::run(scopes::SearchReplyProxy const& searchReply)
4638 {
4639 QString query = QString::fromStdString(impl->query);
4640@@ -336,8 +244,9 @@
4641 categoryTemplate);
4642
4643 std::set<std::string> locallyInstalledApps;
4644- for(const auto& app : localResults)
4645+ for(const auto& app : localResults) {
4646 locallyInstalledApps.insert(app.name);
4647+ }
4648
4649 static const std::string no_net_hint("no-internet");
4650 if (impl->meta.contains_hint(no_net_hint))
4651@@ -347,27 +256,10 @@
4652 {
4653 return;
4654 }
4655+
4656 }
4657-
4658- qt::core::world::enter_with_task([=](qt::core::world::Environment& env)
4659- {
4660- static const QString queryPattern(
4661- "https://search.apps.ubuntu.com/api/v1/search?q=%1"
4662- "%2,architecture:%3");
4663-
4664- QString queryUri = queryPattern.arg(QString::fromUtf8(impl->query.c_str()))
4665- .arg(frameworks_arg()).arg(architecture());
4666-
4667- auto nam = getNetworkAccessManager(env);
4668- auto networkReply = nam->get(QNetworkRequest(QUrl(queryUri)));
4669-
4670- impl->replyWrapper = env.allocate<ReplyWrapper>(networkReply, searchReply, locallyInstalledApps, categoryTemplate, queryUri, &env);
4671- auto rw = env.resolve(impl->replyWrapper);
4672-
4673- QObject::connect(
4674- nam, &QNetworkAccessManager::finished,
4675- rw, &ReplyWrapper::downloadFinished);
4676- });
4677+
4678+ add_available_apps(searchReply, locallyInstalledApps, categoryTemplate);
4679 }
4680
4681 #include "query.moc"
4682
4683=== modified file 'scope/click/query.h'
4684--- scope/click/query.h 2014-04-07 16:41:36 +0000
4685+++ scope/click/query.h 2014-05-02 16:27:07 +0000
4686@@ -36,9 +36,14 @@
4687 namespace scopes = unity::scopes;
4688
4689 #include <QSharedPointer>
4690+#include <set>
4691
4692 namespace click
4693 {
4694+
4695+class Application;
4696+class Index;
4697+
4698 class Query : public scopes::SearchQueryBase
4699 {
4700 public:
4701@@ -64,13 +69,27 @@
4702 constexpr static const char* VERSION{"version"};
4703 };
4704
4705- Query(std::string const& query, scopes::SearchMetadata const& metadata);
4706- ~Query();
4707+ Query(std::string const& query, click::Index& index, scopes::SearchMetadata const& metadata);
4708+ virtual ~Query();
4709
4710 virtual void cancelled() override;
4711
4712 virtual void run(scopes::SearchReplyProxy const& reply) override;
4713
4714+protected:
4715+ virtual void add_available_apps(const scopes::SearchReplyProxy &searchReply, const std::set<std::string> &locallyInstalledApps, const std::string &category);
4716+ virtual bool push_result(const scopes::SearchReplyProxy &searchReply, scopes::CategorisedResult const& res);
4717+ virtual void finished(const scopes::SearchReplyProxy &searchReply);
4718+ virtual void push_local_results(scopes::SearchReplyProxy const &replyProxy,
4719+ std::vector<click::Application> const &apps,
4720+ std::string& categoryTemplate);
4721+ virtual scopes::Category::SCPtr register_category(scopes::SearchReplyProxy const& searchReply,
4722+ std::string const& id,
4723+ std::string const& title,
4724+ std::string const& icon,
4725+ scopes::CategoryRenderer const& renderer_template);
4726+ virtual void run_under_qt(const std::function<void()> &task);
4727+
4728 private:
4729 struct Private;
4730 QSharedPointer<Private> impl;
4731
4732=== modified file 'scope/click/reviews.cpp'
4733--- scope/click/reviews.cpp 2014-04-04 09:05:24 +0000
4734+++ scope/click/reviews.cpp 2014-05-02 16:27:07 +0000
4735@@ -27,12 +27,15 @@
4736 * files in the program, then also delete it here.
4737 */
4738
4739-#include <stdlib.h>
4740+#include <cstdlib>
4741
4742 #include <boost/property_tree/ptree.hpp>
4743 #include <boost/property_tree/json_parser.hpp>
4744 #include <boost/foreach.hpp>
4745
4746+#include <json/value.h>
4747+#include <json/writer.h>
4748+
4749 #include "reviews.h"
4750
4751 namespace click
4752@@ -123,11 +126,50 @@
4753 return click::web::Cancellable(response);
4754 }
4755
4756+click::web::Cancellable Reviews::submit_review (const Review& review,
4757+ std::function<void(Error)> callback)
4758+{
4759+ std::map<std::string, std::string> headers({
4760+ {click::web::CONTENT_TYPE_HEADER, click::web::CONTENT_TYPE_JSON},
4761+ });
4762+ Json::Value root(Json::ValueType::objectValue);
4763+ root["package_name"] = review.package_name;
4764+ root["version"] = review.package_version;
4765+ root["rating"] = review.rating;
4766+ root["review_text"] = review.review_text;
4767+
4768+ root["arch_tag"] = click::Configuration().get_architecture();
4769+ // NOTE: We only use the base language code for reviews.
4770+ root["language"] = click::Configuration().get_language_base();
4771+
4772+ // NOTE: "summary" is a required field, but we don't have one. Use "".
4773+ root["summary"] = "";
4774+
4775+ qDebug() << "Rating" << review.package_name.c_str() << review.rating;
4776+
4777+ QSharedPointer<click::web::Response> response = client->call
4778+ (get_base_url() + click::REVIEWS_API_PATH, "POST", true,
4779+ headers, Json::FastWriter().write(root), click::web::CallParams());
4780+
4781+ QObject::connect(response.data(), &click::web::Response::finished,
4782+ [=](QString) {
4783+ qDebug() << "Review submitted for:" << review.package_name.c_str();
4784+ callback(Error::NoError);
4785+ });
4786+ QObject::connect(response.data(), &click::web::Response::error,
4787+ [=](QString) {
4788+ qCritical() << "Network error submitting a reviews for:" << review.package_name.c_str();
4789+ callback(Error::NetworkError);
4790+ });
4791+
4792+ return click::web::Cancellable(response);
4793+}
4794+
4795 std::string Reviews::get_base_url ()
4796 {
4797 const char *env_url = getenv(REVIEWS_BASE_URL_ENVVAR.c_str());
4798 if (env_url != NULL) {
4799- return env_url;;
4800+ return env_url;
4801 }
4802 return click::REVIEWS_BASE_URL;
4803 }
4804
4805=== modified file 'scope/click/reviews.h'
4806--- scope/click/reviews.h 2014-03-27 15:03:56 +0000
4807+++ scope/click/reviews.h 2014-05-02 16:27:07 +0000
4808@@ -40,7 +40,7 @@
4809 namespace click
4810 {
4811
4812-const std::string REVIEWS_BASE_URL_ENVVAR = "CLICK_REVIEWS_BASE_URL";
4813+const std::string REVIEWS_BASE_URL_ENVVAR = "U1_REVIEWS_BASE_URL";
4814 const std::string REVIEWS_BASE_URL = "https://reviews.ubuntu.com";
4815 const std::string REVIEWS_API_PATH = "/click/api/1.0/reviews/";
4816 const std::string REVIEWS_QUERY_ARGNAME = "package_name";
4817@@ -78,6 +78,8 @@
4818
4819 click::web::Cancellable fetch_reviews (const std::string& package_name,
4820 std::function<void(ReviewList, Error)> callback);
4821+ click::web::Cancellable submit_review (const Review& review,
4822+ std::function<void(Error)> callback);
4823
4824 static std::string get_base_url ();
4825 };
4826
4827=== modified file 'scope/click/scope.cpp'
4828--- scope/click/scope.cpp 2014-04-10 18:19:33 +0000
4829+++ scope/click/scope.cpp 2014-05-02 16:27:07 +0000
4830@@ -34,9 +34,9 @@
4831 #include "network_access_manager.h"
4832 #include "key_file_locator.h"
4833 #include "interface.h"
4834+#include "scope_activation.h"
4835
4836 #include <QSharedPointer>
4837-#include <url-dispatcher.h>
4838
4839 #include "click-i18n.h"
4840
4841@@ -45,34 +45,16 @@
4842 click::Interface& clickInterfaceInstance()
4843 {
4844 static QSharedPointer<click::KeyFileLocator> keyFileLocator(new click::KeyFileLocator());
4845- static click::Interface iface(keyFileLocator);
4846-
4847+ static click::Interface iface(keyFileLocator);
4848 return iface;
4849 }
4850 }
4851
4852-class ScopeActivation : public unity::scopes::ActivationQueryBase
4853-{
4854- unity::scopes::ActivationResponse activate() override
4855- {
4856- auto response = unity::scopes::ActivationResponse(status_);
4857- response.set_scope_data(unity::scopes::Variant(hints_));
4858- return response;
4859- }
4860-
4861-public:
4862- void setStatus(unity::scopes::ActivationResponse::Status status) { status_ = status; }
4863- void setHint(std::string key, unity::scopes::Variant value) { hints_[key] = value; }
4864-private:
4865- unity::scopes::ActivationResponse::Status status_ = unity::scopes::ActivationResponse::Status::ShowPreview;
4866- unity::scopes::VariantMap hints_;
4867-};
4868-
4869 click::Scope::Scope()
4870 {
4871- nam = QSharedPointer<click::network::AccessManager>(new click::network::AccessManager());
4872- sso = QSharedPointer<click::CredentialsService>(new click::CredentialsService());
4873- client = QSharedPointer<click::web::Client>(new click::web::Client(nam, sso));
4874+ nam.reset(new click::network::AccessManager());
4875+ client.reset(new click::web::Client(nam));
4876+ index.reset(new click::Index(client));
4877 }
4878
4879 click::Scope::~Scope()
4880@@ -106,89 +88,29 @@
4881
4882 scopes::SearchQueryBase::UPtr click::Scope::search(unity::scopes::CannedQuery const& q, scopes::SearchMetadata const& metadata)
4883 {
4884- return scopes::SearchQueryBase::UPtr(new click::Query(q.query_string(), metadata));
4885+ return scopes::SearchQueryBase::UPtr(new click::Query(q.query_string(), *index, metadata));
4886 }
4887
4888
4889 unity::scopes::PreviewQueryBase::UPtr click::Scope::preview(const unity::scopes::Result& result,
4890 const unity::scopes::ActionMetadata& metadata) {
4891 qDebug() << "Scope::preview() called.";
4892- std::string action_id = "";
4893- std::string download_url = "";
4894-
4895- if (metadata.scope_data().which() != scopes::Variant::Type::Null) {
4896- auto metadict = metadata.scope_data().get_dict();
4897-
4898- if (metadict.count(click::Preview::Actions::DOWNLOAD_FAILED) != 0) {
4899- return scopes::PreviewQueryBase::UPtr{new DownloadErrorPreview(result)};
4900- } else if (metadict.count(click::Preview::Actions::DOWNLOAD_COMPLETED) != 0 ||
4901- metadict.count(click::Preview::Actions::CLOSE_PREVIEW) != 0) {
4902- qDebug() << "in Scope::preview(), metadata has download_completed="
4903- << metadict.count(click::Preview::Actions::DOWNLOAD_COMPLETED)
4904- << " and close_preview="
4905- << metadict.count(click::Preview::Actions::CLOSE_PREVIEW);
4906-
4907- return scopes::PreviewQueryBase::UPtr{new InstalledPreview(result, client)};
4908- } else if (metadict.count("action_id") != 0 &&
4909- metadict.count("download_url") != 0) {
4910- action_id = metadict["action_id"].get_string();
4911- download_url = metadict["download_url"].get_string();
4912- if (action_id == click::Preview::Actions::INSTALL_CLICK) {
4913- return scopes::PreviewQueryBase::UPtr{new InstallingPreview(download_url, result, client, nam)};
4914- } else {
4915- qWarning() << "unexpected action id " << QString::fromStdString(action_id)
4916- << " given with download_url" << QString::fromStdString(download_url);
4917- return scopes::PreviewQueryBase::UPtr{new UninstalledPreview(result, client)};
4918- }
4919- } else if (metadict.count(click::Preview::Actions::UNINSTALL_CLICK) != 0) {
4920- return scopes::PreviewQueryBase::UPtr{ new UninstallConfirmationPreview(result)};
4921- } else if (metadict.count(click::Preview::Actions::CONFIRM_UNINSTALL) != 0) {
4922- return scopes::PreviewQueryBase::UPtr{new UninstallingPreview(result, client)};
4923- } else {
4924- qWarning() << "preview() called with unexpected metadata. returning uninstalled preview";
4925- return scopes::PreviewQueryBase::UPtr{new UninstalledPreview(result, client)};
4926- }
4927- } else {
4928- // metadata.scope_data() is Null, so we return an appropriate "default" preview:
4929- if (result["installed"].get_bool() == true) {
4930- return scopes::PreviewQueryBase::UPtr{new InstalledPreview(result, client)};
4931- } else {
4932- return scopes::PreviewQueryBase::UPtr{new UninstalledPreview(result, client)};
4933- }
4934- }
4935+ return scopes::PreviewQueryBase::UPtr{new click::Preview(result, metadata, client, nam)};
4936 }
4937
4938-unity::scopes::ActivationQueryBase::UPtr click::Scope::perform_action(unity::scopes::Result const& result, unity::scopes::ActionMetadata const& metadata, std::string const& /* widget_id */, std::string const& action_id)
4939+unity::scopes::ActivationQueryBase::UPtr click::Scope::perform_action(unity::scopes::Result const& /* result */, unity::scopes::ActionMetadata const& metadata, std::string const& /* widget_id */, std::string const& action_id)
4940 {
4941 auto activation = new ScopeActivation();
4942 qDebug() << "perform_action called with action_id" << QString().fromStdString(action_id);
4943
4944- if (action_id == click::Preview::Actions::OPEN_CLICK) {
4945- QString app_url = QString::fromStdString(result.uri());
4946- if (!app_url.startsWith("application:///")) {
4947- qt::core::world::enter_with_task([this, result] (qt::core::world::Environment& /*env*/)
4948- {
4949- clickInterfaceInstance().get_dotdesktop_filename(result["name"].get_string(),
4950- [] (std::string val, click::ManifestError error){
4951- if (error == click::ManifestError::NoError) {
4952- std::string uri = "application:///" + val;
4953- url_dispatch_send(uri.c_str() , NULL, NULL);
4954- }
4955- }
4956- );
4957- });
4958- activation->setStatus(unity::scopes::ActivationResponse::Status::HideDash);
4959- } else {
4960- activation->setStatus(unity::scopes::ActivationResponse::Status::NotHandled);
4961- }
4962- } else if (action_id == click::Preview::Actions::INSTALL_CLICK) {
4963+ // note: OPEN_CLICK and OPEN_ACCOUNTS actions are handled directly by the Dash
4964+ if (action_id == click::Preview::Actions::INSTALL_CLICK) {
4965 std::string download_url = metadata.scope_data().get_dict()["download_url"].get_string();
4966 qDebug() << "the download url is: " << QString::fromStdString(download_url);
4967 activation->setHint("download_url", unity::scopes::Variant(download_url));
4968 activation->setHint("action_id", unity::scopes::Variant(action_id));
4969 qDebug() << "returning ShowPreview";
4970 activation->setStatus(unity::scopes::ActivationResponse::Status::ShowPreview);
4971-
4972 } else if (action_id == click::Preview::Actions::DOWNLOAD_FAILED) {
4973 activation->setHint(click::Preview::Actions::DOWNLOAD_FAILED, unity::scopes::Variant(true));
4974 activation->setStatus(unity::scopes::ActivationResponse::Status::ShowPreview);
4975@@ -204,9 +126,20 @@
4976 } else if (action_id == click::Preview::Actions::CONFIRM_UNINSTALL) {
4977 activation->setHint(click::Preview::Actions::CONFIRM_UNINSTALL, unity::scopes::Variant(true));
4978 activation->setStatus(unity::scopes::ActivationResponse::Status::ShowPreview);
4979- } else if (action_id == click::Preview::Actions::OPEN_ACCOUNTS) {
4980- std::string uri = "settings:///system/online-accounts";
4981- url_dispatch_send(uri.c_str() , NULL, NULL);
4982+ } else if (action_id == click::Preview::Actions::RATED) {
4983+ scopes::VariantMap rating_info = metadata.scope_data().get_dict();
4984+ // Cast to int because widget gives us double, which is wrong.
4985+ int rating = ((int)rating_info["rating"].get_double());
4986+ std::string review_text = rating_info["review"].get_string();
4987+
4988+ // We have to get the values and then set them as hints here, to be
4989+ // able to pass them on to the Preview, which actually makes the
4990+ // call to submit.
4991+ activation->setHint("rating", scopes::Variant(rating));
4992+ activation->setHint("review", scopes::Variant(review_text));
4993+ activation->setHint(click::Preview::Actions::RATED,
4994+ scopes::Variant(true));
4995+ activation->setStatus(scopes::ActivationResponse::Status::ShowPreview);
4996 }
4997 return scopes::ActivationQueryBase::UPtr(activation);
4998 }
4999
5000=== modified file 'scope/click/scope.h'
The diff has been truncated for viewing.

Subscribers

People subscribed via source and target branches

to all changes: