Merge lp:~unity-team/libusermetrics/end-to-end into lp:~unity-team/libusermetrics/file-based-infographics

Proposed by Pete Woods
Status: Merged
Merged at revision: 150
Proposed branch: lp:~unity-team/libusermetrics/end-to-end
Merge into: lp:~unity-team/libusermetrics/file-based-infographics
Diff against target: 5881 lines (+4025/-1090)
86 files modified
CMakeLists.txt (+7/-0)
data/CMakeLists.txt (+70/-1)
data/com.canonical.Infographics.conf (+15/-0)
data/com.canonical.Infographics.service.in (+5/-0)
data/com.canonical.Infographics.xml (+14/-0)
data/com.canonical.UserMetrics.conf (+0/-15)
data/default.json.in (+9/-0)
data/usermetricsservice.conf.in (+10/-0)
debian/changelog (+1/-1)
debian/control (+3/-1)
debian/libusermetricsinput1.symbols (+18/-18)
debian/libusermetricsoutput1.symbols (+11/-0)
debian/rules (+12/-2)
debian/usermetricsservice.infographic.click-hook (+3/-0)
debian/usermetricsservice.install (+2/-0)
debian/usermetricsservice.postinst (+16/-0)
debian/usermetricsservice.postrm (+26/-0)
debian/usermetricsservice.preinst (+30/-0)
debian/usermetricsservice.prerm (+7/-0)
debian/usermetricsservice.usermetrics.click-hook (+3/-0)
doc/Infographic Architecture.svg (+636/-0)
po/en_GB.po (+5/-4)
po/libusermetrics.pot (+1/-1)
src/CMakeLists.txt (+1/-0)
src/infographic/CMakeLists.txt (+2/-2)
src/infographic/main.cpp (+9/-4)
src/infographicservice/CMakeLists.txt (+58/-0)
src/infographicservice/Service.cpp (+131/-0)
src/infographicservice/Service.h (+74/-0)
src/infographicservice/main.cpp (+46/-0)
src/libusermetricscommon/CMakeLists.txt (+8/-1)
src/libusermetricscommon/DBusPaths.h (+37/-0)
src/libusermetricscommon/FileUtils.cpp (+52/-0)
src/libusermetricscommon/FileUtils.h (+47/-0)
src/libusermetricsinput/MetricImpl.cpp (+23/-6)
src/libusermetricsinput/MetricImpl.h (+2/-0)
src/libusermetricsinput/MetricManagerImpl.cpp (+19/-1)
src/libusermetricsoutput/CMakeLists.txt (+3/-0)
src/libusermetricsoutput/DirectoryWatcher.cpp (+114/-0)
src/libusermetricsoutput/DirectoryWatcher.h (+69/-0)
src/libusermetricsoutput/InfographicList.cpp (+32/-0)
src/libusermetricsoutput/InfographicList.h (+106/-0)
src/libusermetricsoutput/InfographicListImpl.cpp (+139/-0)
src/libusermetricsoutput/InfographicListImpl.h (+79/-0)
src/usermetricsservice/CMakeLists.txt (+62/-19)
src/usermetricsservice/DBusUserData.cpp (+0/-186)
src/usermetricsservice/Executor.cpp (+27/-0)
src/usermetricsservice/Executor.h (+42/-0)
src/usermetricsservice/Factory.cpp (+90/-0)
src/usermetricsservice/Factory.h (+69/-0)
src/usermetricsservice/Infographic.cpp (+27/-0)
src/usermetricsservice/Infographic.h (+52/-0)
src/usermetricsservice/InfographicImpl.cpp (+170/-0)
src/usermetricsservice/InfographicImpl.h (+79/-0)
src/usermetricsservice/QProcessExecutor.cpp (+75/-0)
src/usermetricsservice/QProcessExecutor.h (+46/-0)
src/usermetricsservice/ResultTransport.cpp (+27/-0)
src/usermetricsservice/ResultTransport.h (+45/-0)
src/usermetricsservice/ResultTransportImpl.cpp (+66/-0)
src/usermetricsservice/ResultTransportImpl.h (+45/-0)
src/usermetricsservice/Service.cpp (+27/-0)
src/usermetricsservice/Service.h (+45/-0)
src/usermetricsservice/ServiceImpl.cpp (+163/-0)
src/usermetricsservice/ServiceImpl.h (+82/-0)
src/usermetricsservice/SourceDirectory.cpp (+27/-0)
src/usermetricsservice/SourceDirectory.h (+45/-0)
src/usermetricsservice/SourceDirectoryImpl.cpp (+67/-0)
src/usermetricsservice/SourceDirectoryImpl.h (+57/-0)
src/usermetricsservice/aa-exec.cpp (+34/-0)
src/usermetricsservice/main.cpp (+27/-2)
tests/CMakeLists.txt (+5/-0)
tests/data/infographics/test-aggregate.json (+13/-0)
tests/data/infographics/test-iterate.json (+9/-0)
tests/data/valgrind.suppression (+19/-0)
tests/unit/libusermetricsinput/TestMetricImpl.cpp (+1/-1)
tests/unit/libusermetricsinput/TestMetricManagerImpl.cpp (+15/-12)
tests/unit/libusermetricsinput/TestUserMetricInputCAPI.cpp (+2/-2)
tests/unit/libusermetricsoutput/CMakeLists.txt (+1/-0)
tests/unit/libusermetricsoutput/TestInfographicListImpl.cpp (+122/-0)
tests/unit/qml/UserMetricsTest/DBusQuery.cpp (+2/-2)
tests/unit/qml/UserMetricsTest/TestPlugin.cpp (+3/-2)
tests/unit/usermetricsservice/CMakeLists.txt (+25/-0)
tests/unit/usermetricsservice/Mocks.h (+84/-0)
tests/unit/usermetricsservice/TestInfographicImpl.cpp (+124/-0)
tests/unit/usermetricsservice/TestServiceImpl.cpp (+149/-0)
tests/unit/usermetricsservice/TestUserMetricsService.cpp (+0/-807)
To merge this branch: bzr merge lp:~unity-team/libusermetrics/end-to-end
Reviewer Review Type Date Requested Status
Michał Sawicz api Approve
PS Jenkins bot (community) continuous-integration Needs Fixing
Antti Kaijanmäki Pending
Review via email: mp+210435@code.launchpad.net

Commit message

Checking what Jenkins thinks

Description of the change

Checking what Jenkins thinks

To post a comment you must log in.
170. By Pete Woods

Don't know what these are for

171. By Pete Woods

Dead file

172. By Pete Woods

Suppress leaks in Qt

173. By Pete Woods

Merge Qt 5.2 branch

174. By Pete Woods

Fix up the symbols files

Revision history for this message
Michał Sawicz (saviq) wrote :

Hey, this is looking good, I'll try and skim through this for a code review, but I've a few comments looking at the API:

- there's no reason for the separate infographics property, just make InfographicsList a QAbstractListModel (any reason for using *ItemModel instead, btw?) with just a "source" role

- as discussed on IRC, the filesUpdated() signal feels like a dirty API, I'd rather see timestamped file names and dataChanged on the "source" role when applicable; ideally both files would be available at the same time for a while (old files periodically garbage collected, basically?), in case we're still loading the old file while a new one got added

- the timeout logic feels unnecessary, we'll only be loading a single file (two at most during transitions); throttling should probably happen on the visualizer side, though?

- should we be (are we?) running the visualizers whenever data changes, or only when greeter is shown? on one hand that would mean they're ready when greeter is shown, on the other they might never be shown at all (in case user never switches between images)

BTW, what's the plan for i18n? Are we ok with the SVGs only updating the language on next update, or should we maybe kick the visualisers on locale change?

review: Needs Information
175. By Pete Woods

Infographic service writes files with timestamps that get aged off

176. By Pete Woods

This check breaks things when using atomic file writes

177. By Pete Woods

Disabling Valgrind until someone fixes the rules for Qt 5.2

Revision history for this message
Pete Woods (pete-woods) wrote :

> Hey, this is looking good, I'll try and skim through this for a code review,
> but I've a few comments looking at the API:
>
> - there's no reason for the separate infographics property, just make
> InfographicsList a QAbstractListModel (any reason for using *ItemModel
> instead, btw?) with just a "source" role
>
> - as discussed on IRC, the filesUpdated() signal feels like a dirty API, I'd
> rather see timestamped file names and dataChanged on the "source" role when
> applicable; ideally both files would be available at the same time for a while
> (old files periodically garbage collected, basically?), in case we're still
> loading the old file while a new one got added

I have made these changes now. :)

>
> - the timeout logic feels unnecessary, we'll only be loading a single file
> (two at most during transitions); throttling should probably happen on the
> visualizer side, though?
>

I have found the QFileSystemWatcher API to be "noisy", and it sometimes emits duplicate events. Similar throttling occurs in response to the data changes for the visualisers, too, though.

> - should we be (are we?) running the visualizers whenever data changes, or
> only when greeter is shown? on one hand that would mean they're ready when
> greeter is shown, on the other they might never be shown at all (in case user
> never switches between images)
>

We're currently running them whenever data changes. There is only one-way communication to libusermetricsoutput / the greeter, in the form of filesystem changes. So at present there's no way to signal when the Greeter is shown.

> BTW, what's the plan for i18n? Are we ok with the SVGs only updating the
> language on next update, or should we maybe kick the visualisers on locale
> change?

At the moment, it's just the locale that the user was last logged in as. On login we do refresh all the SVGs, however.

Revision history for this message
PS Jenkins bot (ps-jenkins) wrote :
review: Needs Fixing (continuous-integration)
Revision history for this message
Michał Sawicz (saviq) wrote :

224 -libusermetrics (2.0.0-0ubuntu1) UNRELEASED; urgency=medium
225 +libusermetrics (1.2.0-0ubuntu1) UNRELEASED; urgency=medium

That looks wrong?

=====

1656 +static QRegularExpression CLICK_REGEX(
1657 + "^[a-z0-9][a-z0-9+.-]+_[a-zA-Z0-9+.-]+_[0-9][a-zA-Z0-9.+:~-]*$");
1658 +

1815 +static QRegularExpression CLICK_REGEX(
1816 + "^[a-z0-9][a-z0-9+.-]+_[a-zA-Z0-9+.-]+_[0-9][a-zA-Z0-9.+:~-]*$");

Seeing a regex like that makes me twinge already, but having it twice!

=====

2086 + return new InfographicListImpl("/var/lib/usermetrics/");

Do we want that hardcoded? Isn't there somewhere we could request the /var/lib/ part from?

=====

2132 + * Given a user ID, this class watches the corresponding
2133 + *

You fell asleep there, did you?

=====

2139 + * @brief The current username selected.
2140 + */
2141 +Q_PROPERTY(unsigned int uid READ uid WRITE setUid NOTIFY uidChanged FINAL)

User Id, not username.

review: Approve (api)
178. By Pete Woods

Respond to Saviq's review comments

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
1=== modified file 'CMakeLists.txt'
2--- CMakeLists.txt 2014-01-03 12:54:25 +0000
3+++ CMakeLists.txt 2014-04-03 13:02:15 +0000
4@@ -16,12 +16,18 @@
5 find_package(Qt5Core REQUIRED)
6 include_directories(${Qt5Core_INCLUDE_DIRS})
7
8+find_package(Qt5DBus REQUIRED)
9+include_directories(${Qt5DBus_INCLUDE_DIRS})
10+
11 find_package(Qt5Gui REQUIRED)
12 include_directories(${Qt5Gui_INCLUDE_DIRS})
13
14 find_package(Qt5XmlPatterns REQUIRED)
15 include_directories(${Qt5XmlPatterns_INCLUDE_DIRS})
16
17+pkg_check_modules(APPARMOR REQUIRED libapparmor REQUIRED)
18+include_directories(${APPARMOR_INCLUDE_DIRS})
19+
20 pkg_check_modules(GSETTINGS_QT REQUIRED gsettings-qt REQUIRED)
21 include_directories(${GSETTINGS_QT_INCLUDE_DIRS})
22
23@@ -35,6 +41,7 @@
24 set(CMAKE_INCLUDE_CURRENT_DIR ON)
25
26 set(DATA_DIR "${CMAKE_CURRENT_SOURCE_DIR}/data")
27+set(INFOGRAPHIC_SERVICE_XML "${DATA_DIR}/com.canonical.Infographics.xml")
28
29 set(INCLUDE_DIR "${CMAKE_CURRENT_SOURCE_DIR}/include")
30 set(INCLUDE_BINARY_DIR "${CMAKE_CURRENT_BINARY_DIR}/include")
31
32=== modified file 'data/CMakeLists.txt'
33--- data/CMakeLists.txt 2014-01-03 11:40:22 +0000
34+++ data/CMakeLists.txt 2014-04-03 13:02:15 +0000
35@@ -14,6 +14,22 @@
36 )
37
38 ###########################
39+# Default infographic
40+###########################
41+
42+configure_file(
43+ "default.json.in"
44+ "${CMAKE_CURRENT_BINARY_DIR}/default.json" @ONLY
45+)
46+
47+install(
48+ FILES
49+ "${CMAKE_CURRENT_BINARY_DIR}/default.json"
50+ DESTINATION
51+ "${CMAKE_INSTALL_DATADIR}/libusermetrics/infographics/"
52+)
53+
54+###########################
55 # Policy
56 ###########################
57
58@@ -24,7 +40,60 @@
59
60 install(
61 FILES
62- "com.canonical.UserMetrics.conf"
63+ "com.canonical.Infographics.conf"
64 DESTINATION ${DBUSCONFDIR}
65 )
66
67+###########################
68+# Dbus Interfaces
69+###########################
70+
71+set(
72+ DBUSIFACEDIR
73+ "${CMAKE_INSTALL_DATADIR}/dbus-1/interfaces/"
74+)
75+
76+install(
77+ FILES
78+ com.canonical.Infographics.xml
79+ DESTINATION ${DBUSIFACEDIR}
80+)
81+
82+###########################
83+# Dbus Services
84+###########################
85+
86+set(
87+ DBUSSERVICEDIR
88+ "${CMAKE_INSTALL_DATADIR}/dbus-1/system-services/"
89+)
90+
91+set(INFOGRAPHICS_SERVICE
92+ "${CMAKE_CURRENT_BINARY_DIR}/com.canonical.Infographics.service"
93+)
94+
95+configure_file(
96+ "com.canonical.Infographics.service.in"
97+ ${INFOGRAPHICS_SERVICE}
98+ @ONLY
99+)
100+
101+install(
102+ FILES
103+ ${INFOGRAPHICS_SERVICE}
104+ DESTINATION ${DBUSSERVICEDIR}
105+)
106+
107+##############################
108+# Usermetrics session service
109+##############################
110+
111+configure_file(
112+ "usermetricsservice.conf.in"
113+ "${CMAKE_CURRENT_BINARY_DIR}/usermetricsservice.conf" @ONLY
114+)
115+
116+install(
117+ FILES "${CMAKE_CURRENT_BINARY_DIR}/usermetricsservice.conf"
118+ DESTINATION "${CMAKE_INSTALL_DATADIR}/upstart/sessions"
119+)
120
121=== added file 'data/com.canonical.Infographics.conf'
122--- data/com.canonical.Infographics.conf 1970-01-01 00:00:00 +0000
123+++ data/com.canonical.Infographics.conf 2014-04-03 13:02:15 +0000
124@@ -0,0 +1,15 @@
125+<!DOCTYPE busconfig PUBLIC
126+ "-//freedesktop//DTD D-BUS Bus Configuration 1.0//EN"
127+ "http://www.freedesktop.org/standards/dbus/1.0/busconfig.dtd">
128+<busconfig>
129+
130+ <policy user="usermetrics">
131+ <allow own="com.canonical.Infographics"/>
132+ </policy>
133+
134+ <policy context="default">
135+ <allow send_destination="com.canonical.Infographics"/>
136+ <allow receive_sender="com.canonical.Infographics"/>
137+ </policy>
138+
139+</busconfig>
140
141=== added file 'data/com.canonical.Infographics.service.in'
142--- data/com.canonical.Infographics.service.in 1970-01-01 00:00:00 +0000
143+++ data/com.canonical.Infographics.service.in 2014-04-03 13:02:15 +0000
144@@ -0,0 +1,5 @@
145+[D-BUS Service]
146+Name=com.canonical.Infographics
147+Exec=@CMAKE_INSTALL_FULL_LIBEXECDIR@/libusermetrics/infographicservice
148+User=usermetrics
149+StandardOutput=syslog
150
151=== added file 'data/com.canonical.Infographics.xml'
152--- data/com.canonical.Infographics.xml 1970-01-01 00:00:00 +0000
153+++ data/com.canonical.Infographics.xml 2014-04-03 13:02:15 +0000
154@@ -0,0 +1,14 @@
155+<?xml version="1.0" encoding="UTF-8"?>
156+<node name="/">
157+ <interface name="com.canonical.Infographics">
158+ <method name="update">
159+ <!-- in -->
160+ <arg type="s" name="visualizer" direction="in"/>
161+ <arg type="as" name="sources" direction="in"/>
162+ <arg type="s" name="file" direction="in"/>
163+ </method>
164+
165+ <method name="clear">
166+ </method>
167+ </interface>
168+</node>
169
170=== removed file 'data/com.canonical.UserMetrics.conf'
171--- data/com.canonical.UserMetrics.conf 2013-07-01 17:13:45 +0000
172+++ data/com.canonical.UserMetrics.conf 1970-01-01 00:00:00 +0000
173@@ -1,15 +0,0 @@
174-<!DOCTYPE busconfig PUBLIC
175- "-//freedesktop//DTD D-BUS Bus Configuration 1.0//EN"
176- "http://www.freedesktop.org/standards/dbus/1.0/busconfig.dtd">
177-<busconfig>
178-
179- <policy user="usermetrics">
180- <allow own="com.canonical.UserMetrics"/>
181- </policy>
182-
183- <policy context="default">
184- <allow send_destination="com.canonical.UserMetrics"/>
185- <allow receive_sender="com.canonical.UserMetrics"/>
186- </policy>
187-
188-</busconfig>
189\ No newline at end of file
190
191=== added file 'data/default.json.in'
192--- data/default.json.in 1970-01-01 00:00:00 +0000
193+++ data/default.json.in 2014-04-03 13:02:15 +0000
194@@ -0,0 +1,9 @@
195+{
196+ "exec": "@CMAKE_INSTALL_FULL_LIBEXECDIR@/libusermetrics/infographic",
197+ "type": "iterate",
198+ "input": {
199+ "*": [
200+ ".*.libusermetrics.json"
201+ ]
202+ }
203+}
204
205=== added file 'data/usermetricsservice.conf.in'
206--- data/usermetricsservice.conf.in 1970-01-01 00:00:00 +0000
207+++ data/usermetricsservice.conf.in 2014-04-03 13:02:15 +0000
208@@ -0,0 +1,10 @@
209+description "Service to connect infographic data sources to infographic visualizations"
210+
211+start on desktop-start
212+stop on desktop-end
213+
214+respawn
215+respawn limit 5 10
216+
217+exec @CMAKE_INSTALL_FULL_LIBEXECDIR@/libusermetrics/usermetricsservice
218+
219
220=== modified file 'debian/changelog'
221--- debian/changelog 2014-01-06 09:37:47 +0000
222+++ debian/changelog 2014-04-03 13:02:15 +0000
223@@ -1,4 +1,4 @@
224-libusermetrics (2.0.0-0ubuntu1) UNRELEASED; urgency=medium
225+libusermetrics (1.2.0-0ubuntu1) UNRELEASED; urgency=medium
226
227 * Remove the usermetrics database and store metrics in json files
228 inside the ~/.cache directory.
229
230=== modified file 'debian/control'
231--- debian/control 2014-01-06 10:08:27 +0000
232+++ debian/control 2014-04-03 13:02:15 +0000
233@@ -1,12 +1,14 @@
234 Source: libusermetrics
235 Priority: optional
236 Maintainer: Ubuntu Developers <ubuntu-devel-discuss@lists.ubuntu.com>
237-Build-Depends: cmake,
238+Build-Depends: click-dev (>= 0.2.2),
239+ cmake,
240 dbus,
241 debhelper (>= 9),
242 doxygen,
243 gettext,
244 google-mock (>= 1.6.0+svn437),
245+ libapparmor-dev,
246 libgsettings-qt-dev,
247 libgtest-dev,
248 libqt5xmlpatterns5-dev,
249
250=== modified file 'debian/libusermetricsinput1.symbols'
251--- debian/libusermetricsinput1.symbols 2014-01-06 10:00:38 +0000
252+++ debian/libusermetricsinput1.symbols 2014-04-03 13:02:15 +0000
253@@ -17,25 +17,25 @@
254 (c++)"UserMetricsInput::MetricParameters::maximum(double)@Base" 1.1.1
255 (c++)"UserMetricsInput::MetricParameters::minimum(double)@Base" 1.1.1
256 (c++)"UserMetricsInput::MetricParameters::MetricParameters(QString const&)@Base" 1.1.1
257- (c++)"UserMetricsInput::MetricParameters::MetricParameters(UserMetricsInput::MetricParameters const&)@Base" 2.0.0
258+ (c++)"UserMetricsInput::MetricParameters::MetricParameters(UserMetricsInput::MetricParameters const&)@Base" 0replaceme
259 (c++)"UserMetricsInput::MetricParameters::MetricParameters(QString const&)@Base" 1.1.1
260- (c++)"UserMetricsInput::MetricParameters::MetricParameters(UserMetricsInput::MetricParameters const&)@Base" 2.0.0
261- (c++)"UserMetricsInput::MetricParameters::~MetricParameters()@Base" 1.1.1
262- (c++)"UserMetricsInput::MetricParameters::~MetricParameters()@Base" 1.1.1
263- (c++)"UserMetricsInput::MetricParameters::~MetricParameters()@Base" 1.1.1
264- (c++)"UserMetricsInput::MetricParameters::operator=(UserMetricsInput::MetricParameters const&)@Base" 2.0.0
265- (c++)"UserMetricsInput::Metric::Metric(QObject*)@Base" 1.0.1
266- (c++)"UserMetricsInput::Metric::Metric(QObject*)@Base" 1.0.1
267- (c++)"UserMetricsInput::Metric::~Metric()@Base" 1.0.1
268- (c++)"UserMetricsInput::Metric::~Metric()@Base" 1.0.1
269- (c++)"UserMetricsInput::Metric::~Metric()@Base" 1.0.1
270- (c++)"UserMetricsInput::MetricParameters::textDomain() const@Base" 2.0.0
271- (c++)"UserMetricsInput::MetricParameters::formatString() const@Base" 2.0.0
272- (c++)"UserMetricsInput::MetricParameters::emptyDataString() const@Base" 2.0.0
273- (c++)"UserMetricsInput::MetricParameters::id() const@Base" 2.0.0
274- (c++)"UserMetricsInput::MetricParameters::type() const@Base" 2.0.0
275- (c++)"UserMetricsInput::MetricParameters::options() const@Base" 2.0.0
276- (c++)"UserMetricsInput::MetricParameters::operator==(UserMetricsInput::MetricParameters const&) const@Base" 2.0.0
277+ (c++)"UserMetricsInput::MetricParameters::MetricParameters(UserMetricsInput::MetricParameters const&)@Base" 0replaceme
278+ (c++)"UserMetricsInput::MetricParameters::~MetricParameters()@Base" 1.1.1
279+ (c++)"UserMetricsInput::MetricParameters::~MetricParameters()@Base" 1.1.1
280+ (c++)"UserMetricsInput::MetricParameters::~MetricParameters()@Base" 1.1.1
281+ (c++)"UserMetricsInput::MetricParameters::operator=(UserMetricsInput::MetricParameters const&)@Base" 0replaceme
282+ (c++)"UserMetricsInput::Metric::Metric(QObject*)@Base" 1.0.1
283+ (c++)"UserMetricsInput::Metric::Metric(QObject*)@Base" 1.0.1
284+ (c++)"UserMetricsInput::Metric::~Metric()@Base" 1.0.1
285+ (c++)"UserMetricsInput::Metric::~Metric()@Base" 1.0.1
286+ (c++)"UserMetricsInput::Metric::~Metric()@Base" 1.0.1
287+ (c++)"UserMetricsInput::MetricParameters::textDomain() const@Base" 0replaceme
288+ (c++)"UserMetricsInput::MetricParameters::formatString() const@Base" 0replaceme
289+ (c++)"UserMetricsInput::MetricParameters::emptyDataString() const@Base" 0replaceme
290+ (c++)"UserMetricsInput::MetricParameters::id() const@Base" 0replaceme
291+ (c++)"UserMetricsInput::MetricParameters::type() const@Base" 0replaceme
292+ (c++)"UserMetricsInput::MetricParameters::options() const@Base" 0replaceme
293+ (c++)"UserMetricsInput::MetricParameters::operator==(UserMetricsInput::MetricParameters const&) const@Base" 0replaceme
294 (c++)"typeinfo for UserMetricsInput::MetricUpdate@Base" 1.0.1
295 (c++)"typeinfo for UserMetricsInput::MetricManager@Base" 1.0.1
296 (c++)"typeinfo for UserMetricsInput::MetricParameters@Base" 1.1.1
297
298=== modified file 'debian/libusermetricsoutput1.symbols'
299--- debian/libusermetricsoutput1.symbols 2013-06-20 15:59:31 +0000
300+++ debian/libusermetricsoutput1.symbols 2014-04-03 13:02:15 +0000
301@@ -34,11 +34,22 @@
302 (c++)"UserMetricsOutput::UserMetrics::~UserMetrics()@Base" 1.0.1
303 (c++)"UserMetricsOutput::UserMetrics::~UserMetrics()@Base" 1.0.1
304 (c++)"UserMetricsOutput::UserMetrics::~UserMetrics()@Base" 1.0.1
305+ (c++)"UserMetricsOutput::InfographicList::uidChanged(unsigned int)@Base" 0replaceme
306+ (c++)"UserMetricsOutput::InfographicList::getInstance()@Base" 0replaceme
307+ (c++)"UserMetricsOutput::InfographicList::qt_metacall(QMetaObject::Call, int, void**)@Base" 0replaceme
308+ (c++)"UserMetricsOutput::InfographicList::qt_metacast(char const*)@Base" 0replaceme
309+ (c++)"UserMetricsOutput::InfographicList::staticMetaObject@Base" 0replaceme
310+ (c++)"UserMetricsOutput::InfographicList::InfographicList(QObject*)@Base" 0replaceme
311+ (c++)"UserMetricsOutput::InfographicList::~InfographicList()@Base" 0replaceme
312+ (c++)"UserMetricsOutput::InfographicList::metaObject() const@Base" 0replaceme
313 (c++)"UserMetricsOutput::ColorTheme::metaObject() const@Base" 1.0.1
314 (c++)"UserMetricsOutput::UserMetrics::metaObject() const@Base" 1.0.1
315 (c++)"typeinfo for UserMetricsOutput::ColorTheme@Base" 1.0.1
316 (c++)"typeinfo for UserMetricsOutput::UserMetrics@Base" 1.0.1
317 (c++)"typeinfo name for UserMetricsOutput::ColorTheme@Base" 1.0.1
318 (c++)"typeinfo name for UserMetricsOutput::UserMetrics@Base" 1.0.1
319+ (c++)"typeinfo for UserMetricsOutput::InfographicList@Base" 0replaceme
320+ (c++)"typeinfo name for UserMetricsOutput::InfographicList@Base" 0replaceme
321 (c++)"vtable for UserMetricsOutput::ColorTheme@Base" 1.0.1
322+ (c++)"vtable for UserMetricsOutput::InfographicList@Base" 0replaceme
323 (c++)"vtable for UserMetricsOutput::UserMetrics@Base" 1.0.1
324
325=== modified file 'debian/rules'
326--- debian/rules 2013-07-04 10:30:17 +0000
327+++ debian/rules 2014-04-03 13:02:15 +0000
328@@ -3,11 +3,21 @@
329
330 export DPKG_GENSYMBOLS_CHECK_LEVEL=4
331
332+ifeq ($(DEB_HOST_ARCH),armhf)
333+ ENABLE_MEMCHECK_OPTION = OFF
334+else
335+ ENABLE_MEMCHECK_OPTION = OFF
336+endif
337+
338 %:
339- dh $@ --parallel --fail-missing
340+ dh $@ --parallel --fail-missing --with click
341
342 override_dh_auto_configure:
343- dh_auto_configure -- -DBUILD_DOXYGEN=YES -DENABLE_MEMCHECK_OPTION=YES
344+ dh_auto_configure -- -DBUILD_DOXYGEN=YES -DENABLE_MEMCHECK_OPTION=${ENABLE_MEMCHECK_OPTION}
345
346 override_dh_makeshlibs:
347 dh_makeshlibs -V
348+
349+override_dh_click:
350+ dh_click --name infographic
351+ dh_click --name usermetrics
352
353=== added file 'debian/usermetricsservice.infographic.click-hook'
354--- debian/usermetricsservice.infographic.click-hook 1970-01-01 00:00:00 +0000
355+++ debian/usermetricsservice.infographic.click-hook 2014-04-03 13:02:15 +0000
356@@ -0,0 +1,3 @@
357+Pattern: ${home}/.cache/usermetrics/infographics/${id}.json
358+User-Level: yes
359+Hook-Name: infographic
360
361=== modified file 'debian/usermetricsservice.install'
362--- debian/usermetricsservice.install 2014-01-03 16:58:40 +0000
363+++ debian/usermetricsservice.install 2014-04-03 13:02:15 +0000
364@@ -1,5 +1,7 @@
365 etc
366 usr/lib/*/libusermetrics
367+usr/share/dbus-1
368 usr/share/glib-2.0
369 usr/share/libusermetrics
370 usr/share/locale
371+usr/share/upstart
372
373=== added file 'debian/usermetricsservice.postinst'
374--- debian/usermetricsservice.postinst 1970-01-01 00:00:00 +0000
375+++ debian/usermetricsservice.postinst 2014-04-03 13:02:15 +0000
376@@ -0,0 +1,16 @@
377+#!/bin/sh
378+
379+set -e
380+
381+. /usr/share/debconf/confmodule
382+
383+dbus-send --system --print-reply \
384+ --dest=org.freedesktop.DBus \
385+ /org/freedesktop/DBus \
386+ org.freedesktop.DBus.StartServiceByName \
387+ string:"com.canonical.Infographics" uint32:0 \
388+ || true
389+
390+#DEBHELPER#
391+
392+exit 0
393
394=== added file 'debian/usermetricsservice.postrm'
395--- debian/usermetricsservice.postrm 1970-01-01 00:00:00 +0000
396+++ debian/usermetricsservice.postrm 2014-04-03 13:02:15 +0000
397@@ -0,0 +1,26 @@
398+#!/bin/sh
399+set -e
400+
401+if [ "$1" = "purge" ] ; then
402+ if getent passwd usermetrics >/dev/null; then
403+ if [ -x /usr/sbin/deluser ]; then
404+ deluser --system usermetrics
405+ fi
406+ fi
407+
408+ if getent group usermetrics >/dev/null; then
409+ if [ -x /usr/sbin/delgroup ]; then
410+ delgroup --system usermetrics
411+ fi
412+ fi
413+
414+ # we cannot use the --remove-home option when we delete the user above
415+ # because it will refuse to remove things in /var, so clean it up this
416+ # way
417+ if [ -d /var/lib/usermetrics ]; then
418+ rm -r /var/lib/usermetrics
419+ fi
420+
421+fi
422+#DEBHELPER#
423+exit 0
424
425=== added file 'debian/usermetricsservice.preinst'
426--- debian/usermetricsservice.preinst 1970-01-01 00:00:00 +0000
427+++ debian/usermetricsservice.preinst 2014-04-03 13:02:15 +0000
428@@ -0,0 +1,30 @@
429+#!/bin/sh
430+
431+set -e
432+
433+. /usr/share/debconf/confmodule
434+
435+THIS_PACKAGE=usermetricsservice
436+
437+# creating usermetrics group if he isn't already there
438+if ! getent group usermetrics >/dev/null; then
439+ addgroup --system usermetrics
440+fi
441+
442+# creating usermetrics user if he isn't already there
443+if ! getent passwd usermetrics >/dev/null; then
444+ adduser --system --ingroup usermetrics --home /var/lib/usermetrics usermetrics
445+ usermod -c "User Metrics" usermetrics
446+ usermod -d "/var/lib/usermetrics" usermetrics
447+ usermod -g "usermetrics" usermetrics
448+ usermod -s "/bin/false" usermetrics
449+fi
450+
451+if [ -d /var/lib/usermetrics ]; then
452+ chown -R usermetrics:usermetrics /var/lib/usermetrics
453+ chmod 0755 /var/lib/usermetrics
454+fi
455+
456+#DEBHELPER#
457+
458+exit 0
459
460=== added file 'debian/usermetricsservice.prerm'
461--- debian/usermetricsservice.prerm 1970-01-01 00:00:00 +0000
462+++ debian/usermetricsservice.prerm 2014-04-03 13:02:15 +0000
463@@ -0,0 +1,7 @@
464+#!/bin/sh
465+
466+set -e
467+
468+pkill -U usermetrics 2>/dev/null || true
469+
470+#DEBHELPER#
471\ No newline at end of file
472
473=== added file 'debian/usermetricsservice.usermetrics.click-hook'
474--- debian/usermetricsservice.usermetrics.click-hook 1970-01-01 00:00:00 +0000
475+++ debian/usermetricsservice.usermetrics.click-hook 2014-04-03 13:02:15 +0000
476@@ -0,0 +1,3 @@
477+Pattern: ${home}/.cache/usermetrics/sources/${id}.json
478+User-Level: yes
479+Hook-Name: usermetrics
480
481=== added file 'doc/Infographic Architecture.svg'
482--- doc/Infographic Architecture.svg 1970-01-01 00:00:00 +0000
483+++ doc/Infographic Architecture.svg 2014-04-03 13:02:15 +0000
484@@ -0,0 +1,636 @@
485+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
486+<!-- Created with Inkscape (http://www.inkscape.org/) -->
487+
488+<svg
489+ xmlns:dc="http://purl.org/dc/elements/1.1/"
490+ xmlns:cc="http://creativecommons.org/ns#"
491+ xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
492+ xmlns:svg="http://www.w3.org/2000/svg"
493+ xmlns="http://www.w3.org/2000/svg"
494+ xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
495+ xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
496+ width="671.98975"
497+ height="413.13217"
498+ id="svg2"
499+ version="1.1"
500+ inkscape:version="0.48.4 r9939"
501+ sodipodi:docname="infographics version 2.svg">
502+ <defs
503+ id="defs4">
504+ <inkscape:path-effect
505+ effect="spiro"
506+ id="path-effect4676"
507+ is_visible="true" />
508+ <marker
509+ inkscape:stockid="Arrow1Mend"
510+ orient="auto"
511+ refY="0"
512+ refX="0"
513+ id="Arrow1Mend"
514+ style="overflow:visible">
515+ <path
516+ id="path3951"
517+ d="M 0,0 5,-5 -12.5,0 5,5 0,0 z"
518+ style="fill-rule:evenodd;stroke:#000000;stroke-width:1pt"
519+ transform="matrix(-0.4,0,0,-0.4,-4,0)"
520+ inkscape:connector-curvature="0" />
521+ </marker>
522+ <marker
523+ inkscape:stockid="Arrow1Mend"
524+ orient="auto"
525+ refY="0"
526+ refX="0"
527+ id="Arrow1Mend-3"
528+ style="overflow:visible">
529+ <path
530+ inkscape:connector-curvature="0"
531+ id="path3951-3"
532+ d="M 0,0 5,-5 -12.5,0 5,5 0,0 z"
533+ style="fill-rule:evenodd;stroke:#000000;stroke-width:1pt"
534+ transform="matrix(-0.4,0,0,-0.4,-4,0)" />
535+ </marker>
536+ <marker
537+ inkscape:stockid="Arrow1Mend"
538+ orient="auto"
539+ refY="0"
540+ refX="0"
541+ id="Arrow1Mend-3-5"
542+ style="overflow:visible">
543+ <path
544+ inkscape:connector-curvature="0"
545+ id="path3951-3-8"
546+ d="M 0,0 5,-5 -12.5,0 5,5 0,0 z"
547+ style="fill-rule:evenodd;stroke:#000000;stroke-width:1pt"
548+ transform="matrix(-0.4,0,0,-0.4,-4,0)" />
549+ </marker>
550+ <inkscape:path-effect
551+ effect="spiro"
552+ id="path-effect4676-5"
553+ is_visible="true" />
554+ <marker
555+ inkscape:stockid="Arrow1Mend"
556+ orient="auto"
557+ refY="0"
558+ refX="0"
559+ id="Arrow1Mend-3-7"
560+ style="overflow:visible">
561+ <path
562+ inkscape:connector-curvature="0"
563+ id="path3951-3-2"
564+ d="M 0,0 5,-5 -12.5,0 5,5 0,0 z"
565+ style="fill-rule:evenodd;stroke:#000000;stroke-width:1pt"
566+ transform="matrix(-0.4,0,0,-0.4,-4,0)" />
567+ </marker>
568+ <marker
569+ inkscape:stockid="Arrow1Mend"
570+ orient="auto"
571+ refY="0"
572+ refX="0"
573+ id="Arrow1Mend-3-1"
574+ style="overflow:visible">
575+ <path
576+ inkscape:connector-curvature="0"
577+ id="path3951-3-5"
578+ d="M 0,0 5,-5 -12.5,0 5,5 0,0 z"
579+ style="fill-rule:evenodd;stroke:#000000;stroke-width:1pt"
580+ transform="matrix(-0.4,0,0,-0.4,-4,0)" />
581+ </marker>
582+ <marker
583+ inkscape:stockid="Arrow1Mend"
584+ orient="auto"
585+ refY="0"
586+ refX="0"
587+ id="Arrow1Mend-3-3"
588+ style="overflow:visible">
589+ <path
590+ inkscape:connector-curvature="0"
591+ id="path3951-3-4"
592+ d="M 0,0 5,-5 -12.5,0 5,5 0,0 z"
593+ style="fill-rule:evenodd;stroke:#000000;stroke-width:1pt"
594+ transform="matrix(-0.4,0,0,-0.4,-4,0)" />
595+ </marker>
596+ <marker
597+ inkscape:stockid="Arrow1Mend"
598+ orient="auto"
599+ refY="0"
600+ refX="0"
601+ id="Arrow1Mend-3-2"
602+ style="overflow:visible">
603+ <path
604+ inkscape:connector-curvature="0"
605+ id="path3951-3-80"
606+ d="M 0,0 5,-5 -12.5,0 5,5 0,0 z"
607+ style="fill-rule:evenodd;stroke:#000000;stroke-width:1pt"
608+ transform="matrix(-0.4,0,0,-0.4,-4,0)" />
609+ </marker>
610+ <marker
611+ inkscape:stockid="Arrow1Mend"
612+ orient="auto"
613+ refY="0"
614+ refX="0"
615+ id="Arrow1Mend-3-9"
616+ style="overflow:visible">
617+ <path
618+ inkscape:connector-curvature="0"
619+ id="path3951-3-1"
620+ d="M 0,0 5,-5 -12.5,0 5,5 0,0 z"
621+ style="fill-rule:evenodd;stroke:#000000;stroke-width:1pt"
622+ transform="matrix(-0.4,0,0,-0.4,-4,0)" />
623+ </marker>
624+ <marker
625+ inkscape:stockid="Arrow1Mend"
626+ orient="auto"
627+ refY="0"
628+ refX="0"
629+ id="Arrow1Mend-3-19"
630+ style="overflow:visible">
631+ <path
632+ inkscape:connector-curvature="0"
633+ id="path3951-3-3"
634+ d="M 0,0 5,-5 -12.5,0 5,5 0,0 z"
635+ style="fill-rule:evenodd;stroke:#000000;stroke-width:1pt"
636+ transform="matrix(-0.4,0,0,-0.4,-4,0)" />
637+ </marker>
638+ <marker
639+ inkscape:stockid="Arrow1Mend"
640+ orient="auto"
641+ refY="0"
642+ refX="0"
643+ id="Arrow1Mend-3-24"
644+ style="overflow:visible">
645+ <path
646+ inkscape:connector-curvature="0"
647+ id="path3951-3-7"
648+ d="M 0,0 5,-5 -12.5,0 5,5 0,0 z"
649+ style="fill-rule:evenodd;stroke:#000000;stroke-width:1pt"
650+ transform="matrix(-0.4,0,0,-0.4,-4,0)" />
651+ </marker>
652+ <inkscape:path-effect
653+ effect="spiro"
654+ id="path-effect4676-6"
655+ is_visible="true" />
656+ </defs>
657+ <sodipodi:namedview
658+ id="base"
659+ pagecolor="#ffffff"
660+ bordercolor="#666666"
661+ borderopacity="1.0"
662+ inkscape:pageopacity="0.0"
663+ inkscape:pageshadow="2"
664+ inkscape:zoom="1.7277049"
665+ inkscape:cx="335.99487"
666+ inkscape:cy="206.56609"
667+ inkscape:document-units="px"
668+ inkscape:current-layer="layer1"
669+ showgrid="false"
670+ showguides="false"
671+ inkscape:window-width="1680"
672+ inkscape:window-height="1026"
673+ inkscape:window-x="0"
674+ inkscape:window-y="24"
675+ inkscape:window-maximized="1"
676+ fit-margin-top="20"
677+ fit-margin-left="20"
678+ fit-margin-right="20"
679+ fit-margin-bottom="20" />
680+ <metadata
681+ id="metadata7">
682+ <rdf:RDF>
683+ <cc:Work
684+ rdf:about="">
685+ <dc:format>image/svg+xml</dc:format>
686+ <dc:type
687+ rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
688+ <dc:title />
689+ </cc:Work>
690+ </rdf:RDF>
691+ </metadata>
692+ <g
693+ inkscape:label="Layer 1"
694+ inkscape:groupmode="layer"
695+ id="layer1"
696+ transform="translate(9.1737344,-608.13043)">
697+ <g
698+ id="g3761"
699+ transform="translate(9.0102463,20.5802)">
700+ <rect
701+ transform="translate(0,572.36218)"
702+ y="170.37543"
703+ x="244.09557"
704+ height="78.088745"
705+ width="133.78838"
706+ id="rect2985"
707+ style="color:#000000;fill:none;stroke:#000000;stroke-width:1;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate" />
708+ <text
709+ sodipodi:linespacing="100%"
710+ id="text3755"
711+ y="778.51001"
712+ x="310.46051"
713+ style="font-size:16px;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;text-align:center;line-height:100%;letter-spacing:0px;word-spacing:0px;writing-mode:lr-tb;text-anchor:middle;fill:#000000;fill-opacity:1;stroke:none;font-family:Ubuntu;-inkscape-font-specification:Ubuntu"
714+ xml:space="preserve"><tspan
715+ y="778.51001"
716+ x="310.46051"
717+ id="tspan3757"
718+ sodipodi:role="line">Infographic</tspan><tspan
719+ id="tspan3759"
720+ y="794.51001"
721+ x="310.46051"
722+ sodipodi:role="line">Helper</tspan></text>
723+ </g>
724+ <g
725+ id="g3803"
726+ transform="translate(-8.12897,0)">
727+ <rect
728+ style="color:#000000;fill:none;stroke:#000000;stroke-width:1;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
729+ id="rect3767"
730+ width="159.58728"
731+ height="87.497849"
732+ x="430.33533"
733+ y="56.268272"
734+ transform="translate(0,572.36218)" />
735+ <text
736+ xml:space="preserve"
737+ style="font-size:16px;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;text-align:start;line-height:100%;letter-spacing:0px;word-spacing:0px;writing-mode:lr-tb;text-anchor:start;fill:#000000;fill-opacity:1;stroke:none;font-family:Ubuntu;-inkscape-font-specification:Ubuntu"
738+ x="436.38864"
739+ y="677.60724"
740+ id="text3769"
741+ sodipodi:linespacing="100%"><tspan
742+ sodipodi:role="line"
743+ id="tspan3771"
744+ x="436.38864"
745+ y="677.60724"
746+ style="font-size:14px"
747+ dy="-4.9527082">Infographic Source</tspan><tspan
748+ sodipodi:role="line"
749+ x="436.38864"
750+ y="691.60724"
751+ id="tspan3773"
752+ style="font-size:14px"><tspan
753+ style="font-size:14px;font-weight:bold"
754+ id="tspan3777"
755+ dy="-0.55030096">type:</tspan> foo</tspan><tspan
756+ sodipodi:role="line"
757+ x="436.38864"
758+ y="705.60724"
759+ id="tspan3775"
760+ dx="0 0 0 0 0 0 0 0 0 0 -1.1006019"
761+ style="font-size:14px"><tspan
762+ style="font-size:14px;font-weight:bold"
763+ id="tspan3779">file:</tspan> infographic.foo</tspan></text>
764+ <rect
765+ style="color:#000000;fill:#000000;fill-opacity:1;stroke:#000000;stroke-width:1;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
766+ id="rect3767-6"
767+ width="159.03699"
768+ height="26.414476"
769+ x="430.33533"
770+ y="628.63043" />
771+ <text
772+ xml:space="preserve"
773+ style="font-size:16px;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;text-align:start;line-height:100%;letter-spacing:0px;word-spacing:0px;writing-mode:lr-tb;text-anchor:start;fill:#ffffff;fill-opacity:1;stroke:none;font-family:Ubuntu;-inkscape-font-specification:Ubuntu"
774+ x="442.82819"
775+ y="647.92566"
776+ id="text3799"
777+ sodipodi:linespacing="100%"><tspan
778+ sodipodi:role="line"
779+ id="tspan3801"
780+ x="442.82819"
781+ y="647.92566">Foo Click Manifest</tspan></text>
782+ </g>
783+ <g
784+ id="g3918"
785+ transform="translate(-360,-2.1289061e-6)">
786+ <rect
787+ y="628.63043"
788+ x="418.20636"
789+ height="87.497849"
790+ width="159.58728"
791+ id="rect3767-7"
792+ style="color:#000000;fill:none;stroke:#000000;stroke-width:1;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate" />
793+ <text
794+ sodipodi:linespacing="100%"
795+ id="text3769-5"
796+ y="677.60724"
797+ x="424.25967"
798+ style="font-size:16px;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;text-align:start;line-height:100%;letter-spacing:0px;word-spacing:0px;writing-mode:lr-tb;text-anchor:start;fill:#000000;fill-opacity:1;stroke:none;font-family:Ubuntu;-inkscape-font-specification:Ubuntu"
799+ xml:space="preserve"><tspan
800+ dy="-4.9527082"
801+ style="font-size:14px"
802+ y="677.60724"
803+ x="424.25967"
804+ id="tspan3771-4"
805+ sodipodi:role="line">Infographic Sink</tspan><tspan
806+ style="font-size:14px"
807+ id="tspan3773-2"
808+ y="691.60724"
809+ x="424.25967"
810+ sodipodi:role="line"><tspan
811+ dy="-0.55030096"
812+ id="tspan3777-3"
813+ style="font-size:14px;font-weight:bold">type:</tspan> foo</tspan><tspan
814+ style="font-size:14px"
815+ dx="0 0 0 0 0 0 0 0 0 0 -1.1006019"
816+ id="tspan3775-4"
817+ y="705.60724"
818+ x="424.25967"
819+ sodipodi:role="line"><tspan
820+ id="tspan3779-2"
821+ style="font-size:14px;font-weight:bold">file:</tspan> infographic.svg</tspan></text>
822+ <rect
823+ y="628.63043"
824+ x="418.20636"
825+ height="26.414476"
826+ width="159.03699"
827+ id="rect3767-6-7"
828+ style="color:#000000;fill:#000000;fill-opacity:1;stroke:#000000;stroke-width:1;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate" />
829+ <text
830+ sodipodi:linespacing="100%"
831+ id="text3799-8"
832+ y="647.92566"
833+ x="431.91797"
834+ style="font-size:16px;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;text-align:start;line-height:100%;letter-spacing:0px;word-spacing:0px;writing-mode:lr-tb;text-anchor:start;fill:#ffffff;fill-opacity:1;stroke:none;font-family:Ubuntu;-inkscape-font-specification:Ubuntu"
835+ xml:space="preserve"><tspan
836+ y="647.92566"
837+ x="431.91797"
838+ id="tspan3801-6"
839+ sodipodi:role="line">Bar Click Manifest</tspan></text>
840+ </g>
841+ <text
842+ sodipodi:linespacing="100%"
843+ id="text3930"
844+ y="701.8205"
845+ x="319.61853"
846+ style="font-size:16px;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;text-align:center;line-height:100%;letter-spacing:0px;word-spacing:0px;writing-mode:lr-tb;text-anchor:middle;fill:#000000;fill-opacity:1;stroke:none;font-family:Ubuntu;-inkscape-font-specification:Ubuntu"
847+ xml:space="preserve"><tspan
848+ y="701.8205"
849+ x="319.61853"
850+ id="tspan3932"
851+ sodipodi:role="line">Install</tspan><tspan
852+ id="tspan3934"
853+ y="717.8205"
854+ x="319.61853"
855+ sodipodi:role="line">Hooks</tspan></text>
856+ <path
857+ inkscape:connector-curvature="0"
858+ id="path3936"
859+ d="m 226.17369,685.31145 c 45.12468,-1.1006 52.27859,36.31986 52.82889,67.13671"
860+ style="fill:none;stroke:#000000;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;marker-end:url(#Arrow1Mend)" />
861+ <path
862+ inkscape:connector-curvature="0"
863+ id="path3936-1"
864+ d="m 414.31778,685.49855 c -45.12468,-1.10061 -52.27859,36.31985 -52.82889,67.13671"
865+ style="fill:none;stroke:#000000;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;marker-end:url(#Arrow1Mend)" />
866+ <g
867+ id="g4893">
868+ <rect
869+ style="color:#000000;fill:#ffffff;fill-opacity:1;fill-rule:nonzero;stroke:#000000;stroke-width:5;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
870+ id="rect4425"
871+ width="95.752365"
872+ height="95.752365"
873+ x="441.74377"
874+ y="751.89789" />
875+ <text
876+ xml:space="preserve"
877+ style="font-size:16px;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;text-align:center;line-height:100%;letter-spacing:0px;word-spacing:0px;writing-mode:lr-tb;text-anchor:middle;fill:#000000;fill-opacity:1;stroke:none;font-family:Ubuntu;-inkscape-font-specification:Ubuntu"
878+ x="489.69073"
879+ y="796.50208"
880+ id="text4427"
881+ sodipodi:linespacing="100%"><tspan
882+ sodipodi:role="line"
883+ id="tspan4429"
884+ x="489.69073"
885+ y="796.50208">foo</tspan><tspan
886+ sodipodi:role="line"
887+ x="489.69073"
888+ y="812.50208"
889+ id="tspan4431">app</tspan></text>
890+ </g>
891+ <g
892+ id="g4469"
893+ transform="translate(-13.207223,24.763543)">
894+ <rect
895+ y="887.29889"
896+ x="403.61313"
897+ height="35.715553"
898+ width="192.67056"
899+ id="rect2985-1"
900+ style="color:#000000;fill:none;stroke:#000000;stroke-width:1;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate" />
901+ <text
902+ sodipodi:linespacing="100%"
903+ id="text3755-5"
904+ y="908.72668"
905+ x="500.00146"
906+ style="font-size:12px;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;text-align:center;line-height:100%;letter-spacing:0px;word-spacing:0px;writing-mode:lr-tb;text-anchor:middle;fill:#000000;fill-opacity:1;stroke:none;font-family:Ubuntu;-inkscape-font-specification:Ubuntu"
907+ xml:space="preserve"><tspan
908+ id="tspan3759-8"
909+ y="908.72668"
910+ x="500.00146"
911+ sodipodi:role="line">~/.cache/$(appid)/infographic.foo</tspan></text>
912+ </g>
913+ <path
914+ style="fill:none;stroke:#000000;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;marker-end:url(#Arrow1Mend-3)"
915+ d="M 383.55976,356.18229 C 353.84351,354.53139 348.8908,331.96904 347.7902,280.79106"
916+ id="path4474"
917+ inkscape:connector-curvature="0"
918+ transform="translate(0,572.36218)"
919+ sodipodi:nodetypes="cc" />
920+ <text
921+ xml:space="preserve"
922+ style="font-size:14px;font-style:italic;font-variant:normal;font-weight:normal;font-stretch:normal;text-align:start;line-height:100%;letter-spacing:0px;word-spacing:0px;writing-mode:lr-tb;text-anchor:start;fill:#000000;fill-opacity:1;stroke:none;font-family:Ubuntu;-inkscape-font-specification:Ubuntu Italic"
923+ x="361.54773"
924+ y="876.81616"
925+ id="text4660"
926+ sodipodi:linespacing="100%"><tspan
927+ sodipodi:role="line"
928+ id="tspan4662"
929+ x="361.54773"
930+ y="876.81616">File</tspan><tspan
931+ sodipodi:role="line"
932+ x="361.54773"
933+ y="890.81616"
934+ id="tspan4664">Watch</tspan></text>
935+ <text
936+ xml:space="preserve"
937+ style="font-size:12px;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;text-align:start;line-height:112.00000047999999708%;letter-spacing:0px;word-spacing:0px;writing-mode:lr-tb;text-anchor:start;fill:#000000;fill-opacity:1;stroke:none;font-family:Ubuntu;-inkscape-font-specification:Ubuntu;opacity:0.75"
938+ x="571.7627"
939+ y="755.19965"
940+ id="text4666"
941+ sodipodi:linespacing="112%"><tspan
942+ sodipodi:role="line"
943+ id="tspan4668"
944+ x="571.7627"
945+ y="755.19965">Foo</tspan><tspan
946+ sodipodi:role="line"
947+ x="571.7627"
948+ y="768.63965"
949+ id="tspan4670">AppArmor</tspan><tspan
950+ sodipodi:role="line"
951+ x="571.7627"
952+ y="782.07965"
953+ id="tspan4672">Confinement</tspan></text>
954+ <path
955+ style="opacity:0.75;fill:none;stroke:#000000;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;marker-end:url(#Arrow1Mend-3)"
956+ d="m 567.36028,192.74291 c -2.53774,-0.0622 -5.08926,0.61223 -7.26478,1.92031 -0.81305,0.48887 -1.57239,1.06245 -2.381,1.55863 -0.8086,0.49619 -1.68153,0.91914 -2.61893,1.06514 -1.39269,0.2169 -2.80076,-0.19097 -4.13805,-0.63627 -1.33729,-0.44531 -2.69883,-0.93906 -4.10774,-0.89876 -1.25072,0.0358 -2.44503,0.49048 -3.65682,0.80213 -0.33784,0.0869 -0.67847,0.16288 -1.0212,0.22784"
957+ id="path4674"
958+ inkscape:path-effect="#path-effect4676"
959+ inkscape:original-d="m 567.36028,192.74291 c -2.05099,4.0056 -2.57986,1.777 -7.26478,1.92031 -10.78275,0 -8.1675,12.44489 -4.99993,2.62377 3.3427,-11.96353 -5.33958,-3.07508 -8.24579,-1.53503 -2.9062,1.54005 -3.37007,1.24208 -3.65682,0.80213 -0.28674,-0.43995 -0.39635,-1.02187 -1.0212,0.22784"
960+ inkscape:connector-curvature="0"
961+ transform="translate(0,572.36218)"
962+ sodipodi:nodetypes="ccczsc" />
963+ <g
964+ transform="translate(-341.88525,60.753484)"
965+ id="g4893-5">
966+ <rect
967+ style="color:#000000;fill:#ffffff;fill-opacity:1;fill-rule:nonzero;stroke:#000000;stroke-width:5;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
968+ id="rect4425-0"
969+ width="95.752365"
970+ height="95.752365"
971+ x="441.74377"
972+ y="751.89789" />
973+ <text
974+ xml:space="preserve"
975+ style="font-size:16px;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;text-align:center;line-height:100%;letter-spacing:0px;word-spacing:0px;writing-mode:lr-tb;text-anchor:middle;fill:#000000;fill-opacity:1;stroke:none;font-family:Ubuntu;-inkscape-font-specification:Ubuntu"
976+ x="489.69073"
977+ y="796.50208"
978+ id="text4427-5"
979+ sodipodi:linespacing="100%"><tspan
980+ sodipodi:role="line"
981+ id="tspan4429-8"
982+ x="489.69073"
983+ y="796.50208">bar</tspan><tspan
984+ sodipodi:role="line"
985+ x="489.69073"
986+ y="812.50208"
987+ id="tspan4929">visual</tspan></text>
988+ </g>
989+ <text
990+ xml:space="preserve"
991+ style="font-size:12px;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;text-align:start;line-height:112.00000047999999708%;letter-spacing:0px;word-spacing:0px;writing-mode:lr-tb;text-anchor:start;fill:#000000;fill-opacity:1;stroke:none;font-family:Ubuntu;-inkscape-font-specification:Ubuntu;opacity:0.75"
992+ x="10.730266"
993+ y="836.82312"
994+ id="text4666-3"
995+ sodipodi:linespacing="112%"><tspan
996+ sodipodi:role="line"
997+ id="tspan4668-4"
998+ x="10.730266"
999+ y="836.82312">Bar</tspan><tspan
1000+ sodipodi:role="line"
1001+ x="10.730266"
1002+ y="850.26312"
1003+ id="tspan4670-0">AppArmor</tspan><tspan
1004+ sodipodi:role="line"
1005+ x="10.730266"
1006+ y="863.70312"
1007+ id="tspan4672-9">Confinement</tspan></text>
1008+ <path
1009+ style="color:#000000;fill:none;stroke:#000000;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0;marker:none;marker-end:url(#Arrow1Mend-3);visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
1010+ d="m 118.51852,723.61908 c 0,0 0,-0.55125 0,78.82859"
1011+ id="path4987"
1012+ inkscape:connector-curvature="0" />
1013+ <path
1014+ style="color:#000000;fill:none;stroke:#000000;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0;marker:none;marker-end:url(#Arrow1Mend-3);visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
1015+ d="m 490.06029,150.90439 c 0,22.60121 0,22.60121 0,22.60121"
1016+ id="path4989"
1017+ inkscape:connector-curvature="0"
1018+ transform="translate(0,572.36218)" />
1019+ <path
1020+ style="color:#000000;fill:none;stroke:#000000;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0;marker:none;marker-end:url(#Arrow1Mend-3);visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
1021+ d="m 466.90784,282.65289 c 0,47.95865 0,47.95865 0,47.95865"
1022+ id="path4991"
1023+ inkscape:connector-curvature="0"
1024+ transform="translate(0,572.36218)" />
1025+ <path
1026+ style="color:#000000;fill:none;stroke:#000000;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0;marker:none;marker-end:url(#Arrow1Mend-3);visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
1027+ d="m 206.1671,306.90784 c 36.38243,1.1025 65.04737,-4.40999 65.59862,-28.1137"
1028+ id="path4993"
1029+ inkscape:connector-curvature="0"
1030+ transform="translate(0,572.36218)" />
1031+ <path
1032+ style="color:#000000;fill:none;stroke:#000000;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0;marker:none;marker-end:url(#Arrow1Mend-3);visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
1033+ d="m 245.30577,201.06804 c -47.89942,-1.36388 -68.53183,-2.05014 -70.55986,30.3187"
1034+ id="path4995"
1035+ inkscape:connector-curvature="0"
1036+ transform="translate(0,572.36218)"
1037+ sodipodi:nodetypes="cc" />
1038+ <text
1039+ xml:space="preserve"
1040+ style="font-size:14px;font-style:italic;font-variant:normal;font-weight:normal;font-stretch:normal;text-align:start;line-height:100%;letter-spacing:0px;word-spacing:0px;writing-mode:lr-tb;text-anchor:start;fill:#000000;fill-opacity:1;stroke:none;font-family:Ubuntu;-inkscape-font-specification:Ubuntu Italic"
1041+ x="478.94144"
1042+ y="875.39905"
1043+ id="text4660-6"
1044+ sodipodi:linespacing="100%"><tspan
1045+ sodipodi:role="line"
1046+ x="478.94144"
1047+ y="875.39905"
1048+ id="tspan4664-5">Write</tspan><tspan
1049+ sodipodi:role="line"
1050+ x="478.94144"
1051+ y="889.39905"
1052+ id="tspan5086">Data</tspan></text>
1053+ <text
1054+ xml:space="preserve"
1055+ style="font-size:14px;font-style:italic;font-variant:normal;font-weight:normal;font-stretch:normal;text-align:start;line-height:100%;letter-spacing:0px;word-spacing:0px;writing-mode:lr-tb;text-anchor:start;fill:#000000;fill-opacity:1;stroke:none;font-family:Ubuntu;-inkscape-font-specification:Ubuntu Italic"
1056+ x="150.39708"
1057+ y="756.32922"
1058+ id="text4660-8"
1059+ sodipodi:linespacing="100%"><tspan
1060+ sodipodi:role="line"
1061+ id="tspan4662-9"
1062+ x="150.39708"
1063+ y="756.32922">Foo Type</tspan><tspan
1064+ sodipodi:role="line"
1065+ x="150.39708"
1066+ y="770.32922"
1067+ id="tspan4664-51">Data</tspan></text>
1068+ <text
1069+ xml:space="preserve"
1070+ style="font-size:14px;font-style:italic;font-variant:normal;font-weight:normal;font-stretch:normal;text-align:start;line-height:100%;letter-spacing:0px;word-spacing:0px;writing-mode:lr-tb;text-anchor:start;fill:#000000;fill-opacity:1;stroke:none;font-family:Ubuntu;-inkscape-font-specification:Ubuntu Italic"
1071+ x="228.12317"
1072+ y="896.3465"
1073+ id="text4660-5"
1074+ sodipodi:linespacing="100%"><tspan
1075+ sodipodi:role="line"
1076+ id="tspan4662-2"
1077+ x="228.12317"
1078+ y="896.3465">SVG</tspan><tspan
1079+ sodipodi:role="line"
1080+ x="228.12317"
1081+ y="910.3465"
1082+ id="tspan4664-2">Data</tspan></text>
1083+ <g
1084+ id="g4469-4"
1085+ transform="translate(-216.05521,77.196901)">
1086+ <rect
1087+ y="887.29889"
1088+ x="403.61313"
1089+ height="36.266827"
1090+ width="263.23044"
1091+ id="rect2985-1-7"
1092+ style="color:#000000;fill:none;stroke:#000000;stroke-width:1;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate" />
1093+ <text
1094+ sodipodi:linespacing="100%"
1095+ id="text3755-5-0"
1096+ y="908.72668"
1097+ x="535.85309"
1098+ style="font-size:12px;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;text-align:center;line-height:100%;letter-spacing:0px;word-spacing:0px;writing-mode:lr-tb;text-anchor:middle;fill:#000000;fill-opacity:1;stroke:none;font-family:Ubuntu;-inkscape-font-specification:Ubuntu"
1099+ xml:space="preserve"><tspan
1100+ id="tspan3759-8-1"
1101+ y="908.72668"
1102+ x="535.85309"
1103+ sodipodi:role="line">/var/cache/infographic/$(user)/bar-foo.svg</tspan></text>
1104+ </g>
1105+ <path
1106+ style="color:#000000;fill:none;stroke:#000000;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0;marker:none;marker-end:url(#Arrow1Mend-3);visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
1107+ d="m 311.45565,849.40321 c 0,0 0,25.44875 0,104.82859"
1108+ id="path4987-1"
1109+ inkscape:connector-curvature="0"
1110+ sodipodi:nodetypes="cc" />
1111+ <path
1112+ style="opacity:0.75;fill:none;stroke:#000000;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;marker-end:url(#Arrow1Mend-3)"
1113+ d="m 70.370939,844.37253 c 2.166628,-1.32276 4.713537,-2.01444 7.251636,-1.96937 0.948556,0.0168 1.892954,0.13391 2.84132,0.15932 0.948365,0.0254 1.915816,-0.0448 2.800631,-0.38703 1.314563,-0.5085 2.330053,-1.56575 3.265528,-2.62004 0.935476,-1.0543 1.867729,-2.16266 3.108022,-2.83223 1.101035,-0.59439 2.362684,-0.79778 3.567965,-1.13375 0.336018,-0.0937 0.669019,-0.19815 0.998313,-0.31325"
1114+ id="path4674-2"
1115+ inkscape:path-effect="#path-effect4676-6"
1116+ inkscape:original-d="m 70.370939,844.37253 c 3.779008,2.44344 3.122725,0.24899 7.251636,-1.96937 9.338135,-5.39137 13.295708,6.69384 5.641951,-0.22771 -8.876629,-8.68938 3.086675,-5.33288 6.37355,-5.45227 3.286867,-0.11938 3.539607,-0.60936 3.567965,-1.13375 0.02835,-0.52438 -0.167688,-1.08314 0.998313,-0.31325"
1117+ inkscape:connector-curvature="0"
1118+ sodipodi:nodetypes="ccczsc" />
1119+ </g>
1120+</svg>
1121
1122=== added symlink 'include/libusermetricsoutput/InfographicList.h'
1123=== target is u'../../src/libusermetricsoutput/InfographicList.h'
1124=== modified file 'po/en_GB.po'
1125--- po/en_GB.po 2014-01-09 10:17:16 +0000
1126+++ po/en_GB.po 2014-04-03 13:02:15 +0000
1127@@ -7,7 +7,7 @@
1128 msgstr ""
1129 "Project-Id-Version: libusermetrics\n"
1130 "Report-Msgid-Bugs-To: \n"
1131-"POT-Creation-Date: 2014-01-09 10:15+0000\n"
1132+"POT-Creation-Date: 2014-02-19 16:51+0000\n"
1133 "PO-Revision-Date: 2013-07-05 15:09+0100\n"
1134 "Last-Translator: Pete Woods <pete.woods@canonical.com>\n"
1135 "Language-Team: British English <en@li.org>\n"
1136@@ -90,6 +90,10 @@
1137 #~ msgid "Attempt to update data owned by another user"
1138 #~ msgstr "Attempt to update data owned by another user"
1139
1140+#, fuzzy
1141+#~ msgid "Could not locate user data"
1142+#~ msgstr "Couldn't save user data"
1143+
1144 #~ msgid "Could not open database"
1145 #~ msgstr "Could not open database"
1146
1147@@ -102,9 +106,6 @@
1148 #~ msgid "Could not save data source"
1149 #~ msgstr "Couldn't save data source"
1150
1151-#~ msgid "Could not save user data"
1152-#~ msgstr "Couldn't save user data"
1153-
1154 #~ msgid "Data set query failed"
1155 #~ msgstr "Data set query failed"
1156
1157
1158=== modified file 'po/libusermetrics.pot'
1159--- po/libusermetrics.pot 2014-01-09 10:17:16 +0000
1160+++ po/libusermetrics.pot 2014-04-03 13:02:15 +0000
1161@@ -8,7 +8,7 @@
1162 msgstr ""
1163 "Project-Id-Version: libusermetrics\n"
1164 "Report-Msgid-Bugs-To: \n"
1165-"POT-Creation-Date: 2014-01-09 10:15+0000\n"
1166+"POT-Creation-Date: 2014-03-02 20:57+0000\n"
1167 "PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
1168 "Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
1169 "Language-Team: LANGUAGE <LL@li.org>\n"
1170
1171=== modified file 'src/CMakeLists.txt'
1172--- src/CMakeLists.txt 2014-01-08 18:15:21 +0000
1173+++ src/CMakeLists.txt 2014-04-03 13:02:15 +0000
1174@@ -7,6 +7,7 @@
1175 add_compiler_export_flags()
1176
1177 add_subdirectory("infographic")
1178+add_subdirectory("infographicservice")
1179 add_subdirectory("libusermetricscommon")
1180 add_subdirectory("libusermetricsinput")
1181 add_subdirectory("libusermetricsoutput")
1182
1183=== modified file 'src/infographic/CMakeLists.txt'
1184--- src/infographic/CMakeLists.txt 2014-01-08 18:15:21 +0000
1185+++ src/infographic/CMakeLists.txt 2014-04-03 13:02:15 +0000
1186@@ -10,8 +10,8 @@
1187 )
1188
1189 install(
1190- TARGETS infographic
1191- RUNTIME DESTINATION bin
1192+ TARGETS infographic
1193+ RUNTIME DESTINATION "${CMAKE_INSTALL_FULL_LIBEXECDIR}/libusermetrics"
1194 )
1195
1196 qt5_use_modules(
1197
1198=== modified file 'src/infographic/main.cpp'
1199--- src/infographic/main.cpp 2014-01-08 18:15:21 +0000
1200+++ src/infographic/main.cpp 2014-04-03 13:02:15 +0000
1201@@ -28,16 +28,21 @@
1202 int main(int argc, char *argv[]) {
1203 QCoreApplication application(argc, argv);
1204
1205- if (argc != 3) {
1206- qWarning() << "Usage: " << argv[0] << "INPUT_FILE OUTPUT_FILE";
1207+ if (argc < 2) {
1208+ qWarning() << "Usage: " << argv[0] << "INPUT_FILE [OUTPUT_FILE]";
1209 return 1;
1210 }
1211
1212 QFile inputFile(QString::fromUtf8(argv[1]));
1213- QFile outputFile(QString::fromUtf8(argv[2]));
1214+ QFile outputFile;
1215+ if (argc == 3) {
1216+ outputFile.setFileName(QString::fromUtf8(argv[2]));
1217+ outputFile.open(QIODevice::WriteOnly);
1218+ } else {
1219+ outputFile.open(1, QIODevice::WriteOnly);
1220+ }
1221
1222 inputFile.open(QIODevice::ReadOnly);
1223- outputFile.open(QIODevice::WriteOnly);
1224
1225 Infographic infographic(inputFile, outputFile);
1226
1227
1228=== added directory 'src/infographicservice'
1229=== added file 'src/infographicservice/CMakeLists.txt'
1230--- src/infographicservice/CMakeLists.txt 1970-01-01 00:00:00 +0000
1231+++ src/infographicservice/CMakeLists.txt 2014-04-03 13:02:15 +0000
1232@@ -0,0 +1,58 @@
1233+
1234+set(INFOGRAPHICSERVICE_SOURCES
1235+ Service.cpp
1236+)
1237+
1238+qt5_add_dbus_adaptor(
1239+ INFOGRAPHICSERVICE_SOURCES
1240+ ${INFOGRAPHIC_SERVICE_XML}
1241+ infographicservice/Service.h
1242+ InfographicService::Service
1243+ InfographicServiceAdaptor
1244+)
1245+
1246+add_library(
1247+ infographicservice
1248+ STATIC
1249+ ${INFOGRAPHICSERVICE_SOURCES}
1250+)
1251+
1252+qt5_use_modules(
1253+ infographicservice
1254+ Core
1255+ DBus
1256+)
1257+
1258+############################
1259+# Service executable
1260+############################
1261+
1262+add_executable(
1263+ infographicservice-bin
1264+ main.cpp
1265+)
1266+
1267+set_target_properties(
1268+ infographicservice-bin
1269+ PROPERTIES
1270+ OUTPUT_NAME "infographicservice"
1271+)
1272+
1273+target_link_libraries(
1274+ infographicservice-bin
1275+ infographicservice
1276+)
1277+
1278+qt5_use_modules(
1279+ infographicservice-bin
1280+ Core
1281+)
1282+
1283+#########################
1284+# Installation
1285+#########################
1286+
1287+install(
1288+ TARGETS infographicservice-bin
1289+ RUNTIME DESTINATION "${CMAKE_INSTALL_FULL_LIBEXECDIR}/libusermetrics"
1290+)
1291
1292=== added file 'src/infographicservice/Service.cpp'
1293--- src/infographicservice/Service.cpp 1970-01-01 00:00:00 +0000
1294+++ src/infographicservice/Service.cpp 2014-04-03 13:02:15 +0000
1295@@ -0,0 +1,131 @@
1296+/*
1297+ * Service.cpp
1298+ *
1299+ * Created on: 2 Mar 2014
1300+ * Author: pete
1301+ */
1302+
1303+#include <infographicservice/InfographicServiceAdaptor.h>
1304+#include <infographicservice/Service.h>
1305+#include <libusermetricscommon/DBusPaths.h>
1306+
1307+#include <QDateTime>
1308+#include <QFile>
1309+#include <cstdio>
1310+
1311+using namespace InfographicService;
1312+using namespace UserMetricsCommon;
1313+
1314+Service::Service(const QDir &directory, const QDBusConnection &systemConnection) :
1315+ m_directory(directory), m_connection(systemConnection), m_adaptor(
1316+ new InfographicsAdaptor(this)), m_hash(QCryptographicHash::Sha1) {
1317+
1318+ m_dirtyTimer.setSingleShot(true);
1319+ m_dirtyTimer.setTimerType(Qt::VeryCoarseTimer);
1320+ connect(&m_dirtyTimer, &QTimer::timeout, this, &Service::timeout);
1321+
1322+ m_directory.mkpath("tmp");
1323+ m_tempFile.setFileName(
1324+ QDir(m_directory.filePath("tmp")).filePath("tmp.svg"));
1325+
1326+ if (!m_connection.registerObject(DBusPaths::INFOGRAPHIC_DBUS_PATH, this)) {
1327+ throw std::logic_error(
1328+ "Unable to register Infographics object on DBus");
1329+ }
1330+ if (!m_connection.registerService(DBusPaths::INFOGRAPHIC_DBUS_NAME)) {
1331+ throw std::logic_error(
1332+ "Unable to register Infographics service on DBus");
1333+ }
1334+}
1335+
1336+Service::~Service() {
1337+ m_connection.unregisterService(DBusPaths::INFOGRAPHIC_DBUS_NAME);
1338+ m_connection.unregisterObject(DBusPaths::INFOGRAPHIC_DBUS_PATH);
1339+}
1340+
1341+unsigned int Service::uid() {
1342+ if (!calledFromDBus()) {
1343+ return 0;
1344+ }
1345+
1346+ return m_connection.interface()->serviceUid(message().service());
1347+}
1348+
1349+QDir Service::userDirectory() {
1350+ return m_directory.filePath(QString::number(uid()));
1351+}
1352+
1353+void Service::clear() {
1354+ userDirectory().removeRecursively();
1355+}
1356+
1357+void Service::update(const QString &visualizer, const QStringList &sources,
1358+ const QString &filePath) {
1359+
1360+ m_hash.reset();
1361+ m_hash.addData(visualizer.toUtf8());
1362+ for (const QString &source : sources) {
1363+ m_hash.addData(source.toUtf8());
1364+ }
1365+
1366+ QString sha(m_hash.result().toHex());
1367+
1368+ QDir usersDirectory(userDirectory());
1369+ QDir infographicDirectory(usersDirectory.filePath(visualizer));
1370+ QString destination(infographicDirectory.filePath(sha));
1371+ destination.append("-");
1372+ destination.append(QString::number(QDateTime::currentMSecsSinceEpoch()));
1373+ destination.append(".svg");
1374+
1375+ QFile file(filePath);
1376+ QByteArray ba;
1377+ if (file.open(QIODevice::ReadOnly)) {
1378+ ba = file.readAll();
1379+ file.close();
1380+ } else {
1381+ qWarning() << "Failed to open file" << filePath;
1382+ return;
1383+ }
1384+
1385+ if (ba.isEmpty()) {
1386+ return;
1387+ }
1388+
1389+ usersDirectory.mkpath(visualizer);
1390+ if (m_tempFile.open(QIODevice::WriteOnly)) {
1391+ m_tempFile.write(ba);
1392+ m_tempFile.close();
1393+ } else {
1394+ qWarning() << "Failed to write file" << m_tempFile.fileName();
1395+ }
1396+
1397+ int result = std::rename(m_tempFile.fileName().toUtf8().constData(),
1398+ destination.toUtf8().constData());
1399+ if (result == -1) {
1400+ qWarning() << "Failed to move result" << m_tempFile.fileName()
1401+ << "to destination" << destination;
1402+ return;
1403+ }
1404+
1405+ // clean up in one minute
1406+ m_dirty << qMakePair(infographicDirectory.path(), sha + "-*.svg");
1407+ m_dirtyTimer.start(60000);
1408+}
1409+
1410+void Service::timeout() {
1411+ for (const QPair<QString, QString> &result : m_dirty) {
1412+ QDir infographicDirectory(result.first);
1413+
1414+ QStringList entries = infographicDirectory.entryList(
1415+ QStringList() << result.second,
1416+ QDir::Files | QDir::NoDotAndDotDot, QDir::Name);
1417+
1418+ // We don't want to delete the last entry
1419+ entries.pop_back();
1420+ for (const QString &entry : entries) {
1421+ QFile::remove(infographicDirectory.filePath(entry));
1422+ }
1423+ }
1424+
1425+ m_dirty.clear();
1426+}
1427
1428=== added file 'src/infographicservice/Service.h'
1429--- src/infographicservice/Service.h 1970-01-01 00:00:00 +0000
1430+++ src/infographicservice/Service.h 2014-04-03 13:02:15 +0000
1431@@ -0,0 +1,74 @@
1432+/*
1433+ * Copyright (C) 2014 Canonical, Ltd.
1434+ *
1435+ * This program is free software; you can redistribute it and/or modify
1436+ * it under the terms of the GNU General Public License as published by
1437+ * the Free Software Foundation; version 3.
1438+ *
1439+ * This program is distributed in the hope that it will be useful,
1440+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
1441+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
1442+ * GNU General Public License for more details.
1443+ *
1444+ * You should have received a copy of the GNU General Public License
1445+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
1446+ *
1447+ * Author: Pete Woods <pete.woods@canonical.com>
1448+ */
1449+
1450+#ifndef INFOGRAPHICSERVICE_SERVICE_H_
1451+#define INFOGRAPHICSERVICE_SERVICE_H_
1452+
1453+#include <QCryptographicHash>
1454+#include <QDir>
1455+#include <QDBusContext>
1456+#include <QDBusConnection>
1457+#include <QObject>
1458+#include <QSet>
1459+#include <QSharedPointer>
1460+#include <QTimer>
1461+
1462+class InfographicsAdaptor;
1463+
1464+namespace InfographicService {
1465+
1466+class Service: public QObject, protected QDBusContext {
1467+Q_OBJECT
1468+
1469+public:
1470+ Service(const QDir &directory, const QDBusConnection &systemConnection);
1471+
1472+ virtual ~Service();
1473+
1474+public Q_SLOTS:
1475+ void clear();
1476+
1477+ void update(const QString &visualizer, const QStringList &sources,
1478+ const QString &file);
1479+
1480+protected Q_SLOTS:
1481+ void timeout();
1482+
1483+protected:
1484+ virtual unsigned int uid();
1485+
1486+ QDir userDirectory();
1487+
1488+ QDir m_directory;
1489+
1490+ QFile m_tempFile;
1491+
1492+ QDBusConnection m_connection;
1493+
1494+ QSharedPointer<InfographicsAdaptor> m_adaptor;
1495+
1496+ QTimer m_dirtyTimer;
1497+
1498+ QCryptographicHash m_hash;
1499+
1500+ QSet<QPair<QString, QString>> m_dirty;
1501+};
1502+
1503+}
1504+
1505+#endif /* INFOGRAPHICSERVICE_SERVICE_H_ */
1506
1507=== added file 'src/infographicservice/main.cpp'
1508--- src/infographicservice/main.cpp 1970-01-01 00:00:00 +0000
1509+++ src/infographicservice/main.cpp 2014-04-03 13:02:15 +0000
1510@@ -0,0 +1,46 @@
1511+/*
1512+ * Copyright (C) 2014 Canonical, Ltd.
1513+ *
1514+ * This program is free software; you can redistribute it and/or modify
1515+ * it under the terms of the GNU General Public License as published by
1516+ * the Free Software Foundation; version 3.
1517+ *
1518+ * This program is distributed in the hope that it will be useful,
1519+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
1520+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
1521+ * GNU General Public License for more details.
1522+ *
1523+ * You should have received a copy of the GNU General Public License
1524+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
1525+ *
1526+ * Author: Pete Woods <pete.woods@canonical.com>
1527+ */
1528+
1529+#include <infographicservice/Service.h>
1530+
1531+#include <QCoreApplication>
1532+#include <QDebug>
1533+#include <csignal>
1534+
1535+using namespace InfographicService;
1536+
1537+static void exitQt(int sig) {
1538+ Q_UNUSED(sig);
1539+ QCoreApplication::exit(0);
1540+}
1541+
1542+int main(int argc, char *argv[]) {
1543+ QCoreApplication application(argc, argv);
1544+
1545+ signal(SIGINT, &exitQt);
1546+ signal(SIGTERM, &exitQt);
1547+
1548+ try {
1549+ Service service(QDir("/var/lib/usermetrics"),
1550+ QDBusConnection::systemBus());
1551+ return application.exec();
1552+ } catch (std::exception &e) {
1553+ qWarning() << "Infographic Service:" << e.what();
1554+ return 1;
1555+ }
1556+}
1557
1558=== modified file 'src/libusermetricscommon/CMakeLists.txt'
1559--- src/libusermetricscommon/CMakeLists.txt 2014-01-03 11:40:22 +0000
1560+++ src/libusermetricscommon/CMakeLists.txt 2014-04-03 13:02:15 +0000
1561@@ -2,9 +2,16 @@
1562 set(USERMETRICS_COMMON_SOURCES
1563 DateFactory.cpp
1564 DateFactoryImpl.cpp
1565+ FileUtils.cpp
1566 Localisation.cpp
1567 )
1568
1569+qt5_add_dbus_interface(
1570+ USERMETRICS_COMMON_SOURCES
1571+ ${INFOGRAPHIC_SERVICE_XML}
1572+ InfographicsInterface
1573+)
1574+
1575 add_library(
1576 usermetricscommon
1577 STATIC
1578@@ -14,5 +21,5 @@
1579 qt5_use_modules(
1580 usermetricscommon
1581 Core
1582+ DBus
1583 )
1584-
1585
1586=== added file 'src/libusermetricscommon/DBusPaths.h'
1587--- src/libusermetricscommon/DBusPaths.h 1970-01-01 00:00:00 +0000
1588+++ src/libusermetricscommon/DBusPaths.h 2014-04-03 13:02:15 +0000
1589@@ -0,0 +1,37 @@
1590+/*
1591+ * Copyright (C) 2013 Canonical, Ltd.
1592+ *
1593+ * This library is free software; you can redistribute it and/or modify it under
1594+ * the terms of version 3 of the GNU Lesser General Public License as published
1595+ * by the Free Software Foundation.
1596+ *
1597+ * This library is distributed in the hope that it will be useful, but WITHOUT
1598+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
1599+ * FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
1600+ * details.
1601+ *
1602+ * You should have received a copy of the GNU Lesser General Public License
1603+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
1604+ *
1605+ * Author: Pete Woods <pete.woods@canonical.com>
1606+ */
1607+
1608+#ifndef USERMETRICSCOMMON_DBUSPATHS_H_
1609+#define USERMETRICSCOMMON_DBUSPATHS_H_
1610+
1611+#include <QtCore/QString>
1612+
1613+namespace UserMetricsCommon {
1614+
1615+class DBusPaths {
1616+public:
1617+ constexpr static const char* INFOGRAPHIC_DBUS_NAME =
1618+ "com.canonical.Infographics";
1619+
1620+ constexpr static const char* INFOGRAPHIC_DBUS_PATH =
1621+ "/com/canonical/Infographics";
1622+};
1623+
1624+}
1625+
1626+#endif // USERMETRICSCOMMON_DBUSPATHS_H_
1627
1628=== added file 'src/libusermetricscommon/FileUtils.cpp'
1629--- src/libusermetricscommon/FileUtils.cpp 1970-01-01 00:00:00 +0000
1630+++ src/libusermetricscommon/FileUtils.cpp 2014-04-03 13:02:15 +0000
1631@@ -0,0 +1,52 @@
1632+/*
1633+ * Copyright (C) 2014 Canonical, Ltd.
1634+ *
1635+ * This program is free software; you can redistribute it and/or modify
1636+ * it under the terms of the GNU General Public License as published by
1637+ * the Free Software Foundation; version 3.
1638+ *
1639+ * This program is distributed in the hope that it will be useful,
1640+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
1641+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
1642+ * GNU General Public License for more details.
1643+ *
1644+ * You should have received a copy of the GNU General Public License
1645+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
1646+ *
1647+ * Author: Pete Woods <pete.woods@canonical.com>
1648+ */
1649+
1650+#include <libusermetricscommon/FileUtils.h>
1651+
1652+#include <QRegularExpression>
1653+
1654+using namespace UserMetricsCommon;
1655+
1656+QRegularExpression FileUtils::CLICK_REGEX(
1657+ "^[a-z0-9][a-z0-9+.-]+_[a-zA-Z0-9+.-]+_[0-9][a-zA-Z0-9.+:~-]*$");
1658+
1659+FileUtils::FileUtils() {
1660+}
1661+
1662+FileUtils::~FileUtils() {
1663+}
1664+
1665+QStringList FileUtils::listDirectory(const QDir &directory,
1666+ QDir::Filters filters, QDir::SortFlags sort) {
1667+ QStringList names;
1668+ for (const QString& name : directory.entryList(
1669+ filters | QDir::NoDotAndDotDot, sort)) {
1670+ names << directory.filePath(name);
1671+ }
1672+ return names;
1673+}
1674+
1675+void FileUtils::shortApplicationId(QString &applicationId) {
1676+ QRegularExpressionMatch match = CLICK_REGEX.match(applicationId);
1677+ if (match.hasMatch()) {
1678+ int index = applicationId.indexOf('_');
1679+ if (index != -1) {
1680+ applicationId.remove(index, applicationId.size());
1681+ }
1682+ }
1683+}
1684
1685=== added file 'src/libusermetricscommon/FileUtils.h'
1686--- src/libusermetricscommon/FileUtils.h 1970-01-01 00:00:00 +0000
1687+++ src/libusermetricscommon/FileUtils.h 2014-04-03 13:02:15 +0000
1688@@ -0,0 +1,47 @@
1689+/*
1690+ * Copyright (C) 2014 Canonical, Ltd.
1691+ *
1692+ * This program is free software; you can redistribute it and/or modify
1693+ * it under the terms of the GNU General Public License as published by
1694+ * the Free Software Foundation; version 3.
1695+ *
1696+ * This program is distributed in the hope that it will be useful,
1697+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
1698+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
1699+ * GNU General Public License for more details.
1700+ *
1701+ * You should have received a copy of the GNU General Public License
1702+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
1703+ *
1704+ * Author: Pete Woods <pete.woods@canonical.com>
1705+ */
1706+
1707+#ifndef USERMETRICSCOMMON_FILEUTILS_H_
1708+#define USERMETRICSCOMMON_FILEUTILS_H_
1709+
1710+#include <QDir>
1711+#include <QSet>
1712+#include <QSharedPointer>
1713+#include <QStringList>
1714+
1715+namespace UserMetricsCommon {
1716+
1717+class FileUtils {
1718+public:
1719+ typedef QSharedPointer<FileUtils> Ptr;
1720+
1721+ FileUtils();
1722+
1723+ virtual ~FileUtils();
1724+
1725+ static QRegularExpression CLICK_REGEX;
1726+
1727+ virtual QStringList listDirectory(const QDir &directory,
1728+ QDir::Filters filters, QDir::SortFlags sort = QDir::NoSort);
1729+
1730+ void shortApplicationId(QString &applicationId);
1731+};
1732+
1733+}
1734+
1735+#endif /* USERMETRICSCOMMON_FILEUTILS_H_ */
1736
1737=== modified file 'src/libusermetricsinput/MetricImpl.cpp'
1738--- src/libusermetricsinput/MetricImpl.cpp 2014-01-06 17:31:49 +0000
1739+++ src/libusermetricsinput/MetricImpl.cpp 2014-04-03 13:02:15 +0000
1740@@ -17,6 +17,7 @@
1741 */
1742
1743 #include <stdexcept>
1744+#include <cstdio>
1745
1746 #include <libusermetricscommon/Localisation.h>
1747 #include <libusermetricsinput/MetricImpl.h>
1748@@ -183,7 +184,13 @@
1749 }
1750
1751 QString MetricImpl::buildJsonFile() {
1752- return m_metricDirectory.filePath(m_parameters.id() + ".json");
1753+ return m_metricDirectory.filePath(
1754+ m_parameters.id() + ".libusermetrics.json");
1755+}
1756+
1757+QString MetricImpl::buildTmpFile() {
1758+ return QDir(m_metricDirectory.filePath(".tmp")).filePath(
1759+ "." + m_parameters.id() + ".libusermetrics.json");
1760 }
1761
1762 void MetricImpl::loadData() {
1763@@ -241,11 +248,21 @@
1764
1765 QJsonDocument document(QJsonDocument::fromVariant(root));
1766
1767- QFile jsonFile(buildJsonFile());
1768- if (jsonFile.open(QIODevice::WriteOnly)) {
1769- jsonFile.write(document.toJson());
1770- jsonFile.close();
1771+ m_metricDirectory.mkpath(".tmp");
1772+ QFile tmpFile(buildTmpFile());
1773+ if (tmpFile.open(QIODevice::WriteOnly)) {
1774+ tmpFile.write(document.toJson());
1775+ tmpFile.close();
1776 } else {
1777- qWarning() << "Could not write usermetrics file" << jsonFile.fileName();
1778+ qWarning() << "Could not write usermetrics file" << tmpFile.fileName();
1779+ return;
1780+ }
1781+
1782+ QString jsonFile(buildJsonFile());
1783+ int result = std::rename(tmpFile.fileName().toUtf8().constData(),
1784+ jsonFile.toUtf8().constData());
1785+ if (result == -1) {
1786+ qWarning() << "Failed to move result" << tmpFile.fileName()
1787+ << "to destination" << jsonFile;
1788 }
1789 }
1790
1791=== modified file 'src/libusermetricsinput/MetricImpl.h'
1792--- src/libusermetricsinput/MetricImpl.h 2014-01-06 11:25:07 +0000
1793+++ src/libusermetricsinput/MetricImpl.h 2014-04-03 13:02:15 +0000
1794@@ -63,6 +63,8 @@
1795
1796 QString buildJsonFile();
1797
1798+ QString buildTmpFile();
1799+
1800 QDir m_metricDirectory;
1801
1802 MetricParameters m_parameters;
1803
1804=== modified file 'src/libusermetricsinput/MetricManagerImpl.cpp'
1805--- src/libusermetricsinput/MetricManagerImpl.cpp 2014-01-06 17:31:49 +0000
1806+++ src/libusermetricsinput/MetricManagerImpl.cpp 2014-04-03 13:02:15 +0000
1807@@ -16,14 +16,28 @@
1808 * Author: Pete Woods <pete.woods@canonical.com>
1809 */
1810
1811+#include <libusermetricscommon/FileUtils.h>
1812 #include <libusermetricsinput/MetricImpl.h>
1813 #include <libusermetricsinput/MetricManagerImpl.h>
1814
1815 #include <stdexcept>
1816 #include <QDebug>
1817+#include <QRegularExpression>
1818+
1819
1820 using namespace std;
1821 using namespace UserMetricsInput;
1822+using namespace UserMetricsCommon;
1823+
1824+static void shortApplicationId(QString &applicationId) {
1825+ QRegularExpressionMatch match = FileUtils::CLICK_REGEX.match(applicationId);
1826+ if (match.hasMatch()) {
1827+ int index = applicationId.indexOf('_');
1828+ if (index != -1) {
1829+ applicationId.remove(index, applicationId.size());
1830+ }
1831+ }
1832+}
1833
1834 MetricManagerImpl::MetricManagerImpl(Factory::Ptr factory,
1835 const QDir &cacheDirectory, const QString &applicationId,
1836@@ -32,7 +46,11 @@
1837 if (applicationId.isEmpty()) {
1838 throw logic_error("Invalid application ID");
1839 }
1840- QDir applicationDirectory(cacheDirectory.filePath(applicationId));
1841+
1842+ QString shortId(applicationId);
1843+ shortApplicationId(shortId);
1844+
1845+ QDir applicationDirectory(cacheDirectory.filePath(shortId));
1846 if (!applicationDirectory.mkpath("usermetrics")) {
1847 throw logic_error("Cannot write to cache directory");
1848 }
1849
1850=== modified file 'src/libusermetricsoutput/CMakeLists.txt'
1851--- src/libusermetricsoutput/CMakeLists.txt 2014-01-03 11:40:22 +0000
1852+++ src/libusermetricsoutput/CMakeLists.txt 2014-04-03 13:02:15 +0000
1853@@ -12,6 +12,9 @@
1854 GSettingsColorThemeProvider.cpp
1855 DataSet.cpp
1856 DataSource.cpp
1857+ DirectoryWatcher.cpp
1858+ InfographicList.cpp
1859+ InfographicListImpl.cpp
1860 UserData.cpp
1861 UserMetrics.cpp
1862 UserMetricsImpl.cpp
1863
1864=== added file 'src/libusermetricsoutput/DirectoryWatcher.cpp'
1865--- src/libusermetricsoutput/DirectoryWatcher.cpp 1970-01-01 00:00:00 +0000
1866+++ src/libusermetricsoutput/DirectoryWatcher.cpp 2014-04-03 13:02:15 +0000
1867@@ -0,0 +1,114 @@
1868+/*
1869+ * Copyright (C) 2014 Canonical, Ltd.
1870+ *
1871+ * This library is free software; you can redistribute it and/or modify it under
1872+ * the terms of version 3 of the GNU Lesser General Public License as published
1873+ * by the Free Software Foundation.
1874+ *
1875+ * This library is distributed in the hope that it will be useful, but WITHOUT
1876+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
1877+ * FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
1878+ * details.
1879+ *
1880+ * You should have received a copy of the GNU Lesser General Public License
1881+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
1882+ *
1883+ * Author: Pete Woods <pete.woods@canonical.com>
1884+ */
1885+
1886+#include <libusermetricsoutput/DirectoryWatcher.h>
1887+
1888+#include <QDebug>
1889+
1890+using namespace UserMetricsCommon;
1891+using namespace UserMetricsOutput;
1892+
1893+namespace {
1894+
1895+static bool nameCompare(const QString &a, const QString &b) {
1896+ int indexA = a.lastIndexOf('-');
1897+ int indexB = b.lastIndexOf('-');
1898+
1899+ if (indexA == -1 || indexB == -1) {
1900+ return false;
1901+ }
1902+
1903+ QStringRef startA = a.leftRef(indexA);
1904+ QStringRef startB = b.leftRef(indexB);
1905+
1906+ return !!startA.compare(startB);
1907+}
1908+
1909+}
1910+
1911+DirectoryWatcher::DirectoryWatcher(const QDir &path, unsigned int maxDepth,
1912+ FileUtils::Ptr fileUtils) :
1913+ m_path(path), m_maxDepth(maxDepth), m_fileUtils(fileUtils) {
1914+
1915+ m_watcher.addPath(path.path());
1916+
1917+ connect(&m_watcher, &QFileSystemWatcher::directoryChanged, this,
1918+ &DirectoryWatcher::internalDirectoryChanged);
1919+}
1920+
1921+DirectoryWatcher::~DirectoryWatcher() {
1922+}
1923+
1924+void DirectoryWatcher::start() {
1925+ internalDirectoryChanged();
1926+}
1927+
1928+void DirectoryWatcher::internalDirectoryChanged() {
1929+ QStringList files(
1930+ m_fileUtils->listDirectory(m_path, QDir::Files, QDir::Name));
1931+
1932+ QStringList newestFiles;
1933+
1934+ const QString *previous(nullptr);
1935+ for (const QString &file : files) {
1936+ if (!previous) {
1937+ previous = &file;
1938+ } else if (nameCompare(*previous, file)) {
1939+ newestFiles << *previous;
1940+ }
1941+ previous = &file;
1942+ }
1943+
1944+ if (previous) {
1945+ newestFiles << *previous;
1946+ }
1947+
1948+ directoryChanged(m_path.path(), newestFiles);
1949+
1950+ if (m_maxDepth == 0) {
1951+ return;
1952+ }
1953+
1954+ QSet<QString> directories(
1955+ m_fileUtils->listDirectory(m_path, QDir::Dirs).toSet());
1956+
1957+ // Remove deleted files
1958+ QSet<QString> directoriesToRemove(
1959+ m_directories.keys().toSet().subtract(directories));
1960+ for (const QString &name : directoriesToRemove) {
1961+ m_directories.remove(name);
1962+ directoryRemoved(name);
1963+ }
1964+
1965+ // Work out the names we need to add
1966+ directories.subtract(m_directories.keys().toSet());
1967+ for (const QString &name : directories) {
1968+ DirectoryWatcher::Ptr watcher(
1969+ new DirectoryWatcher(name, m_maxDepth - 1, m_fileUtils));
1970+ m_directories.insert(name, watcher);
1971+ connect(watcher.data(), &DirectoryWatcher::directoryChanged, this,
1972+ &DirectoryWatcher::directoryChanged);
1973+ connect(watcher.data(), &DirectoryWatcher::directoryRemoved, this,
1974+ &DirectoryWatcher::directoryRemoved);
1975+ watcher->start();
1976+ }
1977+}
1978+
1979+QStringList DirectoryWatcher::files() {
1980+ return m_watcher.files();
1981+}
1982
1983=== added file 'src/libusermetricsoutput/DirectoryWatcher.h'
1984--- src/libusermetricsoutput/DirectoryWatcher.h 1970-01-01 00:00:00 +0000
1985+++ src/libusermetricsoutput/DirectoryWatcher.h 2014-04-03 13:02:15 +0000
1986@@ -0,0 +1,69 @@
1987+/*
1988+ * Copyright (C) 2014 Canonical, Ltd.
1989+ *
1990+ * This library is free software; you can redistribute it and/or modify it under
1991+ * the terms of version 3 of the GNU Lesser General Public License as published
1992+ * by the Free Software Foundation.
1993+ *
1994+ * This library is distributed in the hope that it will be useful, but WITHOUT
1995+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
1996+ * FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
1997+ * details.
1998+ *
1999+ * You should have received a copy of the GNU Lesser General Public License
2000+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
2001+ *
2002+ * Author: Pete Woods <pete.woods@canonical.com>
2003+ */
2004+
2005+#ifndef USERMETRICSOUTPUT_DIRECTORYWATCHER_H_
2006+#define USERMETRICSOUTPUT_DIRECTORYWATCHER_H_
2007+
2008+#include <libusermetricscommon/FileUtils.h>
2009+
2010+#include <QDir>
2011+#include <QMap>
2012+#include <QFileSystemWatcher>
2013+#include <QSharedPointer>
2014+
2015+namespace UserMetricsOutput {
2016+
2017+class DirectoryWatcher: public QObject {
2018+Q_OBJECT
2019+
2020+public:
2021+ typedef QSharedPointer<DirectoryWatcher> Ptr;
2022+
2023+ DirectoryWatcher(const QDir &path, unsigned int maxDepth,
2024+ UserMetricsCommon::FileUtils::Ptr fileUtils);
2025+
2026+ virtual ~DirectoryWatcher();
2027+
2028+ QStringList files();
2029+
2030+public Q_SLOTS:
2031+ void start();
2032+
2033+Q_SIGNALS:
2034+ void directoryChanged(const QString &directory, const QStringList &files);
2035+
2036+ void directoryRemoved(const QString &directory);
2037+
2038+protected Q_SLOTS:
2039+ void internalDirectoryChanged();
2040+
2041+protected:
2042+ QDir m_path;
2043+
2044+ unsigned int m_maxDepth;
2045+
2046+ UserMetricsCommon::FileUtils::Ptr m_fileUtils;
2047+
2048+ QFileSystemWatcher m_watcher;
2049+
2050+ QMap<QString, DirectoryWatcher::Ptr> m_directories;
2051+};
2052+
2053+}
2054+
2055+#endif /* USERMETRICSOUTPUT_DIRECTORYWATCHER_H_ */
2056
2057=== added file 'src/libusermetricsoutput/InfographicList.cpp'
2058--- src/libusermetricsoutput/InfographicList.cpp 1970-01-01 00:00:00 +0000
2059+++ src/libusermetricsoutput/InfographicList.cpp 2014-04-03 13:02:15 +0000
2060@@ -0,0 +1,32 @@
2061+/*
2062+ * Copyright (C) 2014 Canonical, Ltd.
2063+ *
2064+ * This library is free software; you can redistribute it and/or modify it under
2065+ * the terms of version 3 of the GNU Lesser General Public License as published
2066+ * by the Free Software Foundation.
2067+ *
2068+ * This library is distributed in the hope that it will be useful, but WITHOUT
2069+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
2070+ * FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
2071+ * details.
2072+ *
2073+ * You should have received a copy of the GNU Lesser General Public License
2074+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
2075+ *
2076+ * Author: Pete Woods <pete.woods@canonical.com>
2077+ */
2078+
2079+#include <libusermetricsoutput/InfographicListImpl.h>
2080+
2081+using namespace UserMetricsOutput;
2082+
2083+InfographicList::InfographicList(QObject *parent) :
2084+ QStringListModel(parent) {
2085+}
2086+
2087+InfographicList::~InfographicList() {
2088+}
2089+
2090+InfographicList * InfographicList::getInstance(const QString &path) {
2091+ return new InfographicListImpl(path);
2092+}
2093
2094=== added file 'src/libusermetricsoutput/InfographicList.h'
2095--- src/libusermetricsoutput/InfographicList.h 1970-01-01 00:00:00 +0000
2096+++ src/libusermetricsoutput/InfographicList.h 2014-04-03 13:02:15 +0000
2097@@ -0,0 +1,106 @@
2098+/*
2099+ * Copyright (C) 2014 Canonical, Ltd.
2100+ *
2101+ * This library is free software; you can redistribute it and/or modify it under
2102+ * the terms of version 3 of the GNU Lesser General Public License as published
2103+ * by the Free Software Foundation.
2104+ *
2105+ * This library is distributed in the hope that it will be useful, but WITHOUT
2106+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
2107+ * FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
2108+ * details.
2109+ *
2110+ * You should have received a copy of the GNU Lesser General Public License
2111+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
2112+ *
2113+ * Author: Pete Woods <pete.woods@canonical.com>
2114+ */
2115+
2116+#ifndef USERMETRICSOUTPUT_INFOGRAPHICLIST_H_
2117+#define USERMETRICSOUTPUT_INFOGRAPHICLIST_H_
2118+
2119+#include <QtCore/QStringList>
2120+#include <QtCore/QStringListModel>
2121+
2122+/**
2123+ * @{
2124+ **/
2125+
2126+/**
2127+ * @brief The user metrics output library namespace
2128+ **/
2129+namespace UserMetricsOutput {
2130+
2131+/**
2132+ * @brief Presentation API for infographics.
2133+ *
2134+ * This class essentially provides a list of paths to
2135+ * infographic image files.
2136+ *
2137+ * Given a user ID, this class watches the corresponding
2138+ * directory in /var/lib/usermetrics/{userid}/ for changes
2139+ * to SVG files.
2140+ *
2141+ **/
2142+class Q_DECL_EXPORT InfographicList: public QStringListModel {
2143+Q_OBJECT
2144+
2145+/**
2146+ * @brief The current user ID selected.
2147+ */
2148+Q_PROPERTY(unsigned int uid READ uid WRITE setUid NOTIFY uidChanged FINAL)
2149+
2150+public:
2151+ /**
2152+ * @brief Get a new instance of InfographicList.
2153+ */
2154+ static InfographicList *getInstance(
2155+ const QString &path = QString("/var/lib/usermetrics/"));
2156+
2157+ /**
2158+ * @brief Destructor.
2159+ */
2160+ virtual ~InfographicList();
2161+
2162+ /**
2163+ * @brief The current user ID selected.
2164+ */
2165+ virtual unsigned int uid() const = 0;
2166+
2167+
2168+Q_SIGNALS:
2169+ /**
2170+ * @brief The user ID has changed
2171+ *
2172+ * @param uid
2173+ */
2174+ void uidChanged(unsigned int uid);
2175+
2176+public Q_SLOTS:
2177+ /**
2178+ * @brief Change the current user ID.
2179+ *
2180+ * @param uid
2181+ *
2182+ * The data source will change to the first one available
2183+ * for the given user ID.
2184+ */
2185+ virtual void setUid(unsigned int uid) = 0;
2186+
2187+protected:
2188+ /**
2189+ * @brief Unusable constructor - this class is pure-virtual.
2190+ *
2191+ * @param parent
2192+ */
2193+ explicit InfographicList(QObject *parent = 0);
2194+
2195+ Q_DISABLE_COPY(InfographicList)
2196+
2197+};
2198+
2199+}
2200+
2201+/*@}*/
2202+
2203+#endif // USERMETRICSOUTPUT_INFOGRAPHICLIST_H_
2204
2205=== added file 'src/libusermetricsoutput/InfographicListImpl.cpp'
2206--- src/libusermetricsoutput/InfographicListImpl.cpp 1970-01-01 00:00:00 +0000
2207+++ src/libusermetricsoutput/InfographicListImpl.cpp 2014-04-03 13:02:15 +0000
2208@@ -0,0 +1,139 @@
2209+/*
2210+ * Copyright (C) 2014 Canonical, Ltd.
2211+ *
2212+ * This library is free software; you can redistribute it and/or modify it under
2213+ * the terms of version 3 of the GNU Lesser General Public License as published
2214+ * by the Free Software Foundation.
2215+ *
2216+ * This library is distributed in the hope that it will be useful, but WITHOUT
2217+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
2218+ * FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
2219+ * details.
2220+ *
2221+ * You should have received a copy of the GNU Lesser General Public License
2222+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
2223+ *
2224+ * Author: Pete Woods <pete.woods@canonical.com>
2225+ */
2226+
2227+#include <libusermetricscommon/FileUtils.h>
2228+#include <libusermetricsoutput/InfographicListImpl.h>
2229+
2230+#include <QtCore/QDebug>
2231+#include <algorithm>
2232+
2233+using namespace UserMetricsCommon;
2234+using namespace UserMetricsOutput;
2235+
2236+InfographicListImpl::InfographicListImpl(const QString &path, QObject *parent) :
2237+ InfographicList(parent), m_path(path), m_uid(0) {
2238+
2239+ connect(&m_timer, &QTimer::timeout, this, &InfographicListImpl::timeout);
2240+ connect(&m_filesystemWatcher, &QFileSystemWatcher::directoryChanged, this,
2241+ &InfographicListImpl::internalDirectoryChanged);
2242+
2243+ m_timer.setSingleShot(true);
2244+ m_filesystemWatcher.addPath(path);
2245+ m_workerThread.start();
2246+}
2247+
2248+InfographicListImpl::~InfographicListImpl() {
2249+ m_workerThread.quit();
2250+ m_workerThread.wait();
2251+}
2252+
2253+unsigned int InfographicListImpl::uid() const {
2254+ return m_uid;
2255+}
2256+
2257+void InfographicListImpl::newDirectoryWatcher() {
2258+ m_directoryWatcher.reset(
2259+ new DirectoryWatcher(m_userDir, 1, FileUtils::Ptr(new FileUtils())),
2260+ &QObject::deleteLater);
2261+ m_directoryWatcher->moveToThread(&m_workerThread);
2262+ connect(m_directoryWatcher.data(), &DirectoryWatcher::directoryChanged,
2263+ this, &InfographicListImpl::directoryContentsChanged);
2264+ connect(m_directoryWatcher.data(), &DirectoryWatcher::directoryRemoved,
2265+ this, &InfographicListImpl::directoryRemoved);
2266+ QTimer::singleShot(0, m_directoryWatcher.data(), SLOT(start()));
2267+}
2268+
2269+void InfographicListImpl::setUid(unsigned int uid) {
2270+ if (uid == m_uid) {
2271+ return;
2272+ }
2273+
2274+ m_uid = uid;
2275+ m_userDir = m_path.filePath(QString::number(m_uid));
2276+
2277+ if (m_userDir.exists()) {
2278+ newDirectoryWatcher();
2279+ }
2280+}
2281+
2282+void InfographicListImpl::internalDirectoryChanged() {
2283+ if (m_uid == 0) {
2284+ return;
2285+ }
2286+
2287+ bool exists(m_userDir.exists());
2288+
2289+ if (m_directoryWatcher) {
2290+ if (!exists) {
2291+ m_directoryWatcher.reset();
2292+ }
2293+ } else {
2294+ newDirectoryWatcher();
2295+ }
2296+}
2297+
2298+void InfographicListImpl::directoryContentsChanged(const QString &directory,
2299+ const QStringList &files) {
2300+ m_files.remove(directory);
2301+ for (const QString &file : files) {
2302+ m_files.insert(directory, file);
2303+ }
2304+ m_timer.start(100);
2305+}
2306+
2307+void InfographicListImpl::directoryRemoved(const QString &name) {
2308+ m_files.remove(name);
2309+ m_timer.start(100);
2310+}
2311+
2312+void InfographicListImpl::timeout() {
2313+ if (!m_directoryWatcher) {
2314+ return;
2315+ }
2316+
2317+ int existingRows(rowCount());
2318+ int newRows(m_files.count());
2319+
2320+ // Special case the initial insert
2321+ if (existingRows == 0 && newRows > 0) {
2322+ setStringList(m_files.values());
2323+ return;
2324+ }
2325+
2326+ if (newRows > existingRows) {
2327+ // insert new rows
2328+ insertRows(existingRows, newRows - existingRows);
2329+ } else if (newRows < existingRows) {
2330+ // remove extra rows
2331+ removeRows(newRows, existingRows - newRows);
2332+ }
2333+
2334+ int row(0);
2335+ QMapIterator<QString, QString> it(m_files);
2336+ while (it.hasNext()) {
2337+ it.next();
2338+ const QString &file(it.value());
2339+
2340+ QString existing(data(index(row, 0), Qt::DisplayRole).toString());
2341+ if (existing != file) {
2342+ setData(index(row, 0), file);
2343+ }
2344+ ++row;
2345+ }
2346+}
2347+
2348
2349=== added file 'src/libusermetricsoutput/InfographicListImpl.h'
2350--- src/libusermetricsoutput/InfographicListImpl.h 1970-01-01 00:00:00 +0000
2351+++ src/libusermetricsoutput/InfographicListImpl.h 2014-04-03 13:02:15 +0000
2352@@ -0,0 +1,79 @@
2353+/*
2354+ * Copyright (C) 2014 Canonical, Ltd.
2355+ *
2356+ * This library is free software; you can redistribute it and/or modify it under
2357+ * the terms of version 3 of the GNU Lesser General Public License as published
2358+ * by the Free Software Foundation.
2359+ *
2360+ * This library is distributed in the hope that it will be useful, but WITHOUT
2361+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
2362+ * FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
2363+ * details.
2364+ *
2365+ * You should have received a copy of the GNU Lesser General Public License
2366+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
2367+ *
2368+ * Author: Pete Woods <pete.woods@canonical.com>
2369+ */
2370+
2371+#ifndef USERMETRICSOUTPUT_INFOGRAPHICLISTIMPL_H_
2372+#define USERMETRICSOUTPUT_INFOGRAPHICLISTIMPL_H_
2373+
2374+#include <libusermetricsoutput/DirectoryWatcher.h>
2375+#include <libusermetricsoutput/InfographicList.h>
2376+
2377+#include <QtCore/QDir>
2378+#include <QtCore/QString>
2379+#include <QtCore/QFileSystemWatcher>
2380+#include <QtCore/QMultiMap>
2381+#include <QtCore/QThread>
2382+#include <QtCore/QTimer>
2383+#include <QtCore/QScopedPointer>
2384+
2385+namespace UserMetricsOutput {
2386+
2387+class InfographicListImpl: public InfographicList {
2388+Q_OBJECT
2389+
2390+public:
2391+ InfographicListImpl(const QString &path, QObject *parent = 0);
2392+
2393+ virtual ~InfographicListImpl();
2394+
2395+ unsigned int uid() const override;
2396+
2397+ void setUid(unsigned int uid) override;
2398+
2399+protected Q_SLOTS:
2400+ void internalDirectoryChanged();
2401+
2402+ void directoryContentsChanged(const QString &directory,
2403+ const QStringList &files);
2404+
2405+ void directoryRemoved(const QString &directory);
2406+
2407+ void timeout();
2408+
2409+protected:
2410+ void newDirectoryWatcher();
2411+
2412+ QThread m_workerThread;
2413+
2414+ QTimer m_timer;
2415+
2416+ QDir m_path;
2417+
2418+ QDir m_userDir;
2419+
2420+ unsigned int m_uid;
2421+
2422+ QFileSystemWatcher m_filesystemWatcher;
2423+
2424+ DirectoryWatcher::Ptr m_directoryWatcher;
2425+
2426+ QMultiMap<QString, QString> m_files;
2427+};
2428+
2429+}
2430+
2431+#endif /* USERMETRICSOUTPUT_INFOGRAPHICLISTIMPL_H_ */
2432
2433=== modified file 'src/usermetricsservice/CMakeLists.txt'
2434--- src/usermetricsservice/CMakeLists.txt 2014-01-03 11:40:22 +0000
2435+++ src/usermetricsservice/CMakeLists.txt 2014-04-03 13:02:15 +0000
2436@@ -1,17 +1,34 @@
2437
2438-#set(USERMETRICSSERVICE_SOURCES
2439-#)
2440-
2441-#add_library(
2442-# usermetricsservice
2443-# STATIC
2444-# ${USERMETRICSSERVICE_SOURCES}
2445-#)
2446-
2447-#target_link_libraries(
2448-# usermetricsservice
2449-# ${APPARMOR_LIBRARIES}
2450-#)
2451+set(USERMETRICSSERVICE_SOURCES
2452+ Executor.cpp
2453+ Factory.cpp
2454+ Infographic.cpp
2455+ InfographicImpl.cpp
2456+ QProcessExecutor.cpp
2457+ ResultTransport.cpp
2458+ ResultTransportImpl.cpp
2459+ SourceDirectory.cpp
2460+ SourceDirectoryImpl.cpp
2461+ Service.cpp
2462+ ServiceImpl.cpp
2463+)
2464+
2465+add_library(
2466+ usermetricsservice
2467+ STATIC
2468+ ${USERMETRICSSERVICE_SOURCES}
2469+)
2470+
2471+target_link_libraries(
2472+ usermetricsservice
2473+ usermetricscommon
2474+)
2475+
2476+qt5_use_modules(
2477+ usermetricsservice
2478+ Core
2479+ DBus
2480+)
2481
2482 ############################
2483 # Service executable
2484@@ -28,16 +45,42 @@
2485 OUTPUT_NAME "usermetricsservice"
2486 )
2487
2488-#target_link_libraries(
2489-# usermetricsservice-bin
2490-# usermetricsservice
2491-#)
2492+target_link_libraries(
2493+ usermetricsservice-bin
2494+ usermetricsservice
2495+)
2496+
2497+qt5_use_modules(
2498+ usermetricsservice-bin
2499+ Core
2500+)
2501+
2502+#########################
2503+# Sandbox executable
2504+#########################
2505+
2506+add_executable(
2507+ aa-exec
2508+ aa-exec.cpp
2509+)
2510+
2511+target_link_libraries(
2512+ aa-exec
2513+ ${APPARMOR_LDFLAGS}
2514+)
2515+
2516+add_definitions(
2517+ -DAA_EXEC_PATH="${CMAKE_INSTALL_FULL_LIBEXECDIR}/libusermetrics/aa-exec"
2518+)
2519
2520 #########################
2521 # Installation
2522 #########################
2523
2524 install(
2525- TARGETS usermetricsservice-bin
2526- RUNTIME DESTINATION "${CMAKE_INSTALL_FULL_LIBEXECDIR}/libusermetrics"
2527+ TARGETS
2528+ usermetricsservice-bin
2529+ aa-exec
2530+ RUNTIME DESTINATION
2531+ "${CMAKE_INSTALL_FULL_LIBEXECDIR}/libusermetrics"
2532 )
2533
2534=== removed file 'src/usermetricsservice/DBusUserData.cpp'
2535--- src/usermetricsservice/DBusUserData.cpp 2014-01-20 10:33:36 +0000
2536+++ src/usermetricsservice/DBusUserData.cpp 1970-01-01 00:00:00 +0000
2537@@ -1,186 +0,0 @@
2538-/*
2539- * Copyright (C) 2013 Canonical, Ltd.
2540- *
2541- * This program is free software; you can redistribute it and/or modify
2542- * it under the terms of the GNU General Public License as published by
2543- * the Free Software Foundation; version 3.
2544- *
2545- * This program is distributed in the hope that it will be useful,
2546- * but WITHOUT ANY WARRANTY; without even the implied warranty of
2547- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
2548- * GNU General Public License for more details.
2549- *
2550- * You should have received a copy of the GNU General Public License
2551- * along with this program. If not, see <http://www.gnu.org/licenses/>.
2552- *
2553- * Author: Pete Woods <pete.woods@canonical.com>
2554- */
2555-
2556-#include <stdexcept>
2557-
2558-#include <usermetricsservice/Authentication.h>
2559-#include <usermetricsservice/DBusUserMetrics.h>
2560-#include <usermetricsservice/DBusUserData.h>
2561-#include <usermetricsservice/DBusDataSet.h>
2562-#include <usermetricsservice/DBusDataSource.h>
2563-#include <usermetricsservice/UserDataAdaptor.h>
2564-#include <usermetricsservice/database/DataSet.h>
2565-#include <usermetricsservice/database/DataSource.h>
2566-#include <usermetricsservice/database/UserData.h>
2567-#include <libusermetricscommon/DateFactory.h>
2568-#include <libusermetricscommon/DBusPaths.h>
2569-#include <libusermetricscommon/Localisation.h>
2570-
2571-#include <QDjangoQuerySet.h>
2572-
2573-using namespace std;
2574-using namespace UserMetricsCommon;
2575-using namespace UserMetricsService;
2576-
2577-DBusUserData::DBusUserData(int id, const QString &username,
2578- DBusUserMetrics &userMetrics, QDBusConnection &dbusConnection,
2579- QSharedPointer<DateFactory> dateFactory,
2580- QSharedPointer<Authentication> authentication, QObject *parent) :
2581- QObject(parent), m_dbusConnection(dbusConnection), m_adaptor(
2582- new UserDataAdaptor(this)), m_dateFactory(dateFactory), m_authentication(
2583- authentication), m_userMetrics(userMetrics), m_id(id), m_path(
2584- DBusPaths::userData(m_id)), m_username(username) {
2585-
2586- // DBus setup
2587- if (!m_dbusConnection.registerObject(m_path, this)) {
2588- throw logic_error(_("Could not register user data object with DBus"));
2589- }
2590-
2591-// Database setup
2592- syncDatabase();
2593-}
2594-
2595-DBusUserData::~DBusUserData() {
2596- QDBusConnection connection(QDBusConnection::sessionBus());
2597- connection.unregisterObject(m_path);
2598-}
2599-
2600-QString DBusUserData::path() const {
2601- return m_path;
2602-}
2603-
2604-QString DBusUserData::username() const {
2605- return m_username;
2606-}
2607-
2608-QList<QDBusObjectPath> DBusUserData::dataSets() const {
2609- QList<QDBusObjectPath> dataSets;
2610- for (DBusDataSetPtr dataSet : m_dataSets.values()) {
2611- dataSets << QDBusObjectPath(dataSet->path());
2612- }
2613- return dataSets;
2614-}
2615-
2616-QDBusObjectPath DBusUserData::createDataSet(const QString &dataSourceName) {
2617- if (!DataSource::exists(dataSourceName)) {
2618- qWarning() << _("Unknown data source") << ": [" << dataSourceName
2619- << "]";
2620- return QDBusObjectPath();
2621- }
2622-
2623- QString dbusUsername(m_authentication->getUsername(*this));
2624- if (!dbusUsername.isEmpty() && !m_username.isEmpty()
2625- && dbusUsername != m_username) {
2626- m_authentication->sendErrorReply(*this, QDBusError::AccessDenied,
2627- _("Attempt to create data set owned by another user"));
2628- return QDBusObjectPath();
2629- }
2630-
2631- QString confinementContext(m_authentication->getConfinementContext(*this));
2632- DataSource dataSource;
2633- DataSource::findByNameAndSecret(dataSourceName, confinementContext,
2634- &dataSource);
2635- if (!dataSource.isValid()) {
2636- m_authentication->sendErrorReply(*this, QDBusError::InternalError,
2637- _("Could not locate user data"));
2638- return QDBusObjectPath();
2639- }
2640- if (dataSource.secret() != "unconfined"
2641- && dataSource.secret() != confinementContext) {
2642- m_authentication->sendErrorReply(*this, QDBusError::AccessDenied,
2643- _("Attempt to create data set owned by another application"));
2644- return QDBusObjectPath();
2645- }
2646-
2647- QDjangoQuerySet<DataSet> dataSets;
2648- QDjangoQuerySet<DataSet> query = dataSets.filter(
2649- QDjangoWhere("userData_id", QDjangoWhere::Equals, m_id)).filter(
2650- QDjangoWhere("dataSource__name", QDjangoWhere::Equals,
2651- dataSourceName));
2652-
2653- if (query.size() == -1) {
2654- throw logic_error(_("Data set query failed"));
2655- }
2656-
2657- DataSet dataSet;
2658-
2659- if (query.size() == 0) {
2660- UserData userData;
2661- UserData::findById(m_id, &userData);
2662- dataSet.setUserData(&userData);
2663-
2664- dataSet.setDataSource(&dataSource);
2665-
2666- if (!dataSet.save()) {
2667- throw logic_error(_("Could not save data set"));
2668- }
2669-
2670- syncDatabase();
2671- } else {
2672- query.at(0, &dataSet);
2673- }
2674-
2675- DBusDataSetPtr dataSetPtr(m_dataSets.value(dataSet.id()));
2676- if (dataSetPtr.isNull()) {
2677- throw logic_error(_("New data set could not be found"));
2678- }
2679- return QDBusObjectPath(dataSetPtr->path());
2680-}
2681-
2682-void DBusUserData::syncDatabase() {
2683- QSet<int> dataSetIds;
2684- QDjangoQuerySet<DataSet> dataSets;
2685- QDjangoQuerySet<DataSet> query(
2686- dataSets.filter(
2687- QDjangoWhere("userData_id", QDjangoWhere::Equals, m_id)));
2688- for (const DataSet &dataSet : query.selectRelated()) {
2689- const int id(dataSet.id());
2690- dataSetIds << id;
2691- // if we don't have a local cache
2692- if (!m_dataSets.contains(id)) {
2693- DBusDataSourcePtr dbusDataSource(
2694- m_userMetrics.dataSource(dataSet.dataSource()->name(),
2695- dataSet.dataSource()->secret()));
2696- DBusDataSetPtr dbusDataSet(
2697- new DBusDataSet(id, dbusDataSource->path(),
2698- m_dbusConnection, m_dateFactory, m_authentication));
2699- m_dataSets.insert(id, dbusDataSet);
2700- m_adaptor->dataSetAdded(QDBusObjectPath(dbusDataSet->dataSource()),
2701- QDBusObjectPath(dbusDataSet->path()));
2702- }
2703- }
2704- // remove any cached references to deleted data sets
2705- QSet<int> cachedDataSetIds(QSet<int>::fromList(m_dataSets.keys()));
2706- QSet<int> &toRemove(cachedDataSetIds.subtract(dataSetIds));
2707- for (int id : toRemove) {
2708- DBusDataSetPtr dataSet = m_dataSets.take(id);
2709- m_adaptor->dataSetRemoved(QDBusObjectPath(dataSet->dataSource()),
2710- QDBusObjectPath(dataSet->path()));
2711- }
2712-}
2713-
2714-DBusDataSetPtr DBusUserData::dataSet(const QString &dataSource) const {
2715- QDjangoQuerySet<DataSet> dataSets;
2716- QScopedPointer<DataSet> dataSet(
2717- dataSets.filter(
2718- QDjangoWhere("userData_id", QDjangoWhere::Equals, m_id)).get(
2719- QDjangoWhere("dataSource__name", QDjangoWhere::Equals,
2720- dataSource)));
2721-
2722- return m_dataSets.value(dataSet->id());
2723-}
2724
2725=== added file 'src/usermetricsservice/Executor.cpp'
2726--- src/usermetricsservice/Executor.cpp 1970-01-01 00:00:00 +0000
2727+++ src/usermetricsservice/Executor.cpp 2014-04-03 13:02:15 +0000
2728@@ -0,0 +1,27 @@
2729+/*
2730+ * Copyright (C) 2014 Canonical, Ltd.
2731+ *
2732+ * This program is free software; you can redistribute it and/or modify
2733+ * it under the terms of the GNU General Public License as published by
2734+ * the Free Software Foundation; version 3.
2735+ *
2736+ * This program is distributed in the hope that it will be useful,
2737+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
2738+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
2739+ * GNU General Public License for more details.
2740+ *
2741+ * You should have received a copy of the GNU General Public License
2742+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
2743+ *
2744+ * Author: Pete Woods <pete.woods@canonical.com>
2745+ */
2746+
2747+#include <usermetricsservice/Executor.h>
2748+
2749+using namespace UserMetricsService;
2750+
2751+Executor::Executor() {
2752+}
2753+
2754+Executor::~Executor() {
2755+}
2756
2757=== added file 'src/usermetricsservice/Executor.h'
2758--- src/usermetricsservice/Executor.h 1970-01-01 00:00:00 +0000
2759+++ src/usermetricsservice/Executor.h 2014-04-03 13:02:15 +0000
2760@@ -0,0 +1,42 @@
2761+/*
2762+ * Copyright (C) 2014 Canonical, Ltd.
2763+ *
2764+ * This program is free software; you can redistribute it and/or modify
2765+ * it under the terms of the GNU General Public License as published by
2766+ * the Free Software Foundation; version 3.
2767+ *
2768+ * This program is distributed in the hope that it will be useful,
2769+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
2770+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
2771+ * GNU General Public License for more details.
2772+ *
2773+ * You should have received a copy of the GNU General Public License
2774+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
2775+ *
2776+ * Author: Pete Woods <pete.woods@canonical.com>
2777+ */
2778+
2779+#ifndef USERMETRICSSERVICE_EXECUTOR_H_
2780+#define USERMETRICSSERVICE_EXECUTOR_H_
2781+
2782+#include <QByteArray>
2783+#include <QSharedPointer>
2784+#include <QStringList>
2785+
2786+namespace UserMetricsService {
2787+
2788+class Executor {
2789+public:
2790+ typedef QSharedPointer<Executor> Ptr;
2791+
2792+ Executor();
2793+
2794+ virtual ~Executor();
2795+
2796+ virtual QByteArray execute(const QString &program,
2797+ const QStringList &arguments) = 0;
2798+};
2799+
2800+}
2801+
2802+#endif /* USERMETRICSSERVICE_EXECUTOR_H_ */
2803
2804=== added file 'src/usermetricsservice/Factory.cpp'
2805--- src/usermetricsservice/Factory.cpp 1970-01-01 00:00:00 +0000
2806+++ src/usermetricsservice/Factory.cpp 2014-04-03 13:02:15 +0000
2807@@ -0,0 +1,90 @@
2808+/*
2809+ * Copyright (C) 2014 Canonical, Ltd.
2810+ *
2811+ * This program is free software; you can redistribute it and/or modify
2812+ * it under the terms of the GNU General Public License as published by
2813+ * the Free Software Foundation; version 3.
2814+ *
2815+ * This program is distributed in the hope that it will be useful,
2816+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
2817+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
2818+ * GNU General Public License for more details.
2819+ *
2820+ * You should have received a copy of the GNU General Public License
2821+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
2822+ *
2823+ * Author: Pete Woods <pete.woods@canonical.com>
2824+ */
2825+
2826+#include <libusermetricscommon/DBusPaths.h>
2827+#include <usermetricsservice/Factory.h>
2828+#include <usermetricsservice/InfographicImpl.h>
2829+#include <usermetricsservice/QProcessExecutor.h>
2830+#include <usermetricsservice/ResultTransportImpl.h>
2831+#include <usermetricsservice/SourceDirectoryImpl.h>
2832+#include <usermetricsservice/ServiceImpl.h>
2833+
2834+using namespace UserMetricsCommon;
2835+using namespace UserMetricsService;
2836+
2837+Factory::Factory() {
2838+}
2839+
2840+Factory::~Factory() {
2841+}
2842+
2843+Service::Ptr Factory::singletonService() {
2844+ if (!m_service) {
2845+ m_service.reset(
2846+ new ServiceImpl(QDir::home().filePath(".cache"),
2847+ QDir("/usr/share/libusermetrics/infographics"),
2848+ singletonFileUtils(), singletonResultTransport(),
2849+ *this));
2850+ }
2851+ return m_service;
2852+}
2853+
2854+FileUtils::Ptr Factory::singletonFileUtils() {
2855+ if (!m_fileUtils) {
2856+ m_fileUtils.reset(new FileUtils());
2857+ }
2858+ return m_fileUtils;
2859+}
2860+
2861+Executor::Ptr Factory::singletonExecutor() {
2862+ if (!m_executor) {
2863+ m_executor.reset(new QProcessExecutor(QDir::home().filePath(".cache"),
2864+ AA_EXEC_PATH));
2865+ }
2866+ return m_executor;
2867+}
2868+
2869+QSharedPointer<ComCanonicalInfographicsInterface> Factory::singletonInfographicService() {
2870+ if (!m_infographicService) {
2871+ m_infographicService.reset(
2872+ new ComCanonicalInfographicsInterface(
2873+ DBusPaths::INFOGRAPHIC_DBUS_NAME,
2874+ DBusPaths::INFOGRAPHIC_DBUS_PATH,
2875+ QDBusConnection::systemBus()));
2876+ }
2877+ return m_infographicService;
2878+}
2879+
2880+ResultTransport::Ptr Factory::singletonResultTransport() {
2881+ if (!m_resultTransport) {
2882+ m_resultTransport.reset(
2883+ new ResultTransportImpl(singletonInfographicService()));
2884+ }
2885+ return m_resultTransport;
2886+}
2887+
2888+Infographic::Ptr Factory::newInfographic(const QFile &path) {
2889+ return Infographic::Ptr(
2890+ new InfographicImpl(path, singletonExecutor(),
2891+ singletonResultTransport()));
2892+}
2893+
2894+SourceDirectory::Ptr Factory::newSourceDirectory(const QDir &path) {
2895+ return SourceDirectory::Ptr(
2896+ new SourceDirectoryImpl(path, singletonFileUtils()));
2897+}
2898
2899=== added file 'src/usermetricsservice/Factory.h'
2900--- src/usermetricsservice/Factory.h 1970-01-01 00:00:00 +0000
2901+++ src/usermetricsservice/Factory.h 2014-04-03 13:02:15 +0000
2902@@ -0,0 +1,69 @@
2903+/*
2904+ * Copyright (C) 2014 Canonical, Ltd.
2905+ *
2906+ * This program is free software; you can redistribute it and/or modify
2907+ * it under the terms of the GNU General Public License as published by
2908+ * the Free Software Foundation; version 3.
2909+ *
2910+ * This program is distributed in the hope that it will be useful,
2911+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
2912+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
2913+ * GNU General Public License for more details.
2914+ *
2915+ * You should have received a copy of the GNU General Public License
2916+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
2917+ *
2918+ * Author: Pete Woods <pete.woods@canonical.com>
2919+ */
2920+
2921+#ifndef USERMETRICSSERVICE_FACTORY_H_
2922+#define USERMETRICSSERVICE_FACTORY_H_
2923+
2924+#include <libusermetricscommon/FileUtils.h>
2925+#include <libusermetricscommon/InfographicsInterface.h>
2926+#include <usermetricsservice/Executor.h>
2927+#include <usermetricsservice/Infographic.h>
2928+#include <usermetricsservice/ResultTransport.h>
2929+#include <usermetricsservice/Service.h>
2930+#include <usermetricsservice/SourceDirectory.h>
2931+
2932+#include <QFile>
2933+#include <QDir>
2934+
2935+namespace UserMetricsService {
2936+
2937+class Factory {
2938+public:
2939+ Factory();
2940+
2941+ virtual ~Factory();
2942+
2943+ virtual Service::Ptr singletonService();
2944+
2945+ virtual UserMetricsCommon::FileUtils::Ptr singletonFileUtils();
2946+
2947+ virtual Executor::Ptr singletonExecutor();
2948+
2949+ virtual QSharedPointer<ComCanonicalInfographicsInterface> singletonInfographicService();
2950+
2951+ virtual ResultTransport::Ptr singletonResultTransport();
2952+
2953+ virtual Infographic::Ptr newInfographic(const QFile &path);
2954+
2955+ virtual SourceDirectory::Ptr newSourceDirectory(const QDir &path);
2956+
2957+protected:
2958+ Service::Ptr m_service;
2959+
2960+ UserMetricsCommon::FileUtils::Ptr m_fileUtils;
2961+
2962+ Executor::Ptr m_executor;
2963+
2964+ QSharedPointer<ComCanonicalInfographicsInterface> m_infographicService;
2965+
2966+ ResultTransport::Ptr m_resultTransport;
2967+};
2968+
2969+}
2970+
2971+#endif /* USERMETRICSSERVICE_FACTORY_H_ */
2972
2973=== added file 'src/usermetricsservice/Infographic.cpp'
2974--- src/usermetricsservice/Infographic.cpp 1970-01-01 00:00:00 +0000
2975+++ src/usermetricsservice/Infographic.cpp 2014-04-03 13:02:15 +0000
2976@@ -0,0 +1,27 @@
2977+/*
2978+ * Copyright (C) 2014 Canonical, Ltd.
2979+ *
2980+ * This program is free software; you can redistribute it and/or modify
2981+ * it under the terms of the GNU General Public License as published by
2982+ * the Free Software Foundation; version 3.
2983+ *
2984+ * This program is distributed in the hope that it will be useful,
2985+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
2986+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
2987+ * GNU General Public License for more details.
2988+ *
2989+ * You should have received a copy of the GNU General Public License
2990+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
2991+ *
2992+ * Author: Pete Woods <pete.woods@canonical.com>
2993+ */
2994+
2995+#include <usermetricsservice/Infographic.h>
2996+
2997+using namespace UserMetricsService;
2998+
2999+Infographic::Infographic() {
3000+}
3001+
3002+Infographic::~Infographic() {
3003+}
3004
3005=== added file 'src/usermetricsservice/Infographic.h'
3006--- src/usermetricsservice/Infographic.h 1970-01-01 00:00:00 +0000
3007+++ src/usermetricsservice/Infographic.h 2014-04-03 13:02:15 +0000
3008@@ -0,0 +1,52 @@
3009+/*
3010+ * Copyright (C) 2014 Canonical, Ltd.
3011+ *
3012+ * This program is free software; you can redistribute it and/or modify
3013+ * it under the terms of the GNU General Public License as published by
3014+ * the Free Software Foundation; version 3.
3015+ *
3016+ * This program is distributed in the hope that it will be useful,
3017+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
3018+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
3019+ * GNU General Public License for more details.
3020+ *
3021+ * You should have received a copy of the GNU General Public License
3022+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
3023+ *
3024+ * Author: Pete Woods <pete.woods@canonical.com>
3025+ */
3026+
3027+#ifndef USERMETRICSSERVICE_INFOGRAPHIC_H_
3028+#define USERMETRICSSERVICE_INFOGRAPHIC_H_
3029+
3030+#include <QSharedPointer>
3031+
3032+namespace UserMetricsService {
3033+
3034+class Infographic: public QObject {
3035+Q_OBJECT
3036+
3037+public:
3038+ typedef QSharedPointer<Infographic> Ptr;
3039+
3040+ enum class Type {
3041+ INVALID, ITERATE, AGGREGATE,
3042+ };
3043+
3044+ Infographic();
3045+
3046+ virtual ~Infographic();
3047+
3048+ virtual bool isValid() const = 0;
3049+
3050+ virtual Type type() const = 0;
3051+
3052+public Q_SLOTS:
3053+ virtual void sourcesChanged(
3054+ const QMultiMap<QString, QString> &changedSources,
3055+ const QMultiMap<QString, QString> &allSources) = 0;
3056+};
3057+
3058+}
3059+
3060+#endif /* USERMETRICSSERVICE_INFOGRAPHIC_H_ */
3061
3062=== added file 'src/usermetricsservice/InfographicImpl.cpp'
3063--- src/usermetricsservice/InfographicImpl.cpp 1970-01-01 00:00:00 +0000
3064+++ src/usermetricsservice/InfographicImpl.cpp 2014-04-03 13:02:15 +0000
3065@@ -0,0 +1,170 @@
3066+/*
3067+ * Copyright (C) 2014 Canonical, Ltd.
3068+ *
3069+ * This program is free software; you can redistribute it and/or modify
3070+ * it under the terms of the GNU General Public License as published by
3071+ * the Free Software Foundation; version 3.
3072+ *
3073+ * This program is distributed in the hope that it will be useful,
3074+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
3075+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
3076+ * GNU General Public License for more details.
3077+ *
3078+ * You should have received a copy of the GNU General Public License
3079+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
3080+ *
3081+ * Author: Pete Woods <pete.woods@canonical.com>
3082+ */
3083+
3084+#include <usermetricsservice/InfographicImpl.h>
3085+#include <usermetricsservice/Service.h>
3086+
3087+#include <QDebug>
3088+#include <QFile>
3089+#include <QFileInfo>
3090+#include <QJsonDocument>
3091+#include <QJsonParseError>
3092+#include <QTemporaryFile>
3093+
3094+using namespace UserMetricsService;
3095+
3096+InfographicImpl::InfographicImpl(const QFile &path, Executor::Ptr executor,
3097+ ResultTransport::Ptr resultTransport) :
3098+ m_path(path.fileName()), m_executor(executor), m_resultTransport(
3099+ resultTransport), m_type(Type::INVALID), m_ruleCount(0) {
3100+
3101+ if (!m_path.open(QIODevice::ReadOnly)) {
3102+ qWarning() << "Failed to open path:" << m_path.fileName();
3103+ return;
3104+ }
3105+
3106+ QByteArray ba(m_path.readAll());
3107+ m_path.close();
3108+
3109+ QJsonParseError error;
3110+ QJsonDocument document(QJsonDocument::fromJson(ba, &error));
3111+ if (error.error != QJsonParseError::NoError) {
3112+ qWarning() << "Failed to parse infographic JSON document:"
3113+ << m_path.fileName() << error.errorString();
3114+ return;
3115+ }
3116+
3117+ if (document.isNull() || document.isEmpty()) {
3118+ return;
3119+ }
3120+
3121+ QFileInfo fileInfo(m_path);
3122+ m_id = fileInfo.completeBaseName();
3123+
3124+ QVariantMap map(document.toVariant().toMap());
3125+
3126+ m_exec = map["exec"].toString();
3127+
3128+ QString type = map["type"].toString().toLower();
3129+ if (type == "iterate") {
3130+ m_type = Type::ITERATE;
3131+ } else if (type == "aggregate") {
3132+ m_type = Type::AGGREGATE;
3133+ }
3134+
3135+ QVariantMap input(map["input"].toMap());
3136+ QMapIterator<QString, QVariant> i(input);
3137+ while (i.hasNext()) {
3138+ i.next();
3139+ QStringList rules(i.value().toStringList());
3140+ auto list = m_rules.insert(i.key(), QList<QRegularExpression>());
3141+ for (const QString &rule : rules) {
3142+ *list << QRegularExpression(rule);
3143+ }
3144+ m_ruleCount += rules.size();
3145+ }
3146+}
3147+
3148+InfographicImpl::~InfographicImpl() {
3149+}
3150+
3151+bool InfographicImpl::isValid() const {
3152+ return QFile::exists(m_exec) && m_type != Type::INVALID;
3153+}
3154+
3155+Infographic::Type InfographicImpl::type() const {
3156+ return m_type;
3157+}
3158+
3159+void InfographicImpl::sourcesChanged(
3160+ const QMultiMap<QString, QString> &changedSources,
3161+ const QMultiMap<QString, QString> &allSources) {
3162+ switch (m_type) {
3163+ case Type::INVALID:
3164+ break;
3165+ case Type::ITERATE:
3166+ iterate(changedSources);
3167+ break;
3168+ case Type::AGGREGATE:
3169+ aggregate(changedSources, allSources);
3170+ break;
3171+ }
3172+}
3173+
3174+QStringList InfographicImpl::match(
3175+ const QMultiMap<QString, QString>& changedSources) {
3176+
3177+ QStringList output;
3178+
3179+ QMapIterator<QString, QList<QRegularExpression>> iter(m_rules);
3180+ while (iter.hasNext()) {
3181+ iter.next();
3182+ const QString& sourceName(iter.key());
3183+ QStringList changedFiles;
3184+ if (sourceName == "*") {
3185+ changedFiles = changedSources.values();
3186+ } else if (changedSources.contains(sourceName)) {
3187+ changedFiles = changedSources.values(sourceName);
3188+ }
3189+
3190+ const QList<QRegularExpression> &watchedFiles(iter.value());
3191+ for (const QRegularExpression &watchedFile : watchedFiles) {
3192+ for (const QString &changedFile : changedFiles) {
3193+ QString changedFileName(QFileInfo(changedFile).fileName());
3194+ if (watchedFile.match(changedFileName).hasMatch()) {
3195+ output << changedFile;
3196+ }
3197+ }
3198+ }
3199+ }
3200+ return output;
3201+}
3202+
3203+void InfographicImpl::iterate(
3204+ const QMultiMap<QString, QString> &changedSources) {
3205+
3206+ for (const QString &changedFile : match(changedSources)) {
3207+ execute(QStringList() << changedFile);
3208+ }
3209+}
3210+
3211+void InfographicImpl::aggregate(
3212+ const QMultiMap<QString, QString> &changedSources,
3213+ const QMultiMap<QString, QString> &allSources) {
3214+
3215+ if (match(changedSources).isEmpty()) {
3216+ return;
3217+ }
3218+
3219+ // If we get a match for every rule
3220+ QStringList matches(match(allSources));
3221+ if (m_ruleCount == matches.size()) {
3222+ execute(matches);
3223+ }
3224+}
3225+
3226+void InfographicImpl::execute(const QStringList &arguments) {
3227+ QByteArray ba(m_executor->execute(m_exec, arguments));
3228+
3229+ if (ba.isEmpty()) {
3230+ qWarning() << "No data provided by infographic" << m_exec;
3231+ return;
3232+ }
3233+
3234+ m_resultTransport->send(m_id, arguments, ba);
3235+}
3236
3237=== added file 'src/usermetricsservice/InfographicImpl.h'
3238--- src/usermetricsservice/InfographicImpl.h 1970-01-01 00:00:00 +0000
3239+++ src/usermetricsservice/InfographicImpl.h 2014-04-03 13:02:15 +0000
3240@@ -0,0 +1,79 @@
3241+/*
3242+ * Copyright (C) 2014 Canonical, Ltd.
3243+ *
3244+ * This program is free software; you can redistribute it and/or modify
3245+ * it under the terms of the GNU General Public License as published by
3246+ * the Free Software Foundation; version 3.
3247+ *
3248+ * This program is distributed in the hope that it will be useful,
3249+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
3250+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
3251+ * GNU General Public License for more details.
3252+ *
3253+ * You should have received a copy of the GNU General Public License
3254+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
3255+ *
3256+ * Author: Pete Woods <pete.woods@canonical.com>
3257+ */
3258+
3259+#ifndef USERMETRICSSERVICE_INFOGRAPHICIMPL_H_
3260+#define USERMETRICSSERVICE_INFOGRAPHICIMPL_H_
3261+
3262+#include <usermetricsservice/Executor.h>
3263+#include <usermetricsservice/Infographic.h>
3264+#include <usermetricsservice/ResultTransport.h>
3265+
3266+#include <QFile>
3267+#include <QMap>
3268+#include <QRegularExpression>
3269+#include <QString>
3270+#include <QStringList>
3271+#include <QVariant>
3272+
3273+namespace UserMetricsService {
3274+
3275+class InfographicImpl: public Infographic {
3276+public:
3277+ InfographicImpl(const QFile &path, Executor::Ptr executor,
3278+ ResultTransport::Ptr resultTransport);
3279+
3280+ virtual ~InfographicImpl();
3281+
3282+ bool isValid() const;
3283+
3284+ Type type() const;
3285+
3286+ void sourcesChanged(const QMultiMap<QString, QString> &changedSources,
3287+ const QMultiMap<QString, QString> &allSources);
3288+
3289+protected:
3290+ void iterate(const QMultiMap<QString, QString> &changedSources);
3291+
3292+ void aggregate(const QMultiMap<QString, QString> &changedSources,
3293+ const QMultiMap<QString, QString> &allSources);
3294+
3295+ void execute(const QStringList &args);
3296+
3297+ QStringList match(const QMultiMap<QString, QString>& changedSources);
3298+
3299+ QFile m_path;
3300+
3301+ Executor::Ptr m_executor;
3302+
3303+ ResultTransport::Ptr m_resultTransport;
3304+
3305+ QString m_exec;
3306+
3307+ Type m_type;
3308+
3309+ QMap<QString, QList<QRegularExpression>> m_rules;
3310+
3311+ int m_ruleCount;
3312+
3313+ QString m_id;
3314+
3315+};
3316+
3317+}
3318+
3319+#endif /* USERMETRICSSERVICE_INFOGRAPHICIMPL_H_ */
3320
3321=== added file 'src/usermetricsservice/QProcessExecutor.cpp'
3322--- src/usermetricsservice/QProcessExecutor.cpp 1970-01-01 00:00:00 +0000
3323+++ src/usermetricsservice/QProcessExecutor.cpp 2014-04-03 13:02:15 +0000
3324@@ -0,0 +1,75 @@
3325+/*
3326+ * Copyright (C) 2014 Canonical, Ltd.
3327+ *
3328+ * This program is free software; you can redistribute it and/or modify
3329+ * it under the terms of the GNU General Public License as published by
3330+ * the Free Software Foundation; version 3.
3331+ *
3332+ * This program is distributed in the hope that it will be useful,
3333+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
3334+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
3335+ * GNU General Public License for more details.
3336+ *
3337+ * You should have received a copy of the GNU General Public License
3338+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
3339+ *
3340+ * Author: Pete Woods <pete.woods@canonical.com>
3341+ */
3342+
3343+#include <usermetricsservice/QProcessExecutor.h>
3344+
3345+#include <QDebug>
3346+#include <QProcess>
3347+#include <QThread>
3348+
3349+using namespace UserMetricsService;
3350+
3351+QProcessExecutor::QProcessExecutor(const QDir &cacheDirectory,
3352+ const QString &aaExec) :
3353+ m_aaExec(aaExec) {
3354+
3355+ m_usermetricsDirectory = cacheDirectory.filePath("usermetrics");
3356+ m_tempDirectory = m_usermetricsDirectory.filePath("tmp");
3357+}
3358+
3359+QProcessExecutor::~QProcessExecutor() {
3360+}
3361+
3362+QByteArray QProcessExecutor::execute(const QString &program,
3363+ const QStringList &arguments) {
3364+
3365+ m_tempDirectory.removeRecursively();
3366+ m_usermetricsDirectory.mkpath("tmp");
3367+
3368+ QByteArray output;
3369+
3370+ QStringList finalArguments;
3371+ finalArguments << program;
3372+ for (int i(0); i < arguments.size(); ++i) {
3373+ const QString &argument(arguments[i]);
3374+ QString destination(
3375+ m_tempDirectory.filePath(QString::number(i) + ".svg"));
3376+ if (!QFile::copy(argument, destination)) {
3377+ qWarning() << "Failed to copy file" << argument << destination;
3378+ return output;
3379+ }
3380+ finalArguments << destination;
3381+ }
3382+
3383+ QProcess process;
3384+
3385+ process.start(m_aaExec, finalArguments);
3386+
3387+ if (process.waitForFinished(5000)) {
3388+ output = process.readAllStandardOutput();
3389+ QByteArray error(process.readAllStandardError());
3390+ if (!error.isEmpty()) {
3391+ qWarning() << error;
3392+ }
3393+ } else {
3394+ process.kill();
3395+ }
3396+
3397+ return output;
3398+}
3399+
3400
3401=== added file 'src/usermetricsservice/QProcessExecutor.h'
3402--- src/usermetricsservice/QProcessExecutor.h 1970-01-01 00:00:00 +0000
3403+++ src/usermetricsservice/QProcessExecutor.h 2014-04-03 13:02:15 +0000
3404@@ -0,0 +1,46 @@
3405+/*
3406+ * Copyright (C) 2014 Canonical, Ltd.
3407+ *
3408+ * This program is free software; you can redistribute it and/or modify
3409+ * it under the terms of the GNU General Public License as published by
3410+ * the Free Software Foundation; version 3.
3411+ *
3412+ * This program is distributed in the hope that it will be useful,
3413+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
3414+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
3415+ * GNU General Public License for more details.
3416+ *
3417+ * You should have received a copy of the GNU General Public License
3418+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
3419+ *
3420+ * Author: Pete Woods <pete.woods@canonical.com>
3421+ */
3422+
3423+#ifndef USERMETRICSSERVICE_QPROCESSEXECUTOR_H_
3424+#define USERMETRICSSERVICE_QPROCESSEXECUTOR_H_
3425+
3426+#include <usermetricsservice/Executor.h>
3427+
3428+#include <QDir>
3429+
3430+namespace UserMetricsService {
3431+
3432+class QProcessExecutor: public Executor {
3433+public:
3434+ QProcessExecutor(const QDir &cacheDirectory, const QString &aaExec);
3435+
3436+ virtual ~QProcessExecutor();
3437+
3438+ QByteArray execute(const QString &program, const QStringList &arguments);
3439+
3440+protected:
3441+ QDir m_usermetricsDirectory;
3442+
3443+ QDir m_tempDirectory;
3444+
3445+ QString m_aaExec;
3446+};
3447+
3448+}
3449+
3450+#endif /* USERMETRICSSERVICE_QPROCESSEXECUTOR_H_ */
3451
3452=== added file 'src/usermetricsservice/ResultTransport.cpp'
3453--- src/usermetricsservice/ResultTransport.cpp 1970-01-01 00:00:00 +0000
3454+++ src/usermetricsservice/ResultTransport.cpp 2014-04-03 13:02:15 +0000
3455@@ -0,0 +1,27 @@
3456+/*
3457+ * Copyright (C) 2014 Canonical, Ltd.
3458+ *
3459+ * This program is free software; you can redistribute it and/or modify
3460+ * it under the terms of the GNU General Public License as published by
3461+ * the Free Software Foundation; version 3.
3462+ *
3463+ * This program is distributed in the hope that it will be useful,
3464+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
3465+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
3466+ * GNU General Public License for more details.
3467+ *
3468+ * You should have received a copy of the GNU General Public License
3469+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
3470+ *
3471+ * Author: Pete Woods <pete.woods@canonical.com>
3472+ */
3473+
3474+#include <usermetricsservice/ResultTransport.h>
3475+
3476+using namespace UserMetricsService;
3477+
3478+ResultTransport::ResultTransport() {
3479+}
3480+
3481+ResultTransport::~ResultTransport() {
3482+}
3483
3484=== added file 'src/usermetricsservice/ResultTransport.h'
3485--- src/usermetricsservice/ResultTransport.h 1970-01-01 00:00:00 +0000
3486+++ src/usermetricsservice/ResultTransport.h 2014-04-03 13:02:15 +0000
3487@@ -0,0 +1,45 @@
3488+/*
3489+ * Copyright (C) 2014 Canonical, Ltd.
3490+ *
3491+ * This program is free software; you can redistribute it and/or modify
3492+ * it under the terms of the GNU General Public License as published by
3493+ * the Free Software Foundation; version 3.
3494+ *
3495+ * This program is distributed in the hope that it will be useful,
3496+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
3497+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
3498+ * GNU General Public License for more details.
3499+ *
3500+ * You should have received a copy of the GNU General Public License
3501+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
3502+ *
3503+ * Author: Pete Woods <pete.woods@canonical.com>
3504+ */
3505+
3506+#ifndef USERMETRICSSERVICE_RESULTTRANSPORT_H_
3507+#define USERMETRICSSERVICE_RESULTTRANSPORT_H_
3508+
3509+#include <QByteArray>
3510+#include <QString>
3511+#include <QStringList>
3512+#include <QSharedPointer>
3513+
3514+namespace UserMetricsService {
3515+
3516+class ResultTransport {
3517+public:
3518+ typedef QSharedPointer<ResultTransport> Ptr;
3519+
3520+ ResultTransport();
3521+
3522+ virtual ~ResultTransport();
3523+
3524+ virtual void clear() = 0;
3525+
3526+ virtual void send(const QString &id, const QStringList &arguments,
3527+ const QByteArray &ba) = 0;
3528+};
3529+
3530+}
3531+
3532+#endif /* USERMETRICSSERVICE_RESULTTRANSPORT_H_ */
3533
3534=== added file 'src/usermetricsservice/ResultTransportImpl.cpp'
3535--- src/usermetricsservice/ResultTransportImpl.cpp 1970-01-01 00:00:00 +0000
3536+++ src/usermetricsservice/ResultTransportImpl.cpp 2014-04-03 13:02:15 +0000
3537@@ -0,0 +1,66 @@
3538+/*
3539+ * Copyright (C) 2014 Canonical, Ltd.
3540+ *
3541+ * This program is free software; you can redistribute it and/or modify
3542+ * it under the terms of the GNU General Public License as published by
3543+ * the Free Software Foundation; version 3.
3544+ *
3545+ * This program is distributed in the hope that it will be useful,
3546+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
3547+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
3548+ * GNU General Public License for more details.
3549+ *
3550+ * You should have received a copy of the GNU General Public License
3551+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
3552+ *
3553+ * Author: Pete Woods <pete.woods@canonical.com>
3554+ */
3555+
3556+#include <usermetricsservice/ResultTransportImpl.h>
3557+
3558+#include <QDebug>
3559+#include <sys/stat.h>
3560+
3561+using namespace UserMetricsService;
3562+
3563+ResultTransportImpl::ResultTransportImpl(
3564+ QSharedPointer<ComCanonicalInfographicsInterface> infographicService) :
3565+ m_infographicService(infographicService) {
3566+}
3567+
3568+ResultTransportImpl::~ResultTransportImpl() {
3569+}
3570+
3571+void ResultTransportImpl::clear() {
3572+ m_infographicService->clear().waitForFinished();
3573+}
3574+
3575+void ResultTransportImpl::send(const QString &id, const QStringList &arguments,
3576+ const QByteArray &ba) {
3577+ QFile fifo;
3578+ {
3579+ QTemporaryFile tempFile;
3580+ tempFile.open();
3581+ tempFile.close();
3582+ fifo.setFileName(tempFile.fileName());
3583+ }
3584+
3585+ int err = mkfifo(fifo.fileName().toUtf8().constData(), 0644);
3586+ if (err != 0) {
3587+ // someone is trying something naughty
3588+ qWarning() << "FIFO path already existed" << fifo.fileName();
3589+ return;
3590+ }
3591+
3592+ QDBusPendingReply<> reply(
3593+ m_infographicService->update(id, arguments, fifo.fileName()));
3594+
3595+ if (fifo.open(QIODevice::WriteOnly)) {
3596+ fifo.write(ba);
3597+ fifo.close();
3598+ }
3599+
3600+ reply.waitForFinished();
3601+
3602+ fifo.remove();
3603+}
3604
3605=== added file 'src/usermetricsservice/ResultTransportImpl.h'
3606--- src/usermetricsservice/ResultTransportImpl.h 1970-01-01 00:00:00 +0000
3607+++ src/usermetricsservice/ResultTransportImpl.h 2014-04-03 13:02:15 +0000
3608@@ -0,0 +1,45 @@
3609+/*
3610+ * Copyright (C) 2014 Canonical, Ltd.
3611+ *
3612+ * This program is free software; you can redistribute it and/or modify
3613+ * it under the terms of the GNU General Public License as published by
3614+ * the Free Software Foundation; version 3.
3615+ *
3616+ * This program is distributed in the hope that it will be useful,
3617+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
3618+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
3619+ * GNU General Public License for more details.
3620+ *
3621+ * You should have received a copy of the GNU General Public License
3622+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
3623+ *
3624+ * Author: Pete Woods <pete.woods@canonical.com>
3625+ */
3626+
3627+#ifndef USERMETRICSSERVICE_RESULTTRANSPORTIMPL_H_
3628+#define USERMETRICSSERVICE_RESULTTRANSPORTIMPL_H_
3629+
3630+#include <libusermetricscommon/InfographicsInterface.h>
3631+#include <usermetricsservice/ResultTransport.h>
3632+
3633+namespace UserMetricsService {
3634+
3635+class ResultTransportImpl: public ResultTransport {
3636+public:
3637+ ResultTransportImpl(
3638+ QSharedPointer<ComCanonicalInfographicsInterface> infographicService);
3639+
3640+ virtual ~ResultTransportImpl();
3641+
3642+ void clear();
3643+
3644+ void send(const QString &id, const QStringList &arguments,
3645+ const QByteArray &ba);
3646+
3647+protected:
3648+ QSharedPointer<ComCanonicalInfographicsInterface> m_infographicService;
3649+};
3650+
3651+}
3652+
3653+#endif /* USERMETRICSSERVICE_RESULTTRANSPORTIMPL_H_ */
3654
3655=== added file 'src/usermetricsservice/Service.cpp'
3656--- src/usermetricsservice/Service.cpp 1970-01-01 00:00:00 +0000
3657+++ src/usermetricsservice/Service.cpp 2014-04-03 13:02:15 +0000
3658@@ -0,0 +1,27 @@
3659+/*
3660+ * Copyright (C) 2014 Canonical, Ltd.
3661+ *
3662+ * This program is free software; you can redistribute it and/or modify
3663+ * it under the terms of the GNU General Public License as published by
3664+ * the Free Software Foundation; version 3.
3665+ *
3666+ * This program is distributed in the hope that it will be useful,
3667+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
3668+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
3669+ * GNU General Public License for more details.
3670+ *
3671+ * You should have received a copy of the GNU General Public License
3672+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
3673+ *
3674+ * Author: Pete Woods <pete.woods@canonical.com>
3675+ */
3676+
3677+#include <usermetricsservice/Service.h>
3678+
3679+using namespace UserMetricsService;
3680+
3681+Service::Service() {
3682+}
3683+
3684+Service::~Service() {
3685+}
3686
3687=== added file 'src/usermetricsservice/Service.h'
3688--- src/usermetricsservice/Service.h 1970-01-01 00:00:00 +0000
3689+++ src/usermetricsservice/Service.h 2014-04-03 13:02:15 +0000
3690@@ -0,0 +1,45 @@
3691+/*
3692+ * Copyright (C) 2014 Canonical, Ltd.
3693+ *
3694+ * This program is free software; you can redistribute it and/or modify
3695+ * it under the terms of the GNU General Public License as published by
3696+ * the Free Software Foundation; version 3.
3697+ *
3698+ * This program is distributed in the hope that it will be useful,
3699+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
3700+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
3701+ * GNU General Public License for more details.
3702+ *
3703+ * You should have received a copy of the GNU General Public License
3704+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
3705+ *
3706+ * Author: Pete Woods <pete.woods@canonical.com>
3707+ */
3708+
3709+#ifndef USERMETRICSSERVICE_SERVICE_H_
3710+#define USERMETRICSSERVICE_SERVICE_H_
3711+
3712+#include <QObject>
3713+#include <QMultiMap>
3714+#include <QSharedPointer>
3715+#include <QString>
3716+
3717+namespace UserMetricsService {
3718+
3719+class Service: public QObject {
3720+Q_OBJECT
3721+public:
3722+ typedef QSharedPointer<Service> Ptr;
3723+
3724+ Service();
3725+
3726+ virtual ~Service();
3727+
3728+Q_SIGNALS:
3729+ void sourcesChanged(const QMultiMap<QString, QString> &changedSources,
3730+ const QMultiMap<QString, QString> &allSources);
3731+};
3732+
3733+}
3734+
3735+#endif /* USERMETRICSSERVICE_SERVICE_H_ */
3736
3737=== added file 'src/usermetricsservice/ServiceImpl.cpp'
3738--- src/usermetricsservice/ServiceImpl.cpp 1970-01-01 00:00:00 +0000
3739+++ src/usermetricsservice/ServiceImpl.cpp 2014-04-03 13:02:15 +0000
3740@@ -0,0 +1,163 @@
3741+/*
3742+ * Copyright (C) 2014 Canonical, Ltd.
3743+ *
3744+ * This program is free software; you can redistribute it and/or modify
3745+ * it under the terms of the GNU General Public License as published by
3746+ * the Free Software Foundation; version 3.
3747+ *
3748+ * This program is distributed in the hope that it will be useful,
3749+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
3750+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
3751+ * GNU General Public License for more details.
3752+ *
3753+ * You should have received a copy of the GNU General Public License
3754+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
3755+ *
3756+ * Author: Pete Woods <pete.woods@canonical.com>
3757+ */
3758+
3759+#include <usermetricsservice/ServiceImpl.h>
3760+
3761+#include <QDebug>
3762+#include <QStringList>
3763+#include <stdexcept>
3764+
3765+using namespace UserMetricsCommon;
3766+using namespace UserMetricsService;
3767+using namespace std;
3768+
3769+ServiceImpl::ServiceImpl(const QDir &cacheDirectory,
3770+ const QDir &packageInfographics, FileUtils::Ptr fileUtils,
3771+ ResultTransport::Ptr resultTransport, Factory &factory) :
3772+ m_cacheDirectory(cacheDirectory), m_fileUtils(fileUtils), m_resultTransport(
3773+ resultTransport), m_factory(factory) {
3774+ QDir usermetricsDirectory(cacheDirectory.filePath("usermetrics"));
3775+
3776+ if (!usermetricsDirectory.mkpath("infographics")) {
3777+ throw logic_error("Cannot create infographics directory");
3778+ }
3779+
3780+ if (!usermetricsDirectory.mkpath("sources")) {
3781+ throw logic_error("Cannot create sources directory");
3782+ }
3783+
3784+ m_infographicDirectories << usermetricsDirectory.filePath("infographics");
3785+ m_infographicDirectories << packageInfographics.path();
3786+ m_sourcesDirectory = usermetricsDirectory.filePath("sources");
3787+
3788+ m_timer.setSingleShot(true);
3789+
3790+ connect(&m_infographicWatcher, &QFileSystemWatcher::directoryChanged, this,
3791+ &ServiceImpl::updateInfographicList);
3792+ connect(&m_sourcesWatcher, &QFileSystemWatcher::directoryChanged, this,
3793+ &ServiceImpl::updateSourcesList);
3794+
3795+ connect(&m_timer, &QTimer::timeout, this, &ServiceImpl::flushQueue);
3796+
3797+ updateInfographicList();
3798+ updateSourcesList();
3799+
3800+ m_infographicWatcher.addPaths(m_infographicDirectories);
3801+ m_sourcesWatcher.addPath(m_sourcesDirectory.path());
3802+
3803+ m_resultTransport->clear();
3804+
3805+ QMultiMap<QString, QString> sources(allSources());
3806+ sourcesChanged(sources, sources);
3807+}
3808+
3809+ServiceImpl::~ServiceImpl() {
3810+}
3811+
3812+void ServiceImpl::updateInfographicList() {
3813+ QSet<QString> names;
3814+
3815+ for (const QString &directory : m_infographicDirectories) {
3816+ names.unite(m_fileUtils->listDirectory(directory, QDir::Files).toSet());
3817+ }
3818+
3819+ // Remove deleted infographics
3820+ QSet<QString> toRemove(m_infographics.keys().toSet().subtract(names));
3821+ for (const QString &name : toRemove) {
3822+ m_infographics.take(name);
3823+ }
3824+
3825+ // Work out the names we need to add
3826+ names.subtract(m_infographics.keys().toSet());
3827+ for (const QString &name : names) {
3828+ Infographic::Ptr infographic(m_factory.newInfographic(name));
3829+ m_infographics.insert(name, infographic);
3830+ if (infographic->isValid()) {
3831+ connect(this, &Service::sourcesChanged, infographic.data(),
3832+ &Infographic::sourcesChanged);
3833+ }
3834+ }
3835+}
3836+
3837+void ServiceImpl::updateSourcesList() {
3838+ QSet<QString> fullNames(
3839+ m_fileUtils->listDirectory(m_sourcesDirectory, QDir::Files).toSet());
3840+
3841+ QSet<QString> names;
3842+ for (const QString &name : fullNames) {
3843+ QFileInfo fileInfo(name);
3844+ QString shortName(fileInfo.completeBaseName());
3845+ m_fileUtils->shortApplicationId(shortName);
3846+ QDir applicationDirectory(m_cacheDirectory.filePath(shortName));
3847+ applicationDirectory.mkpath("usermetrics");
3848+ names << applicationDirectory.filePath("usermetrics");
3849+ }
3850+
3851+ // Remove deleted sources
3852+ QSet<QString> toRemove(m_sources.keys().toSet().subtract(names));
3853+ for (const QString &name : toRemove) {
3854+ m_sources.take(name);
3855+ }
3856+
3857+ // Work out the names we need to add
3858+ names.subtract(m_sources.keys().toSet());
3859+ for (const QString &name : names) {
3860+ SourceDirectory::Ptr sourceDirectory(
3861+ m_factory.newSourceDirectory(name));
3862+ connect(sourceDirectory.data(), &SourceDirectory::sourceChanged, this,
3863+ &ServiceImpl::sourceChanged);
3864+ m_sources.insert(name, sourceDirectory);
3865+ }
3866+}
3867+
3868+void ServiceImpl::sourceChanged(const QDir &directory,
3869+ const QString &fileName) {
3870+ QFileInfo directoryInfo(directory.path());
3871+ QString applicationId(directoryInfo.dir().dirName());
3872+ m_fileUtils->shortApplicationId(applicationId);
3873+
3874+ if (m_changedSources.constFind(applicationId, fileName)
3875+ == m_changedSources.constEnd()) {
3876+ m_changedSources.insert(applicationId, fileName);
3877+ }
3878+ m_timer.start(100);
3879+}
3880+
3881+QMultiMap<QString, QString> ServiceImpl::allSources() {
3882+ QMultiMap<QString, QString> sources;
3883+
3884+ QMapIterator<QString, SourceDirectory::Ptr> iter(m_sources);
3885+ while (iter.hasNext()) {
3886+ iter.next();
3887+
3888+ QFileInfo directoryInfo(iter.key());
3889+ QString applicationId(directoryInfo.dir().dirName());
3890+ m_fileUtils->shortApplicationId(applicationId);
3891+
3892+ for (const QString &filePath : iter.value()->files()) {
3893+ sources.insert(applicationId, filePath);
3894+ }
3895+ }
3896+
3897+ return sources;
3898+}
3899+
3900+void ServiceImpl::flushQueue() {
3901+ sourcesChanged(m_changedSources, allSources());
3902+ m_changedSources.clear();
3903+}
3904
3905=== added file 'src/usermetricsservice/ServiceImpl.h'
3906--- src/usermetricsservice/ServiceImpl.h 1970-01-01 00:00:00 +0000
3907+++ src/usermetricsservice/ServiceImpl.h 2014-04-03 13:02:15 +0000
3908@@ -0,0 +1,82 @@
3909+/*
3910+ * Copyright (C) 2014 Canonical, Ltd.
3911+ *
3912+ * This program is free software; you can redistribute it and/or modify
3913+ * it under the terms of the GNU General Public License as published by
3914+ * the Free Software Foundation; version 3.
3915+ *
3916+ * This program is distributed in the hope that it will be useful,
3917+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
3918+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
3919+ * GNU General Public License for more details.
3920+ *
3921+ * You should have received a copy of the GNU General Public License
3922+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
3923+ *
3924+ * Author: Pete Woods <pete.woods@canonical.com>
3925+ */
3926+
3927+#ifndef USERMETRICSSERVICE_SERVICEIMPL_H_
3928+#define USERMETRICSSERVICE_SERVICEIMPL_H_
3929+
3930+#include <usermetricsservice/Factory.h>
3931+
3932+#include <QFileSystemWatcher>
3933+#include <QDir>
3934+#include <QMap>
3935+#include <QMultiMap>
3936+#include <QString>
3937+#include <QTimer>
3938+
3939+namespace UserMetricsService {
3940+
3941+class ServiceImpl: public Service {
3942+Q_OBJECT
3943+
3944+public:
3945+ ServiceImpl(const QDir &cacheDirectory, const QDir &packageInfographics,
3946+ UserMetricsCommon::FileUtils::Ptr fileUtils,
3947+ ResultTransport::Ptr resultTransport, Factory &factory);
3948+
3949+ virtual ~ServiceImpl();
3950+
3951+protected Q_SLOTS:
3952+ void updateInfographicList();
3953+
3954+ void updateSourcesList();
3955+
3956+ void sourceChanged(const QDir &directory, const QString &fileName);
3957+
3958+ void flushQueue();
3959+
3960+ QMultiMap<QString, QString> allSources();
3961+
3962+protected:
3963+ QDir m_cacheDirectory;
3964+
3965+ UserMetricsCommon::FileUtils::Ptr m_fileUtils;
3966+
3967+ ResultTransport::Ptr m_resultTransport;
3968+
3969+ Factory &m_factory;
3970+
3971+ QTimer m_timer;
3972+
3973+ QList<QString> m_infographicDirectories;
3974+
3975+ QFileSystemWatcher m_infographicWatcher;
3976+
3977+ QDir m_sourcesDirectory;
3978+
3979+ QFileSystemWatcher m_sourcesWatcher;
3980+
3981+ QMap<QString, Infographic::Ptr> m_infographics;
3982+
3983+ QMap<QString, SourceDirectory::Ptr> m_sources;
3984+
3985+ QMultiMap<QString, QString> m_changedSources;
3986+};
3987+
3988+}
3989+
3990+#endif /* USERMETRICSSERVICE_SERVICEIMPL_H_ */
3991
3992=== added file 'src/usermetricsservice/SourceDirectory.cpp'
3993--- src/usermetricsservice/SourceDirectory.cpp 1970-01-01 00:00:00 +0000
3994+++ src/usermetricsservice/SourceDirectory.cpp 2014-04-03 13:02:15 +0000
3995@@ -0,0 +1,27 @@
3996+/*
3997+ * Copyright (C) 2014 Canonical, Ltd.
3998+ *
3999+ * This program is free software; you can redistribute it and/or modify
4000+ * it under the terms of the GNU General Public License as published by
4001+ * the Free Software Foundation; version 3.
4002+ *
4003+ * This program is distributed in the hope that it will be useful,
4004+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
4005+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
4006+ * GNU General Public License for more details.
4007+ *
4008+ * You should have received a copy of the GNU General Public License
4009+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
4010+ *
4011+ * Author: Pete Woods <pete.woods@canonical.com>
4012+ */
4013+
4014+#include <usermetricsservice/SourceDirectory.h>
4015+
4016+using namespace UserMetricsService;
4017+
4018+SourceDirectory::SourceDirectory() {
4019+}
4020+
4021+SourceDirectory::~SourceDirectory() {
4022+}
4023
4024=== added file 'src/usermetricsservice/SourceDirectory.h'
4025--- src/usermetricsservice/SourceDirectory.h 1970-01-01 00:00:00 +0000
4026+++ src/usermetricsservice/SourceDirectory.h 2014-04-03 13:02:15 +0000
4027@@ -0,0 +1,45 @@
4028+/*
4029+ * Copyright (C) 2014 Canonical, Ltd.
4030+ *
4031+ * This program is free software; you can redistribute it and/or modify
4032+ * it under the terms of the GNU General Public License as published by
4033+ * the Free Software Foundation; version 3.
4034+ *
4035+ * This program is distributed in the hope that it will be useful,
4036+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
4037+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
4038+ * GNU General Public License for more details.
4039+ *
4040+ * You should have received a copy of the GNU General Public License
4041+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
4042+ *
4043+ * Author: Pete Woods <pete.woods@canonical.com>
4044+ */
4045+
4046+#ifndef USERMETRICSSERVICE_SOURCEDIRECTORY_H_
4047+#define USERMETRICSSERVICE_SOURCEDIRECTORY_H_
4048+
4049+#include <QDir>
4050+#include <QObject>
4051+#include <QSharedPointer>
4052+
4053+namespace UserMetricsService {
4054+
4055+class SourceDirectory: public QObject {
4056+Q_OBJECT
4057+public:
4058+ typedef QSharedPointer<SourceDirectory> Ptr;
4059+
4060+ SourceDirectory();
4061+
4062+ virtual ~SourceDirectory();
4063+
4064+ virtual QStringList files() = 0;
4065+
4066+Q_SIGNALS:
4067+ void sourceChanged(const QDir &directory, const QString &file);
4068+};
4069+
4070+}
4071+
4072+#endif /* USERMETRICSSERVICE_SOURCEDIRECTORY_H_ */
4073
4074=== added file 'src/usermetricsservice/SourceDirectoryImpl.cpp'
4075--- src/usermetricsservice/SourceDirectoryImpl.cpp 1970-01-01 00:00:00 +0000
4076+++ src/usermetricsservice/SourceDirectoryImpl.cpp 2014-04-03 13:02:15 +0000
4077@@ -0,0 +1,67 @@
4078+/*
4079+ * Copyright (C) 2014 Canonical, Ltd.
4080+ *
4081+ * This program is free software; you can redistribute it and/or modify
4082+ * it under the terms of the GNU General Public License as published by
4083+ * the Free Software Foundation; version 3.
4084+ *
4085+ * This program is distributed in the hope that it will be useful,
4086+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
4087+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
4088+ * GNU General Public License for more details.
4089+ *
4090+ * You should have received a copy of the GNU General Public License
4091+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
4092+ *
4093+ * Author: Pete Woods <pete.woods@canonical.com>
4094+ */
4095+
4096+#include <usermetricsservice/SourceDirectoryImpl.h>
4097+
4098+#include <QDebug>
4099+
4100+using namespace UserMetricsCommon;
4101+using namespace UserMetricsService;
4102+
4103+SourceDirectoryImpl::SourceDirectoryImpl(const QDir &path,
4104+ FileUtils::Ptr fileUtils) :
4105+ m_path(path), m_fileUtils(fileUtils) {
4106+
4107+ m_watcher.addPath(path.path());
4108+
4109+ connect(&m_watcher, &QFileSystemWatcher::fileChanged, this,
4110+ &SourceDirectoryImpl::fileChanged);
4111+ connect(&m_watcher, &QFileSystemWatcher::directoryChanged, this,
4112+ &SourceDirectoryImpl::updateFileList);
4113+
4114+ updateFileList();
4115+}
4116+
4117+SourceDirectoryImpl::~SourceDirectoryImpl() {
4118+}
4119+
4120+void SourceDirectoryImpl::fileChanged(const QString &path) {
4121+ sourceChanged(m_path, path);
4122+}
4123+
4124+void SourceDirectoryImpl::updateFileList() {
4125+ QSet<QString> names(
4126+ m_fileUtils->listDirectory(m_path, QDir::Files).toSet());
4127+
4128+ // Remove deleted files
4129+ QSet<QString> toRemove(m_watcher.files().toSet().subtract(names));
4130+ if (!toRemove.isEmpty()) {
4131+ m_watcher.removePaths(toRemove.toList());
4132+ }
4133+
4134+ // Work out the names we need to add
4135+ names.subtract(m_watcher.files().toSet());
4136+ for (const QString &name : names) {
4137+ m_watcher.addPath(name);
4138+ sourceChanged(m_path, name);
4139+ }
4140+}
4141+
4142+QStringList SourceDirectoryImpl::files() {
4143+ return m_watcher.files();
4144+}
4145
4146=== added file 'src/usermetricsservice/SourceDirectoryImpl.h'
4147--- src/usermetricsservice/SourceDirectoryImpl.h 1970-01-01 00:00:00 +0000
4148+++ src/usermetricsservice/SourceDirectoryImpl.h 2014-04-03 13:02:15 +0000
4149@@ -0,0 +1,57 @@
4150+/*
4151+ * Copyright (C) 2014 Canonical, Ltd.
4152+ *
4153+ * This program is free software; you can redistribute it and/or modify
4154+ * it under the terms of the GNU General Public License as published by
4155+ * the Free Software Foundation; version 3.
4156+ *
4157+ * This program is distributed in the hope that it will be useful,
4158+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
4159+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
4160+ * GNU General Public License for more details.
4161+ *
4162+ * You should have received a copy of the GNU General Public License
4163+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
4164+ *
4165+ * Author: Pete Woods <pete.woods@canonical.com>
4166+ */
4167+
4168+#ifndef USERMETRICSSERVICE_SOURCEDIRECTORYIMPL_H_
4169+#define USERMETRICSSERVICE_SOURCEDIRECTORYIMPL_H_
4170+
4171+#include <libusermetricscommon/FileUtils.h>
4172+#include <usermetricsservice/SourceDirectory.h>
4173+
4174+#include <QDir>
4175+#include <QFile>
4176+#include <QFileSystemWatcher>
4177+
4178+namespace UserMetricsService {
4179+
4180+class SourceDirectoryImpl: public SourceDirectory {
4181+Q_OBJECT
4182+
4183+public:
4184+ SourceDirectoryImpl(const QDir &path,
4185+ UserMetricsCommon::FileUtils::Ptr fileUtils);
4186+
4187+ virtual ~SourceDirectoryImpl();
4188+
4189+ QStringList files();
4190+
4191+protected Q_SLOTS:
4192+ void fileChanged(const QString &path);
4193+
4194+ void updateFileList();
4195+
4196+protected:
4197+ QDir m_path;
4198+
4199+ UserMetricsCommon::FileUtils::Ptr m_fileUtils;
4200+
4201+ QFileSystemWatcher m_watcher;
4202+};
4203+
4204+}
4205+
4206+#endif /* USERMETRICSSERVICE_SOURCEDIRECTORYIMPL_H_ */
4207
4208=== added file 'src/usermetricsservice/aa-exec.cpp'
4209--- src/usermetricsservice/aa-exec.cpp 1970-01-01 00:00:00 +0000
4210+++ src/usermetricsservice/aa-exec.cpp 2014-04-03 13:02:15 +0000
4211@@ -0,0 +1,34 @@
4212+/*
4213+ * Copyright (C) 2014 Canonical, Ltd.
4214+ *
4215+ * This program is free software; you can redistribute it and/or modify
4216+ * it under the terms of the GNU General Public License as published by
4217+ * the Free Software Foundation; version 3.
4218+ *
4219+ * This program is distributed in the hope that it will be useful,
4220+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
4221+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
4222+ * GNU General Public License for more details.
4223+ *
4224+ * You should have received a copy of the GNU General Public License
4225+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
4226+ *
4227+ * Author: Pete Woods <pete.woods@canonical.com>
4228+ */
4229+
4230+#include <unistd.h>
4231+#include <sys/apparmor.h>
4232+
4233+int main(int argc, char **argv) {
4234+ if (argc < 2) {
4235+ return 1;
4236+ }
4237+
4238+ // Shift off the first argument
4239+ ++argv;
4240+
4241+// TODO Enable the profile switching
4242+// aa_change_onexec("infographic");
4243+
4244+ return execv(*argv, argv);
4245+}
4246
4247=== modified file 'src/usermetricsservice/main.cpp'
4248--- src/usermetricsservice/main.cpp 2014-02-04 12:07:58 +0000
4249+++ src/usermetricsservice/main.cpp 2014-04-03 13:02:15 +0000
4250@@ -1,5 +1,5 @@
4251 /*
4252- * Copyright (C) 2013 Canonical, Ltd.
4253+ * Copyright (C) 2014 Canonical, Ltd.
4254 *
4255 * This program is free software; you can redistribute it and/or modify
4256 * it under the terms of the GNU General Public License as published by
4257@@ -16,6 +16,31 @@
4258 * Author: Pete Woods <pete.woods@canonical.com>
4259 */
4260
4261+#include <usermetricsservice/Factory.h>
4262+
4263+#include <QCoreApplication>
4264+#include <QDebug>
4265+#include <csignal>
4266+
4267+using namespace UserMetricsService;
4268+
4269+static void exitQt(int sig) {
4270+ Q_UNUSED(sig);
4271+ QCoreApplication::exit(0);
4272+}
4273+
4274 int main(int argc, char *argv[]) {
4275- return 0;
4276+ QCoreApplication application(argc, argv);
4277+
4278+ signal(SIGINT, &exitQt);
4279+ signal(SIGTERM, &exitQt);
4280+
4281+ try {
4282+ Factory factory;
4283+ factory.singletonService();
4284+ return application.exec();
4285+ } catch (std::exception &e) {
4286+ qWarning() << "Usermetrics Service:" << e.what();
4287+ return 1;
4288+ }
4289 }
4290
4291=== modified file 'tests/CMakeLists.txt'
4292--- tests/CMakeLists.txt 2014-01-03 11:40:22 +0000
4293+++ tests/CMakeLists.txt 2014-04-03 13:02:15 +0000
4294@@ -15,6 +15,11 @@
4295 add_definitions(-DTEST_LOCALEDIR="${CMAKE_CURRENT_BINARY_DIR}/data")
4296 add_definitions(-DTEST_DATADIR="${CMAKE_CURRENT_SOURCE_DIR}/data")
4297
4298+set(TEST_INFOGRAPHICS_DIR "${CMAKE_CURRENT_SOURCE_DIR}/data/infographics")
4299+add_definitions(-DTEST_INFOGRAPHICS_DIR="${TEST_INFOGRAPHICS_DIR}")
4300+add_definitions(-DTEST_AGGREGATE_INFOGRAPHIC="${TEST_INFOGRAPHICS_DIR}/test-aggregate.json")
4301+add_definitions(-DTEST_ITERATE_INFOGRAPHIC="${TEST_INFOGRAPHICS_DIR}/test-iterate.json")
4302+
4303 add_definitions(-DDATA_DIR="${DATA_DIR}")
4304
4305 add_subdirectory(data)
4306
4307=== added directory 'tests/data/infographics'
4308=== added file 'tests/data/infographics/test-aggregate.json'
4309--- tests/data/infographics/test-aggregate.json 1970-01-01 00:00:00 +0000
4310+++ tests/data/infographics/test-aggregate.json 2014-04-03 13:02:15 +0000
4311@@ -0,0 +1,13 @@
4312+{
4313+ "exec": "/bin/cat",
4314+ "type": "aggregate",
4315+ "input": {
4316+ "com.ubuntu.camera": [
4317+ "camera-photos.libusermetrics.json",
4318+ "camera-videos.libusermetrics.json"
4319+ ],
4320+ "foo": [
4321+ "source-id.libusermetrics.json"
4322+ ]
4323+ }
4324+}
4325\ No newline at end of file
4326
4327=== added file 'tests/data/infographics/test-iterate.json'
4328--- tests/data/infographics/test-iterate.json 1970-01-01 00:00:00 +0000
4329+++ tests/data/infographics/test-iterate.json 2014-04-03 13:02:15 +0000
4330@@ -0,0 +1,9 @@
4331+{
4332+ "exec": "/bin/echo",
4333+ "type": "iterate",
4334+ "input": {
4335+ "*": [
4336+ ".*.libusermetrics.json"
4337+ ]
4338+ }
4339+}
4340
4341=== modified file 'tests/data/valgrind.suppression'
4342--- tests/data/valgrind.suppression 2014-01-03 15:51:12 +0000
4343+++ tests/data/valgrind.suppression 2014-04-03 13:02:15 +0000
4344@@ -61,6 +61,25 @@
4345 ###################
4346
4347 {
4348+ QThread seems to leak here
4349+ Memcheck:Leak
4350+ match-leak-kinds: definite
4351+ fun:_Znwm
4352+ fun:_ZN14QThreadPrivateC1EP11QThreadData
4353+ fun:_ZN7QThreadC1EP7QObject
4354+}
4355+
4356+{
4357+ QThread seems to leak here
4358+ Memcheck:Leak
4359+ match-leak-kinds: definite
4360+ fun:_Znwj
4361+ fun:_ZN14QThreadPrivateC1EP11QThreadData
4362+ fun:_ZN7QThreadC1EP7QObject
4363+}
4364+
4365+
4366+{
4367 See bug report <https://bugreports.qt-project.org/browse/QTBUG-33677>
4368 Memcheck:Leak
4369 fun:_Znwm
4370
4371=== modified file 'tests/unit/libusermetricsinput/TestMetricImpl.cpp'
4372--- tests/unit/libusermetricsinput/TestMetricImpl.cpp 2014-01-06 13:24:12 +0000
4373+++ tests/unit/libusermetricsinput/TestMetricImpl.cpp 2014-04-03 13:02:15 +0000
4374@@ -70,7 +70,7 @@
4375
4376 QVariantMap readData(const QString &id) {
4377 QVariantMap map;
4378- QFile file(metricDir.filePath(id + ".json"));
4379+ QFile file(metricDir.filePath(id + ".libusermetrics.json"));
4380 EXPECT_TRUE(file.open(QIODevice::ReadOnly));
4381 QJsonDocument doc(QJsonDocument::fromJson(file.readAll()));
4382 file.close();
4383
4384=== modified file 'tests/unit/libusermetricsinput/TestMetricManagerImpl.cpp'
4385--- tests/unit/libusermetricsinput/TestMetricManagerImpl.cpp 2014-01-06 17:31:49 +0000
4386+++ tests/unit/libusermetricsinput/TestMetricManagerImpl.cpp 2014-04-03 13:02:15 +0000
4387@@ -21,6 +21,7 @@
4388 #include <testutils/QStringPrinter.h>
4389 #include <unit/libusermetricsinput/Mocks.h>
4390
4391+#include <QtCore/QDebug>
4392 #include <QtCore/QTemporaryDir>
4393
4394 #include <gtest/gtest.h>
4395@@ -49,6 +50,7 @@
4396 "usermetrics");
4397
4398 applicationIdTwo = "app-id-2";
4399+ applicationIdTwoFull = "app-id-2_app_1.2.12345";
4400 metricDirTwo = QDir(cacheDir.filePath(applicationIdTwo)).filePath(
4401 "usermetrics");
4402 }
4403@@ -77,6 +79,8 @@
4404
4405 QString applicationIdTwo;
4406
4407+ QString applicationIdTwoFull;
4408+
4409 QDir metricDirTwo;
4410 };
4411
4412@@ -85,8 +89,7 @@
4413 params.formatString("format string %1");
4414
4415 MetricManagerPtr manager(
4416- new MetricManagerImpl(factory, temporaryDir.path(),
4417- applicationIdOne));
4418+ new MetricManagerImpl(factory, cacheDir, applicationIdOne));
4419 EXPECT_CALL(*factory, newMetric(metricDirOne,
4420 params, _)).WillOnce(Return(metric));
4421 MetricPtr newMetric(manager->add(params));
4422@@ -95,9 +98,9 @@
4423 newMetric = manager->add(params);
4424 EXPECT_EQ(metric, newMetric);
4425
4426- EXPECT_DIR_CONTAINS(QDir(cacheDir.filePath(applicationIdOne)),
4427+ EXPECT_DIR_CONTAINS(cacheDir, QStringList() << applicationIdOne);
4428+ EXPECT_DIR_CONTAINS(cacheDir.filePath(applicationIdOne),
4429 QStringList() << "usermetrics");
4430- EXPECT_DIR_CONTAINS(cacheDir, QStringList() << applicationIdOne);
4431 }
4432
4433 TEST_F(TestMetricManagerImpl, CreateTwoDifferentApplications) {
4434@@ -106,8 +109,7 @@
4435
4436 {
4437 MetricManagerPtr manager(
4438- new MetricManagerImpl(factory, temporaryDir.path(),
4439- applicationIdOne));
4440+ new MetricManagerImpl(factory, cacheDir, applicationIdOne));
4441 EXPECT_CALL(*factory, newMetric(metricDirOne,
4442 params, _)).WillOnce(Return(metric));
4443 MetricPtr newMetric(manager->add(params));
4444@@ -116,18 +118,19 @@
4445
4446 {
4447 MetricManagerPtr manager(
4448- new MetricManagerImpl(factory, temporaryDir.path(),
4449- applicationIdTwo));
4450+ new MetricManagerImpl(factory, cacheDir, applicationIdTwoFull));
4451 EXPECT_CALL(*factory, newMetric(metricDirTwo,
4452 params, _)).WillOnce(Return(metric));
4453 MetricPtr newMetric(manager->add("data-source-id", "format string %1"));
4454 EXPECT_EQ(metric, newMetric);
4455 }
4456
4457- EXPECT_DIR_CONTAINS(QDir(cacheDir.filePath(applicationIdTwo)),
4458- QStringList() << "usermetrics");
4459 EXPECT_DIR_CONTAINS(cacheDir,
4460 QStringList() << applicationIdOne << applicationIdTwo);
4461+ EXPECT_DIR_CONTAINS(cacheDir.filePath(applicationIdOne),
4462+ QStringList() << "usermetrics");
4463+ EXPECT_DIR_CONTAINS(cacheDir.filePath(applicationIdTwo),
4464+ QStringList() << "usermetrics");
4465 }
4466
4467 TEST_F(TestMetricManagerImpl, TestCanAddDataSourceMultipleTimes) {
4468@@ -154,9 +157,9 @@
4469 EXPECT_EQ(metric, newMetric);
4470 }
4471
4472- EXPECT_DIR_CONTAINS(QDir(cacheDir.filePath(applicationIdOne)),
4473+ EXPECT_DIR_CONTAINS(cacheDir, QStringList() << applicationIdOne);
4474+ EXPECT_DIR_CONTAINS(cacheDir.filePath(applicationIdOne),
4475 QStringList() << "usermetrics");
4476- EXPECT_DIR_CONTAINS(cacheDir, QStringList() << applicationIdOne);
4477 }
4478
4479 } // namespace
4480
4481=== modified file 'tests/unit/libusermetricsinput/TestUserMetricInputCAPI.cpp'
4482--- tests/unit/libusermetricsinput/TestUserMetricInputCAPI.cpp 2014-01-06 17:31:49 +0000
4483+++ tests/unit/libusermetricsinput/TestUserMetricInputCAPI.cpp 2014-04-03 13:02:15 +0000
4484@@ -48,9 +48,9 @@
4485 QVariantMap readData(const QString &id) {
4486 QDir cacheDir(QDir(m_temporaryDir.path()).filePath(".cache"));
4487 QDir applicationDir(cacheDir.filePath("test-app"));
4488- QDir metricDir(applicationDir.filePath("usermetrics"));
4489+ QDir usermetricsDir(applicationDir.filePath("usermetrics"));
4490
4491- QFile file(metricDir.filePath(id + ".json"));
4492+ QFile file(usermetricsDir.filePath(id + ".libusermetrics.json"));
4493 EXPECT_TRUE(file.open(QIODevice::ReadOnly));
4494 QJsonDocument doc(QJsonDocument::fromJson(file.readAll()));
4495 file.close();
4496
4497=== modified file 'tests/unit/libusermetricsoutput/CMakeLists.txt'
4498--- tests/unit/libusermetricsoutput/CMakeLists.txt 2014-01-03 11:40:22 +0000
4499+++ tests/unit/libusermetricsoutput/CMakeLists.txt 2014-04-03 13:02:15 +0000
4500@@ -5,6 +5,7 @@
4501 TestColorThemeImpl.cpp
4502 TestDataSet.cpp
4503 TestGSettingsColorThemeProvider.cpp
4504+ TestInfographicListImpl.cpp
4505 TestQVariantListModel.cpp
4506 TestUserMetricsImpl.cpp
4507 )
4508
4509=== added file 'tests/unit/libusermetricsoutput/TestInfographicListImpl.cpp'
4510--- tests/unit/libusermetricsoutput/TestInfographicListImpl.cpp 1970-01-01 00:00:00 +0000
4511+++ tests/unit/libusermetricsoutput/TestInfographicListImpl.cpp 2014-04-03 13:02:15 +0000
4512@@ -0,0 +1,122 @@
4513+/*
4514+ * Copyright (C) 2014 Canonical, Ltd.
4515+ *
4516+ * This program is free software; you can redistribute it and/or modify
4517+ * it under the terms of the GNU General Public License as published by
4518+ * the Free Software Foundation; version 3.
4519+ *
4520+ * This program is distributed in the hope that it will be useful,
4521+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
4522+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
4523+ * GNU General Public License for more details.
4524+ *
4525+ * You should have received a copy of the GNU General Public License
4526+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
4527+ *
4528+ * Author: Pete Woods <pete.woods@canonical.com>
4529+ */
4530+
4531+#include <libusermetricsoutput/InfographicListImpl.h>
4532+
4533+#include <QDebug>
4534+#include <QSignalSpy>
4535+#include <QTemporaryDir>
4536+
4537+#include <gtest/gtest.h>
4538+#include <gmock/gmock.h>
4539+
4540+using namespace std;
4541+using namespace UserMetricsOutput;
4542+using namespace testing;
4543+
4544+namespace {
4545+
4546+class TestInfographicListImpl: public Test {
4547+protected:
4548+ void SetUp() {
4549+ qRegisterMetaType<QVector<int>>("QVector<int>");
4550+ usermetricsDir = tempDir.path();
4551+ }
4552+
4553+ QDir createUserDir(unsigned int uid) {
4554+ QString name(QString::number(uid));
4555+ usermetricsDir.mkpath(name);
4556+ return QDir(usermetricsDir.filePath(name));
4557+ }
4558+
4559+ QString createInfographic(unsigned int uid, const QString &visualizer,
4560+ const QString &name, const QByteArray &contents) {
4561+ QDir userDir(createUserDir(uid));
4562+
4563+ userDir.mkpath(visualizer);
4564+ QDir visualizerDir(userDir.filePath(visualizer));
4565+
4566+ QFile output(visualizerDir.filePath(name));
4567+ output.open(QIODevice::WriteOnly);
4568+ output.write(contents);
4569+ output.close();
4570+
4571+ return output.fileName();
4572+ }
4573+
4574+ QStringList contents(QAbstractItemModel &model) {
4575+ QStringList contents;
4576+ for (int i(0); i < model.rowCount(); ++i) {
4577+ contents << model.data(model.index(i, 0)).toString();
4578+ }
4579+ contents.sort();
4580+ return contents;
4581+ }
4582+
4583+ QTemporaryDir tempDir;
4584+
4585+ QDir usermetricsDir;
4586+};
4587+
4588+TEST_F(TestInfographicListImpl, ModelUpdated) {
4589+ InfographicListImpl list(tempDir.path());
4590+ EXPECT_EQ(QStringList(), contents(list));
4591+
4592+ QSignalSpy resetSpy(&list, SIGNAL(modelReset()));
4593+ QSignalSpy dataChangedSpy(&list,
4594+ SIGNAL(
4595+ dataChanged(const QModelIndex &, const QModelIndex &, const QVector<int> &)));
4596+
4597+ list.setUid(1234);
4598+
4599+ createInfographic(1234, "com.ubuntu.camera", "apple-1234.svg", "<apple/>");
4600+ QString appleFile = createInfographic(1234, "com.ubuntu.camera",
4601+ "apple-2345.svg", "<apple/>");
4602+
4603+ createInfographic(1234, "com.ubuntu.camera", "banana-1234.svg",
4604+ "<oldBanana/>");
4605+ createInfographic(1234, "com.ubuntu.camera", "banana-2345.svg",
4606+ "<oldBanana/>");
4607+ QString bananaFile = createInfographic(1234, "com.ubuntu.camera",
4608+ "banana-3456.svg", "<banana/>");
4609+
4610+ createInfographic(1234, "com.ubuntu.camera", "cherry-1234.svg",
4611+ "<oldCherry/>");
4612+ createInfographic(1234, "com.ubuntu.camera", "cherry-2345.svg",
4613+ "<oldCherry/>");
4614+ QString cherryFile = createInfographic(1234, "com.ubuntu.camera",
4615+ "cherry-3456.svg", "<cherry/>");
4616+
4617+ resetSpy.wait();
4618+ ASSERT_EQ(1, resetSpy.size());
4619+ resetSpy.clear();
4620+
4621+ EXPECT_EQ(QStringList() << appleFile << bananaFile << cherryFile,
4622+ contents(list));
4623+
4624+ QString fooFile = createInfographic(1234, "com.ubuntu.foo", "foo-1234.svg",
4625+ "<foo/>");
4626+
4627+ dataChangedSpy.wait();
4628+ ASSERT_EQ(1, dataChangedSpy.size());
4629+
4630+ EXPECT_EQ(QStringList() << appleFile << bananaFile << cherryFile << fooFile,
4631+ contents(list));
4632+}
4633+
4634+} // namespace
4635
4636=== modified file 'tests/unit/qml/UserMetricsTest/DBusQuery.cpp'
4637--- tests/unit/qml/UserMetricsTest/DBusQuery.cpp 2014-01-06 17:31:49 +0000
4638+++ tests/unit/qml/UserMetricsTest/DBusQuery.cpp 2014-04-03 13:02:15 +0000
4639@@ -30,10 +30,10 @@
4640 static QVariantMap fileContents(int index) {
4641 QDir cacheDir(TEST_CACHE_DIR);
4642 QDir applicationDir(cacheDir.filePath("test-app"));
4643- QDir metricDir(applicationDir.filePath("usermetrics"));
4644+ QDir usermetricsDir(applicationDir.filePath("usermetrics"));
4645
4646 QFileInfoList list(
4647- metricDir.entryInfoList(QDir::Files | QDir::NoDotAndDotDot,
4648+ usermetricsDir.entryInfoList(QDir::Files | QDir::NoDotAndDotDot,
4649 QDir::Reversed));
4650 if (index - 1 >= list.length()) {
4651 return QVariantMap();
4652
4653=== modified file 'tests/unit/qml/UserMetricsTest/TestPlugin.cpp'
4654--- tests/unit/qml/UserMetricsTest/TestPlugin.cpp 2014-01-06 17:31:49 +0000
4655+++ tests/unit/qml/UserMetricsTest/TestPlugin.cpp 2014-04-03 13:02:15 +0000
4656@@ -28,8 +28,9 @@
4657 void Components::initializeEngine(QQmlEngine *engine, const char *uri) {
4658 QDir cacheDir(TEST_CACHE_DIR);
4659 QDir applicationDir(cacheDir.filePath(qgetenv("APP_ID")));
4660- if (applicationDir.exists()) {
4661- applicationDir.removeRecursively();
4662+ QDir usermetricsDir(applicationDir.filePath("usermetrics"));
4663+ if (usermetricsDir.exists()) {
4664+ usermetricsDir.removeRecursively();
4665 }
4666
4667 m_dbusQuery.reset(new DBusQuery());
4668
4669=== modified file 'tests/unit/usermetricsservice/CMakeLists.txt'
4670--- tests/unit/usermetricsservice/CMakeLists.txt 2014-01-03 11:40:22 +0000
4671+++ tests/unit/usermetricsservice/CMakeLists.txt 2014-04-03 13:02:15 +0000
4672@@ -0,0 +1,25 @@
4673+
4674+set(
4675+ USERMETRICSSERVICE_UNIT_TESTS_SRC
4676+ TestServiceImpl.cpp
4677+ TestInfographicImpl.cpp
4678+)
4679+
4680+add_executable(
4681+ usermetricsservice-unit-tests
4682+ ${USERMETRICSSERVICE_UNIT_TESTS_SRC}
4683+)
4684+
4685+target_link_libraries(
4686+ usermetricsservice-unit-tests
4687+ usermetricsservice
4688+ usermetrics-test-utils
4689+ ${GSETTINGS_QT_LIBRARIES}
4690+ ${GTEST_LIBRARIES}
4691+ ${GMOCK_LIBRARIES}
4692+)
4693+
4694+add_valgrind_test(
4695+ usermetricsservice-unit-tests
4696+ usermetricsservice-unit-tests
4697+)
4698
4699=== added file 'tests/unit/usermetricsservice/Mocks.h'
4700--- tests/unit/usermetricsservice/Mocks.h 1970-01-01 00:00:00 +0000
4701+++ tests/unit/usermetricsservice/Mocks.h 2014-04-03 13:02:15 +0000
4702@@ -0,0 +1,84 @@
4703+/*
4704+ * Copyright (C) 2013 Canonical, Ltd.
4705+ *
4706+ * This program is free software: you can redistribute it and/or modify it
4707+ * under the terms of the GNU General Public License version 3, as published
4708+ * by the Free Software Foundation.
4709+ *
4710+ * This program is distributed in the hope that it will be useful, but
4711+ * WITHOUT ANY WARRANTY; without even the implied warranties of
4712+ * MERCHANTABILITY, SATISFACTORY QUALITY, or FITNESS FOR A PARTICULAR
4713+ * PURPOSE. See the GNU General Public License for more details.
4714+ *
4715+ * You should have received a copy of the GNU General Public License along
4716+ * with this program. If not, see <http://www.gnu.org/licenses/>.
4717+ *
4718+ * Author: Pete Woods <pete.woods@canonical.com>
4719+ */
4720+
4721+#ifndef USERMETRICSSERVICE_TEST_MOCKS_H_
4722+#define USERMETRICSSERVICE_TEST_MOCKS_H_
4723+
4724+#include <usermetricsservice/Factory.h>
4725+
4726+#include <gmock/gmock.h>
4727+
4728+namespace UserMetricsService {
4729+namespace Mocks {
4730+
4731+class MockFactory: public Factory {
4732+public:
4733+
4734+ MOCK_METHOD0(singletonService, Service::Ptr());
4735+
4736+ MOCK_METHOD0(singletonFileUtils, UserMetricsCommon::FileUtils::Ptr());
4737+
4738+ MOCK_METHOD0(singletonExecutor, Executor::Ptr());
4739+
4740+ MOCK_METHOD0(singletonInfographicService, QSharedPointer<ComCanonicalInfographicsInterface>());
4741+
4742+ MOCK_METHOD0(singletonResultTransport, ResultTransport::Ptr());
4743+
4744+ MOCK_METHOD1(newInfographic, Infographic::Ptr(const QFile &));
4745+
4746+ MOCK_METHOD1(newSourceDirectory, SourceDirectory::Ptr(const QDir &));
4747+};
4748+
4749+class MockExecutor: public Executor {
4750+public:
4751+
4752+ MOCK_METHOD2(execute, QByteArray(const QString &,
4753+ const QStringList &));
4754+};
4755+
4756+class MockInfographic: public Infographic {
4757+public:
4758+
4759+ MOCK_CONST_METHOD0(isValid, bool());
4760+
4761+ MOCK_CONST_METHOD0(type, Infographic::Type());
4762+
4763+ MOCK_METHOD2(sourcesChanged, void(const QMultiMap<QString, QString> &,
4764+ const QMultiMap<QString, QString> &));
4765+};
4766+
4767+class MockFileUtils: public UserMetricsCommon::FileUtils {
4768+public:
4769+
4770+ MOCK_METHOD2(listDirectory, QSet<QString>(const QDir &,
4771+ QDir::Filters));
4772+};
4773+
4774+class MockResultTransport: public ResultTransport {
4775+public:
4776+
4777+ MOCK_METHOD0(clear, void());
4778+
4779+ MOCK_METHOD3(send, void(const QString &, const QStringList &,
4780+ const QByteArray &));
4781+};
4782+
4783+}
4784+}
4785+
4786+#endif /* USERMETRICSSERVICE_TEST_MOCKS_H_ */
4787
4788=== added file 'tests/unit/usermetricsservice/TestInfographicImpl.cpp'
4789--- tests/unit/usermetricsservice/TestInfographicImpl.cpp 1970-01-01 00:00:00 +0000
4790+++ tests/unit/usermetricsservice/TestInfographicImpl.cpp 2014-04-03 13:02:15 +0000
4791@@ -0,0 +1,124 @@
4792+/*
4793+ * Copyright (C) 2013 Canonical, Ltd.
4794+ *
4795+ * This program is free software; you can redistribute it and/or modify
4796+ * it under the terms of the GNU General Public License as published by
4797+ * the Free Software Foundation; version 3.
4798+ *
4799+ * This program is distributed in the hope that it will be useful,
4800+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
4801+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
4802+ * GNU General Public License for more details.
4803+ *
4804+ * You should have received a copy of the GNU General Public License
4805+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
4806+ *
4807+ * Author: Pete Woods <pete.woods@canonical.com>
4808+ */
4809+
4810+#include <stdexcept>
4811+
4812+#include <usermetricsservice/InfographicImpl.h>
4813+
4814+#include <unit/usermetricsservice/Mocks.h>
4815+#include <testutils/QStringPrinter.h>
4816+
4817+#include <gtest/gtest.h>
4818+#include <gmock/gmock.h>
4819+
4820+using namespace std;
4821+using namespace testing;
4822+using namespace UserMetricsService;
4823+using namespace UserMetricsService::Mocks;
4824+
4825+namespace {
4826+
4827+class TestInfographicImpl: public Test {
4828+protected:
4829+ void SetUp() {
4830+ executor.reset(new StrictMock<MockExecutor>);
4831+
4832+ resultTransport.reset(new StrictMock<MockResultTransport>);
4833+ }
4834+
4835+ QSharedPointer<MockExecutor> executor;
4836+
4837+ QSharedPointer<MockResultTransport> resultTransport;
4838+
4839+ Infographic::Ptr newInfographic(const QString &path) {
4840+ return Infographic::Ptr(
4841+ new InfographicImpl(path, executor, resultTransport));
4842+ }
4843+};
4844+
4845+TEST_F(TestInfographicImpl, Iterate) {
4846+ Infographic::Ptr infographic(newInfographic (TEST_ITERATE_INFOGRAPHIC));
4847+
4848+ EXPECT_TRUE(infographic->isValid());
4849+ EXPECT_EQ(Infographic::Type::ITERATE, infographic->type());
4850+
4851+ QMultiMap<QString, QString> changedSources;
4852+ changedSources.insert("apple", "/path/orchard.libusermetrics.json");
4853+ changedSources.insert("apple", "/path/grove.json");
4854+ changedSources.insert("banana", "/path/tree.libusermetrics.json");
4855+
4856+ QMultiMap<QString, QString> allSources;
4857+
4858+ QByteArray orchardBa("orchard");
4859+ QStringList orchard;
4860+ orchard << "/path/orchard.libusermetrics.json";
4861+ EXPECT_CALL(*executor,
4862+ execute(QString("/bin/echo"), orchard)).WillOnce(Return(orchardBa));
4863+ EXPECT_CALL(*resultTransport,
4864+ send(QString("test-iterate"), orchard, orchardBa));
4865+
4866+ QByteArray treeBa("tree blah");
4867+ QStringList tree;
4868+ tree << "/path/tree.libusermetrics.json";
4869+ EXPECT_CALL(*executor,
4870+ execute(QString("/bin/echo"), tree)).WillOnce(Return(treeBa));
4871+ EXPECT_CALL(*resultTransport, send(QString("test-iterate"), tree, treeBa));
4872+
4873+ infographic->sourcesChanged(changedSources, allSources);
4874+}
4875+
4876+TEST_F(TestInfographicImpl, Aggregate) {
4877+ Infographic::Ptr infographic(newInfographic (TEST_AGGREGATE_INFOGRAPHIC));
4878+
4879+ EXPECT_TRUE(infographic->isValid());
4880+ EXPECT_EQ(Infographic::Type::AGGREGATE, infographic->type());
4881+
4882+ QMultiMap<QString, QString> changedSources;
4883+ QMultiMap<QString, QString> allSources;
4884+
4885+ // Only two of the 3 requires sources are present
4886+ allSources.insert("foo", "/path/source-1.libusermetrics.json");
4887+ allSources.insert("foo", "/path/source-2.libusermetrics.json");
4888+ allSources.insert("com.ubuntu.camera",
4889+ "/path/camera-photos.libusermetrics.json");
4890+ allSources.insert("com.ubuntu.camera",
4891+ "/path/camera-videos.libusermetrics.json");
4892+ allSources.insert("bar", "/path/bar.libusermetrics.json");
4893+
4894+ changedSources.insert("com.ubuntu.camera",
4895+ "/path/camera-videos.libusermetrics.json");
4896+
4897+ // Nothing should happen
4898+ infographic->sourcesChanged(changedSources, allSources);
4899+
4900+ // Now all of the required sources are present
4901+ allSources.insert("foo", "/path/source-id.libusermetrics.json");
4902+
4903+ QByteArray ba("stuff in the byte array");
4904+ QStringList files;
4905+ files << "/path/camera-photos.libusermetrics.json"
4906+ << "/path/camera-videos.libusermetrics.json"
4907+ << "/path/source-id.libusermetrics.json";
4908+ EXPECT_CALL(*executor,
4909+ execute(QString("/bin/cat"), files)).WillOnce(Return(ba));
4910+ EXPECT_CALL(*resultTransport, send(QString("test-aggregate"), files, ba));
4911+
4912+ infographic->sourcesChanged(changedSources, allSources);
4913+}
4914+
4915+} // namespace
4916
4917=== added file 'tests/unit/usermetricsservice/TestServiceImpl.cpp'
4918--- tests/unit/usermetricsservice/TestServiceImpl.cpp 1970-01-01 00:00:00 +0000
4919+++ tests/unit/usermetricsservice/TestServiceImpl.cpp 2014-04-03 13:02:15 +0000
4920@@ -0,0 +1,149 @@
4921+/*
4922+ * Copyright (C) 2013 Canonical, Ltd.
4923+ *
4924+ * This program is free software; you can redistribute it and/or modify
4925+ * it under the terms of the GNU General Public License as published by
4926+ * the Free Software Foundation; version 3.
4927+ *
4928+ * This program is distributed in the hope that it will be useful,
4929+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
4930+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
4931+ * GNU General Public License for more details.
4932+ *
4933+ * You should have received a copy of the GNU General Public License
4934+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
4935+ *
4936+ * Author: Pete Woods <pete.woods@canonical.com>
4937+ */
4938+
4939+#include <usermetricsservice/ServiceImpl.h>
4940+#include <usermetricsservice/SourceDirectoryImpl.h>
4941+#include <unit/usermetricsservice/Mocks.h>
4942+#include <testutils/QStringPrinter.h>
4943+
4944+#include <QSignalSpy>
4945+#include <QTemporaryDir>
4946+#include <gtest/gtest.h>
4947+#include <gmock/gmock.h>
4948+#include <stdexcept>
4949+
4950+using namespace std;
4951+using namespace testing;
4952+using namespace UserMetricsCommon;
4953+using namespace UserMetricsService;
4954+using namespace UserMetricsService::Mocks;
4955+
4956+MATCHER_P(HasPath, value, ""){ return arg.fileName() == value;}
4957+
4958+namespace {
4959+
4960+class TestServiceImpl: public Test {
4961+protected:
4962+ void SetUp() {
4963+ qRegisterMetaType<QMultiMap<QString, QString>>(
4964+ "QMultiMap<QString, QString>");
4965+
4966+ cacheDir = tempDir.path();
4967+ usermetricsDir = cacheDir.filePath("usermetrics");
4968+ sourcesDir = usermetricsDir.filePath("sources");
4969+ ASSERT_TRUE(usermetricsDir.mkpath("sources"));
4970+
4971+ factory.reset(new NiceMock<MockFactory>);
4972+ fileUtils.reset(new FileUtils);
4973+ resultTransport.reset(new StrictMock<MockResultTransport>);
4974+ }
4975+
4976+ Service::Ptr newService() {
4977+ return Service::Ptr(
4978+ new ServiceImpl(cacheDir.path(), QDir(TEST_INFOGRAPHICS_DIR),
4979+ fileUtils, resultTransport, *factory));
4980+ }
4981+
4982+ QDir applicationDir(const QString &sourceName) {
4983+ QDir applicationDir = cacheDir.filePath(sourceName);
4984+ return applicationDir.filePath("usermetrics");
4985+ }
4986+
4987+ void createSource(const QString &name) {
4988+ QFile source(sourcesDir.filePath(name));
4989+ ASSERT_TRUE(source.open(QIODevice::WriteOnly));
4990+ ASSERT_TRUE(source.write("blah"));
4991+ source.close();
4992+ }
4993+
4994+ QString metricPath(const QString &sourceName, const QString &metricName) {
4995+ QDir applicationDir = cacheDir.filePath(sourceName);
4996+ QDir applicationUsermetricsDir = applicationDir.filePath("usermetrics");
4997+ return applicationUsermetricsDir.filePath(metricName);
4998+ }
4999+
5000+ void createMetric(const QString &sourceName, const QString &metricName) {
The diff has been truncated for viewing.

Subscribers

People subscribed via source and target branches

to all changes: