Merge lp:~charlesk/indicator-display/add-rotation-lock into lp:indicator-display/14.10
- add-rotation-lock
- Merge into trunk.14.10
Status: | Merged |
---|---|
Approved by: | Ted Gould |
Approved revision: | 16 |
Merged at revision: | 2 |
Proposed branch: | lp:~charlesk/indicator-display/add-rotation-lock |
Merge into: | lp:indicator-display/14.10 |
Diff against target: |
1576 lines (+1426/-0) 29 files modified
CMakeLists.txt (+72/-0) cmake/FindGMock.cmake (+10/-0) cmake/GCov.cmake (+51/-0) cmake/GdbusCodegen.cmake (+36/-0) cmake/Translations.cmake (+37/-0) data/CMakeLists.txt (+74/-0) data/com.canonical.indicator.rotation_lock (+11/-0) data/indicator-display.conf.in (+9/-0) data/indicator-display.desktop.in (+9/-0) data/indicator-display.upstart.desktop.in (+9/-0) debian/changelog (+6/-0) debian/compat (+1/-0) debian/control (+34/-0) debian/copyright (+21/-0) debian/rules (+10/-0) po/CMakeLists.txt (+3/-0) po/POTFILES.in (+1/-0) src/CMakeLists.txt (+29/-0) src/exporter.cpp (+217/-0) src/exporter.h (+40/-0) src/indicator.h (+88/-0) src/main.cpp (+62/-0) src/rotation-lock.cpp (+197/-0) src/rotation-lock.h (+42/-0) tests/CMakeLists.txt (+35/-0) tests/glib-fixture.h (+143/-0) tests/gtestdbus-fixture.h (+102/-0) tests/manual (+16/-0) tests/test-rotation-lock.cpp (+61/-0) |
To merge this branch: | bzr merge lp:~charlesk/indicator-display/add-rotation-lock |
Related bugs: |
Reviewer | Review Type | Date Requested | Status |
---|---|---|---|
Ted Gould (community) | Approve | ||
PS Jenkins bot (community) | continuous-integration | Approve | |
Review via email: mp+231663@code.launchpad.net |
Commit message
Add a rotation lock indicator.
Description of the change
Add a rotation lock indicator.
Note, for testing on the phone without unity-system-
$ gsettings set com.ubuntu.
$ gsettings set com.ubuntu.
Enabling/disabling lock with this method should have the same results as in the indicator-
PS Jenkins bot (ps-jenkins) wrote : | # |
- 9. By Charles Kerr
-
remove url-dispatcher dependency.
- 10. By Charles Kerr
-
add cmake/ directory
Charles Kerr (charlesk) wrote : | # |
aha, --split is the bzr-bd argument I was looking for to generate a local tarball since there's not one uploaded yet :)
output of dpkg -c:
./
./usr/
./usr/share/
./usr/
./usr/
./usr/
./usr/
./usr/
./usr/
./usr/share/doc/
./usr/
./usr/
./usr/
./usr/share/unity/
./usr/
./usr/
./usr/lib/
./usr/
./usr/
./usr/
./etc/
./etc/xdg/
./etc/
./etc/
PS Jenkins bot (ps-jenkins) wrote : | # |
FAILED: Continuous integration, rev:9
http://
Executed test runs:
FAILURE: http://
FAILURE: http://
Click here to trigger a rebuild:
http://
PS Jenkins bot (ps-jenkins) wrote : | # |
FAILED: Continuous integration, rev:8
http://
Executed test runs:
FAILURE: http://
FAILURE: http://
Click here to trigger a rebuild:
http://
- 11. By Charles Kerr
-
unit tests passing on desktop and phone, but not in jenkins -- adding gsettings-
ubuntu- schemas to build-depends.
PS Jenkins bot (ps-jenkins) wrote : | # |
FAILED: Continuous integration, rev:10
http://
Executed test runs:
FAILURE: http://
None: http://
Click here to trigger a rebuild:
http://
PS Jenkins bot (ps-jenkins) wrote : | # |
PASSED: Continuous integration, rev:8
http://
Executed test runs:
SUCCESS: http://
SUCCESS: http://
deb: http://
Click here to trigger a rebuild:
http://
PS Jenkins bot (ps-jenkins) wrote : | # |
PASSED: Continuous integration, rev:11
http://
Executed test runs:
SUCCESS: http://
SUCCESS: http://
deb: http://
Click here to trigger a rebuild:
http://
Ted Gould (ted) wrote : | # |
A few cleanup things.
Charles Kerr (charlesk) wrote : | # |
Responded inline
- 12. By Charles Kerr
-
in debian/control, make the Description more informative
- 13. By Charles Kerr
-
fix copy-paste error
- 14. By Charles Kerr
-
in src/exporter.cpp, use G_DBUS_
NAME_OWNER_ FLAGS_NONE when owning the busname
PS Jenkins bot (ps-jenkins) wrote : | # |
PASSED: Continuous integration, rev:14
http://
Executed test runs:
SUCCESS: http://
SUCCESS: http://
deb: http://
Click here to trigger a rebuild:
http://
Ted Gould (ted) wrote : | # |
So, I swear that I'm not trying to be a jerk, but the description is too long now :-) From Lintian:
W: indicator-display: description-
E: indicator-display: extended-
Also if you add a default.conf to your .bzr-builddeb directory to enable split mode it'll build with "bzr bd" right out of the box.
- 15. By Charles Kerr
-
in control/debian, split Description into a shorter description plus an extended description.
- 16. By Charles Kerr
-
in debian/control, bump Standards-Version from 3.9.4 to 3.9.5 to make lintian happy
Charles Kerr (charlesk) wrote : | # |
:-)
I've revised the description and extended-
PS Jenkins bot (ps-jenkins) wrote : | # |
PASSED: Continuous integration, rev:16
http://
Executed test runs:
SUCCESS: http://
SUCCESS: http://
deb: http://
Click here to trigger a rebuild:
http://
Ted Gould (ted) : | # |
Preview Diff
1 | === added file 'CMakeLists.txt' |
2 | --- CMakeLists.txt 1970-01-01 00:00:00 +0000 |
3 | +++ CMakeLists.txt 2014-08-22 00:07:37 +0000 |
4 | @@ -0,0 +1,72 @@ |
5 | +project (indicator-display) |
6 | +cmake_minimum_required (VERSION 2.8.9) |
7 | + |
8 | +list (APPEND CMAKE_MODULE_PATH ${CMAKE_SOURCE_DIR}/cmake) |
9 | + |
10 | +set (PROJECT_VERSION "14.10.0") |
11 | +set (PACKAGE ${CMAKE_PROJECT_NAME}) |
12 | +set (GETTEXT_PACKAGE indicator-display) |
13 | +add_definitions (-DGETTEXT_PACKAGE="${GETTEXT_PACKAGE}" |
14 | + -DGNOMELOCALEDIR="${CMAKE_INSTALL_FULL_LOCALEDIR}") |
15 | + |
16 | +set (SERVICE_LIB ${PACKAGE}) |
17 | +set (SERVICE_EXEC "${PACKAGE}-service") |
18 | + |
19 | +option (enable_tests "Build the package's automatic tests." ON) |
20 | +option (enable_lcov "Generate lcov code coverage reports." ON) |
21 | + |
22 | +## |
23 | +## GNU standard paths |
24 | +## |
25 | +include (GNUInstallDirs) |
26 | +if (EXISTS "/etc/debian_version") # Workaround for libexecdir on debian |
27 | + set (CMAKE_INSTALL_LIBEXECDIR "${CMAKE_INSTALL_LIBDIR}") |
28 | + set (CMAKE_INSTALL_FULL_LIBEXECDIR "${CMAKE_INSTALL_FULL_LIBDIR}") |
29 | +endif () |
30 | +set (CMAKE_INSTALL_PKGLIBEXECDIR "${CMAKE_INSTALL_LIBEXECDIR}/${CMAKE_PROJECT_NAME}") |
31 | +set (CMAKE_INSTALL_FULL_PKGLIBEXECDIR "${CMAKE_INSTALL_FULL_LIBEXECDIR}/${CMAKE_PROJECT_NAME}") |
32 | + |
33 | +## |
34 | +## Check for prerequisites |
35 | +## |
36 | + |
37 | +find_package (PkgConfig REQUIRED) |
38 | + |
39 | +include (FindPkgConfig) |
40 | +pkg_check_modules (SERVICE_DEPS REQUIRED |
41 | + gio-unix-2.0>=2.36 |
42 | + glib-2.0>=2.36) |
43 | +include_directories (SYSTEM ${SERVICE_DEPS_INCLUDE_DIRS}) |
44 | + |
45 | +## |
46 | +## |
47 | +## |
48 | + |
49 | +set (CMAKE_INCLUDE_CURRENT_DIR OFF) |
50 | +include_directories (${CMAKE_CURRENT_SOURCE_DIR}) |
51 | + |
52 | +# set the compiler warnings |
53 | +if ("${CMAKE_CXX_COMPILER_ID}" STREQUAL "Clang") |
54 | + set (CXX_WARNING_ARGS "${CXX_WARNING_ARGS} -Weverything -Wno-c++98-compat") |
55 | +else() |
56 | + set (CXX_WARNING_ARGS "${CXX_WARNING_ARGS} -Wall -Wextra -Wpedantic") |
57 | +endif() |
58 | +set (CXX_WARNING_ARGS "${CXX_WARNING_ARGS} -Wno-missing-field-initializers") # GActionEntry |
59 | + |
60 | +# testing & coverage |
61 | +if (${enable_tests}) |
62 | + set (GTEST_SOURCE_DIR /usr/src/gtest/src) |
63 | + set (GTEST_INCLUDE_DIR ${GTEST_SOURCE_DIR}/..) |
64 | + set (GTEST_LIBS -lpthread) |
65 | + enable_testing () |
66 | + if (${enable_lcov}) |
67 | + include(GCov) |
68 | + endif () |
69 | +endif () |
70 | + |
71 | +add_subdirectory (src) |
72 | +add_subdirectory (data) |
73 | +add_subdirectory (po) |
74 | +if (${enable_tests}) |
75 | + add_subdirectory (tests) |
76 | +endif () |
77 | |
78 | === added directory 'cmake' |
79 | === added file 'cmake/FindGMock.cmake' |
80 | --- cmake/FindGMock.cmake 1970-01-01 00:00:00 +0000 |
81 | +++ cmake/FindGMock.cmake 2014-08-22 00:07:37 +0000 |
82 | @@ -0,0 +1,10 @@ |
83 | +# Build with system gmock and embedded gtest |
84 | +set (GMOCK_INCLUDE_DIRS "/usr/include/gmock/include" CACHE PATH "gmock source include directory") |
85 | +set (GMOCK_SOURCE_DIR "/usr/src/gmock" CACHE PATH "gmock source directory") |
86 | +set (GTEST_INCLUDE_DIRS "${GMOCK_SOURCE_DIR}/gtest/include" CACHE PATH "gtest source include directory") |
87 | + |
88 | +add_subdirectory(${GMOCK_SOURCE_DIR} "${CMAKE_CURRENT_BINARY_DIR}/gmock") |
89 | + |
90 | +set(GTEST_LIBRARIES gtest) |
91 | +set(GTEST_MAIN_LIBRARIES gtest_main) |
92 | +set(GMOCK_LIBRARIES gmock gmock_main) |
93 | |
94 | === added file 'cmake/GCov.cmake' |
95 | --- cmake/GCov.cmake 1970-01-01 00:00:00 +0000 |
96 | +++ cmake/GCov.cmake 2014-08-22 00:07:37 +0000 |
97 | @@ -0,0 +1,51 @@ |
98 | +if (CMAKE_BUILD_TYPE MATCHES coverage) |
99 | + set(GCOV_FLAGS "${GCOV_FLAGS} --coverage") |
100 | + set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} ${GCOV_FLAGS}") |
101 | + set(CMAKE_MODULE_LINKER_FLAGS "${CMAKE_MODULE_LINKER_FLAGS} ${GCOV_FLAGS}") |
102 | + set(CMAKE_SHARED_LINKER_FLAGS "${CMAKE_SHARED_LINKER_FLAGS} ${GCOV_FLAGS}") |
103 | + set(GCOV_LIBS ${GCOV_LIBS} gcov) |
104 | + |
105 | + find_program(GCOVR_EXECUTABLE gcovr HINTS ${GCOVR_ROOT} "${GCOVR_ROOT}/bin") |
106 | + if (NOT GCOVR_EXECUTABLE) |
107 | + message(STATUS "Gcovr binary was not found, can not generate XML coverage info.") |
108 | + else () |
109 | + message(STATUS "Gcovr found, can generate XML coverage info.") |
110 | + add_custom_target (coverage-xml |
111 | + WORKING_DIRECTORY ${CMAKE_BINARY_DIR} |
112 | + COMMAND "${GCOVR_EXECUTABLE}" --exclude="test.*" -x -r "${CMAKE_SOURCE_DIR}" |
113 | + --object-directory=${CMAKE_BINARY_DIR} -o coverage.xml) |
114 | + endif() |
115 | + |
116 | + find_program(LCOV_EXECUTABLE lcov HINTS ${LCOV_ROOT} "${GCOVR_ROOT}/bin") |
117 | + find_program(GENHTML_EXECUTABLE genhtml HINTS ${GENHTML_ROOT}) |
118 | + if (NOT LCOV_EXECUTABLE) |
119 | + message(STATUS "Lcov binary was not found, can not generate HTML coverage info.") |
120 | + else () |
121 | + if(NOT GENHTML_EXECUTABLE) |
122 | + message(STATUS "Genthml binary not found, can not generate HTML coverage info.") |
123 | + else() |
124 | + message(STATUS "Lcov and genhtml found, can generate HTML coverage info.") |
125 | + add_custom_target (coverage-html |
126 | + WORKING_DIRECTORY ${CMAKE_BINARY_DIR} |
127 | + COMMAND "${CMAKE_CTEST_COMMAND}" --force-new-ctest-process --verbose |
128 | + COMMAND "${LCOV_EXECUTABLE}" --directory ${CMAKE_BINARY_DIR} --capture | ${CMAKE_SOURCE_DIR}/trim-lcov.py > dconf-lcov.info |
129 | + COMMAND "${LCOV_EXECUTABLE}" -r dconf-lcov.info /usr/include/\\* -o nosys-lcov.info |
130 | + COMMAND LANG=C "${GENHTML_EXECUTABLE}" --prefix ${CMAKE_BINARY_DIR} --output-directory lcov-html --legend --show-details nosys-lcov.info |
131 | + COMMAND ${CMAKE_COMMAND} -E echo "" |
132 | + COMMAND ${CMAKE_COMMAND} -E echo "file://${CMAKE_BINARY_DIR}/lcov-html/index.html" |
133 | + COMMAND ${CMAKE_COMMAND} -E echo "") |
134 | + #COMMAND "${LCOV_EXECUTABLE}" --directory ${CMAKE_BINARY_DIR} --capture --output-file coverage.info --no-checksum |
135 | + #COMMAND "${GENHTML_EXECUTABLE}" --prefix ${CMAKE_BINARY_DIR} --output-directory coveragereport --title "Code Coverage" --legend --show-details coverage.info |
136 | + #COMMAND ${CMAKE_COMMAND} -E echo "\\#define foo \\\"bar\\\"" |
137 | + #) |
138 | + endif() |
139 | + endif() |
140 | +endif() |
141 | + |
142 | + |
143 | + #$(MAKE) $(AM_MAKEFLAGS) check |
144 | + #lcov --directory $(top_builddir) --capture --test-name dconf | $(top_srcdir)/trim-lcov.py > dconf-lcov.info |
145 | + #LANG=C genhtml --prefix $(top_builddir) --output-directory lcov-html --legend --show-details dconf-lcov.info |
146 | + #@echo |
147 | + #@echo " file://$(abs_top_builddir)/lcov-html/index.html" |
148 | + #@echo |
149 | |
150 | === added file 'cmake/GdbusCodegen.cmake' |
151 | --- cmake/GdbusCodegen.cmake 1970-01-01 00:00:00 +0000 |
152 | +++ cmake/GdbusCodegen.cmake 2014-08-22 00:07:37 +0000 |
153 | @@ -0,0 +1,36 @@ |
154 | +cmake_minimum_required(VERSION 2.6) |
155 | +if(POLICY CMP0011) |
156 | + cmake_policy(SET CMP0011 NEW) |
157 | +endif(POLICY CMP0011) |
158 | + |
159 | +find_program(GDBUS_CODEGEN NAMES gdbus-codegen DOC "gdbus-codegen executable") |
160 | +if(NOT GDBUS_CODEGEN) |
161 | + message(FATAL_ERROR "Excutable gdbus-codegen not found") |
162 | +endif() |
163 | + |
164 | +macro(add_gdbus_codegen outfiles name prefix service_xml) |
165 | + add_custom_command( |
166 | + OUTPUT "${CMAKE_CURRENT_BINARY_DIR}/${name}.h" "${CMAKE_CURRENT_BINARY_DIR}/${name}.c" |
167 | + COMMAND "${GDBUS_CODEGEN}" |
168 | + --interface-prefix "${prefix}" |
169 | + --generate-c-code "${name}" |
170 | + "${service_xml}" |
171 | + WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR} |
172 | + DEPENDS ${ARGN} "${service_xml}" |
173 | + ) |
174 | + list(APPEND ${outfiles} "${CMAKE_CURRENT_BINARY_DIR}/${name}.c") |
175 | +endmacro(add_gdbus_codegen) |
176 | + |
177 | +macro(add_gdbus_codegen_with_namespace outfiles name prefix namespace service_xml) |
178 | + add_custom_command( |
179 | + OUTPUT "${CMAKE_CURRENT_BINARY_DIR}/${name}.h" "${CMAKE_CURRENT_BINARY_DIR}/${name}.c" |
180 | + COMMAND "${GDBUS_CODEGEN}" |
181 | + --interface-prefix "${prefix}" |
182 | + --generate-c-code "${name}" |
183 | + --c-namespace "${namespace}" |
184 | + "${service_xml}" |
185 | + WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR} |
186 | + DEPENDS ${ARGN} "${service_xml}" |
187 | + ) |
188 | + list(APPEND ${outfiles} "${CMAKE_CURRENT_BINARY_DIR}/${name}.c") |
189 | +endmacro(add_gdbus_codegen_with_namespace) |
190 | |
191 | === added file 'cmake/Translations.cmake' |
192 | --- cmake/Translations.cmake 1970-01-01 00:00:00 +0000 |
193 | +++ cmake/Translations.cmake 2014-08-22 00:07:37 +0000 |
194 | @@ -0,0 +1,37 @@ |
195 | +# Translations.cmake, CMake macros written for Marlin, feel free to re-use them |
196 | + |
197 | +macro(add_translations_directory NLS_PACKAGE) |
198 | + add_custom_target (i18n ALL) |
199 | + find_program (MSGFMT_EXECUTABLE msgfmt) |
200 | + file (GLOB PO_FILES ${CMAKE_CURRENT_SOURCE_DIR}/*.po) |
201 | + foreach (PO_INPUT ${PO_FILES}) |
202 | + get_filename_component (PO_INPUT_BASE ${PO_INPUT} NAME_WE) |
203 | + set (MO_OUTPUT ${CMAKE_CURRENT_BINARY_DIR}/${PO_INPUT_BASE}.mo) |
204 | + add_custom_command (TARGET i18n COMMAND ${MSGFMT_EXECUTABLE} -o ${MO_OUTPUT} ${PO_INPUT}) |
205 | + |
206 | + install (FILES ${MO_OUTPUT} DESTINATION |
207 | + ${CMAKE_INSTALL_LOCALEDIR}/${PO_INPUT_BASE}/LC_MESSAGES |
208 | + RENAME ${NLS_PACKAGE}.mo) |
209 | + endforeach (PO_INPUT ${PO_FILES}) |
210 | +endmacro(add_translations_directory) |
211 | + |
212 | + |
213 | +macro(add_translations_catalog NLS_PACKAGE) |
214 | + add_custom_target (pot COMMENT “Building translation catalog.”) |
215 | + find_program (XGETTEXT_EXECUTABLE xgettext) |
216 | + |
217 | + # init this list, which will hold all the sources across all dirs |
218 | + set(SOURCES "") |
219 | + |
220 | + # add each directory's sources to the overall sources list |
221 | + foreach(FILES_INPUT ${ARGN}) |
222 | + set (DIR ${CMAKE_CURRENT_SOURCE_DIR}/${FILES_INPUT}) |
223 | + file (GLOB_RECURSE DIR_SOURCES ${DIR}/*.c ${DIR}/*.cc ${DIR}/*.cpp ${DIR}/*.cxx ${DIR}/*.vala) |
224 | + set (SOURCES ${SOURCES} ${DIR_SOURCES}) |
225 | + endforeach() |
226 | + |
227 | + add_custom_command (TARGET pot COMMAND |
228 | + ${XGETTEXT_EXECUTABLE} -d ${NLS_PACKAGE} -o ${CMAKE_CURRENT_SOURCE_DIR}/${NLS_PACKAGE}.pot |
229 | + ${SOURCES} --keyword="_" --keyword="N_" --from-code=UTF-8 |
230 | + ) |
231 | +endmacro() |
232 | |
233 | === added directory 'data' |
234 | === added file 'data/CMakeLists.txt' |
235 | --- data/CMakeLists.txt 1970-01-01 00:00:00 +0000 |
236 | +++ data/CMakeLists.txt 2014-08-22 00:07:37 +0000 |
237 | @@ -0,0 +1,74 @@ |
238 | +## |
239 | +## Upstart Job File |
240 | +## |
241 | + |
242 | +# where to install |
243 | +set (UPSTART_JOBS_DIR "${CMAKE_INSTALL_FULL_DATADIR}/upstart/sessions") |
244 | +message (STATUS "${UPSTART_JOBS_DIR} is the Upstart Jobs File install dir") |
245 | + |
246 | +set (UPSTART_JOB_NAME "${CMAKE_PROJECT_NAME}.conf") |
247 | +set (UPSTART_JOB_FILE "${CMAKE_CURRENT_BINARY_DIR}/${UPSTART_JOB_NAME}") |
248 | +set (UPSTART_JOB_FILE_IN "${CMAKE_CURRENT_SOURCE_DIR}/${UPSTART_JOB_NAME}.in") |
249 | + |
250 | +# build it |
251 | +set (pkglibexecdir "${CMAKE_INSTALL_FULL_PKGLIBEXECDIR}") |
252 | +configure_file ("${UPSTART_JOB_FILE_IN}" "${UPSTART_JOB_FILE}") |
253 | + |
254 | +# install it |
255 | +install (FILES "${UPSTART_JOB_FILE}" |
256 | + DESTINATION "${UPSTART_JOBS_DIR}") |
257 | + |
258 | +## |
259 | +## XDG Autostart File |
260 | +## |
261 | + |
262 | +# where to install |
263 | +set (XDG_AUTOSTART_DIR "/etc/xdg/autostart") |
264 | +message (STATUS "${XDG_AUTOSTART_DIR} is the XDG Autostart install dir") |
265 | + |
266 | +set (XDG_AUTOSTART_NAME "${CMAKE_PROJECT_NAME}.desktop") |
267 | +set (XDG_AUTOSTART_FILE "${CMAKE_CURRENT_BINARY_DIR}/${XDG_AUTOSTART_NAME}") |
268 | +set (XDG_AUTOSTART_FILE_IN "${CMAKE_CURRENT_SOURCE_DIR}/${XDG_AUTOSTART_NAME}.in") |
269 | + |
270 | +# build it |
271 | +set (pkglibexecdir "${CMAKE_INSTALL_FULL_PKGLIBEXECDIR}") |
272 | +configure_file ("${XDG_AUTOSTART_FILE_IN}" "${XDG_AUTOSTART_FILE}") |
273 | + |
274 | +# install it |
275 | +install (FILES "${XDG_AUTOSTART_FILE}" |
276 | + DESTINATION "${XDG_AUTOSTART_DIR}") |
277 | + |
278 | +## |
279 | +## Upstart XDG Autostart Override |
280 | +## |
281 | + |
282 | +# where to install |
283 | +set (UPSTART_XDG_AUTOSTART_DIR "${CMAKE_INSTALL_FULL_DATAROOTDIR}/upstart/xdg/autostart") |
284 | +message (STATUS "${UPSTART_XDG_AUTOSTART_DIR} is the Upstart XDG autostart override dir") |
285 | + |
286 | +set (UPSTART_XDG_AUTOSTART_NAME "${CMAKE_PROJECT_NAME}.upstart.desktop") |
287 | +set (UPSTART_XDG_AUTOSTART_FILE "${CMAKE_CURRENT_BINARY_DIR}/${UPSTART_XDG_AUTOSTART_NAME}") |
288 | +set (UPSTART_XDG_AUTOSTART_FILE_IN "${CMAKE_CURRENT_SOURCE_DIR}/${UPSTART_XDG_AUTOSTART_NAME}.in") |
289 | + |
290 | +# build it |
291 | +set (pkglibexecdir "${CMAKE_INSTALL_FULL_PKGLIBEXECDIR}") |
292 | +configure_file ("${UPSTART_XDG_AUTOSTART_FILE_IN}" "${UPSTART_XDG_AUTOSTART_FILE}") |
293 | + |
294 | +# install it |
295 | +install (FILES "${UPSTART_XDG_AUTOSTART_FILE}" |
296 | + DESTINATION "${UPSTART_XDG_AUTOSTART_DIR}" |
297 | + RENAME "${XDG_AUTOSTART_NAME}") |
298 | + |
299 | +## |
300 | +## Unity Indicator File |
301 | +## |
302 | + |
303 | +# where to install |
304 | +set (UNITY_INDICATOR_DIR "${CMAKE_INSTALL_FULL_DATAROOTDIR}/unity/indicators") |
305 | +message (STATUS "${UNITY_INDICATOR_DIR} is the Unity Indicator install dir") |
306 | + |
307 | +set (UNITY_INDICATOR_NAME "com.canonical.indicator.rotation_lock") |
308 | +set (UNITY_INDICATOR_FILE "${CMAKE_CURRENT_SOURCE_DIR}/${UNITY_INDICATOR_NAME}") |
309 | + |
310 | +install (FILES "${UNITY_INDICATOR_FILE}" |
311 | + DESTINATION "${UNITY_INDICATOR_DIR}") |
312 | |
313 | === added file 'data/com.canonical.indicator.rotation_lock' |
314 | --- data/com.canonical.indicator.rotation_lock 1970-01-01 00:00:00 +0000 |
315 | +++ data/com.canonical.indicator.rotation_lock 2014-08-22 00:07:37 +0000 |
316 | @@ -0,0 +1,11 @@ |
317 | +[Indicator Service] |
318 | +Name=indicator-rotation-lock |
319 | +ObjectPath=/com/canonical/indicator/rotation_lock |
320 | +Position=90 |
321 | + |
322 | +[phone] |
323 | +ObjectPath=/com/canonical/indicator/rotation_lock/phone |
324 | + |
325 | +[phone_greeter] |
326 | +ObjectPath=/com/canonical/indicator/rotation_lock/phone |
327 | + |
328 | |
329 | === added file 'data/indicator-display.conf.in' |
330 | --- data/indicator-display.conf.in 1970-01-01 00:00:00 +0000 |
331 | +++ data/indicator-display.conf.in 2014-08-22 00:07:37 +0000 |
332 | @@ -0,0 +1,9 @@ |
333 | +description "Indicator Display Backend" |
334 | + |
335 | +start on indicator-services-start |
336 | +stop on desktop-end or indicator-services-end |
337 | + |
338 | +respawn |
339 | +respawn limit 2 10 |
340 | + |
341 | +exec @pkglibexecdir@/indicator-display-service |
342 | |
343 | === added file 'data/indicator-display.desktop.in' |
344 | --- data/indicator-display.desktop.in 1970-01-01 00:00:00 +0000 |
345 | +++ data/indicator-display.desktop.in 2014-08-22 00:07:37 +0000 |
346 | @@ -0,0 +1,9 @@ |
347 | +[Desktop Entry] |
348 | +Type=Application |
349 | +Name=Indicator Display |
350 | +Exec=@pkglibexecdir@/indicator-display-service |
351 | +OnlyShowIn=Unity;GNOME; |
352 | +NoDisplay=true |
353 | +StartupNotify=false |
354 | +Terminal=false |
355 | +AutostartCondition=GNOME3 unless-session gnome |
356 | |
357 | === added file 'data/indicator-display.upstart.desktop.in' |
358 | --- data/indicator-display.upstart.desktop.in 1970-01-01 00:00:00 +0000 |
359 | +++ data/indicator-display.upstart.desktop.in 2014-08-22 00:07:37 +0000 |
360 | @@ -0,0 +1,9 @@ |
361 | +[Desktop Entry] |
362 | +Type=Application |
363 | +Name=Indicator Display |
364 | +Exec=@pkglibexecdir@/indicator-display-service |
365 | +OnlyShowIn=Unity; |
366 | +NoDisplay=true |
367 | +StartupNotify=false |
368 | +Terminal=false |
369 | +Hidden=true |
370 | |
371 | === added directory 'debian' |
372 | === added file 'debian/changelog' |
373 | --- debian/changelog 1970-01-01 00:00:00 +0000 |
374 | +++ debian/changelog 2014-08-22 00:07:37 +0000 |
375 | @@ -0,0 +1,6 @@ |
376 | +indicator-display (0.1-0ubuntu1) utopic; urgency=medium |
377 | + |
378 | + * Initial release. |
379 | + |
380 | + -- Charles Kerr <charles.kerr@canonical.com> Wed, 20 Aug 2014 15:29:27 -0500 |
381 | + |
382 | |
383 | === added file 'debian/compat' |
384 | --- debian/compat 1970-01-01 00:00:00 +0000 |
385 | +++ debian/compat 2014-08-22 00:07:37 +0000 |
386 | @@ -0,0 +1,1 @@ |
387 | +9 |
388 | |
389 | === added file 'debian/control' |
390 | --- debian/control 1970-01-01 00:00:00 +0000 |
391 | +++ debian/control 2014-08-22 00:07:37 +0000 |
392 | @@ -0,0 +1,34 @@ |
393 | +Source: indicator-display |
394 | +Section: misc |
395 | +Priority: optional |
396 | +Maintainer: Charles Kerr <charles.kerr@canonical.com> |
397 | +Build-Depends: cmake, |
398 | + dbus, |
399 | +# make g++ version explicit for ABI safety <https://wiki.ubuntu.com/cpp-11> |
400 | + g++-4.9, |
401 | + libglib2.0-dev (>= 2.36), |
402 | + libproperties-cpp-dev, |
403 | +# for coverage reports |
404 | + lcov, |
405 | +# for tests |
406 | + cppcheck, |
407 | + libgtest-dev, |
408 | + google-mock (>= 1.6.0+svn437), |
409 | + gsettings-ubuntu-schemas (>= 0.0.2+14.10.20140813), |
410 | +# for packaging |
411 | + debhelper (>= 9), |
412 | + dh-translations, |
413 | +Standards-Version: 3.9.5 |
414 | +Homepage: http://launchpad.net/indicator-display/ |
415 | +# If you aren't a member of ~indicator-applet-developers but need to upload |
416 | +# packaging changes, just go ahead. ~indicator-applet-developers will notice and |
417 | +# sync up the code again. |
418 | +Vcs-Bzr: https://code.launchpad.net/~indicator-applet-developers/indicator-display/trunk.14.10 |
419 | + |
420 | +Package: indicator-display |
421 | +Architecture: any |
422 | +Depends: ${shlibs:Depends}, |
423 | + ${misc:Depends}, |
424 | + gsettings-ubuntu-schemas (>= 0.0.2+14.10.20140813), |
425 | +Description: Collection of small indicators |
426 | + Indicators too small to merit separate codebases, such as Rotation Lock |
427 | |
428 | === added file 'debian/copyright' |
429 | --- debian/copyright 1970-01-01 00:00:00 +0000 |
430 | +++ debian/copyright 2014-08-22 00:07:37 +0000 |
431 | @@ -0,0 +1,21 @@ |
432 | +Format: http://www.debian.org/doc/packaging-manuals/copyright-format/1.0/ |
433 | +Upstream-Name: indicator-display |
434 | +Source: http://launchpad.net/indicator-display |
435 | + |
436 | +Files: * |
437 | +Copyright: 2014, Canonical Ltd. |
438 | +License: GPL-3 |
439 | + This package is free software; you can redistribute it and/or modify |
440 | + it under the terms of the GNU General Public License as published by |
441 | + the Free Software Foundation; version 3 of the License. |
442 | + . |
443 | + This package is distributed in the hope that it will be useful, |
444 | + but WITHOUT ANY WARRANTY; without even the implied warranty of |
445 | + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
446 | + GNU General Public License for more details. |
447 | + . |
448 | + You should have received a copy of the GNU General Public License |
449 | + along with this program. If not, see <http://www.gnu.org/licenses/> |
450 | + . |
451 | + On Debian systems, the complete text of the GNU General |
452 | + Public License version 3 can be found in "/usr/share/common-licenses/GPL-3". |
453 | |
454 | === added file 'debian/rules' |
455 | --- debian/rules 1970-01-01 00:00:00 +0000 |
456 | +++ debian/rules 2014-08-22 00:07:37 +0000 |
457 | @@ -0,0 +1,10 @@ |
458 | +#!/usr/bin/make -f |
459 | + |
460 | +# Explicitly selecting a G{CC,++}-version here to avoid ABI breaks |
461 | +# introduced by toolchain updates. <https://wiki.ubuntu.com/cpp-11> |
462 | +export CC=$(DEB_HOST_GNU_TYPE)-gcc-4.9 |
463 | +export CXX=$(DEB_HOST_GNU_TYPE)-g++-4.9 |
464 | + |
465 | +%: |
466 | + dh $@ --with translations |
467 | + |
468 | |
469 | === added directory 'po' |
470 | === added file 'po/CMakeLists.txt' |
471 | --- po/CMakeLists.txt 1970-01-01 00:00:00 +0000 |
472 | +++ po/CMakeLists.txt 2014-08-22 00:07:37 +0000 |
473 | @@ -0,0 +1,3 @@ |
474 | +include (Translations) |
475 | +add_translations_directory("${GETTEXT_PACKAGE}") |
476 | +add_translations_catalog("${GETTEXT_PACKAGE}" ../src/) |
477 | |
478 | === added file 'po/POTFILES.in' |
479 | --- po/POTFILES.in 1970-01-01 00:00:00 +0000 |
480 | +++ po/POTFILES.in 2014-08-22 00:07:37 +0000 |
481 | @@ -0,0 +1,1 @@ |
482 | +src/rotation-lock.cpp |
483 | |
484 | === added directory 'src' |
485 | === added file 'src/CMakeLists.txt' |
486 | --- src/CMakeLists.txt 1970-01-01 00:00:00 +0000 |
487 | +++ src/CMakeLists.txt 2014-08-22 00:07:37 +0000 |
488 | @@ -0,0 +1,29 @@ |
489 | +set (SERVICE_LIB "indicatordisplayservice") |
490 | +set (SERVICE_EXEC "indicator-display-service") |
491 | + |
492 | +add_definitions (-DG_LOG_DOMAIN="${CMAKE_PROJECT_NAME}") |
493 | + |
494 | +# handwritten source code... |
495 | +set (SERVICE_LIB_HANDWRITTEN_SOURCES |
496 | + exporter.cpp |
497 | + rotation-lock.cpp) |
498 | + |
499 | +add_library (${SERVICE_LIB} STATIC |
500 | + ${SERVICE_LIB_HANDWRITTEN_SOURCES}) |
501 | + |
502 | +# add the bin dir to the include path so that |
503 | +# the compiler can find the generated header files |
504 | +include_directories (${CMAKE_CURRENT_BINARY_DIR}) |
505 | + |
506 | +link_directories (${SERVICE_DEPS_LIBRARY_DIRS}) |
507 | + |
508 | +set (SERVICE_EXEC_HANDWRITTEN_SOURCES main.cpp) |
509 | +add_executable (${SERVICE_EXEC} ${SERVICE_EXEC_HANDWRITTEN_SOURCES}) |
510 | +target_link_libraries (${SERVICE_EXEC} ${SERVICE_LIB} ${SERVICE_DEPS_LIBRARIES} ${GCOV_LIBS}) |
511 | +install (TARGETS ${SERVICE_EXEC} RUNTIME DESTINATION ${CMAKE_INSTALL_FULL_PKGLIBEXECDIR}) |
512 | + |
513 | +# add warnings/coverage info on handwritten files |
514 | +# but not the generated ones... |
515 | +set_property (SOURCE ${SERVICE_LIB_HANDWRITTEN_SOURCES} ${SERVICE_EXEC_HANDWRITTEN_SOURCES} |
516 | + APPEND_STRING PROPERTY COMPILE_FLAGS " -std=c++11 -g ${CXX_WARNING_ARGS} ${GCOV_FLAGS}") |
517 | + |
518 | |
519 | === added file 'src/exporter.cpp' |
520 | --- src/exporter.cpp 1970-01-01 00:00:00 +0000 |
521 | +++ src/exporter.cpp 2014-08-22 00:07:37 +0000 |
522 | @@ -0,0 +1,217 @@ |
523 | +/* |
524 | + * Copyright 2014 Canonical Ltd. |
525 | + * |
526 | + * This program is free software: you can redistribute it and/or modify it |
527 | + * under the terms of the GNU General Public License version 3, as published |
528 | + * by the Free Software Foundation. |
529 | + * |
530 | + * This program is distributed in the hope that it will be useful, but |
531 | + * WITHOUT ANY WARRANTY; without even the implied warranties of |
532 | + * MERCHANTABILITY, SATISFACTORY QUALITY, or FITNESS FOR A PARTICULAR |
533 | + * PURPOSE. See the GNU General Public License for more details. |
534 | + * |
535 | + * You should have received a copy of the GNU General Public License along |
536 | + * with this program. If not, see <http://www.gnu.org/licenses/>. |
537 | + * |
538 | + * Authors: |
539 | + * Charles Kerr <charles.kerr@canonical.com> |
540 | + */ |
541 | + |
542 | +#include <src/exporter.h> |
543 | + |
544 | +class Exporter::Impl |
545 | +{ |
546 | +public: |
547 | + |
548 | + Impl(const std::shared_ptr<Indicator>& indicator): |
549 | + m_indicator(indicator) |
550 | + { |
551 | + auto bus_name = g_strdup_printf("com.canonical.indicator.%s", indicator->name()); |
552 | + m_own_id = g_bus_own_name(G_BUS_TYPE_SESSION, |
553 | + bus_name, |
554 | + G_BUS_NAME_OWNER_FLAGS_NONE, |
555 | + on_bus_acquired, |
556 | + nullptr, |
557 | + on_name_lost, |
558 | + this, |
559 | + nullptr); |
560 | + |
561 | + g_free(bus_name); |
562 | + } |
563 | + |
564 | + ~Impl() |
565 | + { |
566 | + if (m_bus != nullptr) |
567 | + { |
568 | + for(const auto& id : m_exported_menu_ids) |
569 | + g_dbus_connection_unexport_menu_model(m_bus, id); |
570 | + |
571 | + if (m_exported_actions_id) |
572 | + g_dbus_connection_unexport_action_group(m_bus, m_exported_actions_id); |
573 | + } |
574 | + |
575 | + if (m_own_id) |
576 | + g_bus_unown_name(m_own_id); |
577 | + |
578 | + g_clear_object(&m_bus); |
579 | + } |
580 | + |
581 | + core::Signal<std::string>& name_lost() |
582 | + { |
583 | + return m_name_lost; |
584 | + } |
585 | + |
586 | +private: |
587 | + |
588 | + void emit_name_lost(const char* bus_name) |
589 | + { |
590 | + m_name_lost(bus_name); |
591 | + } |
592 | + |
593 | + static void on_bus_acquired(GDBusConnection * connection, |
594 | + const gchar * name, |
595 | + gpointer gself) |
596 | + { |
597 | + static_cast<Impl*>(gself)->on_bus_acquired(connection, name); |
598 | + } |
599 | + |
600 | + void on_bus_acquired(GDBusConnection* connection, const gchar* /*name*/) |
601 | + { |
602 | + m_bus = G_DBUS_CONNECTION(g_object_ref(G_OBJECT(connection))); |
603 | + |
604 | + export_actions(m_indicator); |
605 | + |
606 | + for (auto& profile : m_indicator->profiles()) |
607 | + export_profile(m_indicator, profile); |
608 | + } |
609 | + |
610 | + void export_actions(const std::shared_ptr<Indicator>& indicator) |
611 | + { |
612 | + GError* error; |
613 | + char* object_path; |
614 | + guint id; |
615 | + |
616 | + // export the actions |
617 | + |
618 | + error = nullptr; |
619 | + object_path = g_strdup_printf("/com/canonical/indicator/%s", indicator->name()); |
620 | + id = g_dbus_connection_export_action_group(m_bus, |
621 | + object_path, |
622 | + G_ACTION_GROUP(indicator->action_group()), |
623 | + &error); |
624 | + if (id) |
625 | + m_exported_actions_id = id; |
626 | + else |
627 | + g_warning("Can't export action group to '%s': %s", object_path, error->message); |
628 | + |
629 | + g_clear_error(&error); |
630 | + g_free(object_path); |
631 | + } |
632 | + |
633 | + static GVariant* create_header_state(const Header& h) |
634 | + { |
635 | + GVariantBuilder b; |
636 | + g_variant_builder_init(&b, G_VARIANT_TYPE_VARDICT); |
637 | + |
638 | + g_variant_builder_add(&b, "{sv}", "visible", g_variant_new_boolean(h.is_visible)); |
639 | + |
640 | + if (!h.title.empty()) |
641 | + g_variant_builder_add(&b, "{sv}", "title", g_variant_new_string(h.title.c_str())); |
642 | + |
643 | + if (!h.label.empty()) |
644 | + g_variant_builder_add(&b, "{sv}", "label", g_variant_new_string(h.label.c_str())); |
645 | + |
646 | + if (!h.title.empty() || !h.label.empty()) |
647 | + g_variant_builder_add(&b, "{sv}", "accessible-desc", g_variant_new_string(!h.label.empty() ? h.label.c_str() : h.title.c_str())); |
648 | + |
649 | + if (h.icon) |
650 | + g_variant_builder_add(&b, "{sv}", "icon", g_icon_serialize(h.icon.get())); |
651 | + |
652 | + return g_variant_builder_end (&b); |
653 | + } |
654 | + |
655 | + void export_profile(const std::shared_ptr<Indicator>& indicator, |
656 | + const std::shared_ptr<Profile>& profile) |
657 | + { |
658 | + // build the header action |
659 | + auto action_group = indicator->action_group(); |
660 | + std::string action_name = profile->name() + "-header"; |
661 | + auto a = g_simple_action_new_stateful(action_name.c_str(), nullptr, create_header_state(profile->header())); |
662 | + g_action_map_add_action(G_ACTION_MAP(action_group), G_ACTION(a)); |
663 | + profile->header().changed().connect([action_group,action_name](const Header& header){ |
664 | + auto state = create_header_state(header); |
665 | + auto tmp = g_variant_print(state, true); |
666 | + g_message("header changed; updating action state to '%s'", tmp); |
667 | + g_action_group_change_action_state(G_ACTION_GROUP(action_group), |
668 | + action_name.c_str(), |
669 | + create_header_state(header)); |
670 | + g_free(tmp); |
671 | + }); |
672 | + |
673 | + // build the header menu |
674 | + auto detailed_action = g_strdup_printf("indicator.%s", action_name.c_str()); |
675 | + GMenuItem* header = g_menu_item_new(nullptr, detailed_action); |
676 | + g_menu_item_set_attribute(header, "x-canonical-type", "s", "com.canonical.indicator.root"); |
677 | + g_menu_item_set_submenu(header, profile->menu_model().get()); |
678 | + g_free(detailed_action); |
679 | + |
680 | + // build the menu |
681 | + auto menu = g_menu_new(); |
682 | + g_menu_append_item(menu, header); |
683 | + g_object_unref(header); |
684 | + |
685 | + // export the menu |
686 | + auto object_path = g_strdup_printf("/com/canonical/indicator/%s/%s", |
687 | + indicator->name(), |
688 | + profile->name().c_str()); |
689 | + GError* error = nullptr; |
690 | + auto id = g_dbus_connection_export_menu_model(m_bus, object_path, G_MENU_MODEL(menu), &error); |
691 | + if (id) |
692 | + m_exported_menu_ids.insert(id); |
693 | + else if (error != nullptr) |
694 | + g_warning("cannot export '%s': %s", object_path, error->message); |
695 | + |
696 | + g_free(object_path); |
697 | + g_clear_error(&error); |
698 | + //g_object_unref(menu); |
699 | + } |
700 | + |
701 | + static void on_name_lost(GDBusConnection * /*connection*/, |
702 | + const gchar * name, |
703 | + gpointer gthis) |
704 | + { |
705 | + static_cast<Impl*>(gthis)->emit_name_lost(name); |
706 | + } |
707 | + |
708 | + const std::string m_bus_name; |
709 | + core::Signal<std::string> m_name_lost; |
710 | + std::shared_ptr<Indicator> m_indicator; |
711 | + std::set<guint> m_exported_menu_ids; |
712 | + guint m_own_id = 0; |
713 | + guint m_exported_actions_id = 0; |
714 | + GDBusConnection * m_bus = nullptr; |
715 | +}; |
716 | + |
717 | +/*** |
718 | +**** |
719 | +***/ |
720 | + |
721 | +Exporter::Exporter(const std::shared_ptr<Indicator>& indicator): |
722 | + impl(new Impl(indicator)) |
723 | +{ |
724 | +} |
725 | + |
726 | +Exporter::~Exporter() |
727 | +{ |
728 | +} |
729 | + |
730 | +core::Signal<std::string>& |
731 | +Exporter::name_lost() |
732 | +{ |
733 | + return impl->name_lost(); |
734 | +} |
735 | + |
736 | +/*** |
737 | +**** |
738 | +***/ |
739 | + |
740 | |
741 | === added file 'src/exporter.h' |
742 | --- src/exporter.h 1970-01-01 00:00:00 +0000 |
743 | +++ src/exporter.h 2014-08-22 00:07:37 +0000 |
744 | @@ -0,0 +1,40 @@ |
745 | +/* |
746 | + * Copyright 2014 Canonical Ltd. |
747 | + * |
748 | + * This program is free software: you can redistribute it and/or modify it |
749 | + * under the terms of the GNU General Public License version 3, as published |
750 | + * by the Free Software Foundation. |
751 | + * |
752 | + * This program is distributed in the hope that it will be useful, but |
753 | + * WITHOUT ANY WARRANTY; without even the implied warranties of |
754 | + * MERCHANTABILITY, SATISFACTORY QUALITY, or FITNESS FOR A PARTICULAR |
755 | + * PURPOSE. See the GNU General Public License for more details. |
756 | + * |
757 | + * You should have received a copy of the GNU General Public License along |
758 | + * with this program. If not, see <http://www.gnu.org/licenses/>. |
759 | + * |
760 | + * Authors: |
761 | + * Charles Kerr <charles.kerr@canonical.com> |
762 | + */ |
763 | + |
764 | +#include <src/indicator.h> |
765 | + |
766 | +#include <core/signal.h> |
767 | + |
768 | +#include <memory> |
769 | + |
770 | +class Exporter |
771 | +{ |
772 | +public: |
773 | + Exporter(const std::shared_ptr<Indicator>& indicator); |
774 | + ~Exporter(); |
775 | + core::Signal<std::string>& name_lost(); |
776 | + |
777 | +private: |
778 | + class Impl; |
779 | + std::unique_ptr<Impl> impl; |
780 | + |
781 | + Exporter(const Exporter&) =delete; |
782 | + Exporter& operator=(const Exporter&) =delete; |
783 | +}; |
784 | + |
785 | |
786 | === added file 'src/indicator.h' |
787 | --- src/indicator.h 1970-01-01 00:00:00 +0000 |
788 | +++ src/indicator.h 2014-08-22 00:07:37 +0000 |
789 | @@ -0,0 +1,88 @@ |
790 | +/* |
791 | + * Copyright 2014 Canonical Ltd. |
792 | + * |
793 | + * This program is free software: you can redistribute it and/or modify it |
794 | + * under the terms of the GNU General Public License version 3, as published |
795 | + * by the Free Software Foundation. |
796 | + * |
797 | + * This program is distributed in the hope that it will be useful, but |
798 | + * WITHOUT ANY WARRANTY; without even the implied warranties of |
799 | + * MERCHANTABILITY, SATISFACTORY QUALITY, or FITNESS FOR A PARTICULAR |
800 | + * PURPOSE. See the GNU General Public License for more details. |
801 | + * |
802 | + * You should have received a copy of the GNU General Public License along |
803 | + * with this program. If not, see <http://www.gnu.org/licenses/>. |
804 | + * |
805 | + * Authors: |
806 | + * Charles Kerr <charles.kerr@canonical.com> |
807 | + */ |
808 | + |
809 | +#ifndef INDICATOR_DISPLAY_INDICATOR_H |
810 | +#define INDICATOR_DISPLAY_INDICATOR_H |
811 | + |
812 | +#include <core/property.h> |
813 | + |
814 | +#include <gio/gio.h> // GIcon |
815 | + |
816 | +#include <string> |
817 | +#include <vector> |
818 | + |
819 | +struct Header |
820 | +{ |
821 | + bool is_visible = false; |
822 | + std::string title; |
823 | + std::string label; |
824 | + std::string a11y; |
825 | + std::shared_ptr<GIcon> icon; |
826 | + |
827 | + bool operator== (const Header& that) const { |
828 | + return (is_visible == that.is_visible) && |
829 | + (title == that.title) && |
830 | + (label == that.label) && |
831 | + (a11y == that.a11y) && |
832 | + (icon == that.icon); |
833 | + } |
834 | + bool operator!= (const Header& that) const { return !(*this == that);} |
835 | +}; |
836 | + |
837 | + |
838 | +class Profile |
839 | +{ |
840 | +public: |
841 | + virtual std::string name() const =0; |
842 | + virtual const core::Property<Header>& header() const =0; |
843 | + virtual std::shared_ptr<GMenuModel> menu_model() const =0; |
844 | + |
845 | +protected: |
846 | + Profile() =default; |
847 | +}; |
848 | + |
849 | + |
850 | +class SimpleProfile: public Profile |
851 | +{ |
852 | +public: |
853 | + SimpleProfile(const char* name, const std::shared_ptr<GMenuModel>& menu): m_name(name), m_menu(menu) {} |
854 | + |
855 | + std::string name() const {return m_name;} |
856 | + core::Property<Header>& header() {return m_header;} |
857 | + const core::Property<Header>& header() const {return m_header;} |
858 | + std::shared_ptr<GMenuModel> menu_model() const {return m_menu;} |
859 | + |
860 | +protected: |
861 | + const std::string m_name; |
862 | + core::Property<Header> m_header; |
863 | + std::shared_ptr<GMenuModel> m_menu; |
864 | +}; |
865 | + |
866 | + |
867 | +class Indicator |
868 | +{ |
869 | +public: |
870 | + virtual ~Indicator() =default; |
871 | + |
872 | + virtual const char* name() const =0; |
873 | + virtual GSimpleActionGroup* action_group() const =0; |
874 | + virtual std::vector<std::shared_ptr<Profile>> profiles() const =0; |
875 | +}; |
876 | + |
877 | +#endif |
878 | |
879 | === added file 'src/main.cpp' |
880 | --- src/main.cpp 1970-01-01 00:00:00 +0000 |
881 | +++ src/main.cpp 2014-08-22 00:07:37 +0000 |
882 | @@ -0,0 +1,62 @@ |
883 | +/* |
884 | + * Copyright 2014 Canonical Ltd. |
885 | + * |
886 | + * This program is free software: you can redistribute it and/or modify it |
887 | + * under the terms of the GNU General Public License version 3, as published |
888 | + * by the Free Software Foundation. |
889 | + * |
890 | + * This program is distributed in the hope that it will be useful, but |
891 | + * WITHOUT ANY WARRANTY; without even the implied warranties of |
892 | + * MERCHANTABILITY, SATISFACTORY QUALITY, or FITNESS FOR A PARTICULAR |
893 | + * PURPOSE. See the GNU General Public License for more details. |
894 | + * |
895 | + * You should have received a copy of the GNU General Public License along |
896 | + * with this program. If not, see <http://www.gnu.org/licenses/>. |
897 | + * |
898 | + * Authors: |
899 | + * Charles Kerr <charles.kerr@canonical.com> |
900 | + */ |
901 | + |
902 | +#include <src/exporter.h> |
903 | +#include <src/rotation-lock.h> |
904 | + |
905 | +#include <glib/gi18n.h> // bindtextdomain() |
906 | +#include <gio/gio.h> |
907 | + |
908 | +#include <locale.h> |
909 | + |
910 | +int |
911 | +main(int /*argc*/, char** /*argv*/) |
912 | +{ |
913 | + // Work around a deadlock in glib's type initialization. |
914 | + // It can be removed when https://bugzilla.gnome.org/show_bug.cgi?id=674885 is fixed. |
915 | + g_type_ensure(G_TYPE_DBUS_CONNECTION); |
916 | + |
917 | + // boilerplate i18n |
918 | + setlocale(LC_ALL, ""); |
919 | + bindtextdomain(GETTEXT_PACKAGE, GNOMELOCALEDIR); |
920 | + textdomain(GETTEXT_PACKAGE); |
921 | + |
922 | + auto loop = g_main_loop_new(nullptr, false); |
923 | + auto on_name_lost = [loop](const std::string& name){ |
924 | + g_warning("busname lost: '%s'", name.c_str()); |
925 | + g_main_loop_quit(loop); |
926 | + }; |
927 | + |
928 | + // build all our indicators. |
929 | + // Right now we've only got one -- rotation lock -- but hey, we can dream. |
930 | + std::vector<std::shared_ptr<Indicator>> indicators; |
931 | + std::vector<std::shared_ptr<Exporter>> exporters; |
932 | + indicators.push_back(std::make_shared<RotationLockIndicator>()); |
933 | + for (auto& indicator : indicators) { |
934 | + auto exporter = std::make_shared<Exporter>(indicator); |
935 | + exporter->name_lost().connect(on_name_lost); |
936 | + exporters.push_back(exporter); |
937 | + } |
938 | + |
939 | + g_main_loop_run(loop); |
940 | + |
941 | + // cleanup |
942 | + g_main_loop_unref(loop); |
943 | + return 0; |
944 | +} |
945 | |
946 | === added file 'src/rotation-lock.cpp' |
947 | --- src/rotation-lock.cpp 1970-01-01 00:00:00 +0000 |
948 | +++ src/rotation-lock.cpp 2014-08-22 00:07:37 +0000 |
949 | @@ -0,0 +1,197 @@ |
950 | +/* |
951 | + * Copyright 2014 Canonical Ltd. |
952 | + * |
953 | + * This program is free software; you can redistribute it and/or modify |
954 | + * it under the terms of the GNU General Public License as published by |
955 | + * the Free Software Foundation; version 3. |
956 | + * |
957 | + * This program is distributed in the hope that it will be useful, |
958 | + * but WITHOUT ANY WARRANTY; without even the implied warranty of |
959 | + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
960 | + * GNU Lesser General Public License for more details. |
961 | + * |
962 | + * You should have received a copy of the GNU Lesser General Public License |
963 | + * along with this program. If not, see <http://www.gnu.org/licenses/>. |
964 | + * |
965 | + * Authors: |
966 | + * Charles Kerr <charles.kerr@canonical.com> |
967 | + */ |
968 | + |
969 | +#include <src/rotation-lock.h> |
970 | + |
971 | +#include <glib/gi18n.h> |
972 | + |
973 | +class RotationLockIndicator::Impl |
974 | +{ |
975 | +public: |
976 | + |
977 | + Impl(): |
978 | + m_settings(g_settings_new(m_schema_name)), |
979 | + m_action_group(create_action_group()) |
980 | + { |
981 | + // build the rotation lock icon |
982 | + auto icon = g_themed_icon_new_with_default_fallbacks("orientation-lock"); |
983 | + auto icon_deleter = [](GIcon* o){g_object_unref(G_OBJECT(o));}; |
984 | + m_icon.reset(icon, icon_deleter); |
985 | + |
986 | + // build the phone profile |
987 | + auto menu_model_deleter = [](GMenuModel* o){g_object_unref(G_OBJECT(o));}; |
988 | + std::shared_ptr<GMenuModel> phone_menu (create_phone_menu(), menu_model_deleter); |
989 | + m_phone = std::make_shared<SimpleProfile>("phone", phone_menu); |
990 | + update_phone_header(); |
991 | + } |
992 | + |
993 | + ~Impl() |
994 | + { |
995 | + g_clear_object(&m_action_group); |
996 | + g_clear_object(&m_settings); |
997 | + } |
998 | + |
999 | + GSimpleActionGroup* action_group() const |
1000 | + { |
1001 | + return m_action_group; |
1002 | + } |
1003 | + |
1004 | + std::vector<std::shared_ptr<Profile>> profiles() |
1005 | + { |
1006 | + std::vector<std::shared_ptr<Profile>> ret; |
1007 | + ret.push_back(m_phone); |
1008 | + return ret; |
1009 | + } |
1010 | + |
1011 | +private: |
1012 | + |
1013 | + /*** |
1014 | + **** Actions |
1015 | + ***/ |
1016 | + |
1017 | + static gboolean settings_to_action_state(GValue *value, |
1018 | + GVariant *variant, |
1019 | + gpointer /*unused*/) |
1020 | + { |
1021 | + bool is_locked = g_strcmp0(g_variant_get_string(variant, nullptr), "none"); |
1022 | + g_value_set_variant(value, g_variant_new_boolean(is_locked)); |
1023 | + return TRUE; |
1024 | + } |
1025 | + |
1026 | + static GVariant* action_state_to_settings(const GValue *value, |
1027 | + const GVariantType * /*expected_type*/, |
1028 | + gpointer /*unused*/) |
1029 | + { |
1030 | + // Toggling to 'on' *should* lock to the screen's current orientation. |
1031 | + // We don't have any way of knowing Screen.orientation in this service, |
1032 | + // so just pick one at random to satisfy the binding's needs. |
1033 | + // |
1034 | + // In practice this doesn't matter since the indicator isn't visible |
1035 | + // when the lock mode is 'none' so the end user won't ever be able |
1036 | + // to toggle the menuitem from None to anything else. |
1037 | + |
1038 | + auto state_is_true = g_variant_get_boolean(g_value_get_variant(value)); |
1039 | + return g_variant_new_string(state_is_true ? "PrimaryOrientation" : "none"); |
1040 | + } |
1041 | + |
1042 | + GSimpleActionGroup* create_action_group() |
1043 | + { |
1044 | + GSimpleActionGroup* group; |
1045 | + GSimpleAction* action; |
1046 | + |
1047 | + group = g_simple_action_group_new(); |
1048 | + action = g_simple_action_new_stateful("rotation-lock", |
1049 | + nullptr, |
1050 | + g_variant_new_boolean(false)); |
1051 | + g_settings_bind_with_mapping(m_settings, "orientation-lock", |
1052 | + action, "state", |
1053 | + G_SETTINGS_BIND_DEFAULT, |
1054 | + settings_to_action_state, |
1055 | + action_state_to_settings, |
1056 | + nullptr, |
1057 | + nullptr); |
1058 | + g_action_map_add_action(G_ACTION_MAP(group), G_ACTION(action)); |
1059 | + g_object_unref(G_OBJECT(action)); |
1060 | + g_signal_connect_swapped(m_settings, "changed::orientation-lock", |
1061 | + G_CALLBACK(on_orientation_lock_setting_changed), this); |
1062 | + |
1063 | + return group; |
1064 | + } |
1065 | + |
1066 | + /*** |
1067 | + **** Phone profile |
1068 | + ***/ |
1069 | + |
1070 | + static void on_orientation_lock_setting_changed (gpointer gself) |
1071 | + { |
1072 | + static_cast<Impl*>(gself)->update_phone_header(); |
1073 | + } |
1074 | + |
1075 | + GMenuModel* create_phone_menu() |
1076 | + { |
1077 | + GMenu* menu; |
1078 | + GMenuItem* menu_item; |
1079 | + |
1080 | + menu = g_menu_new(); |
1081 | + |
1082 | + menu_item = g_menu_item_new(_("Rotation Lock"), "indicator.rotation-lock"); |
1083 | + g_menu_item_set_attribute(menu_item, "x-canonical-type", "s", "com.canonical.indicator.switch"); |
1084 | + g_menu_append_item(menu, menu_item); |
1085 | + g_object_unref(menu_item); |
1086 | + |
1087 | + return G_MENU_MODEL(menu); |
1088 | + } |
1089 | + |
1090 | + void update_phone_header() |
1091 | + { |
1092 | + Header h; |
1093 | + h.title = _("Rotation lock"); |
1094 | + h.a11y = h.title; |
1095 | + h.is_visible = g_settings_get_enum(m_settings, "orientation-lock") != 0; |
1096 | + h.icon = m_icon; |
1097 | + m_phone->header().set(h); |
1098 | + } |
1099 | + |
1100 | + /*** |
1101 | + **** |
1102 | + ***/ |
1103 | + |
1104 | + static constexpr char const * m_schema_name {"com.ubuntu.touch.system"}; |
1105 | + static constexpr char const * m_orientation_lock_icon_name {"orientation-lock"}; |
1106 | + GSettings* m_settings = nullptr; |
1107 | + GSimpleActionGroup* m_action_group = nullptr; |
1108 | + std::shared_ptr<SimpleProfile> m_phone; |
1109 | + std::shared_ptr<GIcon> m_icon; |
1110 | +}; |
1111 | + |
1112 | +/*** |
1113 | +**** |
1114 | +***/ |
1115 | + |
1116 | +RotationLockIndicator::RotationLockIndicator(): |
1117 | + impl(new Impl()) |
1118 | +{ |
1119 | +} |
1120 | + |
1121 | +RotationLockIndicator::~RotationLockIndicator() |
1122 | +{ |
1123 | +} |
1124 | + |
1125 | +std::vector<std::shared_ptr<Profile>> |
1126 | +RotationLockIndicator::profiles() const |
1127 | +{ |
1128 | + return impl->profiles(); |
1129 | +} |
1130 | + |
1131 | +GSimpleActionGroup* |
1132 | +RotationLockIndicator::action_group() const |
1133 | +{ |
1134 | + return impl->action_group(); |
1135 | +} |
1136 | + |
1137 | +const char* |
1138 | +RotationLockIndicator::name() const |
1139 | +{ |
1140 | + return "rotation_lock"; |
1141 | +} |
1142 | + |
1143 | +/*** |
1144 | +**** |
1145 | +***/ |
1146 | + |
1147 | |
1148 | === added file 'src/rotation-lock.h' |
1149 | --- src/rotation-lock.h 1970-01-01 00:00:00 +0000 |
1150 | +++ src/rotation-lock.h 2014-08-22 00:07:37 +0000 |
1151 | @@ -0,0 +1,42 @@ |
1152 | +/* |
1153 | + * Copyright 2014 Canonical Ltd. |
1154 | + * |
1155 | + * This program is free software: you can redistribute it and/or modify it |
1156 | + * under the terms of the GNU General Public License version 3, as published |
1157 | + * by the Free Software Foundation. |
1158 | + * |
1159 | + * This program is distributed in the hope that it will be useful, but |
1160 | + * WITHOUT ANY WARRANTY; without even the implied warranties of |
1161 | + * MERCHANTABILITY, SATISFACTORY QUALITY, or FITNESS FOR A PARTICULAR |
1162 | + * PURPOSE. See the GNU General Public License for more details. |
1163 | + * |
1164 | + * You should have received a copy of the GNU General Public License along |
1165 | + * with this program. If not, see <http://www.gnu.org/licenses/>. |
1166 | + * |
1167 | + * Authors: |
1168 | + * Charles Kerr <charles.kerr@canonical.com> |
1169 | + */ |
1170 | + |
1171 | +#ifndef INDICATOR_DISPLAY_ROTATION_LOCK_H |
1172 | +#define INDICATOR_DISPLAY_ROTATION_LOCK_H |
1173 | + |
1174 | +#include <src/indicator.h> |
1175 | + |
1176 | +#include <memory> // std::unique_ptr |
1177 | + |
1178 | +class RotationLockIndicator: public Indicator |
1179 | +{ |
1180 | +public: |
1181 | + RotationLockIndicator(); |
1182 | + ~RotationLockIndicator(); |
1183 | + |
1184 | + const char* name() const; |
1185 | + GSimpleActionGroup* action_group() const; |
1186 | + std::vector<std::shared_ptr<Profile>> profiles() const; |
1187 | + |
1188 | +protected: |
1189 | + class Impl; |
1190 | + std::unique_ptr<Impl> impl; |
1191 | +}; |
1192 | + |
1193 | +#endif |
1194 | |
1195 | === added directory 'tests' |
1196 | === added file 'tests/CMakeLists.txt' |
1197 | --- tests/CMakeLists.txt 1970-01-01 00:00:00 +0000 |
1198 | +++ tests/CMakeLists.txt 2014-08-22 00:07:37 +0000 |
1199 | @@ -0,0 +1,35 @@ |
1200 | +include(FindGMock) |
1201 | +include_directories(${CMAKE_CURRENT_SOURCE_DIR}) |
1202 | +include_directories(${GMOCK_INCLUDE_DIRS}) |
1203 | +include_directories(${GTEST_INCLUDE_DIRS}) |
1204 | + |
1205 | +# build libgtest |
1206 | +#add_library (gtest STATIC |
1207 | +# ${GTEST_SOURCE_DIR}/gtest-all.cc |
1208 | +# ${GTEST_SOURCE_DIR}/gtest_main.cc) |
1209 | +#set_target_properties (gtest PROPERTIES INCLUDE_DIRECTORIES ${INCLUDE_DIRECTORIES} ${GTEST_INCLUDE_DIR}) |
1210 | +#set_target_properties (gtest PROPERTIES COMPILE_FLAGS ${COMPILE_FLAGS} -w) |
1211 | + |
1212 | +if ("${CMAKE_CXX_COMPILER_ID}" STREQUAL "Clang") |
1213 | + # turn off the warnings that break Google Test |
1214 | + set (CXX_WARNING_ARGS "${CXX_WARNING_ARGS} -Wno-global-constructors -Wno-weak-vtables -Wno-undef -Wno-c++98-compat-pedantic -Wno-missing-noreturn -Wno-used-but-marked-unused -Wno-padded -Wno-deprecated -Wno-sign-compare -Wno-shift-sign-overflow") |
1215 | +endif() |
1216 | + |
1217 | +SET (CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++11 -g ${CXX_WARNING_ARGS}") |
1218 | + |
1219 | +# look for headers in our src dir, and also in the directories where we autogenerate files... |
1220 | +include_directories (${CMAKE_SOURCE_DIR}/src) |
1221 | +include_directories (${CMAKE_CURRENT_BINARY_DIR}) |
1222 | +include_directories (${DBUSTEST_INCLUDE_DIRS}) |
1223 | + |
1224 | +function(add_test_by_name name) |
1225 | + set (TEST_NAME ${name}) |
1226 | + add_executable (${TEST_NAME} ${TEST_NAME}.cpp) |
1227 | + add_test (${TEST_NAME} ${TEST_NAME}) |
1228 | + add_dependencies (${TEST_NAME} libindicatordisplayservice) |
1229 | + target_link_libraries (${TEST_NAME} indicatordisplayservice ${SERVICE_DEPS_LIBRARIES} ${GTEST_LIBRARIES} ${GMOCK_LIBRARIES}) |
1230 | +endfunction() |
1231 | +add_test_by_name(test-rotation-lock) |
1232 | + |
1233 | +add_test (cppcheck cppcheck --enable=all -q --error-exitcode=2 --inline-suppr -I${CMAKE_SOURCE_DIR} ${CMAKE_SOURCE_DIR}/src ${CMAKE_SOURCE_DIR}/tests) |
1234 | + |
1235 | |
1236 | === added file 'tests/glib-fixture.h' |
1237 | --- tests/glib-fixture.h 1970-01-01 00:00:00 +0000 |
1238 | +++ tests/glib-fixture.h 2014-08-22 00:07:37 +0000 |
1239 | @@ -0,0 +1,143 @@ |
1240 | +/* |
1241 | + * Copyright 2014 Canonical Ltd. |
1242 | + * |
1243 | + * This program is free software: you can redistribute it and/or modify it |
1244 | + * under the terms of the GNU General Public License version 3, as published |
1245 | + * by the Free Software Foundation. |
1246 | + * |
1247 | + * This program is distributed in the hope that it will be useful, but |
1248 | + * WITHOUT ANY WARRANTY; without even the implied warranties of |
1249 | + * MERCHANTABILITY, SATISFACTORY QUALITY, or FITNESS FOR A PARTICULAR |
1250 | + * PURPOSE. See the GNU General Public License for more details. |
1251 | + * |
1252 | + * You should have received a copy of the GNU General Public License along |
1253 | + * with this program. If not, see <http://www.gnu.org/licenses/>. |
1254 | + * |
1255 | + * Authors: |
1256 | + * Charles Kerr <charles.kerr@canonical.com> |
1257 | + */ |
1258 | + |
1259 | +#include <map> |
1260 | + |
1261 | +#include <glib.h> |
1262 | +#include <glib/gstdio.h> |
1263 | +#include <gio/gio.h> |
1264 | + |
1265 | +#include <gtest/gtest.h> |
1266 | + |
1267 | +#include <locale.h> // setlocale() |
1268 | + |
1269 | +class GlibFixture : public ::testing::Test |
1270 | +{ |
1271 | + private: |
1272 | + |
1273 | + GLogFunc realLogHandler; |
1274 | + |
1275 | + std::map<GLogLevelFlags,size_t> expected_log; |
1276 | + std::map<GLogLevelFlags,std::vector<std::string>> log; |
1277 | + |
1278 | + void test_log_counts() |
1279 | + { |
1280 | + const GLogLevelFlags levels_to_test[] = { G_LOG_LEVEL_ERROR, |
1281 | + G_LOG_LEVEL_CRITICAL, |
1282 | + G_LOG_LEVEL_MESSAGE, |
1283 | + G_LOG_LEVEL_WARNING }; |
1284 | + |
1285 | + for(const auto& level : levels_to_test) |
1286 | + { |
1287 | + const auto& v = log[level]; |
1288 | + const auto n = v.size(); |
1289 | + |
1290 | + EXPECT_EQ(expected_log[level], n); |
1291 | + |
1292 | + if (expected_log[level] != n) |
1293 | + for (size_t i=0; i<n; ++i) |
1294 | + g_message("%d %s", (n+1), v[i].c_str()); |
1295 | + } |
1296 | + |
1297 | + expected_log.clear(); |
1298 | + log.clear(); |
1299 | + } |
1300 | + |
1301 | + static void default_log_handler(const gchar * log_domain, |
1302 | + GLogLevelFlags log_level, |
1303 | + const gchar * message, |
1304 | + gpointer self) |
1305 | + { |
1306 | + auto tmp = g_strdup_printf ("%s:%d \"%s\"", log_domain, (int)log_level, message); |
1307 | + static_cast<GlibFixture*>(self)->log[log_level].push_back(tmp); |
1308 | + g_free(tmp); |
1309 | + } |
1310 | + |
1311 | + protected: |
1312 | + |
1313 | + void increment_expected_errors(GLogLevelFlags level, size_t n=1) |
1314 | + { |
1315 | + expected_log[level] += n; |
1316 | + } |
1317 | + |
1318 | + virtual void SetUp() |
1319 | + { |
1320 | + setlocale(LC_ALL, "C.UTF-8"); |
1321 | + |
1322 | + loop = g_main_loop_new(nullptr, false); |
1323 | + |
1324 | + g_log_set_default_handler(default_log_handler, this); |
1325 | + |
1326 | + g_assert(g_setenv("GSETTINGS_BACKEND", "memory", true)); |
1327 | + |
1328 | + g_unsetenv("DISPLAY"); |
1329 | + } |
1330 | + |
1331 | + virtual void TearDown() |
1332 | + { |
1333 | + test_log_counts(); |
1334 | + |
1335 | + g_log_set_default_handler(realLogHandler, this); |
1336 | + |
1337 | + g_clear_pointer(&loop, g_main_loop_unref); |
1338 | + } |
1339 | + |
1340 | + private: |
1341 | + |
1342 | + static gboolean |
1343 | + wait_for_signal__timeout(gpointer name) |
1344 | + { |
1345 | + g_error("%s: timed out waiting for signal '%s'", G_STRLOC, (char*)name); |
1346 | + return G_SOURCE_REMOVE; |
1347 | + } |
1348 | + |
1349 | + static gboolean |
1350 | + wait_msec__timeout(gpointer loop) |
1351 | + { |
1352 | + g_main_loop_quit(static_cast<GMainLoop*>(loop)); |
1353 | + return G_SOURCE_CONTINUE; |
1354 | + } |
1355 | + |
1356 | + protected: |
1357 | + |
1358 | + /* convenience func to loop while waiting for a GObject's signal */ |
1359 | + void wait_for_signal(gpointer o, const gchar * signal, const guint timeout_seconds=5) |
1360 | + { |
1361 | + // wait for the signal or for timeout, whichever comes first |
1362 | + const auto handler_id = g_signal_connect_swapped(o, signal, |
1363 | + G_CALLBACK(g_main_loop_quit), |
1364 | + loop); |
1365 | + const auto timeout_id = g_timeout_add_seconds(timeout_seconds, |
1366 | + wait_for_signal__timeout, |
1367 | + loop); |
1368 | + g_main_loop_run(loop); |
1369 | + g_source_remove(timeout_id); |
1370 | + g_signal_handler_disconnect(o, handler_id); |
1371 | + } |
1372 | + |
1373 | + /* convenience func to loop for N msec */ |
1374 | + void wait_msec(guint msec=50) |
1375 | + { |
1376 | + const auto id = g_timeout_add(msec, wait_msec__timeout, loop); |
1377 | + g_main_loop_run(loop); |
1378 | + g_source_remove(id); |
1379 | + } |
1380 | + |
1381 | + GMainLoop * loop; |
1382 | +}; |
1383 | |
1384 | === added file 'tests/gtestdbus-fixture.h' |
1385 | --- tests/gtestdbus-fixture.h 1970-01-01 00:00:00 +0000 |
1386 | +++ tests/gtestdbus-fixture.h 2014-08-22 00:07:37 +0000 |
1387 | @@ -0,0 +1,102 @@ |
1388 | +/* |
1389 | + * Copyright 2013 Canonical Ltd. |
1390 | + * |
1391 | + * This program is free software: you can redistribute it and/or modify it |
1392 | + * under the terms of the GNU General Public License version 3, as published |
1393 | + * by the Free Software Foundation. |
1394 | + * |
1395 | + * This program is distributed in the hope that it will be useful, but |
1396 | + * WITHOUT ANY WARRANTY; without even the implied warranties of |
1397 | + * MERCHANTABILITY, SATISFACTORY QUALITY, or FITNESS FOR A PARTICULAR |
1398 | + * PURPOSE. See the GNU General Public License for more details. |
1399 | + * |
1400 | + * You should have received a copy of the GNU General Public License along |
1401 | + * with this program. If not, see <http://www.gnu.org/licenses/>. |
1402 | + * |
1403 | + * Authors: |
1404 | + * Charles Kerr <charles.kerr@canonical.com> |
1405 | + */ |
1406 | + |
1407 | +#include "glib-fixture.h" |
1408 | + |
1409 | +/*** |
1410 | +**** |
1411 | +***/ |
1412 | + |
1413 | +class GTestDBusFixture: public GlibFixture |
1414 | +{ |
1415 | + public: |
1416 | + |
1417 | + GTestDBusFixture() {} |
1418 | + |
1419 | + GTestDBusFixture(const std::vector<std::string>& service_dirs_in): service_dirs(service_dirs_in) {} |
1420 | + |
1421 | + private: |
1422 | + |
1423 | + typedef GlibFixture super; |
1424 | + |
1425 | + static void |
1426 | + on_bus_opened (GObject* /*object*/, GAsyncResult * res, gpointer gself) |
1427 | + { |
1428 | + auto self = static_cast<GTestDBusFixture*>(gself); |
1429 | + |
1430 | + GError * err = 0; |
1431 | + self->bus = g_bus_get_finish (res, &err); |
1432 | + g_assert_no_error (err); |
1433 | + |
1434 | + g_main_loop_quit (self->loop); |
1435 | + } |
1436 | + |
1437 | + static void |
1438 | + on_bus_closed (GObject* /*object*/, GAsyncResult * res, gpointer gself) |
1439 | + { |
1440 | + auto self = static_cast<GTestDBusFixture*>(gself); |
1441 | + |
1442 | + GError * err = 0; |
1443 | + g_dbus_connection_close_finish (self->bus, res, &err); |
1444 | + g_assert_no_error (err); |
1445 | + |
1446 | + g_main_loop_quit (self->loop); |
1447 | + } |
1448 | + |
1449 | + protected: |
1450 | + |
1451 | + GTestDBus * test_dbus = nullptr; |
1452 | + GDBusConnection * bus = nullptr; |
1453 | + const std::vector<std::string> service_dirs; |
1454 | + |
1455 | + virtual void SetUp () |
1456 | + { |
1457 | + super::SetUp (); |
1458 | + |
1459 | + // pull up a test dbus |
1460 | + test_dbus = g_test_dbus_new (G_TEST_DBUS_NONE); |
1461 | + for (const auto& dir : service_dirs) |
1462 | + g_test_dbus_add_service_dir (test_dbus, dir.c_str()); |
1463 | + g_test_dbus_up (test_dbus); |
1464 | + const char * address = g_test_dbus_get_bus_address (test_dbus); |
1465 | + g_setenv ("DBUS_SYSTEM_BUS_ADDRESS", address, true); |
1466 | + g_setenv ("DBUS_SESSION_BUS_ADDRESS", address, true); |
1467 | + g_debug ("test_dbus's address is %s", address); |
1468 | + |
1469 | + // wait for the GDBusConnection before returning |
1470 | + g_bus_get (G_BUS_TYPE_SYSTEM, nullptr, on_bus_opened, this); |
1471 | + g_main_loop_run (loop); |
1472 | + } |
1473 | + |
1474 | + virtual void TearDown () |
1475 | + { |
1476 | + wait_msec(); |
1477 | + |
1478 | + // close the system bus |
1479 | + g_dbus_connection_close(bus, nullptr, on_bus_closed, this); |
1480 | + g_main_loop_run(loop); |
1481 | + g_clear_object(&bus); |
1482 | + |
1483 | + // tear down the test dbus |
1484 | + g_test_dbus_down(test_dbus); |
1485 | + g_clear_object(&test_dbus); |
1486 | + |
1487 | + super::TearDown(); |
1488 | + } |
1489 | +}; |
1490 | |
1491 | === added file 'tests/manual' |
1492 | --- tests/manual 1970-01-01 00:00:00 +0000 |
1493 | +++ tests/manual 2014-08-22 00:07:37 +0000 |
1494 | @@ -0,0 +1,16 @@ |
1495 | + |
1496 | +Test-case indicator-display/rotation-indicator |
1497 | +<dl> |
1498 | + <dt>On the phone, enable the orientation lock in ubuntu-system-settings.</dt> |
1499 | + <dd>The rotation lock indicator should appear, and its switch menuitem should be set to 'true'.</dd> |
1500 | + |
1501 | + <dt>With the orientation locked, click on the indicator's switch menuitem to toggle from locked to unlocked.</dd> |
1502 | + <dd>The rotation lock indicator should disappear</dd> |
1503 | + <dd>In ubuntu-system-settings, the orientation lock control should change to 'none'.</dd> |
1504 | +</dl> |
1505 | + |
1506 | + |
1507 | +<strong> |
1508 | + If all actions produce the expected results listed, please <a href="results#add_result">submit</a> a 'passed' result. |
1509 | + If an action fails, or produces an unexpected result, please <a href="results#add_result">submit</a> a 'failed' result and <a href="../../buginstructions">file a bug</a>. Please be sure to include the bug number when you <a href="results#add_result">submit</a> your result</strong>. |
1510 | + |
1511 | |
1512 | === added file 'tests/test-rotation-lock.cpp' |
1513 | --- tests/test-rotation-lock.cpp 1970-01-01 00:00:00 +0000 |
1514 | +++ tests/test-rotation-lock.cpp 2014-08-22 00:07:37 +0000 |
1515 | @@ -0,0 +1,61 @@ |
1516 | +/* |
1517 | + * Copyright 2014 Canonical Ltd. |
1518 | + * |
1519 | + * This program is free software: you can redistribute it and/or modify it |
1520 | + * under the terms of the GNU General Public License version 3, as published |
1521 | + * by the Free Software Foundation. |
1522 | + * |
1523 | + * This program is distributed in the hope that it will be useful, but |
1524 | + * WITHOUT ANY WARRANTY; without even the implied warranties of |
1525 | + * MERCHANTABILITY, SATISFACTORY QUALITY, or FITNESS FOR A PARTICULAR |
1526 | + * PURPOSE. See the GNU General Public License for more details. |
1527 | + * |
1528 | + * You should have received a copy of the GNU General Public License along |
1529 | + * with this program. If not, see <http://www.gnu.org/licenses/>. |
1530 | + * |
1531 | + * Authors: |
1532 | + * Charles Kerr <charles.kerr@canonical.com> |
1533 | + */ |
1534 | + |
1535 | +#include "gtestdbus-fixture.h" |
1536 | + |
1537 | +#include <src/rotation-lock.h> |
1538 | + |
1539 | +class RotationLockFixture: public GTestDBusFixture |
1540 | +{ |
1541 | +private: |
1542 | + typedef GTestDBusFixture super; |
1543 | + |
1544 | +protected: |
1545 | + |
1546 | + void SetUp() |
1547 | + { |
1548 | + super::SetUp(); |
1549 | + } |
1550 | + |
1551 | + void TearDown() |
1552 | + { |
1553 | + super::TearDown(); |
1554 | + } |
1555 | +}; |
1556 | + |
1557 | +/*** |
1558 | +**** |
1559 | +***/ |
1560 | + |
1561 | +TEST_F(RotationLockFixture, CheckIndicator) |
1562 | +{ |
1563 | + RotationLockIndicator indicator; |
1564 | + |
1565 | + ASSERT_STREQ("rotation_lock", indicator.name()); |
1566 | + auto actions = indicator.action_group(); |
1567 | + ASSERT_TRUE(actions != nullptr); |
1568 | + ASSERT_TRUE(g_action_group_has_action(G_ACTION_GROUP(actions), "rotation-lock")); |
1569 | + |
1570 | + std::vector<std::shared_ptr<Profile>> profiles = indicator.profiles(); |
1571 | + ASSERT_EQ(1, profiles.size()); |
1572 | + std::shared_ptr<Profile> phone = profiles[0]; |
1573 | + ASSERT_EQ(std::string("phone"), phone->name()); |
1574 | + ASSERT_FALSE(phone->header()->is_visible); |
1575 | +} |
1576 | + |
FAILED: Continuous integration, rev:8 jenkins. qa.ubuntu. com/job/ indicator- display- ci/1/ jenkins. qa.ubuntu. com/job/ indicator- display- utopic- amd64-ci/ 1/console jenkins. qa.ubuntu. com/job/ indicator- display- utopic- armhf-ci/ 1/console
http://
Executed test runs:
FAILURE: http://
FAILURE: http://
Click here to trigger a rebuild: s-jenkins. ubuntu- ci:8080/ job/indicator- display- ci/1/rebuild
http://