Merge lp:~charlesk/indicator-display/add-rotation-lock into lp:indicator-display/14.10

Proposed by Charles Kerr
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
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-settings, one toggle the orientation lock on and off from the command line:

$ gsettings set com.ubuntu.touch.system orientation-lock 'PrimaryOrientation'

$ gsettings set com.ubuntu.touch.system orientation-lock 'none'

Enabling/disabling lock with this method should have the same results as in the indicator-datetime/rotation-indicator manual test.

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

remove url-dispatcher dependency.

10. By Charles Kerr

add cmake/ directory

Revision history for this message
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/share/upstart/
 ./usr/share/upstart/xdg/
 ./usr/share/upstart/xdg/autostart/
 ./usr/share/upstart/xdg/autostart/indicator-display.desktop
 ./usr/share/upstart/sessions/
 ./usr/share/upstart/sessions/indicator-display.conf
 ./usr/share/doc/
 ./usr/share/doc/indicator-display/
 ./usr/share/doc/indicator-display/copyright
 ./usr/share/doc/indicator-display/changelog.Debian.gz
 ./usr/share/unity/
 ./usr/share/unity/indicators/
 ./usr/share/unity/indicators/com.canonical.indicator.rotation_lock
 ./usr/lib/
 ./usr/lib/i386-linux-gnu/
 ./usr/lib/i386-linux-gnu/indicator-display/
 ./usr/lib/i386-linux-gnu/indicator-display/indicator-display-service
 ./etc/
 ./etc/xdg/
 ./etc/xdg/autostart/
 ./etc/xdg/autostart/indicator-display.desktop

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: Needs Fixing (continuous-integration)
11. By Charles Kerr

unit tests passing on desktop and phone, but not in jenkins -- adding gsettings-ubuntu-schemas to build-depends.

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)
Revision history for this message
PS Jenkins bot (ps-jenkins) wrote :
review: Approve (continuous-integration)
Revision history for this message
Ted Gould (ted) wrote :

A few cleanup things.

Revision history for this message
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

Revision history for this message
PS Jenkins bot (ps-jenkins) wrote :
review: Approve (continuous-integration)
Revision history for this message
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-too-long
E: indicator-display: extended-description-is-empty

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

Revision history for this message
Charles Kerr (charlesk) wrote :

:-)

I've revised the description and extended-description in r15, and since lintian suggested it, bumped the Standards-Version from 3.9.4 to 3.9.5 in r16.

Revision history for this message
PS Jenkins bot (ps-jenkins) wrote :
review: Approve (continuous-integration)
Revision history for this message
Ted Gould (ted) :
review: Approve

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
=== added file 'CMakeLists.txt'
--- CMakeLists.txt 1970-01-01 00:00:00 +0000
+++ CMakeLists.txt 2014-08-22 00:07:37 +0000
@@ -0,0 +1,72 @@
1project (indicator-display)
2cmake_minimum_required (VERSION 2.8.9)
3
4list (APPEND CMAKE_MODULE_PATH ${CMAKE_SOURCE_DIR}/cmake)
5
6set (PROJECT_VERSION "14.10.0")
7set (PACKAGE ${CMAKE_PROJECT_NAME})
8set (GETTEXT_PACKAGE indicator-display)
9add_definitions (-DGETTEXT_PACKAGE="${GETTEXT_PACKAGE}"
10 -DGNOMELOCALEDIR="${CMAKE_INSTALL_FULL_LOCALEDIR}")
11
12set (SERVICE_LIB ${PACKAGE})
13set (SERVICE_EXEC "${PACKAGE}-service")
14
15option (enable_tests "Build the package's automatic tests." ON)
16option (enable_lcov "Generate lcov code coverage reports." ON)
17
18##
19## GNU standard paths
20##
21include (GNUInstallDirs)
22if (EXISTS "/etc/debian_version") # Workaround for libexecdir on debian
23 set (CMAKE_INSTALL_LIBEXECDIR "${CMAKE_INSTALL_LIBDIR}")
24 set (CMAKE_INSTALL_FULL_LIBEXECDIR "${CMAKE_INSTALL_FULL_LIBDIR}")
25endif ()
26set (CMAKE_INSTALL_PKGLIBEXECDIR "${CMAKE_INSTALL_LIBEXECDIR}/${CMAKE_PROJECT_NAME}")
27set (CMAKE_INSTALL_FULL_PKGLIBEXECDIR "${CMAKE_INSTALL_FULL_LIBEXECDIR}/${CMAKE_PROJECT_NAME}")
28
29##
30## Check for prerequisites
31##
32
33find_package (PkgConfig REQUIRED)
34
35include (FindPkgConfig)
36pkg_check_modules (SERVICE_DEPS REQUIRED
37 gio-unix-2.0>=2.36
38 glib-2.0>=2.36)
39include_directories (SYSTEM ${SERVICE_DEPS_INCLUDE_DIRS})
40
41##
42##
43##
44
45set (CMAKE_INCLUDE_CURRENT_DIR OFF)
46include_directories (${CMAKE_CURRENT_SOURCE_DIR})
47
48# set the compiler warnings
49if ("${CMAKE_CXX_COMPILER_ID}" STREQUAL "Clang")
50 set (CXX_WARNING_ARGS "${CXX_WARNING_ARGS} -Weverything -Wno-c++98-compat")
51else()
52 set (CXX_WARNING_ARGS "${CXX_WARNING_ARGS} -Wall -Wextra -Wpedantic")
53endif()
54set (CXX_WARNING_ARGS "${CXX_WARNING_ARGS} -Wno-missing-field-initializers") # GActionEntry
55
56# testing & coverage
57if (${enable_tests})
58 set (GTEST_SOURCE_DIR /usr/src/gtest/src)
59 set (GTEST_INCLUDE_DIR ${GTEST_SOURCE_DIR}/..)
60 set (GTEST_LIBS -lpthread)
61 enable_testing ()
62 if (${enable_lcov})
63 include(GCov)
64 endif ()
65endif ()
66
67add_subdirectory (src)
68add_subdirectory (data)
69add_subdirectory (po)
70if (${enable_tests})
71 add_subdirectory (tests)
72endif ()
073
=== added directory 'cmake'
=== added file 'cmake/FindGMock.cmake'
--- cmake/FindGMock.cmake 1970-01-01 00:00:00 +0000
+++ cmake/FindGMock.cmake 2014-08-22 00:07:37 +0000
@@ -0,0 +1,10 @@
1# Build with system gmock and embedded gtest
2set (GMOCK_INCLUDE_DIRS "/usr/include/gmock/include" CACHE PATH "gmock source include directory")
3set (GMOCK_SOURCE_DIR "/usr/src/gmock" CACHE PATH "gmock source directory")
4set (GTEST_INCLUDE_DIRS "${GMOCK_SOURCE_DIR}/gtest/include" CACHE PATH "gtest source include directory")
5
6add_subdirectory(${GMOCK_SOURCE_DIR} "${CMAKE_CURRENT_BINARY_DIR}/gmock")
7
8set(GTEST_LIBRARIES gtest)
9set(GTEST_MAIN_LIBRARIES gtest_main)
10set(GMOCK_LIBRARIES gmock gmock_main)
011
=== added file 'cmake/GCov.cmake'
--- cmake/GCov.cmake 1970-01-01 00:00:00 +0000
+++ cmake/GCov.cmake 2014-08-22 00:07:37 +0000
@@ -0,0 +1,51 @@
1if (CMAKE_BUILD_TYPE MATCHES coverage)
2 set(GCOV_FLAGS "${GCOV_FLAGS} --coverage")
3 set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} ${GCOV_FLAGS}")
4 set(CMAKE_MODULE_LINKER_FLAGS "${CMAKE_MODULE_LINKER_FLAGS} ${GCOV_FLAGS}")
5 set(CMAKE_SHARED_LINKER_FLAGS "${CMAKE_SHARED_LINKER_FLAGS} ${GCOV_FLAGS}")
6 set(GCOV_LIBS ${GCOV_LIBS} gcov)
7
8 find_program(GCOVR_EXECUTABLE gcovr HINTS ${GCOVR_ROOT} "${GCOVR_ROOT}/bin")
9 if (NOT GCOVR_EXECUTABLE)
10 message(STATUS "Gcovr binary was not found, can not generate XML coverage info.")
11 else ()
12 message(STATUS "Gcovr found, can generate XML coverage info.")
13 add_custom_target (coverage-xml
14 WORKING_DIRECTORY ${CMAKE_BINARY_DIR}
15 COMMAND "${GCOVR_EXECUTABLE}" --exclude="test.*" -x -r "${CMAKE_SOURCE_DIR}"
16 --object-directory=${CMAKE_BINARY_DIR} -o coverage.xml)
17 endif()
18
19 find_program(LCOV_EXECUTABLE lcov HINTS ${LCOV_ROOT} "${GCOVR_ROOT}/bin")
20 find_program(GENHTML_EXECUTABLE genhtml HINTS ${GENHTML_ROOT})
21 if (NOT LCOV_EXECUTABLE)
22 message(STATUS "Lcov binary was not found, can not generate HTML coverage info.")
23 else ()
24 if(NOT GENHTML_EXECUTABLE)
25 message(STATUS "Genthml binary not found, can not generate HTML coverage info.")
26 else()
27 message(STATUS "Lcov and genhtml found, can generate HTML coverage info.")
28 add_custom_target (coverage-html
29 WORKING_DIRECTORY ${CMAKE_BINARY_DIR}
30 COMMAND "${CMAKE_CTEST_COMMAND}" --force-new-ctest-process --verbose
31 COMMAND "${LCOV_EXECUTABLE}" --directory ${CMAKE_BINARY_DIR} --capture | ${CMAKE_SOURCE_DIR}/trim-lcov.py > dconf-lcov.info
32 COMMAND "${LCOV_EXECUTABLE}" -r dconf-lcov.info /usr/include/\\* -o nosys-lcov.info
33 COMMAND LANG=C "${GENHTML_EXECUTABLE}" --prefix ${CMAKE_BINARY_DIR} --output-directory lcov-html --legend --show-details nosys-lcov.info
34 COMMAND ${CMAKE_COMMAND} -E echo ""
35 COMMAND ${CMAKE_COMMAND} -E echo "file://${CMAKE_BINARY_DIR}/lcov-html/index.html"
36 COMMAND ${CMAKE_COMMAND} -E echo "")
37 #COMMAND "${LCOV_EXECUTABLE}" --directory ${CMAKE_BINARY_DIR} --capture --output-file coverage.info --no-checksum
38 #COMMAND "${GENHTML_EXECUTABLE}" --prefix ${CMAKE_BINARY_DIR} --output-directory coveragereport --title "Code Coverage" --legend --show-details coverage.info
39 #COMMAND ${CMAKE_COMMAND} -E echo "\\#define foo \\\"bar\\\""
40 #)
41 endif()
42 endif()
43endif()
44
45
46 #$(MAKE) $(AM_MAKEFLAGS) check
47 #lcov --directory $(top_builddir) --capture --test-name dconf | $(top_srcdir)/trim-lcov.py > dconf-lcov.info
48 #LANG=C genhtml --prefix $(top_builddir) --output-directory lcov-html --legend --show-details dconf-lcov.info
49 #@echo
50 #@echo " file://$(abs_top_builddir)/lcov-html/index.html"
51 #@echo
052
=== added file 'cmake/GdbusCodegen.cmake'
--- cmake/GdbusCodegen.cmake 1970-01-01 00:00:00 +0000
+++ cmake/GdbusCodegen.cmake 2014-08-22 00:07:37 +0000
@@ -0,0 +1,36 @@
1cmake_minimum_required(VERSION 2.6)
2if(POLICY CMP0011)
3 cmake_policy(SET CMP0011 NEW)
4endif(POLICY CMP0011)
5
6find_program(GDBUS_CODEGEN NAMES gdbus-codegen DOC "gdbus-codegen executable")
7if(NOT GDBUS_CODEGEN)
8 message(FATAL_ERROR "Excutable gdbus-codegen not found")
9endif()
10
11macro(add_gdbus_codegen outfiles name prefix service_xml)
12 add_custom_command(
13 OUTPUT "${CMAKE_CURRENT_BINARY_DIR}/${name}.h" "${CMAKE_CURRENT_BINARY_DIR}/${name}.c"
14 COMMAND "${GDBUS_CODEGEN}"
15 --interface-prefix "${prefix}"
16 --generate-c-code "${name}"
17 "${service_xml}"
18 WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}
19 DEPENDS ${ARGN} "${service_xml}"
20 )
21 list(APPEND ${outfiles} "${CMAKE_CURRENT_BINARY_DIR}/${name}.c")
22endmacro(add_gdbus_codegen)
23
24macro(add_gdbus_codegen_with_namespace outfiles name prefix namespace service_xml)
25 add_custom_command(
26 OUTPUT "${CMAKE_CURRENT_BINARY_DIR}/${name}.h" "${CMAKE_CURRENT_BINARY_DIR}/${name}.c"
27 COMMAND "${GDBUS_CODEGEN}"
28 --interface-prefix "${prefix}"
29 --generate-c-code "${name}"
30 --c-namespace "${namespace}"
31 "${service_xml}"
32 WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}
33 DEPENDS ${ARGN} "${service_xml}"
34 )
35 list(APPEND ${outfiles} "${CMAKE_CURRENT_BINARY_DIR}/${name}.c")
36endmacro(add_gdbus_codegen_with_namespace)
037
=== added file 'cmake/Translations.cmake'
--- cmake/Translations.cmake 1970-01-01 00:00:00 +0000
+++ cmake/Translations.cmake 2014-08-22 00:07:37 +0000
@@ -0,0 +1,37 @@
1# Translations.cmake, CMake macros written for Marlin, feel free to re-use them
2
3macro(add_translations_directory NLS_PACKAGE)
4 add_custom_target (i18n ALL)
5 find_program (MSGFMT_EXECUTABLE msgfmt)
6 file (GLOB PO_FILES ${CMAKE_CURRENT_SOURCE_DIR}/*.po)
7 foreach (PO_INPUT ${PO_FILES})
8 get_filename_component (PO_INPUT_BASE ${PO_INPUT} NAME_WE)
9 set (MO_OUTPUT ${CMAKE_CURRENT_BINARY_DIR}/${PO_INPUT_BASE}.mo)
10 add_custom_command (TARGET i18n COMMAND ${MSGFMT_EXECUTABLE} -o ${MO_OUTPUT} ${PO_INPUT})
11
12 install (FILES ${MO_OUTPUT} DESTINATION
13 ${CMAKE_INSTALL_LOCALEDIR}/${PO_INPUT_BASE}/LC_MESSAGES
14 RENAME ${NLS_PACKAGE}.mo)
15 endforeach (PO_INPUT ${PO_FILES})
16endmacro(add_translations_directory)
17
18
19macro(add_translations_catalog NLS_PACKAGE)
20 add_custom_target (pot COMMENT “Building translation catalog.”)
21 find_program (XGETTEXT_EXECUTABLE xgettext)
22
23 # init this list, which will hold all the sources across all dirs
24 set(SOURCES "")
25
26 # add each directory's sources to the overall sources list
27 foreach(FILES_INPUT ${ARGN})
28 set (DIR ${CMAKE_CURRENT_SOURCE_DIR}/${FILES_INPUT})
29 file (GLOB_RECURSE DIR_SOURCES ${DIR}/*.c ${DIR}/*.cc ${DIR}/*.cpp ${DIR}/*.cxx ${DIR}/*.vala)
30 set (SOURCES ${SOURCES} ${DIR_SOURCES})
31 endforeach()
32
33 add_custom_command (TARGET pot COMMAND
34 ${XGETTEXT_EXECUTABLE} -d ${NLS_PACKAGE} -o ${CMAKE_CURRENT_SOURCE_DIR}/${NLS_PACKAGE}.pot
35 ${SOURCES} --keyword="_" --keyword="N_" --from-code=UTF-8
36 )
37endmacro()
038
=== added directory 'data'
=== added file 'data/CMakeLists.txt'
--- data/CMakeLists.txt 1970-01-01 00:00:00 +0000
+++ data/CMakeLists.txt 2014-08-22 00:07:37 +0000
@@ -0,0 +1,74 @@
1##
2## Upstart Job File
3##
4
5# where to install
6set (UPSTART_JOBS_DIR "${CMAKE_INSTALL_FULL_DATADIR}/upstart/sessions")
7message (STATUS "${UPSTART_JOBS_DIR} is the Upstart Jobs File install dir")
8
9set (UPSTART_JOB_NAME "${CMAKE_PROJECT_NAME}.conf")
10set (UPSTART_JOB_FILE "${CMAKE_CURRENT_BINARY_DIR}/${UPSTART_JOB_NAME}")
11set (UPSTART_JOB_FILE_IN "${CMAKE_CURRENT_SOURCE_DIR}/${UPSTART_JOB_NAME}.in")
12
13# build it
14set (pkglibexecdir "${CMAKE_INSTALL_FULL_PKGLIBEXECDIR}")
15configure_file ("${UPSTART_JOB_FILE_IN}" "${UPSTART_JOB_FILE}")
16
17# install it
18install (FILES "${UPSTART_JOB_FILE}"
19 DESTINATION "${UPSTART_JOBS_DIR}")
20
21##
22## XDG Autostart File
23##
24
25# where to install
26set (XDG_AUTOSTART_DIR "/etc/xdg/autostart")
27message (STATUS "${XDG_AUTOSTART_DIR} is the XDG Autostart install dir")
28
29set (XDG_AUTOSTART_NAME "${CMAKE_PROJECT_NAME}.desktop")
30set (XDG_AUTOSTART_FILE "${CMAKE_CURRENT_BINARY_DIR}/${XDG_AUTOSTART_NAME}")
31set (XDG_AUTOSTART_FILE_IN "${CMAKE_CURRENT_SOURCE_DIR}/${XDG_AUTOSTART_NAME}.in")
32
33# build it
34set (pkglibexecdir "${CMAKE_INSTALL_FULL_PKGLIBEXECDIR}")
35configure_file ("${XDG_AUTOSTART_FILE_IN}" "${XDG_AUTOSTART_FILE}")
36
37# install it
38install (FILES "${XDG_AUTOSTART_FILE}"
39 DESTINATION "${XDG_AUTOSTART_DIR}")
40
41##
42## Upstart XDG Autostart Override
43##
44
45# where to install
46set (UPSTART_XDG_AUTOSTART_DIR "${CMAKE_INSTALL_FULL_DATAROOTDIR}/upstart/xdg/autostart")
47message (STATUS "${UPSTART_XDG_AUTOSTART_DIR} is the Upstart XDG autostart override dir")
48
49set (UPSTART_XDG_AUTOSTART_NAME "${CMAKE_PROJECT_NAME}.upstart.desktop")
50set (UPSTART_XDG_AUTOSTART_FILE "${CMAKE_CURRENT_BINARY_DIR}/${UPSTART_XDG_AUTOSTART_NAME}")
51set (UPSTART_XDG_AUTOSTART_FILE_IN "${CMAKE_CURRENT_SOURCE_DIR}/${UPSTART_XDG_AUTOSTART_NAME}.in")
52
53# build it
54set (pkglibexecdir "${CMAKE_INSTALL_FULL_PKGLIBEXECDIR}")
55configure_file ("${UPSTART_XDG_AUTOSTART_FILE_IN}" "${UPSTART_XDG_AUTOSTART_FILE}")
56
57# install it
58install (FILES "${UPSTART_XDG_AUTOSTART_FILE}"
59 DESTINATION "${UPSTART_XDG_AUTOSTART_DIR}"
60 RENAME "${XDG_AUTOSTART_NAME}")
61
62##
63## Unity Indicator File
64##
65
66# where to install
67set (UNITY_INDICATOR_DIR "${CMAKE_INSTALL_FULL_DATAROOTDIR}/unity/indicators")
68message (STATUS "${UNITY_INDICATOR_DIR} is the Unity Indicator install dir")
69
70set (UNITY_INDICATOR_NAME "com.canonical.indicator.rotation_lock")
71set (UNITY_INDICATOR_FILE "${CMAKE_CURRENT_SOURCE_DIR}/${UNITY_INDICATOR_NAME}")
72
73install (FILES "${UNITY_INDICATOR_FILE}"
74 DESTINATION "${UNITY_INDICATOR_DIR}")
075
=== added file 'data/com.canonical.indicator.rotation_lock'
--- data/com.canonical.indicator.rotation_lock 1970-01-01 00:00:00 +0000
+++ data/com.canonical.indicator.rotation_lock 2014-08-22 00:07:37 +0000
@@ -0,0 +1,11 @@
1[Indicator Service]
2Name=indicator-rotation-lock
3ObjectPath=/com/canonical/indicator/rotation_lock
4Position=90
5
6[phone]
7ObjectPath=/com/canonical/indicator/rotation_lock/phone
8
9[phone_greeter]
10ObjectPath=/com/canonical/indicator/rotation_lock/phone
11
012
=== added file 'data/indicator-display.conf.in'
--- data/indicator-display.conf.in 1970-01-01 00:00:00 +0000
+++ data/indicator-display.conf.in 2014-08-22 00:07:37 +0000
@@ -0,0 +1,9 @@
1description "Indicator Display Backend"
2
3start on indicator-services-start
4stop on desktop-end or indicator-services-end
5
6respawn
7respawn limit 2 10
8
9exec @pkglibexecdir@/indicator-display-service
010
=== added file 'data/indicator-display.desktop.in'
--- data/indicator-display.desktop.in 1970-01-01 00:00:00 +0000
+++ data/indicator-display.desktop.in 2014-08-22 00:07:37 +0000
@@ -0,0 +1,9 @@
1[Desktop Entry]
2Type=Application
3Name=Indicator Display
4Exec=@pkglibexecdir@/indicator-display-service
5OnlyShowIn=Unity;GNOME;
6NoDisplay=true
7StartupNotify=false
8Terminal=false
9AutostartCondition=GNOME3 unless-session gnome
010
=== added file 'data/indicator-display.upstart.desktop.in'
--- data/indicator-display.upstart.desktop.in 1970-01-01 00:00:00 +0000
+++ data/indicator-display.upstart.desktop.in 2014-08-22 00:07:37 +0000
@@ -0,0 +1,9 @@
1[Desktop Entry]
2Type=Application
3Name=Indicator Display
4Exec=@pkglibexecdir@/indicator-display-service
5OnlyShowIn=Unity;
6NoDisplay=true
7StartupNotify=false
8Terminal=false
9Hidden=true
010
=== added directory 'debian'
=== added file 'debian/changelog'
--- debian/changelog 1970-01-01 00:00:00 +0000
+++ debian/changelog 2014-08-22 00:07:37 +0000
@@ -0,0 +1,6 @@
1indicator-display (0.1-0ubuntu1) utopic; urgency=medium
2
3 * Initial release.
4
5 -- Charles Kerr <charles.kerr@canonical.com> Wed, 20 Aug 2014 15:29:27 -0500
6
07
=== added file 'debian/compat'
--- debian/compat 1970-01-01 00:00:00 +0000
+++ debian/compat 2014-08-22 00:07:37 +0000
@@ -0,0 +1,1 @@
19
02
=== added file 'debian/control'
--- debian/control 1970-01-01 00:00:00 +0000
+++ debian/control 2014-08-22 00:07:37 +0000
@@ -0,0 +1,34 @@
1Source: indicator-display
2Section: misc
3Priority: optional
4Maintainer: Charles Kerr <charles.kerr@canonical.com>
5Build-Depends: cmake,
6 dbus,
7# make g++ version explicit for ABI safety <https://wiki.ubuntu.com/cpp-11>
8 g++-4.9,
9 libglib2.0-dev (>= 2.36),
10 libproperties-cpp-dev,
11# for coverage reports
12 lcov,
13# for tests
14 cppcheck,
15 libgtest-dev,
16 google-mock (>= 1.6.0+svn437),
17 gsettings-ubuntu-schemas (>= 0.0.2+14.10.20140813),
18# for packaging
19 debhelper (>= 9),
20 dh-translations,
21Standards-Version: 3.9.5
22Homepage: http://launchpad.net/indicator-display/
23# If you aren't a member of ~indicator-applet-developers but need to upload
24# packaging changes, just go ahead. ~indicator-applet-developers will notice and
25# sync up the code again.
26Vcs-Bzr: https://code.launchpad.net/~indicator-applet-developers/indicator-display/trunk.14.10
27
28Package: indicator-display
29Architecture: any
30Depends: ${shlibs:Depends},
31 ${misc:Depends},
32 gsettings-ubuntu-schemas (>= 0.0.2+14.10.20140813),
33Description: Collection of small indicators
34 Indicators too small to merit separate codebases, such as Rotation Lock
035
=== added file 'debian/copyright'
--- debian/copyright 1970-01-01 00:00:00 +0000
+++ debian/copyright 2014-08-22 00:07:37 +0000
@@ -0,0 +1,21 @@
1Format: http://www.debian.org/doc/packaging-manuals/copyright-format/1.0/
2Upstream-Name: indicator-display
3Source: http://launchpad.net/indicator-display
4
5Files: *
6Copyright: 2014, Canonical Ltd.
7License: GPL-3
8 This package is free software; you can redistribute it and/or modify
9 it under the terms of the GNU General Public License as published by
10 the Free Software Foundation; version 3 of the License.
11 .
12 This package is distributed in the hope that it will be useful,
13 but WITHOUT ANY WARRANTY; without even the implied warranty of
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 GNU General Public License for more details.
16 .
17 You should have received a copy of the GNU General Public License
18 along with this program. If not, see <http://www.gnu.org/licenses/>
19 .
20 On Debian systems, the complete text of the GNU General
21 Public License version 3 can be found in "/usr/share/common-licenses/GPL-3".
022
=== added file 'debian/rules'
--- debian/rules 1970-01-01 00:00:00 +0000
+++ debian/rules 2014-08-22 00:07:37 +0000
@@ -0,0 +1,10 @@
1#!/usr/bin/make -f
2
3# Explicitly selecting a G{CC,++}-version here to avoid ABI breaks
4# introduced by toolchain updates. <https://wiki.ubuntu.com/cpp-11>
5export CC=$(DEB_HOST_GNU_TYPE)-gcc-4.9
6export CXX=$(DEB_HOST_GNU_TYPE)-g++-4.9
7
8%:
9 dh $@ --with translations
10
011
=== added directory 'po'
=== added file 'po/CMakeLists.txt'
--- po/CMakeLists.txt 1970-01-01 00:00:00 +0000
+++ po/CMakeLists.txt 2014-08-22 00:07:37 +0000
@@ -0,0 +1,3 @@
1include (Translations)
2add_translations_directory("${GETTEXT_PACKAGE}")
3add_translations_catalog("${GETTEXT_PACKAGE}" ../src/)
04
=== added file 'po/POTFILES.in'
--- po/POTFILES.in 1970-01-01 00:00:00 +0000
+++ po/POTFILES.in 2014-08-22 00:07:37 +0000
@@ -0,0 +1,1 @@
1src/rotation-lock.cpp
02
=== added directory 'src'
=== added file 'src/CMakeLists.txt'
--- src/CMakeLists.txt 1970-01-01 00:00:00 +0000
+++ src/CMakeLists.txt 2014-08-22 00:07:37 +0000
@@ -0,0 +1,29 @@
1set (SERVICE_LIB "indicatordisplayservice")
2set (SERVICE_EXEC "indicator-display-service")
3
4add_definitions (-DG_LOG_DOMAIN="${CMAKE_PROJECT_NAME}")
5
6# handwritten source code...
7set (SERVICE_LIB_HANDWRITTEN_SOURCES
8 exporter.cpp
9 rotation-lock.cpp)
10
11add_library (${SERVICE_LIB} STATIC
12 ${SERVICE_LIB_HANDWRITTEN_SOURCES})
13
14# add the bin dir to the include path so that
15# the compiler can find the generated header files
16include_directories (${CMAKE_CURRENT_BINARY_DIR})
17
18link_directories (${SERVICE_DEPS_LIBRARY_DIRS})
19
20set (SERVICE_EXEC_HANDWRITTEN_SOURCES main.cpp)
21add_executable (${SERVICE_EXEC} ${SERVICE_EXEC_HANDWRITTEN_SOURCES})
22target_link_libraries (${SERVICE_EXEC} ${SERVICE_LIB} ${SERVICE_DEPS_LIBRARIES} ${GCOV_LIBS})
23install (TARGETS ${SERVICE_EXEC} RUNTIME DESTINATION ${CMAKE_INSTALL_FULL_PKGLIBEXECDIR})
24
25# add warnings/coverage info on handwritten files
26# but not the generated ones...
27set_property (SOURCE ${SERVICE_LIB_HANDWRITTEN_SOURCES} ${SERVICE_EXEC_HANDWRITTEN_SOURCES}
28 APPEND_STRING PROPERTY COMPILE_FLAGS " -std=c++11 -g ${CXX_WARNING_ARGS} ${GCOV_FLAGS}")
29
030
=== added file 'src/exporter.cpp'
--- src/exporter.cpp 1970-01-01 00:00:00 +0000
+++ src/exporter.cpp 2014-08-22 00:07:37 +0000
@@ -0,0 +1,217 @@
1/*
2 * Copyright 2014 Canonical Ltd.
3 *
4 * This program is free software: you can redistribute it and/or modify it
5 * under the terms of the GNU General Public License version 3, as published
6 * by the Free Software Foundation.
7 *
8 * This program is distributed in the hope that it will be useful, but
9 * WITHOUT ANY WARRANTY; without even the implied warranties of
10 * MERCHANTABILITY, SATISFACTORY QUALITY, or FITNESS FOR A PARTICULAR
11 * PURPOSE. See the GNU General Public License for more details.
12 *
13 * You should have received a copy of the GNU General Public License along
14 * with this program. If not, see <http://www.gnu.org/licenses/>.
15 *
16 * Authors:
17 * Charles Kerr <charles.kerr@canonical.com>
18 */
19
20#include <src/exporter.h>
21
22class Exporter::Impl
23{
24public:
25
26 Impl(const std::shared_ptr<Indicator>& indicator):
27 m_indicator(indicator)
28 {
29 auto bus_name = g_strdup_printf("com.canonical.indicator.%s", indicator->name());
30 m_own_id = g_bus_own_name(G_BUS_TYPE_SESSION,
31 bus_name,
32 G_BUS_NAME_OWNER_FLAGS_NONE,
33 on_bus_acquired,
34 nullptr,
35 on_name_lost,
36 this,
37 nullptr);
38
39 g_free(bus_name);
40 }
41
42 ~Impl()
43 {
44 if (m_bus != nullptr)
45 {
46 for(const auto& id : m_exported_menu_ids)
47 g_dbus_connection_unexport_menu_model(m_bus, id);
48
49 if (m_exported_actions_id)
50 g_dbus_connection_unexport_action_group(m_bus, m_exported_actions_id);
51 }
52
53 if (m_own_id)
54 g_bus_unown_name(m_own_id);
55
56 g_clear_object(&m_bus);
57 }
58
59 core::Signal<std::string>& name_lost()
60 {
61 return m_name_lost;
62 }
63
64private:
65
66 void emit_name_lost(const char* bus_name)
67 {
68 m_name_lost(bus_name);
69 }
70
71 static void on_bus_acquired(GDBusConnection * connection,
72 const gchar * name,
73 gpointer gself)
74 {
75 static_cast<Impl*>(gself)->on_bus_acquired(connection, name);
76 }
77
78 void on_bus_acquired(GDBusConnection* connection, const gchar* /*name*/)
79 {
80 m_bus = G_DBUS_CONNECTION(g_object_ref(G_OBJECT(connection)));
81
82 export_actions(m_indicator);
83
84 for (auto& profile : m_indicator->profiles())
85 export_profile(m_indicator, profile);
86 }
87
88 void export_actions(const std::shared_ptr<Indicator>& indicator)
89 {
90 GError* error;
91 char* object_path;
92 guint id;
93
94 // export the actions
95
96 error = nullptr;
97 object_path = g_strdup_printf("/com/canonical/indicator/%s", indicator->name());
98 id = g_dbus_connection_export_action_group(m_bus,
99 object_path,
100 G_ACTION_GROUP(indicator->action_group()),
101 &error);
102 if (id)
103 m_exported_actions_id = id;
104 else
105 g_warning("Can't export action group to '%s': %s", object_path, error->message);
106
107 g_clear_error(&error);
108 g_free(object_path);
109 }
110
111 static GVariant* create_header_state(const Header& h)
112 {
113 GVariantBuilder b;
114 g_variant_builder_init(&b, G_VARIANT_TYPE_VARDICT);
115
116 g_variant_builder_add(&b, "{sv}", "visible", g_variant_new_boolean(h.is_visible));
117
118 if (!h.title.empty())
119 g_variant_builder_add(&b, "{sv}", "title", g_variant_new_string(h.title.c_str()));
120
121 if (!h.label.empty())
122 g_variant_builder_add(&b, "{sv}", "label", g_variant_new_string(h.label.c_str()));
123
124 if (!h.title.empty() || !h.label.empty())
125 g_variant_builder_add(&b, "{sv}", "accessible-desc", g_variant_new_string(!h.label.empty() ? h.label.c_str() : h.title.c_str()));
126
127 if (h.icon)
128 g_variant_builder_add(&b, "{sv}", "icon", g_icon_serialize(h.icon.get()));
129
130 return g_variant_builder_end (&b);
131 }
132
133 void export_profile(const std::shared_ptr<Indicator>& indicator,
134 const std::shared_ptr<Profile>& profile)
135 {
136 // build the header action
137 auto action_group = indicator->action_group();
138 std::string action_name = profile->name() + "-header";
139 auto a = g_simple_action_new_stateful(action_name.c_str(), nullptr, create_header_state(profile->header()));
140 g_action_map_add_action(G_ACTION_MAP(action_group), G_ACTION(a));
141 profile->header().changed().connect([action_group,action_name](const Header& header){
142 auto state = create_header_state(header);
143 auto tmp = g_variant_print(state, true);
144 g_message("header changed; updating action state to '%s'", tmp);
145 g_action_group_change_action_state(G_ACTION_GROUP(action_group),
146 action_name.c_str(),
147 create_header_state(header));
148 g_free(tmp);
149 });
150
151 // build the header menu
152 auto detailed_action = g_strdup_printf("indicator.%s", action_name.c_str());
153 GMenuItem* header = g_menu_item_new(nullptr, detailed_action);
154 g_menu_item_set_attribute(header, "x-canonical-type", "s", "com.canonical.indicator.root");
155 g_menu_item_set_submenu(header, profile->menu_model().get());
156 g_free(detailed_action);
157
158 // build the menu
159 auto menu = g_menu_new();
160 g_menu_append_item(menu, header);
161 g_object_unref(header);
162
163 // export the menu
164 auto object_path = g_strdup_printf("/com/canonical/indicator/%s/%s",
165 indicator->name(),
166 profile->name().c_str());
167 GError* error = nullptr;
168 auto id = g_dbus_connection_export_menu_model(m_bus, object_path, G_MENU_MODEL(menu), &error);
169 if (id)
170 m_exported_menu_ids.insert(id);
171 else if (error != nullptr)
172 g_warning("cannot export '%s': %s", object_path, error->message);
173
174 g_free(object_path);
175 g_clear_error(&error);
176 //g_object_unref(menu);
177 }
178
179 static void on_name_lost(GDBusConnection * /*connection*/,
180 const gchar * name,
181 gpointer gthis)
182 {
183 static_cast<Impl*>(gthis)->emit_name_lost(name);
184 }
185
186 const std::string m_bus_name;
187 core::Signal<std::string> m_name_lost;
188 std::shared_ptr<Indicator> m_indicator;
189 std::set<guint> m_exported_menu_ids;
190 guint m_own_id = 0;
191 guint m_exported_actions_id = 0;
192 GDBusConnection * m_bus = nullptr;
193};
194
195/***
196****
197***/
198
199Exporter::Exporter(const std::shared_ptr<Indicator>& indicator):
200 impl(new Impl(indicator))
201{
202}
203
204Exporter::~Exporter()
205{
206}
207
208core::Signal<std::string>&
209Exporter::name_lost()
210{
211 return impl->name_lost();
212}
213
214/***
215****
216***/
217
0218
=== added file 'src/exporter.h'
--- src/exporter.h 1970-01-01 00:00:00 +0000
+++ src/exporter.h 2014-08-22 00:07:37 +0000
@@ -0,0 +1,40 @@
1/*
2 * Copyright 2014 Canonical Ltd.
3 *
4 * This program is free software: you can redistribute it and/or modify it
5 * under the terms of the GNU General Public License version 3, as published
6 * by the Free Software Foundation.
7 *
8 * This program is distributed in the hope that it will be useful, but
9 * WITHOUT ANY WARRANTY; without even the implied warranties of
10 * MERCHANTABILITY, SATISFACTORY QUALITY, or FITNESS FOR A PARTICULAR
11 * PURPOSE. See the GNU General Public License for more details.
12 *
13 * You should have received a copy of the GNU General Public License along
14 * with this program. If not, see <http://www.gnu.org/licenses/>.
15 *
16 * Authors:
17 * Charles Kerr <charles.kerr@canonical.com>
18 */
19
20#include <src/indicator.h>
21
22#include <core/signal.h>
23
24#include <memory>
25
26class Exporter
27{
28public:
29 Exporter(const std::shared_ptr<Indicator>& indicator);
30 ~Exporter();
31 core::Signal<std::string>& name_lost();
32
33private:
34 class Impl;
35 std::unique_ptr<Impl> impl;
36
37 Exporter(const Exporter&) =delete;
38 Exporter& operator=(const Exporter&) =delete;
39};
40
041
=== added file 'src/indicator.h'
--- src/indicator.h 1970-01-01 00:00:00 +0000
+++ src/indicator.h 2014-08-22 00:07:37 +0000
@@ -0,0 +1,88 @@
1/*
2 * Copyright 2014 Canonical Ltd.
3 *
4 * This program is free software: you can redistribute it and/or modify it
5 * under the terms of the GNU General Public License version 3, as published
6 * by the Free Software Foundation.
7 *
8 * This program is distributed in the hope that it will be useful, but
9 * WITHOUT ANY WARRANTY; without even the implied warranties of
10 * MERCHANTABILITY, SATISFACTORY QUALITY, or FITNESS FOR A PARTICULAR
11 * PURPOSE. See the GNU General Public License for more details.
12 *
13 * You should have received a copy of the GNU General Public License along
14 * with this program. If not, see <http://www.gnu.org/licenses/>.
15 *
16 * Authors:
17 * Charles Kerr <charles.kerr@canonical.com>
18 */
19
20#ifndef INDICATOR_DISPLAY_INDICATOR_H
21#define INDICATOR_DISPLAY_INDICATOR_H
22
23#include <core/property.h>
24
25#include <gio/gio.h> // GIcon
26
27#include <string>
28#include <vector>
29
30struct Header
31{
32 bool is_visible = false;
33 std::string title;
34 std::string label;
35 std::string a11y;
36 std::shared_ptr<GIcon> icon;
37
38 bool operator== (const Header& that) const {
39 return (is_visible == that.is_visible) &&
40 (title == that.title) &&
41 (label == that.label) &&
42 (a11y == that.a11y) &&
43 (icon == that.icon);
44 }
45 bool operator!= (const Header& that) const { return !(*this == that);}
46};
47
48
49class Profile
50{
51public:
52 virtual std::string name() const =0;
53 virtual const core::Property<Header>& header() const =0;
54 virtual std::shared_ptr<GMenuModel> menu_model() const =0;
55
56protected:
57 Profile() =default;
58};
59
60
61class SimpleProfile: public Profile
62{
63public:
64 SimpleProfile(const char* name, const std::shared_ptr<GMenuModel>& menu): m_name(name), m_menu(menu) {}
65
66 std::string name() const {return m_name;}
67 core::Property<Header>& header() {return m_header;}
68 const core::Property<Header>& header() const {return m_header;}
69 std::shared_ptr<GMenuModel> menu_model() const {return m_menu;}
70
71protected:
72 const std::string m_name;
73 core::Property<Header> m_header;
74 std::shared_ptr<GMenuModel> m_menu;
75};
76
77
78class Indicator
79{
80public:
81 virtual ~Indicator() =default;
82
83 virtual const char* name() const =0;
84 virtual GSimpleActionGroup* action_group() const =0;
85 virtual std::vector<std::shared_ptr<Profile>> profiles() const =0;
86};
87
88#endif
089
=== added file 'src/main.cpp'
--- src/main.cpp 1970-01-01 00:00:00 +0000
+++ src/main.cpp 2014-08-22 00:07:37 +0000
@@ -0,0 +1,62 @@
1/*
2 * Copyright 2014 Canonical Ltd.
3 *
4 * This program is free software: you can redistribute it and/or modify it
5 * under the terms of the GNU General Public License version 3, as published
6 * by the Free Software Foundation.
7 *
8 * This program is distributed in the hope that it will be useful, but
9 * WITHOUT ANY WARRANTY; without even the implied warranties of
10 * MERCHANTABILITY, SATISFACTORY QUALITY, or FITNESS FOR A PARTICULAR
11 * PURPOSE. See the GNU General Public License for more details.
12 *
13 * You should have received a copy of the GNU General Public License along
14 * with this program. If not, see <http://www.gnu.org/licenses/>.
15 *
16 * Authors:
17 * Charles Kerr <charles.kerr@canonical.com>
18 */
19
20#include <src/exporter.h>
21#include <src/rotation-lock.h>
22
23#include <glib/gi18n.h> // bindtextdomain()
24#include <gio/gio.h>
25
26#include <locale.h>
27
28int
29main(int /*argc*/, char** /*argv*/)
30{
31 // Work around a deadlock in glib's type initialization.
32 // It can be removed when https://bugzilla.gnome.org/show_bug.cgi?id=674885 is fixed.
33 g_type_ensure(G_TYPE_DBUS_CONNECTION);
34
35 // boilerplate i18n
36 setlocale(LC_ALL, "");
37 bindtextdomain(GETTEXT_PACKAGE, GNOMELOCALEDIR);
38 textdomain(GETTEXT_PACKAGE);
39
40 auto loop = g_main_loop_new(nullptr, false);
41 auto on_name_lost = [loop](const std::string& name){
42 g_warning("busname lost: '%s'", name.c_str());
43 g_main_loop_quit(loop);
44 };
45
46 // build all our indicators.
47 // Right now we've only got one -- rotation lock -- but hey, we can dream.
48 std::vector<std::shared_ptr<Indicator>> indicators;
49 std::vector<std::shared_ptr<Exporter>> exporters;
50 indicators.push_back(std::make_shared<RotationLockIndicator>());
51 for (auto& indicator : indicators) {
52 auto exporter = std::make_shared<Exporter>(indicator);
53 exporter->name_lost().connect(on_name_lost);
54 exporters.push_back(exporter);
55 }
56
57 g_main_loop_run(loop);
58
59 // cleanup
60 g_main_loop_unref(loop);
61 return 0;
62}
063
=== added file 'src/rotation-lock.cpp'
--- src/rotation-lock.cpp 1970-01-01 00:00:00 +0000
+++ src/rotation-lock.cpp 2014-08-22 00:07:37 +0000
@@ -0,0 +1,197 @@
1/*
2 * Copyright 2014 Canonical Ltd.
3 *
4 * This program is free software; you can redistribute it and/or modify
5 * it under the terms of the GNU General Public License as published by
6 * the Free Software Foundation; version 3.
7 *
8 * This program is distributed in the hope that it will be useful,
9 * but WITHOUT ANY WARRANTY; without even the implied warranty of
10 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 * GNU Lesser General Public License for more details.
12 *
13 * You should have received a copy of the GNU Lesser General Public License
14 * along with this program. If not, see <http://www.gnu.org/licenses/>.
15 *
16 * Authors:
17 * Charles Kerr <charles.kerr@canonical.com>
18 */
19
20#include <src/rotation-lock.h>
21
22#include <glib/gi18n.h>
23
24class RotationLockIndicator::Impl
25{
26public:
27
28 Impl():
29 m_settings(g_settings_new(m_schema_name)),
30 m_action_group(create_action_group())
31 {
32 // build the rotation lock icon
33 auto icon = g_themed_icon_new_with_default_fallbacks("orientation-lock");
34 auto icon_deleter = [](GIcon* o){g_object_unref(G_OBJECT(o));};
35 m_icon.reset(icon, icon_deleter);
36
37 // build the phone profile
38 auto menu_model_deleter = [](GMenuModel* o){g_object_unref(G_OBJECT(o));};
39 std::shared_ptr<GMenuModel> phone_menu (create_phone_menu(), menu_model_deleter);
40 m_phone = std::make_shared<SimpleProfile>("phone", phone_menu);
41 update_phone_header();
42 }
43
44 ~Impl()
45 {
46 g_clear_object(&m_action_group);
47 g_clear_object(&m_settings);
48 }
49
50 GSimpleActionGroup* action_group() const
51 {
52 return m_action_group;
53 }
54
55 std::vector<std::shared_ptr<Profile>> profiles()
56 {
57 std::vector<std::shared_ptr<Profile>> ret;
58 ret.push_back(m_phone);
59 return ret;
60 }
61
62private:
63
64 /***
65 **** Actions
66 ***/
67
68 static gboolean settings_to_action_state(GValue *value,
69 GVariant *variant,
70 gpointer /*unused*/)
71 {
72 bool is_locked = g_strcmp0(g_variant_get_string(variant, nullptr), "none");
73 g_value_set_variant(value, g_variant_new_boolean(is_locked));
74 return TRUE;
75 }
76
77 static GVariant* action_state_to_settings(const GValue *value,
78 const GVariantType * /*expected_type*/,
79 gpointer /*unused*/)
80 {
81 // Toggling to 'on' *should* lock to the screen's current orientation.
82 // We don't have any way of knowing Screen.orientation in this service,
83 // so just pick one at random to satisfy the binding's needs.
84 //
85 // In practice this doesn't matter since the indicator isn't visible
86 // when the lock mode is 'none' so the end user won't ever be able
87 // to toggle the menuitem from None to anything else.
88
89 auto state_is_true = g_variant_get_boolean(g_value_get_variant(value));
90 return g_variant_new_string(state_is_true ? "PrimaryOrientation" : "none");
91 }
92
93 GSimpleActionGroup* create_action_group()
94 {
95 GSimpleActionGroup* group;
96 GSimpleAction* action;
97
98 group = g_simple_action_group_new();
99 action = g_simple_action_new_stateful("rotation-lock",
100 nullptr,
101 g_variant_new_boolean(false));
102 g_settings_bind_with_mapping(m_settings, "orientation-lock",
103 action, "state",
104 G_SETTINGS_BIND_DEFAULT,
105 settings_to_action_state,
106 action_state_to_settings,
107 nullptr,
108 nullptr);
109 g_action_map_add_action(G_ACTION_MAP(group), G_ACTION(action));
110 g_object_unref(G_OBJECT(action));
111 g_signal_connect_swapped(m_settings, "changed::orientation-lock",
112 G_CALLBACK(on_orientation_lock_setting_changed), this);
113
114 return group;
115 }
116
117 /***
118 **** Phone profile
119 ***/
120
121 static void on_orientation_lock_setting_changed (gpointer gself)
122 {
123 static_cast<Impl*>(gself)->update_phone_header();
124 }
125
126 GMenuModel* create_phone_menu()
127 {
128 GMenu* menu;
129 GMenuItem* menu_item;
130
131 menu = g_menu_new();
132
133 menu_item = g_menu_item_new(_("Rotation Lock"), "indicator.rotation-lock");
134 g_menu_item_set_attribute(menu_item, "x-canonical-type", "s", "com.canonical.indicator.switch");
135 g_menu_append_item(menu, menu_item);
136 g_object_unref(menu_item);
137
138 return G_MENU_MODEL(menu);
139 }
140
141 void update_phone_header()
142 {
143 Header h;
144 h.title = _("Rotation lock");
145 h.a11y = h.title;
146 h.is_visible = g_settings_get_enum(m_settings, "orientation-lock") != 0;
147 h.icon = m_icon;
148 m_phone->header().set(h);
149 }
150
151 /***
152 ****
153 ***/
154
155 static constexpr char const * m_schema_name {"com.ubuntu.touch.system"};
156 static constexpr char const * m_orientation_lock_icon_name {"orientation-lock"};
157 GSettings* m_settings = nullptr;
158 GSimpleActionGroup* m_action_group = nullptr;
159 std::shared_ptr<SimpleProfile> m_phone;
160 std::shared_ptr<GIcon> m_icon;
161};
162
163/***
164****
165***/
166
167RotationLockIndicator::RotationLockIndicator():
168 impl(new Impl())
169{
170}
171
172RotationLockIndicator::~RotationLockIndicator()
173{
174}
175
176std::vector<std::shared_ptr<Profile>>
177RotationLockIndicator::profiles() const
178{
179 return impl->profiles();
180}
181
182GSimpleActionGroup*
183RotationLockIndicator::action_group() const
184{
185 return impl->action_group();
186}
187
188const char*
189RotationLockIndicator::name() const
190{
191 return "rotation_lock";
192}
193
194/***
195****
196***/
197
0198
=== added file 'src/rotation-lock.h'
--- src/rotation-lock.h 1970-01-01 00:00:00 +0000
+++ src/rotation-lock.h 2014-08-22 00:07:37 +0000
@@ -0,0 +1,42 @@
1/*
2 * Copyright 2014 Canonical Ltd.
3 *
4 * This program is free software: you can redistribute it and/or modify it
5 * under the terms of the GNU General Public License version 3, as published
6 * by the Free Software Foundation.
7 *
8 * This program is distributed in the hope that it will be useful, but
9 * WITHOUT ANY WARRANTY; without even the implied warranties of
10 * MERCHANTABILITY, SATISFACTORY QUALITY, or FITNESS FOR A PARTICULAR
11 * PURPOSE. See the GNU General Public License for more details.
12 *
13 * You should have received a copy of the GNU General Public License along
14 * with this program. If not, see <http://www.gnu.org/licenses/>.
15 *
16 * Authors:
17 * Charles Kerr <charles.kerr@canonical.com>
18 */
19
20#ifndef INDICATOR_DISPLAY_ROTATION_LOCK_H
21#define INDICATOR_DISPLAY_ROTATION_LOCK_H
22
23#include <src/indicator.h>
24
25#include <memory> // std::unique_ptr
26
27class RotationLockIndicator: public Indicator
28{
29public:
30 RotationLockIndicator();
31 ~RotationLockIndicator();
32
33 const char* name() const;
34 GSimpleActionGroup* action_group() const;
35 std::vector<std::shared_ptr<Profile>> profiles() const;
36
37protected:
38 class Impl;
39 std::unique_ptr<Impl> impl;
40};
41
42#endif
043
=== added directory 'tests'
=== added file 'tests/CMakeLists.txt'
--- tests/CMakeLists.txt 1970-01-01 00:00:00 +0000
+++ tests/CMakeLists.txt 2014-08-22 00:07:37 +0000
@@ -0,0 +1,35 @@
1include(FindGMock)
2include_directories(${CMAKE_CURRENT_SOURCE_DIR})
3include_directories(${GMOCK_INCLUDE_DIRS})
4include_directories(${GTEST_INCLUDE_DIRS})
5
6# build libgtest
7#add_library (gtest STATIC
8# ${GTEST_SOURCE_DIR}/gtest-all.cc
9# ${GTEST_SOURCE_DIR}/gtest_main.cc)
10#set_target_properties (gtest PROPERTIES INCLUDE_DIRECTORIES ${INCLUDE_DIRECTORIES} ${GTEST_INCLUDE_DIR})
11#set_target_properties (gtest PROPERTIES COMPILE_FLAGS ${COMPILE_FLAGS} -w)
12
13if ("${CMAKE_CXX_COMPILER_ID}" STREQUAL "Clang")
14 # turn off the warnings that break Google Test
15 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")
16endif()
17
18SET (CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++11 -g ${CXX_WARNING_ARGS}")
19
20# look for headers in our src dir, and also in the directories where we autogenerate files...
21include_directories (${CMAKE_SOURCE_DIR}/src)
22include_directories (${CMAKE_CURRENT_BINARY_DIR})
23include_directories (${DBUSTEST_INCLUDE_DIRS})
24
25function(add_test_by_name name)
26 set (TEST_NAME ${name})
27 add_executable (${TEST_NAME} ${TEST_NAME}.cpp)
28 add_test (${TEST_NAME} ${TEST_NAME})
29 add_dependencies (${TEST_NAME} libindicatordisplayservice)
30 target_link_libraries (${TEST_NAME} indicatordisplayservice ${SERVICE_DEPS_LIBRARIES} ${GTEST_LIBRARIES} ${GMOCK_LIBRARIES})
31endfunction()
32add_test_by_name(test-rotation-lock)
33
34add_test (cppcheck cppcheck --enable=all -q --error-exitcode=2 --inline-suppr -I${CMAKE_SOURCE_DIR} ${CMAKE_SOURCE_DIR}/src ${CMAKE_SOURCE_DIR}/tests)
35
036
=== added file 'tests/glib-fixture.h'
--- tests/glib-fixture.h 1970-01-01 00:00:00 +0000
+++ tests/glib-fixture.h 2014-08-22 00:07:37 +0000
@@ -0,0 +1,143 @@
1/*
2 * Copyright 2014 Canonical Ltd.
3 *
4 * This program is free software: you can redistribute it and/or modify it
5 * under the terms of the GNU General Public License version 3, as published
6 * by the Free Software Foundation.
7 *
8 * This program is distributed in the hope that it will be useful, but
9 * WITHOUT ANY WARRANTY; without even the implied warranties of
10 * MERCHANTABILITY, SATISFACTORY QUALITY, or FITNESS FOR A PARTICULAR
11 * PURPOSE. See the GNU General Public License for more details.
12 *
13 * You should have received a copy of the GNU General Public License along
14 * with this program. If not, see <http://www.gnu.org/licenses/>.
15 *
16 * Authors:
17 * Charles Kerr <charles.kerr@canonical.com>
18 */
19
20#include <map>
21
22#include <glib.h>
23#include <glib/gstdio.h>
24#include <gio/gio.h>
25
26#include <gtest/gtest.h>
27
28#include <locale.h> // setlocale()
29
30class GlibFixture : public ::testing::Test
31{
32 private:
33
34 GLogFunc realLogHandler;
35
36 std::map<GLogLevelFlags,size_t> expected_log;
37 std::map<GLogLevelFlags,std::vector<std::string>> log;
38
39 void test_log_counts()
40 {
41 const GLogLevelFlags levels_to_test[] = { G_LOG_LEVEL_ERROR,
42 G_LOG_LEVEL_CRITICAL,
43 G_LOG_LEVEL_MESSAGE,
44 G_LOG_LEVEL_WARNING };
45
46 for(const auto& level : levels_to_test)
47 {
48 const auto& v = log[level];
49 const auto n = v.size();
50
51 EXPECT_EQ(expected_log[level], n);
52
53 if (expected_log[level] != n)
54 for (size_t i=0; i<n; ++i)
55 g_message("%d %s", (n+1), v[i].c_str());
56 }
57
58 expected_log.clear();
59 log.clear();
60 }
61
62 static void default_log_handler(const gchar * log_domain,
63 GLogLevelFlags log_level,
64 const gchar * message,
65 gpointer self)
66 {
67 auto tmp = g_strdup_printf ("%s:%d \"%s\"", log_domain, (int)log_level, message);
68 static_cast<GlibFixture*>(self)->log[log_level].push_back(tmp);
69 g_free(tmp);
70 }
71
72 protected:
73
74 void increment_expected_errors(GLogLevelFlags level, size_t n=1)
75 {
76 expected_log[level] += n;
77 }
78
79 virtual void SetUp()
80 {
81 setlocale(LC_ALL, "C.UTF-8");
82
83 loop = g_main_loop_new(nullptr, false);
84
85 g_log_set_default_handler(default_log_handler, this);
86
87 g_assert(g_setenv("GSETTINGS_BACKEND", "memory", true));
88
89 g_unsetenv("DISPLAY");
90 }
91
92 virtual void TearDown()
93 {
94 test_log_counts();
95
96 g_log_set_default_handler(realLogHandler, this);
97
98 g_clear_pointer(&loop, g_main_loop_unref);
99 }
100
101 private:
102
103 static gboolean
104 wait_for_signal__timeout(gpointer name)
105 {
106 g_error("%s: timed out waiting for signal '%s'", G_STRLOC, (char*)name);
107 return G_SOURCE_REMOVE;
108 }
109
110 static gboolean
111 wait_msec__timeout(gpointer loop)
112 {
113 g_main_loop_quit(static_cast<GMainLoop*>(loop));
114 return G_SOURCE_CONTINUE;
115 }
116
117 protected:
118
119 /* convenience func to loop while waiting for a GObject's signal */
120 void wait_for_signal(gpointer o, const gchar * signal, const guint timeout_seconds=5)
121 {
122 // wait for the signal or for timeout, whichever comes first
123 const auto handler_id = g_signal_connect_swapped(o, signal,
124 G_CALLBACK(g_main_loop_quit),
125 loop);
126 const auto timeout_id = g_timeout_add_seconds(timeout_seconds,
127 wait_for_signal__timeout,
128 loop);
129 g_main_loop_run(loop);
130 g_source_remove(timeout_id);
131 g_signal_handler_disconnect(o, handler_id);
132 }
133
134 /* convenience func to loop for N msec */
135 void wait_msec(guint msec=50)
136 {
137 const auto id = g_timeout_add(msec, wait_msec__timeout, loop);
138 g_main_loop_run(loop);
139 g_source_remove(id);
140 }
141
142 GMainLoop * loop;
143};
0144
=== added file 'tests/gtestdbus-fixture.h'
--- tests/gtestdbus-fixture.h 1970-01-01 00:00:00 +0000
+++ tests/gtestdbus-fixture.h 2014-08-22 00:07:37 +0000
@@ -0,0 +1,102 @@
1/*
2 * Copyright 2013 Canonical Ltd.
3 *
4 * This program is free software: you can redistribute it and/or modify it
5 * under the terms of the GNU General Public License version 3, as published
6 * by the Free Software Foundation.
7 *
8 * This program is distributed in the hope that it will be useful, but
9 * WITHOUT ANY WARRANTY; without even the implied warranties of
10 * MERCHANTABILITY, SATISFACTORY QUALITY, or FITNESS FOR A PARTICULAR
11 * PURPOSE. See the GNU General Public License for more details.
12 *
13 * You should have received a copy of the GNU General Public License along
14 * with this program. If not, see <http://www.gnu.org/licenses/>.
15 *
16 * Authors:
17 * Charles Kerr <charles.kerr@canonical.com>
18 */
19
20#include "glib-fixture.h"
21
22/***
23****
24***/
25
26class GTestDBusFixture: public GlibFixture
27{
28 public:
29
30 GTestDBusFixture() {}
31
32 GTestDBusFixture(const std::vector<std::string>& service_dirs_in): service_dirs(service_dirs_in) {}
33
34 private:
35
36 typedef GlibFixture super;
37
38 static void
39 on_bus_opened (GObject* /*object*/, GAsyncResult * res, gpointer gself)
40 {
41 auto self = static_cast<GTestDBusFixture*>(gself);
42
43 GError * err = 0;
44 self->bus = g_bus_get_finish (res, &err);
45 g_assert_no_error (err);
46
47 g_main_loop_quit (self->loop);
48 }
49
50 static void
51 on_bus_closed (GObject* /*object*/, GAsyncResult * res, gpointer gself)
52 {
53 auto self = static_cast<GTestDBusFixture*>(gself);
54
55 GError * err = 0;
56 g_dbus_connection_close_finish (self->bus, res, &err);
57 g_assert_no_error (err);
58
59 g_main_loop_quit (self->loop);
60 }
61
62 protected:
63
64 GTestDBus * test_dbus = nullptr;
65 GDBusConnection * bus = nullptr;
66 const std::vector<std::string> service_dirs;
67
68 virtual void SetUp ()
69 {
70 super::SetUp ();
71
72 // pull up a test dbus
73 test_dbus = g_test_dbus_new (G_TEST_DBUS_NONE);
74 for (const auto& dir : service_dirs)
75 g_test_dbus_add_service_dir (test_dbus, dir.c_str());
76 g_test_dbus_up (test_dbus);
77 const char * address = g_test_dbus_get_bus_address (test_dbus);
78 g_setenv ("DBUS_SYSTEM_BUS_ADDRESS", address, true);
79 g_setenv ("DBUS_SESSION_BUS_ADDRESS", address, true);
80 g_debug ("test_dbus's address is %s", address);
81
82 // wait for the GDBusConnection before returning
83 g_bus_get (G_BUS_TYPE_SYSTEM, nullptr, on_bus_opened, this);
84 g_main_loop_run (loop);
85 }
86
87 virtual void TearDown ()
88 {
89 wait_msec();
90
91 // close the system bus
92 g_dbus_connection_close(bus, nullptr, on_bus_closed, this);
93 g_main_loop_run(loop);
94 g_clear_object(&bus);
95
96 // tear down the test dbus
97 g_test_dbus_down(test_dbus);
98 g_clear_object(&test_dbus);
99
100 super::TearDown();
101 }
102};
0103
=== added file 'tests/manual'
--- tests/manual 1970-01-01 00:00:00 +0000
+++ tests/manual 2014-08-22 00:07:37 +0000
@@ -0,0 +1,16 @@
1
2Test-case indicator-display/rotation-indicator
3<dl>
4 <dt>On the phone, enable the orientation lock in ubuntu-system-settings.</dt>
5 <dd>The rotation lock indicator should appear, and its switch menuitem should be set to 'true'.</dd>
6
7 <dt>With the orientation locked, click on the indicator's switch menuitem to toggle from locked to unlocked.</dd>
8 <dd>The rotation lock indicator should disappear</dd>
9 <dd>In ubuntu-system-settings, the orientation lock control should change to 'none'.</dd>
10</dl>
11
12
13<strong>
14 If all actions produce the expected results listed, please <a href="results#add_result">submit</a> a 'passed' result.
15 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>.
16
017
=== added file 'tests/test-rotation-lock.cpp'
--- tests/test-rotation-lock.cpp 1970-01-01 00:00:00 +0000
+++ tests/test-rotation-lock.cpp 2014-08-22 00:07:37 +0000
@@ -0,0 +1,61 @@
1/*
2 * Copyright 2014 Canonical Ltd.
3 *
4 * This program is free software: you can redistribute it and/or modify it
5 * under the terms of the GNU General Public License version 3, as published
6 * by the Free Software Foundation.
7 *
8 * This program is distributed in the hope that it will be useful, but
9 * WITHOUT ANY WARRANTY; without even the implied warranties of
10 * MERCHANTABILITY, SATISFACTORY QUALITY, or FITNESS FOR A PARTICULAR
11 * PURPOSE. See the GNU General Public License for more details.
12 *
13 * You should have received a copy of the GNU General Public License along
14 * with this program. If not, see <http://www.gnu.org/licenses/>.
15 *
16 * Authors:
17 * Charles Kerr <charles.kerr@canonical.com>
18 */
19
20#include "gtestdbus-fixture.h"
21
22#include <src/rotation-lock.h>
23
24class RotationLockFixture: public GTestDBusFixture
25{
26private:
27 typedef GTestDBusFixture super;
28
29protected:
30
31 void SetUp()
32 {
33 super::SetUp();
34 }
35
36 void TearDown()
37 {
38 super::TearDown();
39 }
40};
41
42/***
43****
44***/
45
46TEST_F(RotationLockFixture, CheckIndicator)
47{
48 RotationLockIndicator indicator;
49
50 ASSERT_STREQ("rotation_lock", indicator.name());
51 auto actions = indicator.action_group();
52 ASSERT_TRUE(actions != nullptr);
53 ASSERT_TRUE(g_action_group_has_action(G_ACTION_GROUP(actions), "rotation-lock"));
54
55 std::vector<std::shared_ptr<Profile>> profiles = indicator.profiles();
56 ASSERT_EQ(1, profiles.size());
57 std::shared_ptr<Profile> phone = profiles[0];
58 ASSERT_EQ(std::string("phone"), phone->name());
59 ASSERT_FALSE(phone->header()->is_visible);
60}
61

Subscribers

People subscribed via source and target branches