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

Proposed by Pete Woods
Status: Approved
Approved by: Antti Kaijanmäki
Approved revision: 182
Proposed branch: lp:~unity-team/libusermetrics/file-based-infographics
Merge into: lp:libusermetrics
Diff against target: 14066 lines (+6354/-5861)
162 files modified
CMakeLists.txt (+6/-13)
cmake/FindValgrind.cmake (+1/-1)
cmake/Plugins.cmake (+102/-0)
data/CMakeLists.txt (+37/-10)
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/com.canonical.UserMetrics.service.in (+0/-5)
data/com.canonical.UserMetrics.xml (+0/-44)
data/com.canonical.usermetrics.DataSet.xml (+0/-24)
data/com.canonical.usermetrics.DataSource.xml (+0/-42)
data/com.canonical.usermetrics.UserData.xml (+0/-25)
data/default.json.in (+9/-0)
data/usermetricsservice.conf.in (+10/-0)
debian/changelog (+7/-0)
debian/control (+18/-7)
debian/libusermetricsinput1.symbols (+19/-8)
debian/libusermetricsoutput1.symbols (+18/-0)
debian/qtdeclarative5-infographics0.1.install (+1/-0)
debian/rules (+6/-2)
debian/usermetricsservice.infographic.click-hook (+3/-0)
debian/usermetricsservice.install (+1/-0)
debian/usermetricsservice.postinst (+0/-16)
debian/usermetricsservice.postrm (+0/-26)
debian/usermetricsservice.preinst (+0/-30)
debian/usermetricsservice.prerm (+0/-7)
debian/usermetricsservice.usermetrics.click-hook (+3/-0)
doc/Infographic Architecture.svg (+636/-0)
doc/mainpage.md (+87/-0)
po/en_GB.po (+88/-120)
po/libusermetrics.pot (+18/-108)
po/pl.po (+92/-121)
po/zh_CN.po (+28/-117)
src/CMakeLists.txt (+2/-0)
src/infographic/CMakeLists.txt (+20/-0)
src/infographic/Infographic.cpp (+292/-0)
src/infographic/Infographic.h (+79/-0)
src/infographic/main.cpp (+53/-0)
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 (+7/-29)
src/libusermetricscommon/DBusPaths.cpp (+0/-41)
src/libusermetricscommon/DBusPaths.h (+0/-41)
src/libusermetricscommon/FileUtils.cpp (+52/-0)
src/libusermetricscommon/FileUtils.h (+47/-0)
src/libusermetricsinput/CMakeLists.txt (+2/-0)
src/libusermetricsinput/Factory.cpp (+48/-0)
src/libusermetricsinput/Factory.h (+47/-0)
src/libusermetricsinput/Metric.h (+1/-1)
src/libusermetricsinput/MetricImpl.cpp (+228/-75)
src/libusermetricsinput/MetricImpl.h (+43/-20)
src/libusermetricsinput/MetricManager.cpp (+7/-13)
src/libusermetricsinput/MetricManager.h (+9/-23)
src/libusermetricsinput/MetricManagerImpl.cpp (+40/-93)
src/libusermetricsinput/MetricManagerImpl.h (+6/-4)
src/libusermetricsinput/MetricParameters.cpp (+132/-0)
src/libusermetricsinput/MetricParameters.h (+74/-0)
src/libusermetricsinput/MetricUpdate.h (+1/-1)
src/libusermetricsinput/MetricUpdateImpl.cpp (+6/-13)
src/libusermetricsinput/MetricUpdateImpl.h (+5/-8)
src/libusermetricsinput/usermetricsinput.cpp (+9/-8)
src/libusermetricsoutput/CMakeLists.txt (+3/-4)
src/libusermetricsoutput/ColorThemeProvider.h (+1/-0)
src/libusermetricsoutput/DirectoryWatcher.cpp (+118/-0)
src/libusermetricsoutput/DirectoryWatcher.h (+69/-0)
src/libusermetricsoutput/InfographicList.cpp (+32/-0)
src/libusermetricsoutput/InfographicList.h (+127/-0)
src/libusermetricsoutput/InfographicListImpl.cpp (+181/-0)
src/libusermetricsoutput/InfographicListImpl.h (+98/-0)
src/libusermetricsoutput/SyncedDataSet.cpp (+0/-34)
src/libusermetricsoutput/SyncedDataSet.h (+0/-43)
src/libusermetricsoutput/SyncedDataSource.cpp (+0/-54)
src/libusermetricsoutput/SyncedDataSource.h (+0/-46)
src/libusermetricsoutput/SyncedUserData.cpp (+0/-89)
src/libusermetricsoutput/SyncedUserData.h (+0/-56)
src/libusermetricsoutput/SyncedUserMetricsStore.cpp (+0/-142)
src/libusermetricsoutput/SyncedUserMetricsStore.h (+0/-63)
src/libusermetricsoutput/UserMetrics.cpp (+4/-9)
src/libusermetricsoutput/UserMetricsImpl.cpp (+6/-5)
src/libusermetricsoutput/UserMetricsStore.h (+2/-0)
src/modules/CMakeLists.txt (+1/-0)
src/modules/Infographics/CMakeLists.txt (+39/-0)
src/modules/Infographics/Components.cpp (+34/-0)
src/modules/Infographics/Components.h (+34/-0)
src/modules/Infographics/qmldir (+2/-0)
src/modules/UserMetrics/CMakeLists.txt (+27/-34)
src/usermetricsservice/Authentication.cpp (+0/-104)
src/usermetricsservice/Authentication.h (+0/-54)
src/usermetricsservice/CMakeLists.txt (+42/-53)
src/usermetricsservice/DBusDataSet.cpp (+0/-221)
src/usermetricsservice/DBusDataSet.h (+0/-100)
src/usermetricsservice/DBusDataSource.cpp (+0/-244)
src/usermetricsservice/DBusDataSource.h (+0/-115)
src/usermetricsservice/DBusUserData.cpp (+0/-186)
src/usermetricsservice/DBusUserData.h (+0/-95)
src/usermetricsservice/DBusUserMetrics.cpp (+0/-291)
src/usermetricsservice/DBusUserMetrics.h (+0/-90)
src/usermetricsservice/Executor.cpp (+27/-0)
src/usermetricsservice/Executor.h (+42/-0)
src/usermetricsservice/Factory.cpp (+91/-0)
src/usermetricsservice/Factory.h (+69/-0)
src/usermetricsservice/Infographic.cpp (+27/-0)
src/usermetricsservice/Infographic.h (+52/-0)
src/usermetricsservice/InfographicImpl.cpp (+180/-0)
src/usermetricsservice/InfographicImpl.h (+81/-0)
src/usermetricsservice/QProcessExecutor.cpp (+75/-0)
src/usermetricsservice/QProcessExecutor.h (+47/-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 (+172/-0)
src/usermetricsservice/ServiceImpl.h (+87/-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 (+56/-0)
src/usermetricsservice/database/DataSet.cpp (+0/-83)
src/usermetricsservice/database/DataSet.h (+0/-93)
src/usermetricsservice/database/DataSource.cpp (+0/-142)
src/usermetricsservice/database/DataSource.h (+0/-139)
src/usermetricsservice/database/UserData.cpp (+0/-56)
src/usermetricsservice/database/UserData.h (+0/-61)
src/usermetricsservice/main.cpp (+12/-63)
tests/CMakeLists.txt (+4/-1)
tests/data/infographics/test-aggregate.json (+13/-0)
tests/data/infographics/test-iterate.json (+9/-0)
tests/data/valgrind.suppression (+94/-0)
tests/integration/CMakeLists.txt (+0/-2)
tests/integration/libusermetricsinput/CMakeLists.txt (+0/-23)
tests/integration/libusermetricsinput/TestMetricManager.cpp (+0/-52)
tests/integration/libusermetricsoutput/CMakeLists.txt (+0/-23)
tests/integration/libusermetricsoutput/TestUserMetrics.cpp (+0/-46)
tests/testutils/CMakeLists.txt (+0/-2)
tests/testutils/DBusTest.cpp (+0/-50)
tests/testutils/DBusTest.h (+0/-49)
tests/testutils/main.cpp (+1/-1)
tests/unit/libusermetricsinput/CMakeLists.txt (+1/-0)
tests/unit/libusermetricsinput/Mocks.h (+51/-0)
tests/unit/libusermetricsinput/TestMetricImpl.cpp (+412/-0)
tests/unit/libusermetricsinput/TestMetricManagerImpl.cpp (+127/-322)
tests/unit/libusermetricsinput/TestUserMetricInputCAPI.cpp (+57/-57)
tests/unit/libusermetricsoutput/CMakeLists.txt (+1/-1)
tests/unit/libusermetricsoutput/TestInfographicListImpl.cpp (+121/-0)
tests/unit/libusermetricsoutput/TestSyncedUserMetricsStore.cpp (+0/-426)
tests/unit/qml/CMakeLists.txt (+9/-1)
tests/unit/qml/UserMetricsTest/DBusQuery.cpp (+42/-47)
tests/unit/qml/UserMetricsTest/DBusQuery.h (+0/-4)
tests/unit/qml/UserMetricsTest/TestPlugin.cpp (+7/-0)
tests/unit/qml/tst_Metrics.qml (+13/-2)
tests/unit/usermetricsservice/CMakeLists.txt (+3/-3)
tests/unit/usermetricsservice/Mocks.h (+84/-0)
tests/unit/usermetricsservice/TestAuthentication.cpp (+0/-62)
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/file-based-infographics
Reviewer Review Type Date Requested Status
Antti Kaijanmäki (community) Approve
Michał Sawicz Needs Information
PS Jenkins bot (community) continuous-integration Approve
Review via email: mp+214020@code.launchpad.net

Commit message

Wait until the Unity8 branch for the UI is ready

Description of the change

Wait until the Unity8 branch for the UI is ready

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

Merge trunk

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

Fix symbols file

Revision history for this message
PS Jenkins bot (ps-jenkins) wrote :
review: Approve (continuous-integration)
154. By Pete Woods

Add new plug-in for unity8 shell to use

155. By Pete Woods

Use the correct subdirectory

156. By Pete Woods

Linewrap the control file

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

Use Qt5 by default

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

Add missing dependency

Revision history for this message
PS Jenkins bot (ps-jenkins) wrote :
review: Approve (continuous-integration)
159. By Pete Woods

Avoid using new style connect method to (hopefully) fix test failures on ppc64 and arm64

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

I forgot the parameters to the signals

161. By Pete Woods

Enable -fPIE for all executables

Revision history for this message
PS Jenkins bot (ps-jenkins) wrote :
review: Approve (continuous-integration)
162. By Ricardo Salveti

Merging trunk

Revision history for this message
PS Jenkins bot (ps-jenkins) wrote :
review: Approve (continuous-integration)
163. By Pete Woods

Additional documentation

Revision history for this message
PS Jenkins bot (ps-jenkins) wrote :
review: Approve (continuous-integration)
164. By Pete Woods

Start on dbus started, like everyone else

165. By Pete Woods

Clean up the QML plugin

Revision history for this message
PS Jenkins bot (ps-jenkins) wrote :
review: Approve (continuous-integration)
166. By Pete Woods

Derive the infographic confinement profile from the application ID

167. By Pete Woods

Remove needless logging

168. By Pete Woods

Move hook paths to ~/.local instead of ~/.cache

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

Add data get method to help UI developers

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

Merge trunk

Revision history for this message
PS Jenkins bot (ps-jenkins) wrote :
review: Approve (continuous-integration)
171. By Pete Woods

Change output API to expose simple "path" property with "next" method

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

Make jenkins happy with its non-optimised builds

173. By Pete Woods

Consistent formatting

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

Make ARM builds on Jenkins happy

Revision history for this message
PS Jenkins bot (ps-jenkins) wrote :
review: Needs Fixing (continuous-integration)
Revision history for this message
PS Jenkins bot (ps-jenkins) wrote :
review: Approve (continuous-integration)
175. By Pete Woods

Merge trunk

Revision history for this message
PS Jenkins bot (ps-jenkins) wrote :
review: Approve (continuous-integration)
176. By Pete Woods

Merge trunk

Revision history for this message
PS Jenkins bot (ps-jenkins) wrote :
review: Approve (continuous-integration)
177. By Pete Woods

Updated translations

178. By Pete Woods

Support sources provided by normal debian packages

179. By Pete Woods

Add package directories

180. By Pete Woods

Handle relative executable paths

181. By Pete Woods

Extra suppression

Revision history for this message
PS Jenkins bot (ps-jenkins) wrote :
review: Approve (continuous-integration)
182. By Pete Woods

Extra method to specify APP_ID manually for non-UAL processes

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

Check out bug #1339002, seems to still happen - I disabled "stats on welcome screen" and locked, but they are still shown (even after reboot).

Not sure if the visualizer is here, but a few bugs for it:
- text not centered in the circle
- text is not pluralized correctly ("1 calls made today")

I wonder, (how) do we deal with language changes? I changed my display language, rebooted and infographics are still in English. Not sure if it's missing translations, or whether you're reacting to changed language at all?

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

> Check out bug #1339002, seems to still happen - I disabled "stats on welcome
> screen" and locked, but they are still shown (even after reboot).
>
I think unity8 was doing this with the old infographics implementation. Is it possible for me to read a user's settings as the lightdm user? Does unity8 know about this setting already for the user that's being displayed in the greeter?

> Not sure if the visualizer is here, but a few bugs for it:
> - text not centered in the circle
I will have a go at fixing this. SVGs have no concept of vertical centering, so it's hard.

> - text is not pluralized correctly ("1 calls made today")
This is because gettext doesn't support non-whole numbers, and the value is a double. e.g. for uses like "walked 1.1 km today".

> I wonder, (how) do we deal with language changes? I changed my display
> language, rebooted and infographics are still in English. Not sure if it's
> missing translations, or whether you're reacting to changed language at all?
The data source can either provide pre-translated strings (non optimal) or provide gettext translations under a specified domain. I don't think the apps are doing this at present.

All visualisers are basically re-run at user session start.

For custom visualisers that do completely their own wacky thing, it's up to the visualiser to be translatable.

Revision history for this message
Antti Kaijanmäki (kaijanmaki) wrote :

Had a review session with pete. LGTM.

review: Approve

Unmerged revisions

182. By Pete Woods

Extra method to specify APP_ID manually for non-UAL processes

181. By Pete Woods

Extra suppression

180. By Pete Woods

Handle relative executable paths

179. By Pete Woods

Add package directories

178. By Pete Woods

Support sources provided by normal debian packages

177. By Pete Woods

Updated translations

176. By Pete Woods

Merge trunk

175. By Pete Woods

Merge trunk

174. By Pete Woods

Make ARM builds on Jenkins happy

173. By Pete Woods

Consistent formatting

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

Subscribers

People subscribed via source and target branches

to all changes: