Merge lp:~larryprice/libertine-scope/preview-2 into lp:~larryprice/libertine-scope/libertine-store-search

Proposed by Larry Price
Status: Merged
Approved by: Larry Price
Approved revision: 105
Merged at revision: 101
Proposed branch: lp:~larryprice/libertine-scope/preview-2
Merge into: lp:~larryprice/libertine-scope/libertine-store-search
Diff against target: 1298 lines (+909/-82)
18 files modified
scope/store/i18n.h (+0/-1)
scope/store/package.cpp (+52/-0)
scope/store/package.h (+57/-0)
scope/store/preview.cpp (+220/-0)
scope/store/preview.h (+74/-0)
scope/store/query.cpp (+13/-37)
scope/store/query.h (+3/-1)
scope/store/scope.cpp (+5/-3)
scope/store/service_manager.cpp (+18/-6)
scope/store/service_manager.h (+7/-3)
service/libertine_service/apt.py (+37/-4)
service/libertine_service/dbus.py (+10/-5)
tests/scope/apps/test_preview.cpp (+0/-1)
tests/scope/store/CMakeLists.txt (+3/-0)
tests/scope/store/mock_service_manager.h (+46/-0)
tests/scope/store/test_package.cpp (+107/-0)
tests/scope/store/test_preview.cpp (+196/-0)
tests/scope/store/test_query.cpp (+61/-21)
To merge this branch: bzr merge lp:~larryprice/libertine-scope/preview-2
Reviewer Review Type Date Requested Status
Brandon Schaefer (community) Approve
Christopher Townsend (community) Approve
Libertine CI Bot (community) continuous-integration Approve
Review via email: mp+302839@code.launchpad.net

This proposal supersedes a proposal from 2016-07-26.

Commit message

Preview for the libertine store and initial AppStream integration into the service.

Description of the change

Preview for the libertine store and initial AppStream integration into the service.

To post a comment you must log in.
Revision history for this message
Libertine CI Bot (libertine-ci-bot) wrote : Posted in a previous version of this proposal

PASSED: Continuous integration, rev:90
https://jenkins.canonical.com/libertine/job/lp-libertine-scope-ci/55/
Executed test runs:
    SUCCESS: https://jenkins.canonical.com/libertine/job/build/210
    SUCCESS: https://jenkins.canonical.com/libertine/job/test-0-autopkgtest/label=amd64,release=vivid+overlay,testname=default/170
    SUCCESS: https://jenkins.canonical.com/libertine/job/test-0-autopkgtest/label=amd64,release=xenial+overlay,testname=default/170
    SUCCESS: https://jenkins.canonical.com/libertine/job/test-0-autopkgtest/label=amd64,release=yakkety,testname=default/170
    SUCCESS: https://jenkins.canonical.com/libertine/job/test-0-autopkgtest/label=i386,release=vivid+overlay,testname=default/170
    SUCCESS: https://jenkins.canonical.com/libertine/job/test-0-autopkgtest/label=i386,release=xenial+overlay,testname=default/170
    SUCCESS: https://jenkins.canonical.com/libertine/job/test-0-autopkgtest/label=i386,release=yakkety,testname=default/170
    None: https://jenkins.canonical.com/libertine/job/lp-generic-update-mp/160/console
    SUCCESS: https://jenkins.canonical.com/libertine/job/build-0-fetch/213
    SUCCESS: https://jenkins.canonical.com/libertine/job/build-1-sourcepkg/release=vivid+overlay/198
    SUCCESS: https://jenkins.canonical.com/libertine/job/build-1-sourcepkg/release=xenial+overlay/198
    SUCCESS: https://jenkins.canonical.com/libertine/job/build-1-sourcepkg/release=yakkety/198
    SUCCESS: https://jenkins.canonical.com/libertine/job/build-2-binpkg/arch=amd64,release=vivid+overlay/191
        deb: https://jenkins.canonical.com/libertine/job/build-2-binpkg/arch=amd64,release=vivid+overlay/191/artifact/output/*zip*/output.zip
    SUCCESS: https://jenkins.canonical.com/libertine/job/build-2-binpkg/arch=amd64,release=xenial+overlay/191
        deb: https://jenkins.canonical.com/libertine/job/build-2-binpkg/arch=amd64,release=xenial+overlay/191/artifact/output/*zip*/output.zip
    SUCCESS: https://jenkins.canonical.com/libertine/job/build-2-binpkg/arch=amd64,release=yakkety/191
        deb: https://jenkins.canonical.com/libertine/job/build-2-binpkg/arch=amd64,release=yakkety/191/artifact/output/*zip*/output.zip
    SUCCESS: https://jenkins.canonical.com/libertine/job/build-2-binpkg/arch=i386,release=vivid+overlay/191
        deb: https://jenkins.canonical.com/libertine/job/build-2-binpkg/arch=i386,release=vivid+overlay/191/artifact/output/*zip*/output.zip
    SUCCESS: https://jenkins.canonical.com/libertine/job/build-2-binpkg/arch=i386,release=xenial+overlay/191
        deb: https://jenkins.canonical.com/libertine/job/build-2-binpkg/arch=i386,release=xenial+overlay/191/artifact/output/*zip*/output.zip
    SUCCESS: https://jenkins.canonical.com/libertine/job/build-2-binpkg/arch=i386,release=yakkety/191
        deb: https://jenkins.canonical.com/libertine/job/build-2-binpkg/arch=i386,release=yakkety/191/artifact/output/*zip*/output.zip

Click here to trigger a rebuild:
https://jenkins.canonical.com/libertine/job/lp-libertine-scope-ci/55/rebuild

review: Approve (continuous-integration)
Revision history for this message
Libertine CI Bot (libertine-ci-bot) wrote : Posted in a previous version of this proposal

FAILED: Continuous integration, rev:91
https://jenkins.canonical.com/libertine/job/lp-libertine-scope-ci/59/
Executed test runs:
    FAILURE: https://jenkins.canonical.com/libertine/job/build/220/console
    None: https://jenkins.canonical.com/libertine/job/lp-generic-update-mp/166/console
    SUCCESS: https://jenkins.canonical.com/libertine/job/build-0-fetch/223
    SUCCESS: https://jenkins.canonical.com/libertine/job/build-1-sourcepkg/release=vivid+overlay/208
    SUCCESS: https://jenkins.canonical.com/libertine/job/build-1-sourcepkg/release=xenial+overlay/208
    SUCCESS: https://jenkins.canonical.com/libertine/job/build-1-sourcepkg/release=yakkety/208
    FAILURE: https://jenkins.canonical.com/libertine/job/build-2-binpkg/arch=amd64,release=vivid+overlay/201/console
    FAILURE: https://jenkins.canonical.com/libertine/job/build-2-binpkg/arch=amd64,release=xenial+overlay/201/console
    FAILURE: https://jenkins.canonical.com/libertine/job/build-2-binpkg/arch=amd64,release=yakkety/201/console
    FAILURE: https://jenkins.canonical.com/libertine/job/build-2-binpkg/arch=i386,release=vivid+overlay/201/console
    FAILURE: https://jenkins.canonical.com/libertine/job/build-2-binpkg/arch=i386,release=xenial+overlay/201/console
    FAILURE: https://jenkins.canonical.com/libertine/job/build-2-binpkg/arch=i386,release=yakkety/201/console

Click here to trigger a rebuild:
https://jenkins.canonical.com/libertine/job/lp-libertine-scope-ci/59/rebuild

review: Needs Fixing (continuous-integration)
Revision history for this message
Libertine CI Bot (libertine-ci-bot) wrote : Posted in a previous version of this proposal

PASSED: Continuous integration, rev:92
https://jenkins.canonical.com/libertine/job/lp-libertine-scope-ci/61/
Executed test runs:
    SUCCESS: https://jenkins.canonical.com/libertine/job/build/222
    SUCCESS: https://jenkins.canonical.com/libertine/job/test-0-autopkgtest/label=amd64,release=vivid+overlay,testname=default/180
    SUCCESS: https://jenkins.canonical.com/libertine/job/test-0-autopkgtest/label=amd64,release=xenial+overlay,testname=default/180
    SUCCESS: https://jenkins.canonical.com/libertine/job/test-0-autopkgtest/label=amd64,release=yakkety,testname=default/180
    SUCCESS: https://jenkins.canonical.com/libertine/job/test-0-autopkgtest/label=i386,release=vivid+overlay,testname=default/180
    SUCCESS: https://jenkins.canonical.com/libertine/job/test-0-autopkgtest/label=i386,release=xenial+overlay,testname=default/180
    SUCCESS: https://jenkins.canonical.com/libertine/job/test-0-autopkgtest/label=i386,release=yakkety,testname=default/180
    None: https://jenkins.canonical.com/libertine/job/lp-generic-update-mp/168/console
    SUCCESS: https://jenkins.canonical.com/libertine/job/build-0-fetch/225
    SUCCESS: https://jenkins.canonical.com/libertine/job/build-1-sourcepkg/release=vivid+overlay/210
    SUCCESS: https://jenkins.canonical.com/libertine/job/build-1-sourcepkg/release=xenial+overlay/210
    SUCCESS: https://jenkins.canonical.com/libertine/job/build-1-sourcepkg/release=yakkety/210
    SUCCESS: https://jenkins.canonical.com/libertine/job/build-2-binpkg/arch=amd64,release=vivid+overlay/203
        deb: https://jenkins.canonical.com/libertine/job/build-2-binpkg/arch=amd64,release=vivid+overlay/203/artifact/output/*zip*/output.zip
    SUCCESS: https://jenkins.canonical.com/libertine/job/build-2-binpkg/arch=amd64,release=xenial+overlay/203
        deb: https://jenkins.canonical.com/libertine/job/build-2-binpkg/arch=amd64,release=xenial+overlay/203/artifact/output/*zip*/output.zip
    SUCCESS: https://jenkins.canonical.com/libertine/job/build-2-binpkg/arch=amd64,release=yakkety/203
        deb: https://jenkins.canonical.com/libertine/job/build-2-binpkg/arch=amd64,release=yakkety/203/artifact/output/*zip*/output.zip
    SUCCESS: https://jenkins.canonical.com/libertine/job/build-2-binpkg/arch=i386,release=vivid+overlay/203
        deb: https://jenkins.canonical.com/libertine/job/build-2-binpkg/arch=i386,release=vivid+overlay/203/artifact/output/*zip*/output.zip
    SUCCESS: https://jenkins.canonical.com/libertine/job/build-2-binpkg/arch=i386,release=xenial+overlay/203
        deb: https://jenkins.canonical.com/libertine/job/build-2-binpkg/arch=i386,release=xenial+overlay/203/artifact/output/*zip*/output.zip
    SUCCESS: https://jenkins.canonical.com/libertine/job/build-2-binpkg/arch=i386,release=yakkety/203
        deb: https://jenkins.canonical.com/libertine/job/build-2-binpkg/arch=i386,release=yakkety/203/artifact/output/*zip*/output.zip

Click here to trigger a rebuild:
https://jenkins.canonical.com/libertine/job/lp-libertine-scope-ci/61/rebuild

review: Approve (continuous-integration)
Revision history for this message
Libertine CI Bot (libertine-ci-bot) wrote : Posted in a previous version of this proposal

FAILED: Continuous integration, rev:94
https://jenkins.canonical.com/libertine/job/lp-libertine-scope-ci/71/
Executed test runs:
    FAILURE: https://jenkins.canonical.com/libertine/job/build/280/console
    None: https://jenkins.canonical.com/libertine/job/lp-generic-update-mp/213/console
    SUCCESS: https://jenkins.canonical.com/libertine/job/build-0-fetch/282
    SUCCESS: https://jenkins.canonical.com/libertine/job/build-1-sourcepkg/release=vivid+overlay/266
    SUCCESS: https://jenkins.canonical.com/libertine/job/build-1-sourcepkg/release=xenial+overlay/266
    SUCCESS: https://jenkins.canonical.com/libertine/job/build-1-sourcepkg/release=yakkety/266
    FAILURE: https://jenkins.canonical.com/libertine/job/build-2-binpkg/arch=amd64,release=vivid+overlay/259/console
    FAILURE: https://jenkins.canonical.com/libertine/job/build-2-binpkg/arch=amd64,release=xenial+overlay/259/console
    FAILURE: https://jenkins.canonical.com/libertine/job/build-2-binpkg/arch=amd64,release=yakkety/259/console
    FAILURE: https://jenkins.canonical.com/libertine/job/build-2-binpkg/arch=i386,release=vivid+overlay/259/console
    FAILURE: https://jenkins.canonical.com/libertine/job/build-2-binpkg/arch=i386,release=xenial+overlay/259/console
    FAILURE: https://jenkins.canonical.com/libertine/job/build-2-binpkg/arch=i386,release=yakkety/259/console

Click here to trigger a rebuild:
https://jenkins.canonical.com/libertine/job/lp-libertine-scope-ci/71/rebuild

review: Needs Fixing (continuous-integration)
95. By Larry Price

Removing appstream code so i can do it in a separate branch

96. By Larry Price

Fix compile issue

97. By Larry Price

merge

98. By Larry Price

purging ratings - not feasible for this draft

99. By Larry Price

merge

Revision history for this message
Libertine CI Bot (libertine-ci-bot) wrote : Posted in a previous version of this proposal

FAILED: Continuous integration, rev:94
https://jenkins.canonical.com/libertine/job/lp-libertine-scope-ci/77/
Executed test runs:
    FAILURE: https://jenkins.canonical.com/libertine/job/build/311/console
    None: https://jenkins.canonical.com/libertine/job/lp-generic-update-mp/232/console
    SUCCESS: https://jenkins.canonical.com/libertine/job/build-0-fetch/313
    SUCCESS: https://jenkins.canonical.com/libertine/job/build-1-sourcepkg/release=vivid+overlay/297
    SUCCESS: https://jenkins.canonical.com/libertine/job/build-1-sourcepkg/release=xenial+overlay/297
    SUCCESS: https://jenkins.canonical.com/libertine/job/build-1-sourcepkg/release=yakkety/297
    FAILURE: https://jenkins.canonical.com/libertine/job/build-2-binpkg/arch=amd64,release=vivid+overlay/291/console
    FAILURE: https://jenkins.canonical.com/libertine/job/build-2-binpkg/arch=amd64,release=xenial+overlay/291/console
    FAILURE: https://jenkins.canonical.com/libertine/job/build-2-binpkg/arch=amd64,release=yakkety/291/console
    FAILURE: https://jenkins.canonical.com/libertine/job/build-2-binpkg/arch=i386,release=vivid+overlay/291/console
    FAILURE: https://jenkins.canonical.com/libertine/job/build-2-binpkg/arch=i386,release=xenial+overlay/291/console
    FAILURE: https://jenkins.canonical.com/libertine/job/build-2-binpkg/arch=i386,release=yakkety/291/console

Click here to trigger a rebuild:
https://jenkins.canonical.com/libertine/job/lp-libertine-scope-ci/77/rebuild

review: Needs Fixing (continuous-integration)
Revision history for this message
Libertine CI Bot (libertine-ci-bot) wrote :

FAILED: Continuous integration, rev:94
https://jenkins.canonical.com/libertine/job/lp-libertine-scope-ci/78/
Executed test runs:
    FAILURE: https://jenkins.canonical.com/libertine/job/build/312/console
    None: https://jenkins.canonical.com/libertine/job/lp-generic-update-mp/233/console
    SUCCESS: https://jenkins.canonical.com/libertine/job/build-0-fetch/314
    SUCCESS: https://jenkins.canonical.com/libertine/job/build-1-sourcepkg/release=vivid+overlay/298
    SUCCESS: https://jenkins.canonical.com/libertine/job/build-1-sourcepkg/release=xenial+overlay/298
    SUCCESS: https://jenkins.canonical.com/libertine/job/build-1-sourcepkg/release=yakkety/298
    FAILURE: https://jenkins.canonical.com/libertine/job/build-2-binpkg/arch=amd64,release=vivid+overlay/292/console
    FAILURE: https://jenkins.canonical.com/libertine/job/build-2-binpkg/arch=amd64,release=xenial+overlay/292/console
    FAILURE: https://jenkins.canonical.com/libertine/job/build-2-binpkg/arch=amd64,release=yakkety/292/console
    FAILURE: https://jenkins.canonical.com/libertine/job/build-2-binpkg/arch=i386,release=vivid+overlay/292/console
    FAILURE: https://jenkins.canonical.com/libertine/job/build-2-binpkg/arch=i386,release=xenial+overlay/292/console
    FAILURE: https://jenkins.canonical.com/libertine/job/build-2-binpkg/arch=i386,release=yakkety/292/console

Click here to trigger a rebuild:
https://jenkins.canonical.com/libertine/job/lp-libertine-scope-ci/78/rebuild

review: Needs Fixing (continuous-integration)
100. By Larry Price

Merge

Revision history for this message
Libertine CI Bot (libertine-ci-bot) wrote :

FAILED: Continuous integration, rev:94
https://jenkins.canonical.com/libertine/job/lp-libertine-scope-ci/79/
Executed test runs:
    FAILURE: https://jenkins.canonical.com/libertine/job/build/313/console
    None: https://jenkins.canonical.com/libertine/job/lp-generic-update-mp/234/console
    SUCCESS: https://jenkins.canonical.com/libertine/job/build-0-fetch/315
    SUCCESS: https://jenkins.canonical.com/libertine/job/build-1-sourcepkg/release=vivid+overlay/299
    SUCCESS: https://jenkins.canonical.com/libertine/job/build-1-sourcepkg/release=xenial+overlay/299
    SUCCESS: https://jenkins.canonical.com/libertine/job/build-1-sourcepkg/release=yakkety/299
    FAILURE: https://jenkins.canonical.com/libertine/job/build-2-binpkg/arch=amd64,release=vivid+overlay/293/console
    FAILURE: https://jenkins.canonical.com/libertine/job/build-2-binpkg/arch=amd64,release=xenial+overlay/293/console
    FAILURE: https://jenkins.canonical.com/libertine/job/build-2-binpkg/arch=amd64,release=yakkety/293/console
    FAILURE: https://jenkins.canonical.com/libertine/job/build-2-binpkg/arch=i386,release=vivid+overlay/293/console
    FAILURE: https://jenkins.canonical.com/libertine/job/build-2-binpkg/arch=i386,release=xenial+overlay/293/console
    FAILURE: https://jenkins.canonical.com/libertine/job/build-2-binpkg/arch=i386,release=yakkety/293/console

Click here to trigger a rebuild:
https://jenkins.canonical.com/libertine/job/lp-libertine-scope-ci/79/rebuild

review: Needs Fixing (continuous-integration)
Revision history for this message
Libertine CI Bot (libertine-ci-bot) wrote :

PASSED: Continuous integration, rev:100
https://jenkins.canonical.com/libertine/job/lp-libertine-scope-ci/80/
Executed test runs:
    SUCCESS: https://jenkins.canonical.com/libertine/job/build/314
    SUCCESS: https://jenkins.canonical.com/libertine/job/test-0-autopkgtest/label=amd64,release=vivid+overlay,testname=default/258
    SUCCESS: https://jenkins.canonical.com/libertine/job/test-0-autopkgtest/label=amd64,release=xenial+overlay,testname=default/258
    SUCCESS: https://jenkins.canonical.com/libertine/job/test-0-autopkgtest/label=amd64,release=yakkety,testname=default/258
    SUCCESS: https://jenkins.canonical.com/libertine/job/test-0-autopkgtest/label=i386,release=vivid+overlay,testname=default/258
    SUCCESS: https://jenkins.canonical.com/libertine/job/test-0-autopkgtest/label=i386,release=xenial+overlay,testname=default/258
    SUCCESS: https://jenkins.canonical.com/libertine/job/test-0-autopkgtest/label=i386,release=yakkety,testname=default/258
    None: https://jenkins.canonical.com/libertine/job/lp-generic-update-mp/235/console
    SUCCESS: https://jenkins.canonical.com/libertine/job/build-0-fetch/316
    SUCCESS: https://jenkins.canonical.com/libertine/job/build-1-sourcepkg/release=vivid+overlay/300
    SUCCESS: https://jenkins.canonical.com/libertine/job/build-1-sourcepkg/release=xenial+overlay/300
    SUCCESS: https://jenkins.canonical.com/libertine/job/build-1-sourcepkg/release=yakkety/300
    SUCCESS: https://jenkins.canonical.com/libertine/job/build-2-binpkg/arch=amd64,release=vivid+overlay/294
        deb: https://jenkins.canonical.com/libertine/job/build-2-binpkg/arch=amd64,release=vivid+overlay/294/artifact/output/*zip*/output.zip
    SUCCESS: https://jenkins.canonical.com/libertine/job/build-2-binpkg/arch=amd64,release=xenial+overlay/294
        deb: https://jenkins.canonical.com/libertine/job/build-2-binpkg/arch=amd64,release=xenial+overlay/294/artifact/output/*zip*/output.zip
    SUCCESS: https://jenkins.canonical.com/libertine/job/build-2-binpkg/arch=amd64,release=yakkety/294
        deb: https://jenkins.canonical.com/libertine/job/build-2-binpkg/arch=amd64,release=yakkety/294/artifact/output/*zip*/output.zip
    SUCCESS: https://jenkins.canonical.com/libertine/job/build-2-binpkg/arch=i386,release=vivid+overlay/294
        deb: https://jenkins.canonical.com/libertine/job/build-2-binpkg/arch=i386,release=vivid+overlay/294/artifact/output/*zip*/output.zip
    SUCCESS: https://jenkins.canonical.com/libertine/job/build-2-binpkg/arch=i386,release=xenial+overlay/294
        deb: https://jenkins.canonical.com/libertine/job/build-2-binpkg/arch=i386,release=xenial+overlay/294/artifact/output/*zip*/output.zip
    SUCCESS: https://jenkins.canonical.com/libertine/job/build-2-binpkg/arch=i386,release=yakkety/294
        deb: https://jenkins.canonical.com/libertine/job/build-2-binpkg/arch=i386,release=yakkety/294/artifact/output/*zip*/output.zip

Click here to trigger a rebuild:
https://jenkins.canonical.com/libertine/job/lp-libertine-scope-ci/80/rebuild

review: Approve (continuous-integration)
101. By Larry Price

Proper directory name

102. By Larry Price

merge

103. By Larry Price

forget about fun, work, and pink

104. By Larry Price

merge

105. By Larry Price

Merge with parent

Revision history for this message
Christopher Townsend (townsend) wrote :

Ok, this is good with me. I'm going to get an extra set of eyes on the code though.

review: Approve
Revision history for this message
Brandon Schaefer (brandontschaefer) wrote :

lgtm

review: Approve
Revision history for this message
Christopher Townsend (townsend) wrote :

Ok, I think we can merge this into the base MP.

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
=== modified file 'scope/store/i18n.h'
--- scope/store/i18n.h 2016-09-01 17:12:55 +0000
+++ scope/store/i18n.h 2016-09-15 17:01:59 +0000
@@ -60,4 +60,3 @@
60}60}
6161
62#endif /* LIBERTINE_STORE_I18N_H_ */62#endif /* LIBERTINE_STORE_I18N_H_ */
63
6463
=== added file 'scope/store/package.cpp'
--- scope/store/package.cpp 1970-01-01 00:00:00 +0000
+++ scope/store/package.cpp 2016-09-15 17:01:59 +0000
@@ -0,0 +1,52 @@
1/*
2 * Copyright 2016 Canonical Ltd.
3 *
4 * This program is free software: you can redistribute it and/or modify it under
5 * the terms of the GNU General Public License, version 3, as published by the
6 * Free Software Foundation.
7 *
8 * This program is distributed in the hope that it will be useful,
9 * but WITHOUT ANY WARRANTY; without even the implied warranty of
10 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 * GNU General Public License for more details.
12 *
13 * You should have received a copy of the GNU General Public License
14 * along with this program. If not, see <http://www.gnu.org/licenses/>.
15 */
16#include "scope/store/package.h"
17
18
19Libertine::Store::Package Libertine::Store::Package::
20from_map(QVariantMap const& pkgMap)
21{
22 Package pkg;
23 pkg.name = pkgMap["name"].toString().toStdString();
24 pkg.summary = pkgMap["summary"].toString().toStdString();
25 pkg.description = pkgMap["description"].toString().toStdString();
26 pkg.icon = pkgMap["icon"].toString().toStdString();
27 pkg.publisher = pkgMap["publisher"].toString().toStdString();
28 pkg.website = pkgMap["website"].toString().toStdString();
29 pkg.license = pkgMap["license"].toString().toStdString();
30 pkg.id = pkgMap["id"].toString().toStdString();
31
32 for (auto const& screenshot: pkgMap["screenshots"].toStringList())
33 {
34 pkg.screenshots.push_back(screenshot.toStdString());
35 }
36
37 return pkg;
38}
39
40
41QList<Libertine::Store::Package> Libertine::Store::Package::
42from_map(QList<QVariantMap> const& pkgMap)
43{
44 QList<Package> pkgs;
45
46 for (auto const& pkg: pkgMap)
47 {
48 pkgs << Package::from_map(pkg);
49 }
50
51 return pkgs;
52}
053
=== added file 'scope/store/package.h'
--- scope/store/package.h 1970-01-01 00:00:00 +0000
+++ scope/store/package.h 2016-09-15 17:01:59 +0000
@@ -0,0 +1,57 @@
1/*
2 * Copyright 2016 Canonical Ltd.
3 *
4 * This program is free software: you can redistribute it and/or modify it under
5 * the terms of the GNU General Public License, version 3, as published by the
6 * Free Software Foundation.
7 *
8 * This program is distributed in the hope that it will be useful,
9 * but WITHOUT ANY WARRANTY; without even the implied warranty of
10 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 * GNU General Public License for more details.
12 *
13 * You should have received a copy of the GNU General Public License
14 * along with this program. If not, see <http://www.gnu.org/licenses/>.
15 */
16#ifndef LIBERTINE_STORE_PACKAGE_H_
17#define LIBERTINE_STORE_PACKAGE_H_
18
19
20#include <QList>
21#include <QVariant>
22
23
24namespace Libertine
25{
26namespace Store
27{
28
29
30class Package
31{
32public:
33 explicit Package() = default;
34 virtual ~Package() = default;
35
36 static Package from_map(QVariantMap const&);
37 static QList<Package> from_map(QList<QVariantMap> const&);
38
39
40 std::string id;
41 std::string name;
42 std::string summary;
43
44 std::string description;
45 std::string icon;
46 std::string publisher;
47 std::string website;
48 std::string license;
49
50 std::vector<std::string> screenshots;
51};
52
53
54} // Store
55} // Libertine
56
57#endif // LIBERTINE_STORE_PACKAGE_H_
058
=== added file 'scope/store/preview.cpp'
--- scope/store/preview.cpp 1970-01-01 00:00:00 +0000
+++ scope/store/preview.cpp 2016-09-15 17:01:59 +0000
@@ -0,0 +1,220 @@
1/*
2 * Copyright 2016 Canonical Ltd.
3 *
4 * This program is free software: you can redistribute it and/or modify it under
5 * the terms of the GNU General Public License, version 3, as published by the
6 * Free Software Foundation.
7 *
8 * This program is distributed in the hope that it will be useful,
9 * but WITHOUT ANY WARRANTY; without even the implied warranty of
10 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 * GNU General Public License for more details.
12 *
13 * You should have received a copy of the GNU General Public License
14 * along with this program. If not, see <http://www.gnu.org/licenses/>.
15 */
16#include "scope/store/preview.h"
17
18
19#include "scope/store/i18n.h"
20#include "scope/store/service_manager.h"
21#include <unity/UnityExceptions.h>
22#include <unity/scopes/ColumnLayout.h>
23#include <unity/scopes/PreviewReply.h>
24#include <unity/scopes/Variant.h>
25#include <unity/scopes/VariantBuilder.h>
26#include <unity/scopes/ActionMetadata.h>
27#include <unity/scopes/Result.h>
28#include <QDebug>
29
30
31namespace usc = unity::scopes;
32
33
34namespace
35{
36static auto constexpr HEADER_ID = "hdr";
37static auto constexpr ACTIONS_ID = "buttons";
38static auto constexpr METADATA_ID = "other_metadata";
39static auto constexpr SUMMARY_ID = "summary";
40static auto constexpr SCREENSHOTS_ID = "screenshots";
41static auto const SUMMARY_TITLE = _("Info");
42static auto const ACTION_INSTALL = _("Install");
43static auto const METADATA_PUBLISHER = _("Publisher/Creator");
44static auto const METADATA_WEBSITE = _("Website");
45static auto const METADATA_LICENSE = _("License");
46
47
48static usc::PreviewWidgetList
49headerWidgets(Libertine::Store::Package const& app)
50{
51 usc::PreviewWidget header(HEADER_ID, "header");
52 header.add_attribute_value("title", usc::Variant(app.name));
53 header.add_attribute_value("subtitle", usc::Variant(app.summary));
54 header.add_attribute_value("mascot", usc::Variant(app.icon));
55 header.add_attribute_value("fallback", usc::Variant("image://theme/placeholder-app-icon"));
56
57 usc::PreviewWidgetList widgets;
58 widgets.push_back(header);
59
60 qDebug() << "Pushed widgets for package:" << QString::fromStdString(app.name);
61 return widgets;
62}
63
64
65static usc::PreviewWidget
66metadataWidgets(Libertine::Store::Package const& app)
67{
68 usc::PreviewWidget widget(METADATA_ID, "table");
69 usc::VariantArray values;
70 if (!app.publisher.empty())
71 {
72 values.push_back(usc::Variant{usc::VariantArray{usc::Variant{METADATA_PUBLISHER}, usc::Variant{app.publisher}}});
73 }
74 if (!app.website.empty())
75 {
76 values.push_back(usc::Variant{usc::VariantArray{usc::Variant{METADATA_WEBSITE}, usc::Variant{app.website}}});
77 }
78 if (!app.license.empty())
79 {
80 values.push_back(usc::Variant{usc::VariantArray{usc::Variant{METADATA_LICENSE}, usc::Variant{app.license}}});
81 }
82
83 widget.add_attribute_value("values", usc::Variant(values));
84 return widget;
85}
86
87
88static usc::PreviewWidget
89buttonWidgets(Libertine::Store::Package const&)
90{
91 usc::PreviewWidget buttons(ACTIONS_ID, "actions");
92 usc::VariantBuilder builder;
93 builder.add_tuple(
94 {
95 {"id", usc::Variant("install_xapp")},
96 {"label", usc::Variant(ACTION_INSTALL)},
97 });
98 buttons.add_attribute_value("actions", builder.end());
99 return buttons;
100}
101
102
103static usc::PreviewWidget
104descriptionWidgets(Libertine::Store::Package const& app)
105{
106 usc::PreviewWidget summary(SUMMARY_ID, "text");
107 summary.add_attribute_value("title", usc::Variant(SUMMARY_TITLE));
108 summary.add_attribute_value("text", usc::Variant(app.description));
109 return summary;
110}
111
112
113static usc::PreviewWidget
114screenshotWidgets(Libertine::Store::Package const& app)
115{
116 usc::PreviewWidget gallery(SCREENSHOTS_ID, "gallery");
117 usc::VariantArray arr;
118 for (auto const& screenshot: app.screenshots)
119 {
120 arr.push_back(usc::Variant(screenshot));
121 }
122 gallery.add_attribute_value("sources", usc::Variant(arr));
123 return gallery;
124}
125
126
127static usc::PreviewWidgetList
128createWidgets(Libertine::Store::Package const& app)
129{
130 auto widgets = headerWidgets(app);
131 widgets.push_back(buttonWidgets(app));
132 widgets.push_back(metadataWidgets(app));
133 if (!app.screenshots.empty())
134 {
135 widgets.push_back(screenshotWidgets(app));
136 }
137 widgets.push_back(descriptionWidgets(app));
138
139 return widgets;
140}
141}
142
143
144Libertine::Store::Preview::
145Preview(usc::Result const& result,
146 usc::ActionMetadata const& metadata,
147 std::shared_ptr<ServiceManager> const& service)
148 : PreviewQueryBase(result, metadata)
149 , service_(service)
150{
151}
152
153
154void Libertine::Store::Preview::
155cancelled()
156{
157}
158
159
160void Libertine::Store::Preview::
161createSingleColumnLayout(Package const& app)
162{
163 oneColumn.column.push_back(HEADER_ID);
164 oneColumn.column.push_back(ACTIONS_ID);
165 oneColumn.column.push_back(METADATA_ID);
166 if (!app.screenshots.empty())
167 {
168 oneColumn.column.push_back(SCREENSHOTS_ID);
169 }
170 oneColumn.column.push_back(SUMMARY_ID);
171}
172
173
174void Libertine::Store::Preview::
175createDualColumnLayout(Package const& app)
176{
177 twoColumns.column1.push_back(HEADER_ID);
178 twoColumns.column1.push_back(ACTIONS_ID);
179 twoColumns.column1.push_back(SUMMARY_ID);
180 twoColumns.column2.push_back(METADATA_ID);
181 if (!app.screenshots.empty())
182 {
183 twoColumns.column2.push_back(SCREENSHOTS_ID);
184 }
185}
186
187
188void Libertine::Store::Preview::
189run(usc::PreviewReplyProxy const& reply)
190{
191 auto app = service_->app_info(QString::fromStdString(result()["id"].get_string()));
192 auto widgets = createWidgets(app);
193
194 createSingleColumnLayout(app);
195 createDualColumnLayout(app);
196
197 registerLayouts(reply);
198 reply->push(widgets);
199}
200
201
202void Libertine::Store::Preview::
203registerLayouts(unity::scopes::PreviewReplyProxy const& reply)
204{
205 usc::ColumnLayout layout1col(1);
206 layout1col.add_column(oneColumn.column);
207
208 usc::ColumnLayout layout2col(2);
209 layout2col.add_column(twoColumns.column1);
210 layout2col.add_column(twoColumns.column2);
211
212 try
213 {
214 reply->register_layout({layout1col, layout2col});
215 }
216 catch (unity::LogicException const& e)
217 {
218 qWarning() << "Failed to register layout:" << QString::fromStdString(e.what());
219 }
220}
0221
=== added file 'scope/store/preview.h'
--- scope/store/preview.h 1970-01-01 00:00:00 +0000
+++ scope/store/preview.h 2016-09-15 17:01:59 +0000
@@ -0,0 +1,74 @@
1/*
2 * Copyright 2016 Canonical Ltd.
3 *
4 * This program is free software: you can redistribute it and/or modify it under
5 * the terms of the GNU General Public License, version 3, as published by the
6 * Free Software Foundation.
7 *
8 * This program is distributed in the hope that it will be useful,
9 * but WITHOUT ANY WARRANTY; without even the implied warranty of
10 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 * GNU General Public License for more details.
12 *
13 * You should have received a copy of the GNU General Public License
14 * along with this program. If not, see <http://www.gnu.org/licenses/>.
15 */
16#ifndef LIBERTINE_STORE_PREVIEW_H
17#define LIBERTINE_STORE_PREVIEW_H
18
19#include <unity/scopes/PreviewQueryBase.h>
20
21
22namespace Libertine
23{
24namespace Store
25{
26
27
28class ServiceManager;
29class Package;
30
31
32class Preview
33: public unity::scopes::PreviewQueryBase
34{
35public:
36 explicit Preview(unity::scopes::Result const& result,
37 unity::scopes::ActionMetadata const& metadata,
38 std::shared_ptr<ServiceManager> const& service);
39
40 virtual ~Preview() = default;
41
42 virtual void
43 cancelled() override;
44
45 virtual void
46 run(unity::scopes::PreviewReplyProxy const& reply) override;
47
48private:
49 void
50 registerLayouts(unity::scopes::PreviewReplyProxy const& reply);
51
52 void
53 createSingleColumnLayout(Package const& app);
54
55 void
56 createDualColumnLayout(Package const& app);
57
58 struct {
59 std::vector<std::string> column;
60 } oneColumn;
61
62 struct {
63 std::vector<std::string> column1;
64 std::vector<std::string> column2;
65 } twoColumns;
66
67 std::shared_ptr<ServiceManager> service_;
68};
69
70
71}
72}
73
74#endif /* LIBERTINE_STORE_PREVIEW_H */
075
=== modified file 'scope/store/query.cpp'
--- scope/store/query.cpp 2016-09-01 15:58:02 +0000
+++ scope/store/query.cpp 2016-09-15 17:01:59 +0000
@@ -20,7 +20,6 @@
20#include <unity/scopes/SearchReply.h>20#include <unity/scopes/SearchReply.h>
21#include <unity/scopes/CategoryRenderer.h>21#include <unity/scopes/CategoryRenderer.h>
22#include <unity/scopes/VariantBuilder.h>22#include <unity/scopes/VariantBuilder.h>
23#include <sstream>
24#include <QtDBus>23#include <QtDBus>
25#include <QDebug>24#include <QDebug>
2625
@@ -65,27 +64,9 @@
65 }64 }
66)";65)";
6766
68static std::string render_rating_stars(double rating)67
69{68static auto const SINGLE_RESULT_FOUND = _("%1 result found");
70 std::ostringstream ss;69static auto const MULTIPLE_RESULTS_FOUND = _("%1 results found");
71 int rounded;
72
73 if (rating < 0.0f) {
74 rounded = 0;
75 } else if (rating > 5.0f) {
76 rounded = 5;
77 } else {
78 rounded = floor(rating);
79 }
80
81 for (int i = 0; i < rounded; i++) {
82 ss << "★";
83 }
84 for (int j = 0; j < 5 - rounded; j++) {
85 ss << "☆";
86 }
87 return ss.str();
88}
89}70}
9071
9172
@@ -94,9 +75,9 @@
9475
9576
96Libertine::Store::Query::77Libertine::Store::Query::
97Query(usc::CannedQuery const& query,78Query(usc::CannedQuery const& query,
98 usc::SearchMetadata const& metadata,79 usc::SearchMetadata const& metadata,
99 std::shared_ptr<ServiceManager> const& service)80 std::shared_ptr<ServiceManager> const& service)
100 : usc::SearchQueryBase(query, metadata)81 : usc::SearchQueryBase(query, metadata)
101 , service_(service)82 , service_(service)
102{83{
@@ -139,20 +120,15 @@
139 for (auto const& result: results)120 for (auto const& result: results)
140 {121 {
141 usc::CategorisedResult cr(category);122 usc::CategorisedResult cr(category);
142 cr.set_title(result.toStdString());123 cr.set_title(result.name);
143 cr["subtitle"] = "Publisher Placeholder";124 cr["subtitle"] = result.summary;
144 cr["rating"] = render_rating_stars(3);125 cr["id"] = result.id;
145126 cr.set_art(result.icon);
146 usc::VariantBuilder builder;127 cr.set_uri("appid://" + result.id);
147 builder.add_tuple({128
148 {"value", cr["rating"]},
149 });
150 cr["attributes"] = builder.end();
151
152 cr.set_uri(self_uri);
153 if (!reply->push(cr))129 if (!reply->push(cr))
154 {130 {
155 qCritical() << "Error while adding result " << result;131 qCritical() << "Error while adding result " << QString::fromStdString(result.name);
156 return;132 return;
157 }133 }
158 }134 }
159135
=== modified file 'scope/store/query.h'
--- scope/store/query.h 2016-07-18 20:41:41 +0000
+++ scope/store/query.h 2016-09-15 17:01:59 +0000
@@ -16,7 +16,7 @@
16#ifndef LIBERTINE_STORE_QUERY_H_16#ifndef LIBERTINE_STORE_QUERY_H_
17#define LIBERTINE_STORE_QUERY_H_17#define LIBERTINE_STORE_QUERY_H_
1818
19#include "scope/store/service_manager.h"19
20#include <unity/scopes/ReplyProxyFwd.h>20#include <unity/scopes/ReplyProxyFwd.h>
21#include <unity/scopes/SearchQueryBase.h>21#include <unity/scopes/SearchQueryBase.h>
2222
@@ -28,6 +28,8 @@
28namespace Store28namespace Store
29{29{
3030
31class ServiceManager;
32
31/**33/**
32 * Engine to run a specific store query.34 * Engine to run a specific store query.
33 */35 */
3436
=== modified file 'scope/store/scope.cpp'
--- scope/store/scope.cpp 2016-08-04 14:56:27 +0000
+++ scope/store/scope.cpp 2016-09-15 17:01:59 +0000
@@ -20,7 +20,9 @@
20#include "scope/store/scope.h"20#include "scope/store/scope.h"
2121
22#include "scope/store/i18n.h"22#include "scope/store/i18n.h"
23#include "scope/store/preview.h"
23#include "scope/store/query.h"24#include "scope/store/query.h"
25#include "scope/store/service_manager.h"
2426
2527
26namespace usc = unity::scopes;28namespace usc = unity::scopes;
@@ -45,8 +47,8 @@
4547
4648
47usc::PreviewQueryBase::UPtr Libertine::Store::Scope::49usc::PreviewQueryBase::UPtr Libertine::Store::Scope::
48preview(usc::Result const&,50preview(usc::Result const& result,
49 usc::ActionMetadata const&)51 usc::ActionMetadata const& metadata)
50{52{
51 return usc::PreviewQueryBase::UPtr();53 return usc::PreviewQueryBase::UPtr(new Preview(result, metadata, std::make_shared<ServiceManager>()));
52}54}
5355
=== modified file 'scope/store/service_manager.cpp'
--- scope/store/service_manager.cpp 2016-08-31 17:59:10 +0000
+++ scope/store/service_manager.cpp 2016-09-15 17:01:59 +0000
@@ -17,20 +17,36 @@
1717
18#include <QtDBus>18#include <QtDBus>
19#include <QDebug>19#include <QDebug>
20#include <QDBusMetaType>
2021
21namespace22namespace
22{23{
23constexpr auto SEARCH_CACHE_METHOD = "search";24constexpr auto SEARCH_CACHE_METHOD = "search";
25constexpr auto APP_INFO_METHOD = "app_info";
24constexpr auto LIBERTINE_SERVICE_DESTINATION = "com.canonical.libertine.ContainerManager";26constexpr auto LIBERTINE_SERVICE_DESTINATION = "com.canonical.libertine.ContainerManager";
25constexpr auto LIBERTINE_SERVICE_INTERFACE = "com.canonical.libertine.ContainerManager";27constexpr auto LIBERTINE_SERVICE_INTERFACE = "com.canonical.libertine.ContainerManager";
26constexpr auto LIBERTINE_SERVICE_OBJECT = "/Manager";28constexpr auto LIBERTINE_SERVICE_OBJECT = "/Manager";
27}29}
2830
2931
30QStringList Libertine::Store::ServiceManager::32Libertine::Store::ServiceManager::
33ServiceManager()
34{
35 qDBusRegisterMetaType<QList<QVariantMap > >();
36}
37
38
39Libertine::Store::Package Libertine::Store::ServiceManager::
40app_info(const QString &app_id) const
41{
42 return Package::from_map(call<QVariantMap >(APP_INFO_METHOD, QVariant(app_id)));
43}
44
45
46QList<Libertine::Store::Package> Libertine::Store::ServiceManager::
31search_cache(const QString &query) const47search_cache(const QString &query) const
32{48{
33 return call<QStringList>(SEARCH_CACHE_METHOD, QVariant(query));49 return Package::from_map(call<QList<QVariantMap > >(SEARCH_CACHE_METHOD, QVariant(query)));
34}50}
3551
3652
@@ -62,7 +78,3 @@
62 return QDBusConnection::sessionBus().isConnected();78 return QDBusConnection::sessionBus().isConnected();
63}79}
6480
65
66// explicit template declarations so we can define template in implementation file
67template QStringList Libertine::Store::ServiceManager::
68call<QStringList>(QString const&, QVariant const&) const;
6981
=== modified file 'scope/store/service_manager.h'
--- scope/store/service_manager.h 2016-07-18 20:41:41 +0000
+++ scope/store/service_manager.h 2016-09-15 17:01:59 +0000
@@ -13,13 +13,15 @@
13 * You should have received a copy of the GNU General Public License13 * You should have received a copy of the GNU General Public License
14 * along with this program. If not, see <http://www.gnu.org/licenses/>.14 * along with this program. If not, see <http://www.gnu.org/licenses/>.
15 */15 */
16
17#ifndef SERVICE_MANAGER_H16#ifndef SERVICE_MANAGER_H
18#define SERVICE_MANAGER_H17#define SERVICE_MANAGER_H
1918
19#include "scope/store/package.h"
20
20#include <QString>21#include <QString>
21#include <QVariant>22#include <QVariant>
2223
24
23namespace Libertine25namespace Libertine
24{26{
25namespace Store27namespace Store
@@ -29,10 +31,11 @@
29class ServiceManager31class ServiceManager
30{32{
31public:33public:
32 ServiceManager() = default;34 explicit ServiceManager();
33 virtual ~ServiceManager() = default;35 virtual ~ServiceManager() = default;
3436
35 virtual QStringList search_cache(QString const& query) const;37 virtual QList<Package> search_cache(QString const& query) const;
38 virtual Package app_info(QString const& app_id) const;
3639
37private:40private:
38 bool valid() const;41 bool valid() const;
@@ -45,4 +48,5 @@
45} // namespace Libertine48} // namespace Libertine
46} // namespace Store49} // namespace Store
4750
51
48#endif // SERVICE_MANAGER_H52#endif // SERVICE_MANAGER_H
4953
=== modified file 'service/libertine_service/apt.py'
--- service/libertine_service/apt.py 2016-07-18 20:41:41 +0000
+++ service/libertine_service/apt.py 2016-09-15 17:01:59 +0000
@@ -15,7 +15,7 @@
15import apt15import apt
16import glob16import glob
17import os17import os
1818import re
1919
20def _use_system_gpg():20def _use_system_gpg():
21 """ Configures APT to use the system-wide GPG store. Always."""21 """ Configures APT to use the system-wide GPG store. Always."""
@@ -28,12 +28,10 @@
28 sources_path = os.path.join('/etc', 'apt')28 sources_path = os.path.join('/etc', 'apt')
29 sources_list = glob.glob(os.path.join(sources_path, 'sources.list.d', '*.list'))29 sources_list = glob.glob(os.path.join(sources_path, 'sources.list.d', '*.list'))
30 sources_list.append(os.path.join(sources_path, 'sources.list'))30 sources_list.append(os.path.join(sources_path, 'sources.list'))
31
32 sources = ''31 sources = ''
33 for source in sources_list:32 for source in sources_list:
34 with open(source) as f:33 with open(source) as f:
35 sources += f.read()34 sources += f.read()
36
37 return sources35 return sources
3836
3937
@@ -61,10 +59,45 @@
61 return apt_cache59 return apt_cache
6260
6361
64def get_apt_cache(config):62def _get_apt_cache(config):
65 """ Factory function to get the APT cache obejct. """63 """ Factory function to get the APT cache obejct. """
66 _use_system_gpg()64 _use_system_gpg()
67 if config.use_local_cache:65 if config.use_local_cache:
68 return _get_local_apt_cache()66 return _get_local_apt_cache()
69 else:67 else:
70 return apt.Cache()68 return apt.Cache()
69
70class AptCache(object):
71 """docstring for AptCache"""
72 def __init__(self, config):
73 super(AptCache, self).__init__()
74 self.config = config
75
76 def search(self, query):
77 apps = []
78
79 cache = _get_apt_cache(self.config)
80 pkg_keys = [key for key in cache.keys() if re.match(query, key)]
81 for key in pkg_keys:
82 app = {}
83 app["name"] = cache[key].name
84 app["id"] = cache[key].name
85 if len(cache[key].versions) > 0:
86 app["summary"] = cache[key].versions[0].summary
87 app["website"] = cache[key].versions[0].homepage
88 apps.append(app)
89 return apps
90
91 def app_info(self, app_id):
92 app_data = {}
93 cache = _get_apt_cache(self.config)
94 if app_id in cache:
95 app = cache[app_id]
96 app_data["name"] = app.name
97 app_data["id"] = app.name
98 if len(app.versions) > 0:
99 app_data["summary"] = app.versions[0].summary
100 app_data["website"] = app.versions[0].homepage
101 app_data["description"] = app.versions[0].description
102
103 return app_data
71104
=== modified file 'service/libertine_service/dbus.py'
--- service/libertine_service/dbus.py 2016-08-31 16:57:31 +0000
+++ service/libertine_service/dbus.py 2016-09-15 17:01:59 +0000
@@ -15,7 +15,6 @@
15import dbus15import dbus
16import dbus.service16import dbus.service
17import logging17import logging
18import re
19from libertine_service import apt18from libertine_service import apt
20from dbus.mainloop.glib import DBusGMainLoop19from dbus.mainloop.glib import DBusGMainLoop
2120
@@ -31,7 +30,7 @@
3130
32 def __init__(self, config):31 def __init__(self, config):
33 log.info("creating service")32 log.info("creating service")
34 self.config = config33 self.cache = apt.AptCache(config)
35 DBusGMainLoop(set_as_default=True)34 DBusGMainLoop(set_as_default=True)
36 try:35 try:
37 bus_name = dbus.service.BusName(LIBERTINE_SERVICE_NAME,36 bus_name = dbus.service.BusName(LIBERTINE_SERVICE_NAME,
@@ -62,11 +61,17 @@
6261
63 @dbus.service.method(LIBERTINE_STORE_INTERFACE,62 @dbus.service.method(LIBERTINE_STORE_INTERFACE,
64 in_signature='s',63 in_signature='s',
65 out_signature='as')64 out_signature='aa{sv}')
66 def search(self, search_string):65 def search(self, search_string):
67 log.debug("search('{}') called".format(search_string))66 log.debug("search('{}') called".format(search_string))
68 cache = apt.get_apt_cache(self.config)67 return self.cache.search(search_string)
69 return {k: cache[k] for k in cache.keys() if re.match(search_string, k)}68
69 @dbus.service.method(LIBERTINE_STORE_INTERFACE,
70 in_signature='s',
71 out_signature='a{sv}')
72 def app_info(self, app_id):
73 log.debug("app_info('{}') called".format(app_id))
74 return self.cache.app_info(app_id)
7075
71 @dbus.service.signal(LIBERTINE_STORE_INTERFACE,76 @dbus.service.signal(LIBERTINE_STORE_INTERFACE,
72 signature='su')77 signature='su')
7378
=== modified file 'tests/scope/apps/test_preview.cpp'
--- tests/scope/apps/test_preview.cpp 2016-07-18 13:53:20 +0000
+++ tests/scope/apps/test_preview.cpp 2016-09-15 17:01:59 +0000
@@ -22,7 +22,6 @@
22#include <unity/scopes/testing/MockPreviewReply.h>22#include <unity/scopes/testing/MockPreviewReply.h>
23#include <unity/scopes/PreviewWidget.h>23#include <unity/scopes/PreviewWidget.h>
24#include <memory>24#include <memory>
25#include <QDir>
2625
2726
28TEST(TestPreview, pushesWidgetsWithAppInformation)27TEST(TestPreview, pushesWidgetsWithAppInformation)
2928
=== modified file 'tests/scope/store/CMakeLists.txt'
--- tests/scope/store/CMakeLists.txt 2016-07-19 14:18:12 +0000
+++ tests/scope/store/CMakeLists.txt 2016-09-15 17:01:59 +0000
@@ -1,5 +1,6 @@
1function(create_test test_name test_file)1function(create_test test_name test_file)
2 add_executable(${test_name}_exe2 add_executable(${test_name}_exe
3 mock_service_manager.h
3 ${test_file}.cpp4 ${test_file}.cpp
4 )5 )
56
@@ -15,3 +16,5 @@
15endfunction(create_test)16endfunction(create_test)
1617
17create_test(test_store_query test_query)18create_test(test_store_query test_query)
19create_test(test_store_preview test_preview)
20create_test(test_store_package test_package)
1821
=== added file 'tests/scope/store/mock_service_manager.h'
--- tests/scope/store/mock_service_manager.h 1970-01-01 00:00:00 +0000
+++ tests/scope/store/mock_service_manager.h 2016-09-15 17:01:59 +0000
@@ -0,0 +1,46 @@
1/*
2 * Copyright 2016 Canonical Ltd.
3 *
4 * This program is free software: you can redistribute it and/or modify it under
5 * the terms of the GNU General Public License, version 3, as published by the
6 * Free Software Foundation.
7 *
8 * This program is distributed in the hope that it will be useful,
9 * but WITHOUT ANY WARRANTY; without even the implied warranty of
10 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 * GNU General Public License for more details.
12 *
13 * You should have received a copy of the GNU General Public License
14 * along with this program. If not, see <http://www.gnu.org/licenses/>.
15 */
16
17#ifndef _MOCK_SERVICE_MANAGER_H
18#define _MOCK_SERVICE_MANAGER_H
19
20#include "scope/store/service_manager.h"
21#include <gmock/gmock.h>
22
23
24namespace Libertine
25{
26namespace Store
27{
28
29
30class MockServiceManager : public ServiceManager
31{
32public:
33 MockServiceManager()
34 : ServiceManager()
35 {
36 }
37
38 MOCK_CONST_METHOD1(search_cache, QList<Package>(QString const&));
39 MOCK_CONST_METHOD1(app_info, Package(QString const&));
40};
41
42
43} // namesapce Store
44} // namesapce Libertine
45
46#endif // _MOCK_SERVICE_MANAGER_H
047
=== added file 'tests/scope/store/test_package.cpp'
--- tests/scope/store/test_package.cpp 1970-01-01 00:00:00 +0000
+++ tests/scope/store/test_package.cpp 2016-09-15 17:01:59 +0000
@@ -0,0 +1,107 @@
1/*
2 * Copyright 2016 Canonical Ltd.
3 *
4 * This program is free software: you can redistribute it and/or modify it under
5 * the terms of the GNU General Public License, version 3, as published by the
6 * Free Software Foundation.
7 *
8 * This program is distributed in the hope that it will be useful,
9 * but WITHOUT ANY WARRANTY; without even the implied warranty of
10 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 * GNU General Public License for more details.
12 *
13 * You should have received a copy of the GNU General Public License
14 * along with this program. If not, see <http://www.gnu.org/licenses/>.
15 */
16#include "scope/store/package.h"
17
18#include <gtest/gtest.h>
19#include <gmock/gmock.h>
20
21
22namespace
23{
24using namespace Libertine::Store;
25
26
27static QVariantMap
28attribute_map(QString const& name, QString const& summary, QString const& description,
29 QString const& icon, QString const& publisher, QString const& website,
30 QString const& license, QString const& id, QStringList screenshots)
31{
32 QVariantMap attributes;
33 attributes["name"] = name;
34 attributes["summary"] = summary;
35 attributes["description"] = description;
36 attributes["icon"] = icon;
37 attributes["publisher"] = publisher;
38 attributes["website"] = website;
39 attributes["license"] = license;
40 attributes["id"] = id;
41 attributes["screenshots"] = screenshots;
42 return attributes;
43}
44
45
46static void
47package_matches_attributes(Package actual, std::string const& name, std::string const& summary,
48 std::string const& description, std::string const& icon, std::string const& publisher,
49 std::string const& website, std::string const& license, std::string const& id,
50 QStringList screenshots)
51{
52 EXPECT_EQ(name, actual.name);
53 EXPECT_EQ(summary, actual.summary);
54 EXPECT_EQ(description, actual.description);
55 EXPECT_EQ(icon, actual.icon);
56 EXPECT_EQ(publisher, actual.publisher);
57 EXPECT_EQ(website, actual.website);
58 EXPECT_EQ(license, actual.license);
59 EXPECT_EQ(id, actual.id);
60
61 ASSERT_EQ(actual.screenshots.size(), screenshots.size());
62 for (auto i = 0u; i < actual.screenshots.size(); ++i)
63 {
64 EXPECT_EQ(screenshots[i], QString::fromStdString(actual.screenshots[i]));
65 }
66}
67
68
69TEST(PackageTest, FromMapCreatesSinglePackage)
70{
71 QStringList screenshots{"file:///some/image.png", "file:///some/other/image.jpg"};
72 auto attributeMap = attribute_map("Harry", "The Philosopher's Stone",
73 "Boy with head injury seeks magic rock",
74 "harry.png", "JK", "pottermore.com", "Private",
75 "com.pottermore.harry", screenshots);
76 auto package = Package::from_map(attributeMap);
77 package_matches_attributes(package, "Harry", "The Philosopher's Stone",
78 "Boy with head injury seeks magic rock",
79 "harry.png", "JK", "pottermore.com", "Private",
80 "com.pottermore.harry", screenshots);
81}
82
83
84TEST(PackageTest, FromMapCreatesListOfPackages)
85{
86 QStringList screenshots{"file:///some/image.png", "file:///some/other/image.jpg"};
87 auto attributePkg1Map = attribute_map("Harry", "The Philosopher's Stone",
88 "Boy with head injury seeks magic rock",
89 "harry.png", "JK", "pottermore.com", "Private",
90 "com.pottermore.harry", screenshots);
91 QStringList screenshots2{"file://imageFor2.png"};
92 auto attributePkg2Map = attribute_map("Dune", "Classic science fiction",
93 "The spice must flow", "worms.png",
94 "Herbert", "dunebook.net", "Other",
95 "net.dunebook.dune", screenshots2);
96 auto packages = Package::from_map(QList<QVariantMap>{attributePkg1Map, attributePkg2Map});
97 ASSERT_EQ(2, packages.size());
98 package_matches_attributes(packages[0], "Harry", "The Philosopher's Stone",
99 "Boy with head injury seeks magic rock",
100 "harry.png", "JK", "pottermore.com", "Private",
101 "com.pottermore.harry", screenshots);
102 package_matches_attributes(packages[1], "Dune", "Classic science fiction",
103 "The spice must flow", "worms.png",
104 "Herbert", "dunebook.net", "Other",
105 "net.dunebook.dune", screenshots2);
106}
107}
0108
=== added file 'tests/scope/store/test_preview.cpp'
--- tests/scope/store/test_preview.cpp 1970-01-01 00:00:00 +0000
+++ tests/scope/store/test_preview.cpp 2016-09-15 17:01:59 +0000
@@ -0,0 +1,196 @@
1/*
2 * Copyright 2016 Canonical Ltd.
3 *
4 * This program is free software: you can redistribute it and/or modify it under
5 * the terms of the GNU General Public License, version 3, as published by the
6 * Free Software Foundation.
7 *
8 * This program is distributed in the hope that it will be useful,
9 * but WITHOUT ANY WARRANTY; without even the implied warranty of
10 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 * GNU General Public License for more details.
12 *
13 * You should have received a copy of the GNU General Public License
14 * along with this program. If not, see <http://www.gnu.org/licenses/>.
15 */
16#include "scope/store/preview.h"
17#include "tests/scope/store/mock_service_manager.h"
18
19#include <unity/scopes/ActionMetadata.h>
20#include <unity/scopes/PreviewWidget.h>
21#include <unity/scopes/testing/MockPreviewReply.h>
22#include <unity/scopes/testing/Result.h>
23#include <gtest/gtest.h>
24#include <gmock/gmock.h>
25
26namespace
27{
28using namespace Libertine::Store;
29
30
31static void
32verifyHeader(Package const& package, unity::scopes::PreviewWidget const& header)
33{
34 EXPECT_EQ("hdr", header.id());
35 EXPECT_EQ("header", header.widget_type());
36
37 EXPECT_EQ(package.name, header.attribute_values()["title"].get_string());
38 EXPECT_EQ(package.summary, header.attribute_values()["subtitle"].get_string());
39 EXPECT_EQ(package.icon, header.attribute_values()["mascot"].get_string());
40}
41
42
43static void
44verifyButtons(unity::scopes::PreviewWidget const& buttons)
45{
46 EXPECT_EQ("buttons", buttons.id());
47 EXPECT_EQ("actions", buttons.widget_type());
48 auto buttons_actions = buttons.attribute_values()["actions"].get_array();
49 ASSERT_EQ(1, buttons_actions.size());
50 EXPECT_EQ("install_xapp", buttons_actions[0].get_dict()["id"].get_string());
51 EXPECT_EQ("Install", buttons_actions[0].get_dict()["label"].get_string());
52}
53
54
55static void
56verifyMetadata(Package const& package, unity::scopes::PreviewWidget const& props)
57{
58 EXPECT_EQ("other_metadata", props.id());
59 EXPECT_EQ("table", props.widget_type());
60
61 auto propValues = props.attribute_values()["values"].get_array();
62 ASSERT_EQ(3, propValues.size());
63 ASSERT_EQ(2, propValues[0].get_array().size());
64 EXPECT_EQ("Publisher/Creator", propValues[0].get_array()[0].get_string());
65 EXPECT_EQ(package.publisher, propValues[0].get_array()[1].get_string());
66 ASSERT_EQ(2, propValues[1].get_array().size());
67 EXPECT_EQ("Website", propValues[1].get_array()[0].get_string());
68 EXPECT_EQ(package.website, propValues[1].get_array()[1].get_string());
69 ASSERT_EQ(2, propValues[2].get_array().size());
70 EXPECT_EQ("License", propValues[2].get_array()[0].get_string());
71 EXPECT_EQ(package.license, propValues[2].get_array()[1].get_string());
72}
73
74
75static void
76verifyDescription(Package const& package, unity::scopes::PreviewWidget const& description)
77{
78 EXPECT_EQ("summary", description.id());
79 EXPECT_EQ("text", description.widget_type());
80 EXPECT_EQ("Info", description.attribute_values()["title"].get_string());
81 EXPECT_EQ(package.description, description.attribute_values()["text"].get_string());
82}
83
84
85static void
86verifyScreenshots(Package const& package, unity::scopes::PreviewWidget const& screenshots)
87{
88 EXPECT_EQ("screenshots", screenshots.id());
89 EXPECT_EQ("gallery", screenshots.widget_type());
90
91 auto sources = screenshots.attribute_values()["sources"].get_array();
92 ASSERT_EQ(package.screenshots.size(), sources.size());
93
94 for (auto i = 0u; i < package.screenshots.size(); ++i)
95 {
96 EXPECT_EQ(package.screenshots[i], sources[i].get_string());
97 }
98
99}
100
101
102class StorePreviewTest : public testing::Test
103{
104protected:
105 StorePreviewTest()
106 : testing::Test()
107 , result()
108 , metadata("en_US", "phone")
109 , list(new unity::scopes::PreviewWidgetList())
110 , reply()
111 , proxy(&reply, [](unity::scopes::PreviewReply*) {})
112 , service(new testing::NiceMock<MockServiceManager>())
113 {
114 }
115
116 virtual void
117 SetUp()
118 {
119 EXPECT_CALL(reply, push(testing::_)).WillOnce(testing::SaveArg<0>(list.get()));
120 }
121
122 void usePackage(Package const& package)
123 {
124 result["id"] = unity::scopes::Variant(package.id);
125 EXPECT_CALL(*service, app_info(QString::fromStdString(package.id))).WillOnce(testing::Return(package));
126 }
127
128 unity::scopes::testing::Result result;
129 unity::scopes::ActionMetadata metadata;
130 std::unique_ptr<unity::scopes::PreviewWidgetList> list;
131 testing::NiceMock<unity::scopes::testing::MockPreviewReply> reply;
132 unity::scopes::PreviewReplyProxy proxy;
133 std::shared_ptr<testing::NiceMock<MockServiceManager> > service;
134};
135
136
137TEST_F(StorePreviewTest, ShowsDetailedInformationForPackage)
138{
139 Package package;
140 package.name = "vim";
141 package.summary = "classic text editor";
142 package.description = "this or emacs";
143 package.icon = "file:///test/file.png";
144 package.publisher = "Woody Boyd";
145 package.website = "http://canonical.com/";
146 package.license = "GPLv8+";
147 package.id = "vim.desktop";
148 usePackage(package);
149
150 Preview preview(result, metadata, service);
151 preview.run(proxy);
152
153 ASSERT_NE(nullptr, list);
154 ASSERT_EQ(4, list->size());
155
156 verifyHeader(package, list->front());
157 list->pop_front();
158 verifyButtons(list->front());
159 list->pop_front();
160 verifyMetadata(package, list->front());
161 list->pop_front();
162 verifyDescription(package, list->front());
163}
164
165
166TEST_F(StorePreviewTest, ShowsScreenshotsWhenAvailable)
167{
168 Package package;
169 package.name = "vim";
170 package.summary = "classic text editor";
171 package.description = "this or emacs";
172 package.icon = "file:///test/file.png";
173 package.publisher = "Woody Boyd";
174 package.website = "http://canonical.com/";
175 package.license = "GPLv8+";
176 package.id = "vim.desktop";
177 package.screenshots = std::vector<std::string>{"file:///some/string/uri.png", "file:///some/other/string/uri.jpg"};
178 usePackage(package);
179
180 Preview preview(result, metadata, service);
181 preview.run(proxy);
182
183 ASSERT_NE(nullptr, list);
184 ASSERT_EQ(5, list->size());
185
186 verifyHeader(package, list->front());
187 list->pop_front();
188 verifyButtons(list->front());
189 list->pop_front();
190 verifyMetadata(package, list->front());
191 list->pop_front();
192 verifyScreenshots(package, list->front());
193 list->pop_front();
194 verifyDescription(package, list->front());
195}
196}
0197
=== modified file 'tests/scope/store/test_query.cpp'
--- tests/scope/store/test_query.cpp 2016-07-20 13:35:09 +0000
+++ tests/scope/store/test_query.cpp 2016-09-15 17:01:59 +0000
@@ -13,9 +13,10 @@
13 * You should have received a copy of the GNU General Public License13 * You should have received a copy of the GNU General Public License
14 * along with this program. If not, see <http://www.gnu.org/licenses/>.14 * along with this program. If not, see <http://www.gnu.org/licenses/>.
15 */15 */
16
17#include "scope/store/query.h"16#include "scope/store/query.h"
18#include "scope/store/service_manager.h"17
18
19#include "tests/scope/store/mock_service_manager.h"
19#include <unity/scopes/SearchMetadata.h>20#include <unity/scopes/SearchMetadata.h>
20#include <unity/scopes/CannedQuery.h>21#include <unity/scopes/CannedQuery.h>
21#include <unity/scopes/testing/MockSearchReply.h>22#include <unity/scopes/testing/MockSearchReply.h>
@@ -41,24 +42,20 @@
41};42};
4243
4344
44class MockServiceManager : public ServiceManager
45{
46public:
47 MockServiceManager()
48 : ServiceManager()
49 {
50 }
51
52 MOCK_CONST_METHOD1(search_cache, QStringList(QString const&));
53};
54
55
56MATCHER_P(ResultTitleMatch, title, "")45MATCHER_P(ResultTitleMatch, title, "")
57{46{
58 return arg.contains("title") && arg["title"] == unity::scopes::Variant(title);47 return arg.contains("title") && arg["title"] == unity::scopes::Variant(title);
59}48}
6049
6150
51MATCHER_P3(ResultPackageMatch, title, subtitle, id, "")
52{
53 return arg.contains("title") && arg["title"].get_string() == title &&
54 arg.contains("subtitle") && arg["subtitle"].get_string() == subtitle &&
55 arg.contains("id") && arg["id"].get_string() == id;
56}
57
58
62class TestStoreQuery : public ::testing::Test59class TestStoreQuery : public ::testing::Test
63{60{
64protected:61protected:
@@ -72,6 +69,21 @@
72 {69 {
73 }70 }
7471
72 Package create_package(std::string name, std::string summary, std::string id)
73 {
74 Package package;
75 package.name = name;
76 package.summary = summary;
77 package.id = id;
78
79 return package;
80 }
81
82 void expect_push(std::string title, std::string subtitle, std::string id, bool result = true)
83 {
84 EXPECT_CALL(reply_, push(testing::Matcher<unity::scopes::CategorisedResult const&>(ResultPackageMatch(title, subtitle, id)))).WillOnce(testing::Return(result));
85 }
86
75 unity::scopes::SearchMetadata metadata_;87 unity::scopes::SearchMetadata metadata_;
76 unity::scopes::CannedQuery canned_query_;88 unity::scopes::CannedQuery canned_query_;
77 testing::NiceMock<unity::scopes::testing::MockSearchReply> reply_;89 testing::NiceMock<unity::scopes::testing::MockSearchReply> reply_;
@@ -95,7 +107,7 @@
95{107{
96 EXPECT_CALL(reply_, register_category("hint", "", "", testing::_)).WillOnce(testing::Return(category_));108 EXPECT_CALL(reply_, register_category("hint", "", "", testing::_)).WillOnce(testing::Return(category_));
97 EXPECT_CALL(reply_, push(testing::Matcher<unity::scopes::CategorisedResult const&>(ResultTitleMatch(Query::NO_SEARCH_RESULTS_HINT)))).WillOnce(testing::Return(true));109 EXPECT_CALL(reply_, push(testing::Matcher<unity::scopes::CategorisedResult const&>(ResultTitleMatch(Query::NO_SEARCH_RESULTS_HINT)))).WillOnce(testing::Return(true));
98 EXPECT_CALL(*service_, search_cache(testing::_)).WillOnce(testing::Return(QStringList{}));110 EXPECT_CALL(*service_, search_cache(testing::_)).WillOnce(testing::Return(QList<Package>{}));
99 canned_query_.set_query_string("foobar");111 canned_query_.set_query_string("foobar");
100112
101 Query q(canned_query_, metadata_, service_);113 Query q(canned_query_, metadata_, service_);
@@ -106,8 +118,11 @@
106TEST_F(TestStoreQuery, ShowSingleSearchResult)118TEST_F(TestStoreQuery, ShowSingleSearchResult)
107{119{
108 EXPECT_CALL(reply_, register_category("aptcache", "1 result found", "Application", testing::_)).WillOnce(testing::Return(category_));120 EXPECT_CALL(reply_, register_category("aptcache", "1 result found", "Application", testing::_)).WillOnce(testing::Return(category_));
109 EXPECT_CALL(reply_, push(testing::Matcher<unity::scopes::CategorisedResult const&>(ResultTitleMatch("vim")))).WillOnce(testing::Return(true));121
110 EXPECT_CALL(*service_, search_cache(testing::_)).WillOnce(testing::Return(QStringList{"vim"}));122 auto package = create_package("vim", "Writin' stuff", "vim.desktop");
123 expect_push("vim", "Writin' stuff", "vim.desktop");
124
125 EXPECT_CALL(*service_, search_cache(testing::_)).WillOnce(testing::Return(QList<Package>{package}));
111 canned_query_.set_query_string("vim");126 canned_query_.set_query_string("vim");
112127
113 Query q(canned_query_, metadata_, service_);128 Query q(canned_query_, metadata_, service_);
@@ -118,10 +133,35 @@
118TEST_F(TestStoreQuery, ShowMultipleSearchResults)133TEST_F(TestStoreQuery, ShowMultipleSearchResults)
119{134{
120 EXPECT_CALL(reply_, register_category("aptcache", "3 results found", "Application", testing::_)).WillOnce(testing::Return(category_));135 EXPECT_CALL(reply_, register_category("aptcache", "3 results found", "Application", testing::_)).WillOnce(testing::Return(category_));
121 EXPECT_CALL(reply_, push(testing::Matcher<unity::scopes::CategorisedResult const&>(ResultTitleMatch("vim")))).WillOnce(testing::Return(true));136
122 EXPECT_CALL(reply_, push(testing::Matcher<unity::scopes::CategorisedResult const&>(ResultTitleMatch("vim-common")))).WillOnce(testing::Return(true));137 auto vim = create_package("vim", "Writin' stuff", "vim.desktop");
123 EXPECT_CALL(reply_, push(testing::Matcher<unity::scopes::CategorisedResult const&>(ResultTitleMatch("vim-uncommon")))).WillOnce(testing::Return(true));138 auto gedit = create_package("gedit", "Writin' gui stuff", "gedit.desktop");
124 EXPECT_CALL(*service_, search_cache(testing::_)).WillOnce(testing::Return(QStringList{"vim", "vim-common", "vim-uncommon"}));139 auto ed = create_package("ed", "Writin' simple stuff", "ed.desktop");
140
141 expect_push("vim", "Writin' stuff", "vim.desktop");
142 expect_push("gedit", "Writin' gui stuff", "gedit.desktop");
143 expect_push("ed", "Writin' simple stuff", "ed.desktop");
144
145 EXPECT_CALL(*service_, search_cache(testing::_)).WillOnce(testing::Return(QList<Package>{vim, gedit, ed}));
146 canned_query_.set_query_string("vim");
147
148 Query q(canned_query_, metadata_, service_);
149 q.run(proxy_);
150}
151
152
153TEST_F(TestStoreQuery, FailureToPushEndsQueryPrematurely)
154{
155 EXPECT_CALL(reply_, register_category("aptcache", "3 results found", "Application", testing::_)).WillOnce(testing::Return(category_));
156
157 auto vim = create_package("vim", "Writin' stuff", "vim.desktop");
158 auto gedit = create_package("gedit", "Writin' gui stuff", "gedit.desktop");
159 auto ed = create_package("ed", "Writin' simple stuff", "ed.desktop");
160
161 expect_push("vim", "Writin' stuff", "vim.desktop");
162 expect_push("gedit", "Writin' gui stuff", "gedit.desktop", false);
163
164 EXPECT_CALL(*service_, search_cache(testing::_)).WillOnce(testing::Return(QList<Package>{vim, gedit, ed}));
125 canned_query_.set_query_string("vim");165 canned_query_.set_query_string("vim");
126166
127 Query q(canned_query_, metadata_, service_);167 Query q(canned_query_, metadata_, service_);

Subscribers

People subscribed via source and target branches

to all changes: