Merge lp:~charlesk/indicator-location/gmenuify into lp:indicator-location/13.10

Proposed by Charles Kerr
Status: Merged
Approved by: Ted Gould
Approved revision: 68
Merged at revision: 40
Proposed branch: lp:~charlesk/indicator-location/gmenuify
Merge into: lp:indicator-location/13.10
Diff against target: 3554 lines (+2024/-1300)
42 files modified
CMakeLists.txt (+60/-0)
INSTALL (+69/-0)
Makefile.am (+0/-35)
Makefile.am.coverage (+0/-48)
autogen.sh (+0/-4)
cmake/GCov.cmake (+53/-0)
cmake/Translations.cmake (+41/-0)
configure.ac (+0/-57)
data/CMakeLists.txt (+33/-0)
data/Makefile.am (+0/-14)
data/com.canonical.indicator.location (+8/-0)
data/indicator-location-neighborhood.svg (+0/-106)
data/indicator-location-region.svg (+0/-96)
data/indicator-location-specific.svg (+0/-116)
data/indicator-location-unknown.svg (+0/-106)
data/indicator-location.desktop (+0/-9)
data/indicator-location.service.in (+3/-0)
debian/changelog (+8/-0)
debian/control (+12/-12)
debian/rules (+12/-6)
m4/gcov.m4 (+0/-86)
po/CMakeLists.txt (+3/-0)
po/POTFILES.in (+1/-1)
src/CMakeLists.txt (+45/-0)
src/Makefile.am (+0/-17)
src/controller-mock.h (+48/-0)
src/controller-ualc.cc (+106/-0)
src/controller-ualc.h (+53/-0)
src/controller.cc (+46/-0)
src/controller.h (+63/-0)
src/indicator-location.c (+0/-587)
src/main.cc (+54/-0)
src/phone.cc (+265/-0)
src/phone.h (+69/-0)
src/service.cc (+166/-0)
src/service.h (+64/-0)
src/utils.h (+36/-0)
tests/CMakeLists.txt (+32/-0)
tests/gtest-dbus-fixture.h (+134/-0)
tests/gtest-dbus-indicator-fixture.h (+273/-0)
tests/phone-test.cc (+214/-0)
trim-lcov.py (+53/-0)
To merge this branch: bzr merge lp:~charlesk/indicator-location/gmenuify
Reviewer Review Type Date Requested Status
Ted Gould (community) Approve
PS Jenkins bot (community) continuous-integration Approve
Review via email: mp+182097@code.launchpad.net

Commit message

This implements the frontend of the location indicator.

Description of the change

This implements the frontend of the location indicator.

It contains unit tests that confirm that the service can get up and running on the bus, connect to the backend, and keep the UI and backend in sync with each other.

It has an interface class for two backends -- one for libubuntu-platform-api, and a simple Mock backend for unit tests.

NB: The default backend is currently the Mock backend because libubuntu-platform-api isn't ready yet. (FTBFS blockers: bug #1216473 and bug #1216483; even after those are resolved, the platform-api backend is itself only a stub).

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

temporarily remove the ubuntu-platform-api from debian/control. Our hooks for that code is stubbed out right now anyway pending the location service API landing there.

56. By Charles Kerr

add missing header files

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)
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)
57. By Charles Kerr

remove autoreconf from rules since we've gone from autotools -> cmake. Copy the rules from indicator-session

58. By Charles Kerr

add python and dh-translations to debian/control

Revision history for this message
PS Jenkins bot (ps-jenkins) wrote :
review: Needs Fixing (continuous-integration)
Revision history for this message
Charles Kerr (charlesk) wrote :

Jenkins, I can keep this up all day...

59. By Charles Kerr

fix copy/paste error introduced when copying 'rules' from indicator-session.

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 :

Oh, and please put the bug numbers blocking the platform API stuff as a
comment in the code.

Revision history for this message
Ted Gould (ted) wrote :

* Need to drop data/indicator-location.desktop

* I don't think that we need to update the icon cache, that's handled by
the dpkg hook as it needs to be refreshed on package install not source
install.

* Need to add phone.cc to po/POTFILES.in

* The build system doesn't seem to be building the internationalization
at all

* Surprised the compiler doesn't hate this, but should probably put a
"static" in the cc file for
on_location_service_controller_status_changed() just to make it clearer

* I think that in controller.cc you need to check to see if
on_gps_enabled_changed or on_location_service_enabled_changed is null as
it's possible a subclass would implment one and not both

* We probably should either use or remove the icons. I don't care which
way we go there :-)

* The accessible string "Location" should be translatable.

* If you're going to use C++ 11 would have liked to see more usage of
lambdas ;-)

* Showing the settings needs to use URL Dispatcher

  review needs-fixing

review: Needs Fixing
60. By Charles Kerr

remove data/indicator-location.desktop

61. By Charles Kerr

after installing icons, don't update the icon cache -- that's handled by the dpkg hook because it needs to be refreshed upon package install, not source install.

62. By Charles Kerr

update po/POTFILES.in

63. By Charles Kerr

mark the accessible string Loation translatable

64. By Charles Kerr

remove icons.

65. By Charles Kerr

copy gettext i18n cmake rules from lp:indicator-session

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

> * Need to drop data/indicator-location.desktop

Fixed r60

> * I don't think that we need to update the icon cache, that's handled by
> the dpkg hook as it needs to be refreshed on package install not source
> install.

Fixed r61

> * Need to add phone.cc to po/POTFILES.in

Fixed r62

> * The accessible string "Location" should be translatable.

Fixed r63

> * We probably should either use or remove the icons. I don't care which
> way we go there :-)

Removed r64. I was keeping them around in case we get a chance to bring the Desktop indicator-location back, but I guess they'll still be in the old branches when we need them.

> * The build system doesn't seem to be building the internationalization
> at all

Oog, that's ugly. Fixed r65.

> * Surprised the compiler doesn't hate this, but should probably put a
> "static" in the cc file for
> on_location_service_controller_status_changed() just to make it clearer

No, not in C++. That method's been declared static in the class declaration; using it in the .cc file has a meaning more like the one in C.

> * I think that in controller.cc you need to check to see if
> on_gps_enabled_changed or on_location_service_enabled_changed is null as
> it's possible a subclass would implement one and not both

No, not in C++. The compiler wouldn't allow the client to instantiate an object whose class still has pure virtual functions.

Revision history for this message
PS Jenkins bot (ps-jenkins) wrote :
review: Approve (continuous-integration)
66. By Charles Kerr

set version number to 13.10.0 in CMakeLists.txt and in debian/changelog

67. By Charles Kerr

change version in debian/changelog to 13.10.0-0ubuntu1

Revision history for this message
PS Jenkins bot (ps-jenkins) wrote :
review: Approve (continuous-integration)
68. By Charles Kerr

use url-dispatcher-1 for launching the settings paneL

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
1=== added file 'CMakeLists.txt'
2--- CMakeLists.txt 1970-01-01 00:00:00 +0000
3+++ CMakeLists.txt 2013-08-26 21:42:23 +0000
4@@ -0,0 +1,60 @@
5+project (indicator-location)
6+cmake_minimum_required (VERSION 2.8.9)
7+
8+list (APPEND CMAKE_MODULE_PATH ${CMAKE_SOURCE_DIR}/cmake)
9+
10+set (PROJECT_VERSION "13.10.0")
11+set (PACKAGE ${CMAKE_PROJECT_NAME})
12+set (GETTEXT_PACKAGE ${CMAKE_PROJECT_NAME})
13+
14+option (enable_tests "Build the package's automatic tests." ON)
15+option (enable_lcov "Generate lcov code coverage reports." ON)
16+
17+##
18+## GNU standard paths
19+##
20+include (GNUInstallDirs)
21+if (EXISTS "/etc/debian_version") # Workaround for libexecdir on debian
22+ set (CMAKE_INSTALL_LIBEXECDIR "${CMAKE_INSTALL_LIBDIR}")
23+ set (CMAKE_INSTALL_FULL_LIBEXECDIR "${CMAKE_INSTALL_FULL_LIBDIR}")
24+endif ()
25+set (CMAKE_INSTALL_PKGLIBEXECDIR "${CMAKE_INSTALL_LIBEXECDIR}/${CMAKE_PROJECT_NAME}")
26+set (CMAKE_INSTALL_FULL_PKGLIBEXECDIR "${CMAKE_INSTALL_FULL_LIBEXECDIR}/${CMAKE_PROJECT_NAME}")
27+
28+##
29+## Check for prerequisites
30+##
31+
32+find_package (PkgConfig REQUIRED)
33+
34+include (FindPkgConfig)
35+pkg_check_modules (SERVICE REQUIRED
36+ url-dispatcher-1
37+ gio-unix-2.0>=2.36
38+ glib-2.0>=2.36)
39+ #ubuntu-platform-api>=1.0.0
40+
41+##
42+##
43+##
44+
45+set (CMAKE_INCLUDE_CURRENT_DIR ON)
46+set (CC_WARNING_ARGS " -Wall -Wextra -Wno-missing-field-initializers")
47+
48+# testing & coverage
49+if (${enable_tests})
50+ set (GTEST_SOURCE_DIR /usr/src/gtest/src)
51+ set (GTEST_INCLUDE_DIR ${GTEST_SOURCE_DIR}/..)
52+ set (GTEST_LIBS -lpthread)
53+ enable_testing ()
54+ if (${enable_lcov})
55+ include(GCov)
56+ endif ()
57+endif ()
58+
59+add_subdirectory (src)
60+add_subdirectory (data)
61+add_subdirectory (po)
62+if (${enable_tests})
63+ add_subdirectory (tests)
64+endif ()
65
66=== added file 'INSTALL'
67--- INSTALL 1970-01-01 00:00:00 +0000
68+++ INSTALL 2013-08-26 21:42:23 +0000
69@@ -0,0 +1,69 @@
70+#
71+# Copyright (C) 2013 Canonical Ltd
72+#
73+# This program is free software: you can redistribute it and/or modify
74+# it under the terms of the GNU General Public License version 3 as
75+# published by the Free Software Foundation.
76+#
77+# This program is distributed in the hope that it will be useful,
78+# but WITHOUT ANY WARRANTY; without even the implied warranty of
79+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
80+# GNU General Public License for more details.
81+#
82+# You should have received a copy of the GNU General Public License
83+# along with this program. If not, see <http://www.gnu.org/licenses/>.
84+#
85+
86+Compile-time build dependencies
87+-------------------------------
88+ - gettext (gettext 0.18.1.1-10ubuntu3 or later)
89+ - glib (libglib2.0, 2.36 or later)
90+ - cmake (cmake, 2.8.9 or later)
91+ - gcovr (gcovr, 2.4 or later)
92+ - lcov (lcov, 1.9 or later)
93+ - google test (libgtest-dev, 1.6.0 or later)
94+ - ubuntu-platform-api (libubuntu-platform-api1)
95+
96+Building the code
97+-----------------
98+The simplest case is:
99+ $ cd indicator-location-X.Y.Z
100+ $ mkdir build
101+ $ cd build
102+ $ cmake ..
103+ $ make
104+
105+Running the tests
106+-----------------
107+ $ cd indicator-location-X.Y.Z
108+ $ mkdir build
109+ $ cd build
110+ $ cmake ..
111+ $ make
112+ $ make test
113+
114+Generating Test Coverage Reports
115+--------------------------------
116+ $ cd indicator-location-X.Y.Z
117+ $ mkdir build-coverage
118+ $ cd build-coverage
119+ $ cmake -DCMAKE_BUILD_TYPE=coverage ..
120+ $ make
121+ $ make coverage-html
122+
123+Installation
124+------------
125+ $ mkdir build
126+ $ cd build
127+ $ cmake -DCMAKE_INSTALL_PREFIX=/usr .. # Or wherever...
128+ $ make
129+ $ make release
130+ $ make install
131+
132+What Gets Installed
133+-------------------
134+ ${datadir}/dbus-1/indicator-location.service
135+ ${datadir}/unity/indicators/com.canonical.indicator.location
136+ ${libexecdir}/indicator-location/indicator-location-service
137+
138+
139
140=== removed file 'Makefile.am'
141--- Makefile.am 2012-08-02 11:54:15 +0000
142+++ Makefile.am 1970-01-01 00:00:00 +0000
143@@ -1,35 +0,0 @@
144-
145-SUBDIRS = \
146- src \
147- data \
148- po
149-
150-DISTCHECK_CONFIGURE_FLAGS = --enable-localinstall
151-
152-dist-hook:
153- @if test -d "$(top_srcdir)/.bzr"; \
154- then \
155- echo Creating ChangeLog && \
156- ( cd "$(top_srcdir)" && \
157- echo '# Generated by Makefile. Do not edit.'; echo; \
158- $(top_srcdir)/missing --run bzr log --gnu-changelog ) > ChangeLog.tmp \
159- && mv -f ChangeLog.tmp $(top_distdir)/ChangeLog \
160- || (rm -f ChangeLog.tmp; \
161- echo Failed to generate ChangeLog >&2 ); \
162- else \
163- echo Failed to generate ChangeLog: not a branch >&2; \
164- fi
165- @if test -d "$(top_srcdir)/.bzr"; \
166- then \
167- echo Creating AUTHORS && \
168- ( cd "$(top_srcdir)" && \
169- echo '# Generated by Makefile. Do not edit.'; echo; \
170- $(top_srcdir)/missing --run bzr log --long --levels=0 | grep -e "^\s*author:" -e "^\s*committer:" | cut -d ":" -f 2 | cut -d "<" -f 1 | sort -u) > AUTHORS.tmp \
171- && mv -f AUTHORS.tmp $(top_distdir)/AUTHORS \
172- || (rm -f AUTHORS.tmp; \
173- echo Failed to generate AUTHORS >&2 ); \
174- else \
175- echo Failed to generate AUTHORS: not a branch >&2; \
176- fi
177-
178-include $(top_srcdir)/Makefile.am.coverage
179
180=== removed file 'Makefile.am.coverage'
181--- Makefile.am.coverage 2012-08-02 11:43:45 +0000
182+++ Makefile.am.coverage 1970-01-01 00:00:00 +0000
183@@ -1,48 +0,0 @@
184-
185-# Coverage targets
186-
187-.PHONY: clean-gcno clean-gcda \
188- coverage-html generate-coverage-html clean-coverage-html \
189- coverage-gcovr generate-coverage-gcovr clean-coverage-gcovr
190-
191-clean-local: clean-gcno clean-coverage-html clean-coverage-gcovr
192-
193-if HAVE_GCOV
194-
195-clean-gcno:
196- @echo Removing old coverage instrumentation
197- -find -name '*.gcno' -print | xargs -r rm
198-
199-clean-gcda:
200- @echo Removing old coverage results
201- -find -name '*.gcda' -print | xargs -r rm
202-
203-coverage-html: clean-gcda
204- -$(MAKE) $(AM_MAKEFLAGS) -k check
205- $(MAKE) $(AM_MAKEFLAGS) generate-coverage-html
206-
207-generate-coverage-html:
208- @echo Collecting coverage data
209- $(LCOV) --directory $(top_builddir) --capture --output-file coverage.info --no-checksum --compat-libtool
210- LANG=C $(GENHTML) --prefix $(top_builddir) --output-directory coveragereport --title "Code Coverage" --legend --show-details coverage.info
211-
212-clean-coverage-html: clean-gcda
213- -$(LCOV) --directory $(top_builddir) -z
214- -rm -rf coverage.info coveragereport
215-
216-if HAVE_GCOVR
217-
218-coverage-gcovr: clean-gcda
219- -$(MAKE) $(AM_MAKEFLAGS) -k check
220- $(MAKE) $(AM_MAKEFLAGS) generate-coverage-gcovr
221-
222-generate-coverage-gcovr:
223- @echo Generating coverage GCOVR report
224- $(GCOVR) -x -r $(top_builddir) -o $(top_builddir)/coverage.xml
225-
226-clean-coverage-gcovr: clean-gcda
227- -rm -rf $(top_builddir)/coverage.xml
228-
229-endif # HAVE_GCOVR
230-
231-endif # HAVE_GCOV
232
233=== removed file 'autogen.sh'
234--- autogen.sh 2013-06-21 17:43:09 +0000
235+++ autogen.sh 1970-01-01 00:00:00 +0000
236@@ -1,4 +0,0 @@
237-#!/bin/sh -e
238-
239-autoreconf -i -f
240-intltoolize
241
242=== added directory 'cmake'
243=== added file 'cmake/GCov.cmake'
244--- cmake/GCov.cmake 1970-01-01 00:00:00 +0000
245+++ cmake/GCov.cmake 2013-08-26 21:42:23 +0000
246@@ -0,0 +1,53 @@
247+if (CMAKE_BUILD_TYPE MATCHES coverage)
248+ set(LCOV_RAW_FILE "lcov-raw.info")
249+ set(LCOV_FILE "lcov.info")
250+ set(GCOV_FLAGS "${GCOV_FLAGS} --coverage")
251+ set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} ${GCOV_FLAGS}")
252+ set(CMAKE_MODULE_LINKER_FLAGS "${CMAKE_MODULE_LINKER_FLAGS} ${GCOV_FLAGS}")
253+ set(CMAKE_SHARED_LINKER_FLAGS "${CMAKE_SHARED_LINKER_FLAGS} ${GCOV_FLAGS}")
254+ set(GCOV_LIBS ${GCOV_LIBS} gcov)
255+
256+ find_program(GCOVR_EXECUTABLE gcovr HINTS ${GCOVR_ROOT} "${GCOVR_ROOT}/bin")
257+ if (NOT GCOVR_EXECUTABLE)
258+ message(STATUS "Gcovr binary was not found, can not generate XML coverage info.")
259+ else ()
260+ message(STATUS "Gcovr found, can generate XML coverage info.")
261+ add_custom_target (coverage-xml
262+ WORKING_DIRECTORY ${CMAKE_BINARY_DIR}
263+ COMMAND "${GCOVR_EXECUTABLE}" --exclude="test.*" -x -r "${CMAKE_SOURCE_DIR}"
264+ --object-directory=${CMAKE_BINARY_DIR} -o coverage.xml)
265+ endif()
266+
267+ find_program(LCOV_EXECUTABLE lcov HINTS ${LCOV_ROOT} "${GCOVR_ROOT}/bin")
268+ find_program(GENHTML_EXECUTABLE genhtml HINTS ${GENHTML_ROOT})
269+ if (NOT LCOV_EXECUTABLE)
270+ message(STATUS "Lcov binary was not found, can not generate HTML coverage info.")
271+ else ()
272+ if(NOT GENHTML_EXECUTABLE)
273+ message(STATUS "Genthml binary not found, can not generate HTML coverage info.")
274+ else()
275+ message(STATUS "Lcov and genhtml found, can generate HTML coverage info.")
276+ add_custom_target (coverage-html
277+ WORKING_DIRECTORY ${CMAKE_BINARY_DIR}
278+ COMMAND "${CMAKE_CTEST_COMMAND}" --force-new-ctest-process --verbose
279+ # generate the raw lcov data
280+ COMMAND "${LCOV_EXECUTABLE}" --directory ${CMAKE_BINARY_DIR} --capture -o ${LCOV_RAW_FILE}
281+ # FIXME: when ubuntu gets lcov 1.10 we can use --no-external instead of the brittle --remove
282+ COMMAND "${LCOV_EXECUTABLE}" --remove ${LCOV_RAW_FILE} "/usr/include/*" | ${CMAKE_SOURCE_DIR}/trim-lcov.py > ${LCOV_FILE}
283+ COMMAND LANG=C "${GENHTML_EXECUTABLE}" --prefix ${CMAKE_BINARY_DIR} --output-directory lcov-html --legend --show-details ${LCOV_FILE}
284+ COMMAND ${CMAKE_COMMAND} -E echo ""
285+ COMMAND ${CMAKE_COMMAND} -E echo "file://${CMAKE_BINARY_DIR}/lcov-html/index.html"
286+ COMMAND ${CMAKE_COMMAND} -E echo ""
287+ VERBATIM) # VERBATIM is necessary here for the wildcard in --remove... again, when we go to lcov 1.10 we can drop this
288+ #)
289+ endif()
290+ endif()
291+endif()
292+
293+
294+ #$(MAKE) $(AM_MAKEFLAGS) check
295+ #lcov --directory $(top_builddir) --capture --test-name dconf | $(top_srcdir)/trim-lcov.py > dconf-lcov.info
296+ #LANG=C genhtml --prefix $(top_builddir) --output-directory lcov-html --legend --show-details dconf-lcov.info
297+ #@echo
298+ #@echo " file://$(abs_top_builddir)/lcov-html/index.html"
299+ #@echo
300
301=== added file 'cmake/Translations.cmake'
302--- cmake/Translations.cmake 1970-01-01 00:00:00 +0000
303+++ cmake/Translations.cmake 2013-08-26 21:42:23 +0000
304@@ -0,0 +1,41 @@
305+# Translations.cmake, CMake macros written for Marlin, feel free to re-use them
306+
307+macro(add_translations_directory NLS_PACKAGE)
308+ add_custom_target (i18n ALL)
309+ find_program (MSGFMT_EXECUTABLE msgfmt)
310+ file (GLOB PO_FILES ${CMAKE_CURRENT_SOURCE_DIR}/*.po)
311+ foreach (PO_INPUT ${PO_FILES})
312+ get_filename_component (PO_INPUT_BASE ${PO_INPUT} NAME_WE)
313+ set (MO_OUTPUT ${CMAKE_CURRENT_BINARY_DIR}/${PO_INPUT_BASE}.mo)
314+ add_custom_command (TARGET i18n COMMAND ${MSGFMT_EXECUTABLE} -o ${MO_OUTPUT} ${PO_INPUT})
315+
316+ install (FILES ${MO_OUTPUT} DESTINATION
317+ ${CMAKE_INSTALL_LOCALEDIR}/LC_MESSAGES
318+ RENAME ${NLS_PACKAGE}.mo)
319+ endforeach (PO_INPUT ${PO_FILES})
320+endmacro(add_translations_directory)
321+
322+
323+macro(add_translations_catalog NLS_PACKAGE)
324+ add_custom_target (pot COMMENT “Building translation catalog.”)
325+ find_program (XGETTEXT_EXECUTABLE xgettext)
326+
327+
328+ set(C_SOURCE "")
329+
330+ foreach(FILES_INPUT ${ARGN})
331+ file (GLOB_RECURSE SOURCE_FILES ${CMAKE_CURRENT_SOURCE_DIR}/${FILES_INPUT}/*.c)
332+ foreach(C_FILE ${SOURCE_FILES})
333+ set(C_SOURCE ${C_SOURCE} ${C_FILE})
334+ endforeach()
335+ file (GLOB_RECURSE SOURCE_FILES ${CMAKE_CURRENT_SOURCE_DIR}/${FILES_INPUT}/*.vala)
336+ foreach(C_FILE ${SOURCE_FILES})
337+ set(C_SOURCE ${C_SOURCE} ${C_FILE})
338+ endforeach()
339+ endforeach()
340+
341+ add_custom_command (TARGET pot COMMAND
342+ ${XGETTEXT_EXECUTABLE} -d ${NLS_PACKAGE} -o ${CMAKE_CURRENT_SOURCE_DIR}/${NLS_PACKAGE}.pot
343+ ${VALA_SOURCE} ${C_SOURCE} --keyword="_" --keyword="N_" --from-code=UTF-8
344+ )
345+endmacro()
346
347=== removed file 'configure.ac'
348--- configure.ac 2012-10-11 18:02:30 +0000
349+++ configure.ac 1970-01-01 00:00:00 +0000
350@@ -1,57 +0,0 @@
351-
352-AC_INIT(indicator-location, 0.0.4)
353-
354-AC_PREREQ(2.53)
355-AM_INIT_AUTOMAKE([])
356-
357-AC_PROG_CC
358-AC_PROG_INSTALL
359-AC_PROG_LIBTOOL
360-AM_PROG_CC_C_O
361-AM_SILENT_RULES([yes])
362-AC_CONFIG_MACRO_DIR([m4])
363-
364-IT_PROG_INTLTOOL([0.35.0])
365-GETTEXT_PACKAGE=indicator-location
366-AC_SUBST(GETTEXT_PACKAGE)
367-AC_DEFINE_UNQUOTED(GETTEXT_PACKAGE, "$GETTEXT_PACKAGE", [gettext package])
368-AM_GLIB_GNU_GETTEXT
369-
370-AC_CONFIG_HEADER(config.h)
371-AC_CONFIG_FILES([
372- Makefile
373- data/Makefile
374- src/Makefile
375- po/Makefile.in
376-])
377-
378-PKG_CHECK_MODULES(INDICATOR, glib-2.0
379- geoclue
380- appindicator3-0.1)
381-
382-###########################
383-# Local Install
384-###########################
385-
386-with_localinstall="no"
387-AC_ARG_ENABLE(localinstall, AS_HELP_STRING([--enable-localinstall],
388- [install all files locally (for distcheck)]),
389- with_localinstall=$enableval,
390- with_localinstall=no)
391-
392-###########################
393-# gcov coverage reporting
394-###########################
395-
396-m4_include([m4/gcov.m4])
397-AC_TDD_GCOV
398-AM_CONDITIONAL([HAVE_GCOV], [test "x$ac_cv_check_gcov" = xyes])
399-AM_CONDITIONAL([HAVE_LCOV], [test "x$ac_cv_check_lcov" = xyes])
400-AM_CONDITIONAL([HAVE_GCOVR], [test "x$ac_cv_check_gcovr" = xyes])
401-AC_SUBST(COVERAGE_CFLAGS)
402-AC_SUBST(COVERAGE_LDFLAGS)
403-
404-AC_SUBST(AM_CFLAGS, "-Wall -Werror")
405-
406-AC_OUTPUT
407-
408
409=== added file 'data/CMakeLists.txt'
410--- data/CMakeLists.txt 1970-01-01 00:00:00 +0000
411+++ data/CMakeLists.txt 2013-08-26 21:42:23 +0000
412@@ -0,0 +1,33 @@
413+##
414+## DBus Service File
415+##
416+
417+# where to install
418+set (DBUS_SERVICE_DIR "${CMAKE_INSTALL_FULL_DATADIR}/dbus-1/services")
419+message (STATUS "${DBUS_SERVICE_DIR} is the DBus Service File install dir")
420+
421+set (SERVICE_NAME "${CMAKE_PROJECT_NAME}.service")
422+set (SERVICE_FILE "${CMAKE_CURRENT_BINARY_DIR}/${SERVICE_NAME}")
423+set (SERVICE_FILE_IN "${CMAKE_CURRENT_SOURCE_DIR}/${SERVICE_NAME}.in")
424+
425+# build it
426+set (pkglibexecdir "${CMAKE_INSTALL_FULL_PKGLIBEXECDIR}")
427+configure_file ("${SERVICE_FILE_IN}" "${SERVICE_FILE}")
428+
429+# install it
430+install (FILES "${SERVICE_FILE}"
431+ DESTINATION "${DBUS_SERVICE_DIR}")
432+
433+##
434+## Unity Indicator File
435+##
436+
437+# where to install
438+set (UNITY_INDICATOR_DIR "${CMAKE_INSTALL_FULL_DATAROOTDIR}/unity/indicators")
439+message (STATUS "${UNITY_INDICATOR_DIR} is the Unity Indicator install dir")
440+
441+set (UNITY_INDICATOR_NAME "com.canonical.indicator.location")
442+set (UNITY_INDICATOR_FILE "${CMAKE_CURRENT_SOURCE_DIR}/${UNITY_INDICATOR_NAME}")
443+
444+install (FILES "${UNITY_INDICATOR_FILE}"
445+ DESTINATION "${UNITY_INDICATOR_DIR}")
446
447=== removed file 'data/Makefile.am'
448--- data/Makefile.am 2012-08-02 13:43:13 +0000
449+++ data/Makefile.am 1970-01-01 00:00:00 +0000
450@@ -1,14 +0,0 @@
451-
452-iconsdir = $(pkgdatadir)/icons/
453-icons_DATA = \
454- indicator-location-neighborhood.svg \
455- indicator-location-region.svg \
456- indicator-location-specific.svg \
457- indicator-location-unknown.svg
458-
459-autostartdir = $(sysconfdir)/xdg/autostart
460-autostart_DATA = indicator-location.desktop
461-
462-EXTRA_DIST = \
463- $(autostart_DATA) \
464- $(icons_DATA)
465
466=== added file 'data/com.canonical.indicator.location'
467--- data/com.canonical.indicator.location 1970-01-01 00:00:00 +0000
468+++ data/com.canonical.indicator.location 2013-08-26 21:42:23 +0000
469@@ -0,0 +1,8 @@
470+[Indicator Service]
471+Name=indicator-location
472+ObjectPath=/com/canonical/indicator/location
473+Position=90
474+
475+[phone]
476+ObjectPath=/com/canonical/indicator/location/phone
477+
478
479=== removed file 'data/indicator-location-neighborhood.svg'
480--- data/indicator-location-neighborhood.svg 2012-08-02 11:12:50 +0000
481+++ data/indicator-location-neighborhood.svg 1970-01-01 00:00:00 +0000
482@@ -1,106 +0,0 @@
483-<?xml version="1.0" encoding="UTF-8" standalone="no"?>
484-<!-- Created with Inkscape (http://www.inkscape.org/) -->
485-
486-<svg
487- xmlns:dc="http://purl.org/dc/elements/1.1/"
488- xmlns:cc="http://creativecommons.org/ns#"
489- xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
490- xmlns:svg="http://www.w3.org/2000/svg"
491- xmlns="http://www.w3.org/2000/svg"
492- xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
493- xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
494- width="16"
495- height="16"
496- id="svg2"
497- version="1.1"
498- inkscape:version="0.48.3.1 r9886"
499- sodipodi:docname="indicator-location-region.svg">
500- <defs
501- id="defs4" />
502- <sodipodi:namedview
503- id="base"
504- pagecolor="#ffffff"
505- bordercolor="#666666"
506- borderopacity="1.0"
507- inkscape:pageopacity="0.0"
508- inkscape:pageshadow="2"
509- inkscape:zoom="56.0625"
510- inkscape:cx="3.6222677"
511- inkscape:cy="8"
512- inkscape:document-units="px"
513- inkscape:current-layer="layer1"
514- showgrid="true"
515- inkscape:window-width="1680"
516- inkscape:window-height="1026"
517- inkscape:window-x="0"
518- inkscape:window-y="24"
519- inkscape:window-maximized="1">
520- <inkscape:grid
521- type="xygrid"
522- id="grid2985"
523- empspacing="5"
524- visible="true"
525- enabled="true"
526- snapvisiblegridlinesonly="true"
527- dotted="true" />
528- </sodipodi:namedview>
529- <metadata
530- id="metadata7">
531- <rdf:RDF>
532- <cc:Work
533- rdf:about="">
534- <dc:format>image/svg+xml</dc:format>
535- <dc:type
536- rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
537- <dc:title></dc:title>
538- </cc:Work>
539- </rdf:RDF>
540- </metadata>
541- <g
542- inkscape:label="Layer 1"
543- inkscape:groupmode="layer"
544- id="layer1"
545- transform="translate(0,-1036.3622)">
546- <path
547- sodipodi:type="arc"
548- style="color:#000000;fill:none;fill-opacity:1;fill-rule:nonzero;stroke:#dfdbd3;stroke-width:1.83333332;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
549- id="path2993"
550- sodipodi:cx="8"
551- sodipodi:cy="7"
552- sodipodi:rx="5"
553- sodipodi:ry="5"
554- d="M 13,7 C 13,9.7614237 10.761424,12 8,12 5.2385763,12 3,9.7614237 3,7 3,4.2385763 5.2385763,2 8,2 c 2.761424,0 5,2.2385763 5,5 z"
555- transform="matrix(1.0909091,0,0,1.0909091,-0.72727275,1036.7257)" />
556- <path
557- style="fill:none;stroke:#dfdbd3;stroke-width:2;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;stroke-miterlimit:4;stroke-dasharray:none;color:#000000;stroke-dashoffset:0;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
558- d="M 1,8 C 3,8 3,8 3,8"
559- id="path3763"
560- inkscape:connector-curvature="0"
561- transform="translate(0,1036.3622)" />
562- <path
563- style="fill:none;stroke:#dfdbd3;stroke-width:2;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none"
564- d="m 8,1037.3622 c 0,2 0,2 0,2"
565- id="path3763-7"
566- inkscape:connector-curvature="0" />
567- <path
568- style="fill:none;stroke:#dfdbd3;stroke-width:2;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;color:#000000;stroke-dashoffset:0;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
569- d="m 13,1044.3622 c 2,0 2,0 2,0"
570- id="path3763-0"
571- inkscape:connector-curvature="0" />
572- <path
573- style="fill:none;stroke:#dfdbd3;stroke-width:2;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;color:#000000;stroke-dashoffset:0;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
574- d="m 8,1049.3622 c 0,2 0,2 0,2"
575- id="path3763-7-0"
576- inkscape:connector-curvature="0" />
577- <path
578- sodipodi:type="arc"
579- style="color:#000000;fill:#dfdbd3;stroke:#dfdbd3;stroke-width:1.31250004999999992;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate;fill-opacity:1"
580- id="path3040"
581- sodipodi:cx="6.5"
582- sodipodi:cy="6.5"
583- sodipodi:rx="2.5"
584- sodipodi:ry="2.5"
585- d="m 9,6.5 a 2.5,2.5 0 1 1 -5,0 2.5,2.5 0 1 1 5,0 z"
586- transform="matrix(1.1428571,0,0,1.1428571,0.5714284,1036.9337)" />
587- </g>
588-</svg>
589
590=== removed file 'data/indicator-location-region.svg'
591--- data/indicator-location-region.svg 2012-08-02 11:12:50 +0000
592+++ data/indicator-location-region.svg 1970-01-01 00:00:00 +0000
593@@ -1,96 +0,0 @@
594-<?xml version="1.0" encoding="UTF-8" standalone="no"?>
595-<!-- Created with Inkscape (http://www.inkscape.org/) -->
596-
597-<svg
598- xmlns:dc="http://purl.org/dc/elements/1.1/"
599- xmlns:cc="http://creativecommons.org/ns#"
600- xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
601- xmlns:svg="http://www.w3.org/2000/svg"
602- xmlns="http://www.w3.org/2000/svg"
603- xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
604- xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
605- width="16"
606- height="16"
607- id="svg2"
608- version="1.1"
609- inkscape:version="0.48.3.1 r9886"
610- sodipodi:docname="indicator-location-region.svg">
611- <defs
612- id="defs4" />
613- <sodipodi:namedview
614- id="base"
615- pagecolor="#ffffff"
616- bordercolor="#666666"
617- borderopacity="1.0"
618- inkscape:pageopacity="0.0"
619- inkscape:pageshadow="2"
620- inkscape:zoom="56.0625"
621- inkscape:cx="6.788377"
622- inkscape:cy="8"
623- inkscape:document-units="px"
624- inkscape:current-layer="layer1"
625- showgrid="true"
626- inkscape:window-width="1680"
627- inkscape:window-height="1026"
628- inkscape:window-x="0"
629- inkscape:window-y="24"
630- inkscape:window-maximized="1">
631- <inkscape:grid
632- type="xygrid"
633- id="grid2985"
634- empspacing="5"
635- visible="true"
636- enabled="true"
637- snapvisiblegridlinesonly="true"
638- dotted="true" />
639- </sodipodi:namedview>
640- <metadata
641- id="metadata7">
642- <rdf:RDF>
643- <cc:Work
644- rdf:about="">
645- <dc:format>image/svg+xml</dc:format>
646- <dc:type
647- rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
648- <dc:title />
649- </cc:Work>
650- </rdf:RDF>
651- </metadata>
652- <g
653- inkscape:label="Layer 1"
654- inkscape:groupmode="layer"
655- id="layer1"
656- transform="translate(0,-1036.3622)">
657- <path
658- sodipodi:type="arc"
659- style="color:#000000;fill:none;fill-opacity:1;fill-rule:nonzero;stroke:#dfdbd3;stroke-width:1.83333332;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
660- id="path2993"
661- sodipodi:cx="8"
662- sodipodi:cy="7"
663- sodipodi:rx="5"
664- sodipodi:ry="5"
665- d="M 13,7 C 13,9.7614237 10.761424,12 8,12 5.2385763,12 3,9.7614237 3,7 3,4.2385763 5.2385763,2 8,2 c 2.761424,0 5,2.2385763 5,5 z"
666- transform="matrix(1.0909091,0,0,1.0909091,-0.72727275,1036.7257)" />
667- <path
668- style="fill:none;stroke:#dfdbd3;stroke-width:2;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;stroke-miterlimit:4;stroke-dasharray:none;color:#000000;stroke-dashoffset:0;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
669- d="M 1,8 C 3,8 3,8 3,8"
670- id="path3763"
671- inkscape:connector-curvature="0"
672- transform="translate(0,1036.3622)" />
673- <path
674- style="fill:none;stroke:#dfdbd3;stroke-width:2;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none"
675- d="m 8,1037.3622 c 0,2 0,2 0,2"
676- id="path3763-7"
677- inkscape:connector-curvature="0" />
678- <path
679- style="fill:none;stroke:#dfdbd3;stroke-width:2;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;color:#000000;stroke-dashoffset:0;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
680- d="m 13,1044.3622 c 2,0 2,0 2,0"
681- id="path3763-0"
682- inkscape:connector-curvature="0" />
683- <path
684- style="fill:none;stroke:#dfdbd3;stroke-width:2;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;color:#000000;stroke-dashoffset:0;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
685- d="m 8,1049.3622 c 0,2 0,2 0,2"
686- id="path3763-7-0"
687- inkscape:connector-curvature="0" />
688- </g>
689-</svg>
690
691=== removed file 'data/indicator-location-specific.svg'
692--- data/indicator-location-specific.svg 2012-08-02 11:12:50 +0000
693+++ data/indicator-location-specific.svg 1970-01-01 00:00:00 +0000
694@@ -1,116 +0,0 @@
695-<?xml version="1.0" encoding="UTF-8" standalone="no"?>
696-<!-- Created with Inkscape (http://www.inkscape.org/) -->
697-
698-<svg
699- xmlns:dc="http://purl.org/dc/elements/1.1/"
700- xmlns:cc="http://creativecommons.org/ns#"
701- xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
702- xmlns:svg="http://www.w3.org/2000/svg"
703- xmlns="http://www.w3.org/2000/svg"
704- xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
705- xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
706- width="16"
707- height="16"
708- id="svg2"
709- version="1.1"
710- inkscape:version="0.48.3.1 r9886"
711- sodipodi:docname="indicator-location-specific.svg">
712- <defs
713- id="defs4" />
714- <sodipodi:namedview
715- id="base"
716- pagecolor="#ffffff"
717- bordercolor="#666666"
718- borderopacity="1.0"
719- inkscape:pageopacity="0.0"
720- inkscape:pageshadow="2"
721- inkscape:zoom="32"
722- inkscape:cx="7.5"
723- inkscape:cy="7.7133869"
724- inkscape:document-units="px"
725- inkscape:current-layer="layer1"
726- showgrid="true"
727- inkscape:window-width="1680"
728- inkscape:window-height="1026"
729- inkscape:window-x="0"
730- inkscape:window-y="24"
731- inkscape:window-maximized="1">
732- <inkscape:grid
733- type="xygrid"
734- id="grid2985"
735- empspacing="5"
736- visible="true"
737- enabled="true"
738- snapvisiblegridlinesonly="true"
739- dotted="true" />
740- </sodipodi:namedview>
741- <metadata
742- id="metadata7">
743- <rdf:RDF>
744- <cc:Work
745- rdf:about="">
746- <dc:format>image/svg+xml</dc:format>
747- <dc:type
748- rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
749- <dc:title />
750- </cc:Work>
751- </rdf:RDF>
752- </metadata>
753- <g
754- inkscape:label="Layer 1"
755- inkscape:groupmode="layer"
756- id="layer1"
757- transform="translate(0,-1036.3622)">
758- <path
759- sodipodi:type="arc"
760- style="color:#000000;fill:none;fill-opacity:1;fill-rule:nonzero;stroke:#dfdbd3;stroke-width:1.83333332;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
761- id="path2993"
762- sodipodi:cx="8"
763- sodipodi:cy="7"
764- sodipodi:rx="5"
765- sodipodi:ry="5"
766- d="M 13,7 C 13,9.7614237 10.761424,12 8,12 5.2385763,12 3,9.7614237 3,7 3,4.2385763 5.2385763,2 8,2 c 2.761424,0 5,2.2385763 5,5 z"
767- transform="matrix(1.0909091,0,0,1.0909091,-0.72727275,1036.7257)" />
768- <path
769- style="fill:none;stroke:#dfdbd3;stroke-width:2;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;stroke-miterlimit:4;stroke-dasharray:none;color:#000000;stroke-dashoffset:0;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
770- d="M 1,8 C 3,8 3,8 3,8"
771- id="path3763"
772- inkscape:connector-curvature="0"
773- transform="translate(0,1036.3622)" />
774- <path
775- style="fill:none;stroke:#dfdbd3;stroke-width:2;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none"
776- d="m 8,1037.3622 c 0,2 0,2 0,2"
777- id="path3763-7"
778- inkscape:connector-curvature="0" />
779- <path
780- style="fill:none;stroke:#dfdbd3;stroke-width:2;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;color:#000000;stroke-dashoffset:0;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
781- d="m 13,1044.3622 c 2,0 2,0 2,0"
782- id="path3763-0"
783- inkscape:connector-curvature="0" />
784- <path
785- style="fill:none;stroke:#dfdbd3;stroke-width:2;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;color:#000000;stroke-dashoffset:0;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
786- d="m 8,1049.3622 c 0,2 0,2 0,2"
787- id="path3763-7-0"
788- inkscape:connector-curvature="0" />
789- <path
790- sodipodi:type="arc"
791- style="color:#000000;fill:none;stroke:#dfdbd3;stroke-width:0.87500003;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate;fill-opacity:1"
792- id="path3040"
793- sodipodi:cx="6.5"
794- sodipodi:cy="6.5"
795- sodipodi:rx="2.5"
796- sodipodi:ry="2.5"
797- d="m 9,6.5 a 2.5,2.5 0 1 1 -5,0 2.5,2.5 0 1 1 5,0 z"
798- transform="matrix(1.1428571,0,0,1.1428571,0.5714284,1036.9337)" />
799- <path
800- sodipodi:type="arc"
801- style="color:#000000;fill:#dfdbd3;fill-opacity:1;stroke:#dfdbd3;stroke-width:1.3125;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
802- id="path3040-3"
803- sodipodi:cx="6.5"
804- sodipodi:cy="6.5"
805- sodipodi:rx="2.5"
806- sodipodi:ry="2.5"
807- d="m 9,6.5 a 2.5,2.5 0 1 1 -5,0 2.5,2.5 0 1 1 5,0 z"
808- transform="matrix(0.47524752,0,0,0.47524752,4.9108911,1041.2731)" />
809- </g>
810-</svg>
811
812=== removed file 'data/indicator-location-unknown.svg'
813--- data/indicator-location-unknown.svg 2012-08-02 14:08:13 +0000
814+++ data/indicator-location-unknown.svg 1970-01-01 00:00:00 +0000
815@@ -1,106 +0,0 @@
816-<?xml version="1.0" encoding="UTF-8" standalone="no"?>
817-<!-- Created with Inkscape (http://www.inkscape.org/) -->
818-
819-<svg
820- xmlns:dc="http://purl.org/dc/elements/1.1/"
821- xmlns:cc="http://creativecommons.org/ns#"
822- xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
823- xmlns:svg="http://www.w3.org/2000/svg"
824- xmlns="http://www.w3.org/2000/svg"
825- xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
826- xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
827- width="16"
828- height="16"
829- id="svg2"
830- version="1.1"
831- inkscape:version="0.48.3.1 r9886"
832- sodipodi:docname="indicator-location-unknown.svg">
833- <defs
834- id="defs4" />
835- <sodipodi:namedview
836- id="base"
837- pagecolor="#ffffff"
838- bordercolor="#666666"
839- borderopacity="1.0"
840- inkscape:pageopacity="0.0"
841- inkscape:pageshadow="2"
842- inkscape:zoom="32"
843- inkscape:cx="6.0949687"
844- inkscape:cy="6.8368806"
845- inkscape:document-units="px"
846- inkscape:current-layer="layer1"
847- showgrid="true"
848- inkscape:window-width="1680"
849- inkscape:window-height="1026"
850- inkscape:window-x="0"
851- inkscape:window-y="24"
852- inkscape:window-maximized="1">
853- <inkscape:grid
854- type="xygrid"
855- id="grid2985"
856- empspacing="5"
857- visible="true"
858- enabled="true"
859- snapvisiblegridlinesonly="true"
860- dotted="true" />
861- </sodipodi:namedview>
862- <metadata
863- id="metadata7">
864- <rdf:RDF>
865- <cc:Work
866- rdf:about="">
867- <dc:format>image/svg+xml</dc:format>
868- <dc:type
869- rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
870- <dc:title />
871- </cc:Work>
872- </rdf:RDF>
873- </metadata>
874- <g
875- inkscape:label="Layer 1"
876- inkscape:groupmode="layer"
877- id="layer1"
878- transform="translate(0,-1036.3622)">
879- <path
880- sodipodi:type="arc"
881- style="color:#000000;fill:none;fill-opacity:1;fill-rule:nonzero;stroke:#dfdbd3;stroke-width:1.83333332;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
882- id="path2993"
883- sodipodi:cx="8"
884- sodipodi:cy="7"
885- sodipodi:rx="5"
886- sodipodi:ry="5"
887- d="M 13,7 C 13,9.7614237 10.761424,12 8,12 5.2385763,12 3,9.7614237 3,7 3,4.2385763 5.2385763,2 8,2 c 2.761424,0 5,2.2385763 5,5 z"
888- transform="matrix(1.0909091,0,0,1.0909091,-0.72727275,1036.7257)" />
889- <path
890- style="fill:none;stroke:#dfdbd3;stroke-width:2;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;stroke-miterlimit:4;stroke-dasharray:none;color:#000000;stroke-dashoffset:0;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
891- d="M 1,8 C 3,8 3,8 3,8"
892- id="path3763"
893- inkscape:connector-curvature="0"
894- transform="translate(0,1036.3622)" />
895- <path
896- style="fill:none;stroke:#dfdbd3;stroke-width:2;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none"
897- d="m 8,1037.3622 c 0,2 0,2 0,2"
898- id="path3763-7"
899- inkscape:connector-curvature="0" />
900- <path
901- style="fill:none;stroke:#dfdbd3;stroke-width:2;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;color:#000000;stroke-dashoffset:0;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
902- d="m 13,1044.3622 c 2,0 2,0 2,0"
903- id="path3763-0"
904- inkscape:connector-curvature="0" />
905- <path
906- style="fill:none;stroke:#000000;stroke-width:2;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none"
907- d="m 8,1049.3622 c 0,2 0,2 0,2"
908- id="path3763-7-0"
909- inkscape:connector-curvature="0" />
910- <path
911- inkscape:connector-curvature="0"
912- id="path2992"
913- style="font-size:8.69258404px;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;text-align:start;line-height:100%;letter-spacing:0px;word-spacing:0px;writing-mode:lr-tb;text-anchor:start;fill:#dfdbd3;fill-opacity:1;stroke:none;font-family:Ubuntu;-inkscape-font-specification:Ubuntu"
914- d="m 7.9644153,1041.8324 c -0.3824748,0 -0.7562555,0.099 -1.1213433,0.2955 l -0.2260072,-0.6259 c 0.1970316,-0.1043 0.4172435,-0.1883 0.6606364,-0.252 0.2491863,-0.064 0.5128611,-0.096 0.7910252,-0.096 0.3303162,0 0.599786,0.046 0.8084103,0.1391 0.2144144,0.087 0.3853684,0.2 0.5128624,0.339 0.1274882,0.1391 0.214414,0.2956 0.2607776,0.4694 0.052152,0.1681 0.07823,0.3304 0.078233,0.4868 -3.3e-6,0.1971 -0.037671,0.3738 -0.1130036,0.5303 -0.075339,0.1506 -0.1680596,0.2926 -0.2781627,0.4259 -0.1101088,0.1333 -0.2318049,0.2608 -0.3650885,0.3825 -0.1332887,0.1217 -0.2549847,0.2492 -0.3650885,0.3824 -0.1101081,0.1275 -0.2028289,0.2695 -0.2781627,0.426 -0.075338,0.1507 -0.1130054,0.3216 -0.1130036,0.5128 -1.8e-6,0.029 -1.8e-6,0.061 0,0.096 -1.8e-6,0.035 0.0029,0.067 0.00869,0.096 l -0.6780216,0 c -0.023181,-0.1159 -0.034771,-0.2376 -0.03477,-0.3651 -1.1e-6,-0.1854 0.031872,-0.3535 0.095618,-0.5042 0.06954,-0.1506 0.1564652,-0.2897 0.2607775,-0.4172 0.1043095,-0.1333 0.2144155,-0.255 0.3303182,-0.3651 0.1158993,-0.1159 0.2260052,-0.2318 0.3303182,-0.3477 0.1043088,-0.1159 0.1883371,-0.2376 0.2520849,-0.3651 0.069538,-0.1275 0.1043086,-0.2666 0.1043111,-0.4172 -2.5e-6,-0.2434 -0.078236,-0.4405 -0.2346998,-0.5911 -0.1564686,-0.1565 -0.3853731,-0.2347 -0.6867142,-0.2347 m 0.5476328,5.0156 c -2e-6,0.1565 -0.052157,0.2926 -0.1564665,0.4085 -0.1043128,0.1159 -0.2462915,0.1739 -0.4259366,0.1739 -0.179648,0 -0.3216268,-0.058 -0.4259366,-0.1739 -0.104312,-0.1159 -0.1564674,-0.252 -0.1564665,-0.4085 -9e-7,-0.1565 0.052154,-0.2927 0.1564665,-0.4086 0.1043098,-0.1159 0.2462886,-0.1738 0.4259366,-0.1738 0.1796451,0 0.3216238,0.058 0.4259366,0.1738 0.104309,0.1159 0.1564645,0.2521 0.1564665,0.4086" />
915- <path
916- style="fill:none;stroke:#dfdbd3;stroke-width:2;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none"
917- d="m 8,1049.3622 c 0,2 0,2 0,2"
918- id="path3763-7-9"
919- inkscape:connector-curvature="0" />
920- </g>
921-</svg>
922
923=== removed file 'data/indicator-location.desktop'
924--- data/indicator-location.desktop 2012-08-02 13:43:13 +0000
925+++ data/indicator-location.desktop 1970-01-01 00:00:00 +0000
926@@ -1,9 +0,0 @@
927-[Desktop Entry]
928-Name=Indicator Location
929-Comment=Show the accuracy of your location in the menubar
930-Icon=indicator-location-neighborhood
931-Exec=indicator-location
932-Terminal=false
933-Type=Application
934-NoDisplay=true
935-X-GNOME-Autostart-enabled=true
936
937=== added file 'data/indicator-location.service.in'
938--- data/indicator-location.service.in 1970-01-01 00:00:00 +0000
939+++ data/indicator-location.service.in 2013-08-26 21:42:23 +0000
940@@ -0,0 +1,3 @@
941+[D-BUS Service]
942+Name=com.canonical.indicator.location
943+Exec=@pkglibexecdir@/indicator-location-service
944
945=== modified file 'debian/changelog'
946--- debian/changelog 2013-07-19 13:10:54 +0000
947+++ debian/changelog 2013-08-26 21:42:23 +0000
948@@ -1,3 +1,11 @@
949+indicator-location (13.10.0-0ubuntu1) UNRELEASED; urgency=low
950+
951+ [ Charles Kerr]
952+ * Implement the phone's location indicator
953+ * Switch build system from autotools to cmake
954+
955+ -- Charles Kerr <charles.kerr@canonical.com> Mon, 26 Aug 2013 16:07:44 -0500
956+
957 indicator-location (0.0.4+13.10.20130719-0ubuntu1) saucy; urgency=low
958
959 [ Ken VanDine ]
960
961=== modified file 'debian/control'
962--- debian/control 2013-06-26 18:35:13 +0000
963+++ debian/control 2013-08-26 21:42:23 +0000
964@@ -1,14 +1,16 @@
965 Source: indicator-location
966 Section: misc
967 Priority: optional
968-Maintainer: Ted Gould <ted@ubuntu.com>
969-Build-Depends: debhelper (>= 9),
970- dh-autoreconf,
971+Maintainer: Charles Kerr <charles.kerr@canonical.com>
972+Build-Depends: cmake,
973+ dbus,
974+ debhelper (>= 9),
975+ dh-translations,
976 intltool (>= 0.35.0),
977- libappindicator3-dev,
978- libgeoclue-dev,
979- libglib2.0-dev (>= 2.29.19),
980- libgtk-3-dev,
981+ libglib2.0-dev (>= 2.36),
982+ libgtest-dev,
983+ liburl-dispatcher1-dev,
984+ python,
985 Standards-Version: 3.9.4
986 Homepage: http://launchpad.net/indicator-location/
987 # If you aren't a member of ~indicator-applet-developers but need to upload
988@@ -20,8 +22,6 @@
989 Architecture: any
990 Depends: ${shlibs:Depends},
991 ${misc:Depends},
992-Recommends: emerillon,
993- geoclue-ubuntu-geoip,
994-Description: Indicator to show the state of GeoClue
995- An indicator that gives you data about your location
996- and if the computer knows it.
997+Description: Indicator to show when the system is using your
998+ physical location data and allow the user to toggle
999+ permissions on its use.
1000
1001=== modified file 'debian/rules'
1002--- debian/rules 2013-07-19 06:18:34 +0000
1003+++ debian/rules 2013-08-26 21:42:23 +0000
1004@@ -1,10 +1,16 @@
1005 #!/usr/bin/make -f
1006-# -*- makefile -*-
1007-# Uncomment this to turn on verbose mode.
1008-#export DH_VERBOSE=1
1009
1010-override_dh_autoreconf:
1011- NOCONFIGURE=1 dh_autoreconf ./autogen.sh
1012+export DPKG_GENSYMBOLS_CHECK_LEVEL=4
1013
1014 %:
1015- dh $@ --with autoreconf --fail-missing
1016+ dh $@ --with translations
1017+
1018+override_dh_install:
1019+ find debian/indicator-location/usr/lib -name *.la -delete
1020+ find debian/indicator-location/usr/lib -name *.a -delete
1021+ dh_install --fail-missing
1022+
1023+# Hack as it seems it's not possible to easy run that under dbus-test-runner
1024+override_dh_auto_test:
1025+ env -u LD_PRELOAD dh_auto_test
1026+
1027
1028=== removed directory 'm4'
1029=== removed file 'm4/gcov.m4'
1030--- m4/gcov.m4 2012-08-02 11:43:45 +0000
1031+++ m4/gcov.m4 1970-01-01 00:00:00 +0000
1032@@ -1,86 +0,0 @@
1033-# Checks for existence of coverage tools:
1034-# * gcov
1035-# * lcov
1036-# * genhtml
1037-# * gcovr
1038-#
1039-# Sets ac_cv_check_gcov to yes if tooling is present
1040-# and reports the executables to the variables LCOV, GCOVR and GENHTML.
1041-AC_DEFUN([AC_TDD_GCOV],
1042-[
1043- AC_ARG_ENABLE(gcov,
1044- AS_HELP_STRING([--enable-gcov],
1045- [enable coverage testing with gcov]),
1046- [use_gcov=$enableval], [use_gcov=no])
1047-
1048- if test "x$use_gcov" = "xyes"; then
1049- # we need gcc:
1050- if test "$GCC" != "yes"; then
1051- AC_MSG_ERROR([GCC is required for --enable-gcov])
1052- fi
1053-
1054- # Check if ccache is being used
1055- AC_CHECK_PROG(SHTOOL, shtool, shtool)
1056- case `$SHTOOL path $CC` in
1057- *ccache*[)] gcc_ccache=yes;;
1058- *[)] gcc_ccache=no;;
1059- esac
1060-
1061- if test "$gcc_ccache" = "yes" && (test -z "$CCACHE_DISABLE" || test "$CCACHE_DISABLE" != "1"); then
1062- AC_MSG_ERROR([ccache must be disabled when --enable-gcov option is used. You can disable ccache by setting environment variable CCACHE_DISABLE=1.])
1063- fi
1064-
1065- lcov_version_list="1.6 1.7 1.8 1.9"
1066- AC_CHECK_PROG(LCOV, lcov, lcov)
1067- AC_CHECK_PROG(GENHTML, genhtml, genhtml)
1068-
1069- if test "$LCOV"; then
1070- AC_CACHE_CHECK([for lcov version], glib_cv_lcov_version, [
1071- glib_cv_lcov_version=invalid
1072- lcov_version=`$LCOV -v 2>/dev/null | $SED -e 's/^.* //'`
1073- for lcov_check_version in $lcov_version_list; do
1074- if test "$lcov_version" = "$lcov_check_version"; then
1075- glib_cv_lcov_version="$lcov_check_version (ok)"
1076- fi
1077- done
1078- ])
1079- else
1080- lcov_msg="To enable code coverage reporting you must have one of the following lcov versions installed: $lcov_version_list"
1081- AC_MSG_ERROR([$lcov_msg])
1082- fi
1083-
1084- case $glib_cv_lcov_version in
1085- ""|invalid[)]
1086- lcov_msg="You must have one of the following versions of lcov: $lcov_version_list (found: $lcov_version)."
1087- AC_MSG_ERROR([$lcov_msg])
1088- LCOV="exit 0;"
1089- ;;
1090- esac
1091-
1092- if test -z "$GENHTML"; then
1093- AC_MSG_ERROR([Could not find genhtml from the lcov package])
1094- fi
1095-
1096- ac_cv_check_gcov=yes
1097- ac_cv_check_lcov=yes
1098-
1099- # Remove all optimization flags from CFLAGS
1100- changequote({,})
1101- CFLAGS=`echo "$CFLAGS" | $SED -e 's/-O[0-9]*//g'`
1102- changequote([,])
1103-
1104- # Add the special gcc flags
1105- COVERAGE_CFLAGS="-O0 -fprofile-arcs -ftest-coverage"
1106- COVERAGE_CXXFLAGS="-O0 -fprofile-arcs -ftest-coverage"
1107- COVERAGE_LDFLAGS="-lgcov"
1108-
1109- # Check availability of gcovr
1110- AC_CHECK_PROG(GCOVR, gcovr, gcovr)
1111- if test -z "$GCOVR"; then
1112- ac_cv_check_gcovr=no
1113- else
1114- ac_cv_check_gcovr=yes
1115- fi
1116-
1117-fi
1118-]) # AC_TDD_GCOV
1119
1120=== added file 'po/CMakeLists.txt'
1121--- po/CMakeLists.txt 1970-01-01 00:00:00 +0000
1122+++ po/CMakeLists.txt 2013-08-26 21:42:23 +0000
1123@@ -0,0 +1,3 @@
1124+include (Translations)
1125+add_translations_directory ("${GETTEXT_PACKAGE}")
1126+add_translations_catalog ("${GETTEXT_PACKAGE}" ../src/)
1127
1128=== modified file 'po/POTFILES.in'
1129--- po/POTFILES.in 2012-08-02 12:19:46 +0000
1130+++ po/POTFILES.in 2013-08-26 21:42:23 +0000
1131@@ -1,1 +1,1 @@
1132-src/indicator-location.c
1133+src/phone.cc
1134
1135=== added file 'src/CMakeLists.txt'
1136--- src/CMakeLists.txt 1970-01-01 00:00:00 +0000
1137+++ src/CMakeLists.txt 2013-08-26 21:42:23 +0000
1138@@ -0,0 +1,45 @@
1139+
1140+set_property (DIRECTORY
1141+ APPEND PROPERTY INCLUDE_DIRECTORIES ${SERVICE_INCLUDE_DIRS})
1142+
1143+set_property (DIRECTORY
1144+ APPEND PROPERTY LINK_DIRECTORIES ${SERVICE_INCLUDE_DIRS})
1145+
1146+
1147+###
1148+### The library.
1149+### this doesn't get installed anywhere;
1150+### it's built apart from main() as a convenience for tests/
1151+###
1152+
1153+set (INDICATOR_LIB "libindicator-location-service")
1154+
1155+add_library (${INDICATOR_LIB} STATIC controller.cc phone.cc service.cc)
1156+
1157+set_property (TARGET ${INDICATOR_LIB}
1158+ APPEND PROPERTY LINK_LIBRARIES ${INDICATOR_LIB} ${SERVICE_LIBRARIES} ${GCOV_LIBS})
1159+
1160+
1161+###
1162+### The service execuable.
1163+###
1164+
1165+set (INDICATOR_EXEC "indicator-location-service")
1166+
1167+add_executable (${INDICATOR_EXEC} main.cc)
1168+
1169+set_property (SOURCE main.cc
1170+ APPEND PROPERTY COMPILE_DEFINITIONS
1171+ GETTEXT_PACKAGE="${GETTEXT_PACKAGE}"
1172+ GNOMELOCALEDIR="@CMAKE_INSTALL_FULL_LOCALEDIR@")
1173+
1174+target_link_libraries (${INDICATOR_EXEC} libindicator-location-service)
1175+
1176+install (TARGETS ${INDICATOR_EXEC}
1177+ RUNTIME DESTINATION ${CMAKE_INSTALL_FULL_PKGLIBEXECDIR})
1178+
1179+
1180+
1181+set_property (TARGET ${INDICATOR_LIB} ${INDICATOR_EXEC}
1182+ APPEND_STRING PROPERTY COMPILE_FLAGS " ${CC_WARNING_ARGS} ${GCOV_FLAGS} --std=c++11")
1183+
1184
1185=== removed file 'src/Makefile.am'
1186--- src/Makefile.am 2013-04-26 22:52:44 +0000
1187+++ src/Makefile.am 1970-01-01 00:00:00 +0000
1188@@ -1,17 +0,0 @@
1189-
1190-bin_PROGRAMS = \
1191- indicator-location
1192-
1193-indicator_location_SOURCES = \
1194- indicator-location.c
1195-
1196-indicator_location_CFLAGS = \
1197- $(INDICATOR_CFLAGS) \
1198- $(COVERAGE_CFLAGS) \
1199- -DICON_DIR="\"$(pkgdatadir)/icons/\""
1200-
1201-indicator_location_LDFLAGS = \
1202- $(COVERAGE_LDFLAGS)
1203-
1204-indicator_location_LDADD = \
1205- $(INDICATOR_LIBS)
1206
1207=== added file 'src/controller-mock.h'
1208--- src/controller-mock.h 1970-01-01 00:00:00 +0000
1209+++ src/controller-mock.h 2013-08-26 21:42:23 +0000
1210@@ -0,0 +1,48 @@
1211+/*
1212+ * Copyright 2013 Canonical Ltd.
1213+ *
1214+ * This program is free software; you can redistribute it and/or modify
1215+ * it under the terms of the GNU General Public License as published by
1216+ * the Free Software Foundation; version 3.
1217+ *
1218+ * This program is distributed in the hope that it will be useful,
1219+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
1220+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
1221+ * GNU Lesser General Public License for more details.
1222+ *
1223+ * You should have received a copy of the GNU Lesser General Public License
1224+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
1225+ *
1226+ * Authors:
1227+ * Charles Kerr <charles.kerr@canonical.com>
1228+ */
1229+
1230+#ifndef __INDICATOR_LOCATION_CONTROLLER_MOCK__H__
1231+#define __INDICATOR_LOCATION_CONTROLLER_MOCK__H__
1232+
1233+#include "controller.h"
1234+
1235+class MockController: public Controller
1236+{
1237+ public:
1238+
1239+ MockController (): valid(true), gps(false), loc(false) { }
1240+ virtual ~MockController() { }
1241+
1242+ bool is_valid () const { return valid; }
1243+ bool is_gps_enabled () const { return gps; }
1244+ bool is_location_service_enabled () const { return loc; }
1245+
1246+ void set_gps_enabled (bool enabled) { notify_gps_enabled (gps=enabled); }
1247+ void set_location_service_enabled (bool enabled) { notify_location_service_enabled (loc=enabled); }
1248+
1249+ private:
1250+
1251+ bool valid;
1252+ bool gps;
1253+ bool loc;
1254+};
1255+
1256+#endif // __INDICATOR_LOCATION_CONTROLLER_MOCK__H__
1257+
1258+
1259
1260=== added file 'src/controller-ualc.cc'
1261--- src/controller-ualc.cc 1970-01-01 00:00:00 +0000
1262+++ src/controller-ualc.cc 2013-08-26 21:42:23 +0000
1263@@ -0,0 +1,106 @@
1264+
1265+/*
1266+ * Copyright 2013 Canonical Ltd.
1267+ *
1268+ * This program is free software; you can redistribute it and/or modify
1269+ * it under the terms of the GNU General Public License as published by
1270+ * the Free Software Foundation; version 3.
1271+ *
1272+ * This program is distributed in the hope that it will be useful,
1273+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
1274+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
1275+ * GNU Lesser General Public License for more details.
1276+ *
1277+ * You should have received a copy of the GNU Lesser General Public License
1278+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
1279+ *
1280+ * Authors:
1281+ * Charles Kerr <charles.kerr@canonical.com>
1282+ */
1283+
1284+#include <iostream>
1285+
1286+#include "controller-ualc.h"
1287+
1288+UbuntuAppLocController :: UbuntuAppLocController ():
1289+ ualc (ua_location_service_create_controller ())
1290+{
1291+ if (ualc)
1292+ {
1293+ ua_location_service_controller_set_status_changed_handler (
1294+ ualc,
1295+ on_location_service_controller_status_changed,
1296+ this);
1297+ }
1298+}
1299+
1300+UbuntuAppLocController :: ~UbuntuAppLocController ()
1301+{
1302+ if (ualc)
1303+ ua_location_service_controller_unref (ualc);
1304+}
1305+
1306+void
1307+UbuntuAppLocController :: on_location_service_controller_status_changed (
1308+ UALocationServiceStatusFlags f,
1309+ void * vself)
1310+{
1311+ auto self = static_cast<UbuntuAppLocController*>(vself);
1312+
1313+ if (f & (UA_LOCATION_SERVICE_ENABLED | UA_LOCATION_SERVICE_DISABLED))
1314+ self->notify_gps_enabled (self->is_location_service_enabled ());
1315+
1316+ if (f & (UA_LOCATION_SERVICE_GPS_ENABLED | UA_LOCATION_SERVICE_GPS_DISABLED))
1317+ self->notify_gps_enabled (self->is_gps_enabled());
1318+}
1319+
1320+/***
1321+****
1322+***/
1323+
1324+bool
1325+UbuntuAppLocController :: is_gps_enabled () const
1326+{
1327+ UALocationServiceStatusFlags flags = 0;
1328+
1329+ return (ualc != nullptr)
1330+ && (!ua_location_service_controller_query_status (ualc, &flags))
1331+ && (flags & UA_LOCATION_SERVICE_GPS_ENABLED);
1332+}
1333+
1334+void
1335+UbuntuAppLocController :: set_gps_enabled (bool enabled)
1336+{
1337+ UStatus status = enabled
1338+ ? ua_location_service_controller_enable_gps (ualc)
1339+ : ua_location_service_controller_disable_gps (ualc);
1340+
1341+ if (status != U_STATUS_SUCCESS)
1342+ std::cerr << "Error turning GPS " << (enabled?"on":"off") << std::endl;
1343+}
1344+
1345+/***
1346+****
1347+***/
1348+
1349+bool
1350+UbuntuAppLocController :: is_location_service_enabled () const
1351+{
1352+ UALocationServiceStatusFlags flags = 0;
1353+
1354+ return (ualc != nullptr)
1355+ && (!ua_location_service_controller_query_status (ualc, &flags))
1356+ && (flags & UA_LOCATION_SERVICE_ENABLED);
1357+}
1358+
1359+void
1360+UbuntuAppLocController :: set_location_service_enabled (bool enabled)
1361+{
1362+ UStatus status = enabled
1363+ ? ua_location_service_controller_enable_service (ualc)
1364+ : ua_location_service_controller_disable_service (ualc);
1365+
1366+ if (status != U_STATUS_SUCCESS)
1367+ std::cerr << "Error turning Location Service " << (enabled?"on":"off")
1368+ << std::endl;
1369+}
1370
1371=== added file 'src/controller-ualc.h'
1372--- src/controller-ualc.h 1970-01-01 00:00:00 +0000
1373+++ src/controller-ualc.h 2013-08-26 21:42:23 +0000
1374@@ -0,0 +1,53 @@
1375+/*
1376+ * Copyright 2013 Canonical Ltd.
1377+ *
1378+ * This program is free software; you can redistribute it and/or modify
1379+ * it under the terms of the GNU General Public License as published by
1380+ * the Free Software Foundation; version 3.
1381+ *
1382+ * This program is distributed in the hope that it will be useful,
1383+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
1384+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
1385+ * GNU Lesser General Public License for more details.
1386+ *
1387+ * You should have received a copy of the GNU Lesser General Public License
1388+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
1389+ *
1390+ * Authors:
1391+ * Charles Kerr <charles.kerr@canonical.com>
1392+ */
1393+
1394+#ifndef __INDICATOR_LOCATION_CONTROLLER_UALC__H__
1395+#define __INDICATOR_LOCATION_CONTROLLER_UALC__H__
1396+
1397+#include <ubuntu/status.h>
1398+#include <ubuntu/application/location/controller.h>
1399+#include <ubuntu/application/location/service.h>
1400+
1401+#include "controller.h"
1402+
1403+class UbuntuAppLocController: public Controller
1404+{
1405+ public:
1406+
1407+ UbuntuAppLocController ();
1408+ virtual ~UbuntuAppLocController();
1409+
1410+ bool is_valid () const { return ualc != nullptr; }
1411+ bool is_gps_enabled () const;
1412+ bool is_location_service_enabled () const;
1413+
1414+ void set_gps_enabled (bool enabled);
1415+ void set_location_service_enabled (bool enabled);
1416+
1417+ private:
1418+
1419+ UbuntuApplicationLocationServiceController * ualc;
1420+
1421+ static void on_location_service_controller_status_changed (
1422+ UALocationServiceStatusFlags, void *);
1423+};
1424+
1425+#endif // __INDICATOR_LOCATION_CONTROLLER_UALC__H__
1426+
1427+
1428
1429=== added file 'src/controller.cc'
1430--- src/controller.cc 1970-01-01 00:00:00 +0000
1431+++ src/controller.cc 2013-08-26 21:42:23 +0000
1432@@ -0,0 +1,46 @@
1433+/*
1434+ * Copyright 2013 Canonical Ltd.
1435+ *
1436+ * This program is free software; you can redistribute it and/or modify
1437+ * it under the terms of the GNU General Public License as published by
1438+ * the Free Software Foundation; version 3.
1439+ *
1440+ * This program is distributed in the hope that it will be useful,
1441+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
1442+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
1443+ * GNU Lesser General Public License for more details.
1444+ *
1445+ * You should have received a copy of the GNU Lesser General Public License
1446+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
1447+ *
1448+ * Authors:
1449+ * Charles Kerr <charles.kerr@canonical.com>
1450+ */
1451+
1452+#include "controller.h"
1453+
1454+void
1455+Controller :: add_listener (ControllerListener * l)
1456+{
1457+ listeners.insert (l);
1458+}
1459+
1460+void
1461+Controller :: remove_listener (ControllerListener * l)
1462+{
1463+ listeners.erase (l);
1464+}
1465+
1466+void
1467+Controller :: notify_gps_enabled (bool enabled)
1468+{
1469+ for (auto it : listeners)
1470+ it->on_gps_enabled_changed (enabled);
1471+}
1472+
1473+void
1474+Controller :: notify_location_service_enabled (bool enabled)
1475+{
1476+ for (auto it : listeners)
1477+ it->on_location_service_enabled_changed (enabled);
1478+}
1479
1480=== added file 'src/controller.h'
1481--- src/controller.h 1970-01-01 00:00:00 +0000
1482+++ src/controller.h 2013-08-26 21:42:23 +0000
1483@@ -0,0 +1,63 @@
1484+/*
1485+ * Copyright 2013 Canonical Ltd.
1486+ *
1487+ * This program is free software; you can redistribute it and/or modify
1488+ * it under the terms of the GNU General Public License as published by
1489+ * the Free Software Foundation; version 3.
1490+ *
1491+ * This program is distributed in the hope that it will be useful,
1492+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
1493+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
1494+ * GNU Lesser General Public License for more details.
1495+ *
1496+ * You should have received a copy of the GNU Lesser General Public License
1497+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
1498+ *
1499+ * Authors:
1500+ * Charles Kerr <charles.kerr@canonical.com>
1501+ */
1502+
1503+#ifndef __INDICATOR_LOCATION_CONTROLLER_H__
1504+#define __INDICATOR_LOCATION_CONTROLLER_H__
1505+
1506+#include <set>
1507+
1508+class ControllerListener
1509+{
1510+ public:
1511+ ControllerListener() {}
1512+ virtual ~ControllerListener() {}
1513+
1514+ public:
1515+ virtual void on_gps_enabled_changed (bool is_enabled) = 0;
1516+ virtual void on_location_service_enabled_changed (bool is_enabled) = 0;
1517+};
1518+
1519+class Controller
1520+{
1521+ public:
1522+
1523+ Controller () {}
1524+ virtual ~Controller() {}
1525+
1526+ void add_listener (ControllerListener *);
1527+ void remove_listener (ControllerListener *);
1528+
1529+ virtual bool is_valid () const = 0;
1530+ virtual bool is_gps_enabled () const = 0;
1531+ virtual bool is_location_service_enabled () const = 0;
1532+
1533+ virtual void set_gps_enabled (bool enabled) = 0;
1534+ virtual void set_location_service_enabled (bool enabled) = 0;
1535+
1536+ private:
1537+
1538+ std::set<ControllerListener*> listeners;
1539+
1540+ protected:
1541+
1542+ void notify_gps_enabled (bool);
1543+ void notify_location_service_enabled (bool);
1544+};
1545+
1546+#endif // __INDICATOR_LOCATION_CONTROLLER_H__
1547
1548=== removed file 'src/indicator-location.c'
1549--- src/indicator-location.c 2013-06-26 18:35:13 +0000
1550+++ src/indicator-location.c 1970-01-01 00:00:00 +0000
1551@@ -1,587 +0,0 @@
1552-/*
1553- * Copyright © 2012 Canonical Ltd.
1554- *
1555- * This program is free software: you can redistribute it and/or modify it
1556- * under the terms of the GNU General Public License version 3, as
1557- * published by the Free Software Foundation.
1558- *
1559- * This program is distributed in the hope that it will be useful, but
1560- * WITHOUT ANY WARRANTY; without even the implied warranties of
1561- * MERCHANTABILITY, SATISFACTORY QUALITY, or FITNESS FOR A PARTICULAR
1562- * PURPOSE. See the GNU General Public License for more details.
1563- *
1564- * You should have received a copy of the GNU General Public License along
1565- * with this program. If not, see <http://www.gnu.org/licenses/>.
1566- *
1567- * Author: Ted Gould <ted@canonical.com>
1568- */
1569-
1570-#include <glib/gi18n.h>
1571-
1572-#include <libappindicator/app-indicator.h>
1573-
1574-#include <geoclue/geoclue-master.h>
1575-#include <geoclue/geoclue-master-client.h>
1576-
1577-/* Base variables */
1578-AppIndicator * indicator = NULL;
1579-GMainLoop * mainloop = NULL;
1580-
1581-/* Menu items */
1582-GtkMenuItem * accuracy_item = NULL;
1583-GtkMenuItem * details_item = NULL;
1584-
1585-gboolean has_location_details = FALSE;
1586-GtkMenuItem * lat_item = NULL;
1587-GtkMenuItem * lon_item = NULL;
1588-GtkMenuItem * alt_item = NULL;
1589-
1590-GtkMenuItem * detail_sep_item = NULL;
1591-
1592-gboolean has_address_details = FALSE;
1593-GtkMenuItem * ccode_item = NULL;
1594-GtkMenuItem * country_item = NULL;
1595-GtkMenuItem * region_item = NULL;
1596-GtkMenuItem * locality_item = NULL;
1597-GtkMenuItem * area_item = NULL;
1598-GtkMenuItem * postcode_item = NULL;
1599-GtkMenuItem * street_item = NULL;
1600-GtkMenuItem * timezone_item = NULL;
1601-
1602-/* Geoclue trackers */
1603-static GeoclueMasterClient * geo_master = NULL;
1604-static GeoclueAddress * geo_address = NULL;
1605-static GeocluePosition * geo_position = NULL;
1606-
1607-/* Prototypes */
1608-static void geo_client_invalid (GeoclueMasterClient * client, gpointer user_data);
1609-static void geo_create_client (GeoclueMaster * master, GeoclueMasterClient * client, gchar * path, GError * error, gpointer user_data);
1610-
1611-
1612-/* Update accuracy */
1613-static void
1614-update_accuracy (GeoclueAccuracyLevel level)
1615-{
1616- const char * icon = NULL;
1617- const char * icon_desc = NULL;
1618- const char * item_text = NULL;
1619- gboolean details_sensitive = TRUE;
1620-
1621- switch (level) {
1622- case GEOCLUE_ACCURACY_LEVEL_NONE:
1623- icon = "indicator-location-unknown";
1624- icon_desc = _("Location accuracy unknown");
1625- item_text = _("Accuracy:\xE2\x80\x82Unknown");
1626- details_sensitive = FALSE;
1627- break;
1628- case GEOCLUE_ACCURACY_LEVEL_COUNTRY:
1629- case GEOCLUE_ACCURACY_LEVEL_REGION:
1630- case GEOCLUE_ACCURACY_LEVEL_LOCALITY:
1631- icon = "indicator-location-region";
1632- icon_desc = _("Location regional accuracy");
1633- item_text = _("Accuracy:\xE2\x80\x82Regional");
1634- details_sensitive = TRUE;
1635- break;
1636- case GEOCLUE_ACCURACY_LEVEL_POSTALCODE:
1637- case GEOCLUE_ACCURACY_LEVEL_STREET:
1638- icon = "indicator-location-neighborhood";
1639- icon_desc = _("Location neighborhood accuracy");
1640- item_text = _("Accuracy:\xE2\x80\x82Neighborhood");
1641- details_sensitive = TRUE;
1642- break;
1643- case GEOCLUE_ACCURACY_LEVEL_DETAILED:
1644- icon = "indicator-location-specific";
1645- icon_desc = _("Location specific accuracy");
1646- item_text = _("Accuracy:\xE2\x80\x82" "Detailed");
1647- details_sensitive = TRUE;
1648- break;
1649- default:
1650- g_assert_not_reached();
1651- }
1652-
1653- if (indicator != NULL) {
1654- app_indicator_set_icon_full(indicator, icon, icon_desc);
1655- }
1656-
1657- if (accuracy_item != NULL) {
1658- gtk_menu_item_set_label(accuracy_item, item_text);
1659- }
1660-
1661- if (details_item != NULL) {
1662- gtk_widget_set_sensitive(GTK_WIDGET(details_item), details_sensitive);
1663- }
1664-
1665- return;
1666-}
1667-
1668-struct {
1669- const gchar * hash_value;
1670- const gchar * item_label;
1671- GtkMenuItem ** item;
1672-} address_detail_table[] = {
1673- {GEOCLUE_ADDRESS_KEY_COUNTRYCODE, N_("Country Code:\xE2\x80\x82%s"), &ccode_item},
1674- {GEOCLUE_ADDRESS_KEY_COUNTRY, N_("Country:\xE2\x80\x82%s"), &country_item},
1675- {GEOCLUE_ADDRESS_KEY_REGION, N_("Region:\xE2\x80\x82%s"), &region_item},
1676- {GEOCLUE_ADDRESS_KEY_LOCALITY, N_("Locality:\xE2\x80\x82%s"), &locality_item},
1677- {GEOCLUE_ADDRESS_KEY_AREA, N_("Area:\xE2\x80\x82%s"), &area_item},
1678- {GEOCLUE_ADDRESS_KEY_POSTALCODE, N_("Zip Code:\xE2\x80\x82%s"), &postcode_item},
1679- {GEOCLUE_ADDRESS_KEY_STREET, N_("Street:\xE2\x80\x82%s"), &street_item},
1680- {"timezone", N_("Timezone:\xE2\x80\x82%s"), &timezone_item},
1681- {NULL, NULL, NULL}
1682-};
1683-
1684-void
1685-update_address_details (GHashTable * details)
1686-{
1687- int i;
1688- has_address_details = FALSE;
1689-
1690- for (i = 0; address_detail_table[i].hash_value != NULL; i++) {
1691- const gchar * hashval = NULL;
1692- if (g_hash_table_contains(details, address_detail_table[i].hash_value)) {
1693- hashval = g_hash_table_lookup(details, address_detail_table[i].hash_value);
1694-
1695- if (hashval[0] == '\0') {
1696- hashval = NULL;
1697- }
1698- }
1699-
1700- if (hashval != NULL) {
1701- gchar * string = g_strdup_printf(_(address_detail_table[i].item_label), hashval);
1702- gtk_menu_item_set_label(*address_detail_table[i].item, string);
1703- g_free(string);
1704-
1705- gtk_widget_show(GTK_WIDGET(*address_detail_table[i].item));
1706-
1707- has_address_details = TRUE;
1708- } else {
1709- gtk_widget_hide(GTK_WIDGET(*address_detail_table[i].item));
1710- }
1711- }
1712-
1713- if (has_location_details && has_address_details) {
1714- gtk_widget_show(GTK_WIDGET(detail_sep_item));
1715- } else {
1716- gtk_widget_hide(GTK_WIDGET(detail_sep_item));
1717- }
1718-
1719- return;
1720-}
1721-
1722-/* Callback from getting the address */
1723-static void
1724-geo_address_cb (GeoclueAddress * address, int timestamp, GHashTable * addy_data, GeoclueAccuracy * accuracy, GError * error, gpointer user_data)
1725-{
1726- if (error != NULL) {
1727- g_warning("Unable to get Geoclue address: %s", error->message);
1728- g_clear_error (&error);
1729- return;
1730- }
1731-
1732- GeoclueAccuracyLevel level = GEOCLUE_ACCURACY_LEVEL_NONE;
1733- geoclue_accuracy_get_details(accuracy, &level, NULL, NULL);
1734- update_accuracy(level);
1735-
1736- update_address_details(addy_data);
1737-
1738- return;
1739-}
1740-
1741-/* Callback from getting the position */
1742-static void
1743-geo_position_cb (GeocluePosition * position, GeocluePositionFields field, int timestamp, double lat, double lon, double alt, GeoclueAccuracy * accuracy, GError * error, gpointer user_data)
1744-{
1745- if (error != NULL) {
1746- g_warning("Unable to get Geoclue position: %s", error->message);
1747- g_clear_error (&error);
1748- return;
1749- }
1750-
1751- has_location_details = FALSE;
1752-
1753- if (field & GEOCLUE_POSITION_FIELDS_LATITUDE && lat != 0.0) {
1754- gchar * label = g_strdup_printf(_("Latitude:\xE2\x80\x82%f"), lat);
1755- gtk_menu_item_set_label(lat_item, label);
1756- g_free(label);
1757-
1758- gtk_widget_show(GTK_WIDGET(lat_item));
1759- has_location_details = TRUE;
1760- } else {
1761- gtk_widget_hide(GTK_WIDGET(lat_item));
1762- }
1763-
1764- if (field & GEOCLUE_POSITION_FIELDS_LONGITUDE && lon != 0.0) {
1765- gchar * label = g_strdup_printf(_("Longitude:\xE2\x80\x82%f"), lon);
1766- gtk_menu_item_set_label(lon_item, label);
1767- g_free(label);
1768-
1769- gtk_widget_show(GTK_WIDGET(lon_item));
1770- has_location_details = TRUE;
1771- } else {
1772- gtk_widget_hide(GTK_WIDGET(lon_item));
1773- }
1774-
1775- if (field & GEOCLUE_POSITION_FIELDS_ALTITUDE && alt != 0.0) {
1776- gchar * label = g_strdup_printf(_("Altitude:\xE2\x80\x82%f"), alt);
1777- gtk_menu_item_set_label(alt_item, label);
1778- g_free(label);
1779-
1780- gtk_widget_show(GTK_WIDGET(alt_item));
1781- has_location_details = TRUE;
1782- } else {
1783- gtk_widget_hide(GTK_WIDGET(alt_item));
1784- }
1785-
1786- if (has_location_details && has_address_details) {
1787- gtk_widget_show(GTK_WIDGET(detail_sep_item));
1788- } else {
1789- gtk_widget_hide(GTK_WIDGET(detail_sep_item));
1790- }
1791-
1792- return;
1793-}
1794-
1795-/* Clean up the reference we kept to the address and make sure to
1796- drop the signals incase someone else has one. */
1797-static void
1798-geo_address_clean (void)
1799-{
1800- if (geo_address == NULL) {
1801- return;
1802- }
1803-
1804- g_signal_handlers_disconnect_by_func(G_OBJECT(geo_address), geo_address_cb, NULL);
1805- g_object_unref(G_OBJECT(geo_address));
1806-
1807- geo_address = NULL;
1808-
1809- return;
1810-}
1811-
1812-/* Clean up the reference we kept to the position and make sure to
1813- drop the signals incase someone else has one. */
1814-static void
1815-geo_position_clean (void)
1816-{
1817- if (geo_position == NULL) {
1818- return;
1819- }
1820-
1821- g_signal_handlers_disconnect_by_func(G_OBJECT(geo_position), geo_position_cb, NULL);
1822- g_clear_object(&geo_position);
1823-
1824- return;
1825-}
1826-
1827-
1828-/* Clean up and remove all signal handlers from the client as we
1829- unreference it as well. */
1830-static void
1831-geo_client_clean (void)
1832-{
1833- if (geo_master == NULL) {
1834- return;
1835- }
1836-
1837- g_signal_handlers_disconnect_by_func(G_OBJECT(geo_master), geo_client_invalid, NULL);
1838- g_object_unref(G_OBJECT(geo_master));
1839-
1840- geo_master = NULL;
1841-
1842- return;
1843-}
1844-
1845-/* Callback from async creation of a position */
1846-static void
1847-geo_create_position (GeoclueMasterClient * master, GeocluePosition * position, GError * error, gpointer user_data)
1848-{
1849- if (error != NULL) {
1850- g_warning("Unable to create GeoClue position: %s", error->message);
1851- g_clear_error (&error);
1852- return;
1853- }
1854-
1855- /* We shouldn't have created a new position if we already had one
1856- so this is a warning. But, it really is only a mem-leak so we
1857- don't need to error out. */
1858- g_warn_if_fail(geo_position == NULL);
1859- geo_position_clean();
1860-
1861- g_debug("Created Geoclue Position");
1862- geo_position = position;
1863- g_object_ref(G_OBJECT(geo_position));
1864-
1865- geoclue_position_get_position_async(geo_position, geo_position_cb, NULL);
1866-
1867- g_signal_connect(G_OBJECT(position), "position-changed", G_CALLBACK(geo_position_cb), NULL);
1868-
1869- return;
1870-}
1871-
1872-/* Callback from creating the address */
1873-static void
1874-geo_create_address (GeoclueMasterClient * master, GeoclueAddress * address, GError * error, gpointer user_data)
1875-{
1876- if (error != NULL) {
1877- g_warning("Unable to create GeoClue address: %s", error->message);
1878- g_clear_error (&error);
1879- return;
1880- }
1881-
1882- /* We shouldn't have created a new address if we already had one
1883- so this is a warning. But, it really is only a mem-leak so we
1884- don't need to error out. */
1885- g_warn_if_fail(geo_address == NULL);
1886- geo_address_clean();
1887-
1888- g_debug("Created Geoclue Address");
1889- geo_address = address;
1890- g_object_ref(G_OBJECT(geo_address));
1891-
1892- geoclue_address_get_address_async(geo_address, geo_address_cb, NULL);
1893-
1894- g_signal_connect(G_OBJECT(address), "address-changed", G_CALLBACK(geo_address_cb), NULL);
1895-
1896- return;
1897-}
1898-
1899-/* Callback from setting requirements */
1900-static void
1901-geo_req_set (GeoclueMasterClient * master, GError * error, gpointer user_data)
1902-{
1903- if (error != NULL) {
1904- g_warning("Unable to set Geoclue requirements: %s", error->message);
1905- g_clear_error (&error);
1906- }
1907- return;
1908-}
1909-
1910-/* Client is killing itself rather oddly */
1911-static void
1912-geo_client_invalid (GeoclueMasterClient * client, gpointer user_data)
1913-{
1914- g_warning("Master client invalid, rebuilding.");
1915-
1916- /* Client changes we can assume the address is now invalid so we
1917- need to unreference the one we had. */
1918- geo_address_clean();
1919- geo_position_clean();
1920-
1921- /* And our master client is invalid */
1922- geo_client_clean();
1923-
1924- GeoclueMaster * master = geoclue_master_get_default();
1925- geoclue_master_create_client_async(master, geo_create_client, NULL);
1926-
1927- update_accuracy(GEOCLUE_ACCURACY_LEVEL_NONE);
1928-
1929- return;
1930-}
1931-
1932-/* Callback from creating the client */
1933-static void
1934-geo_create_client (GeoclueMaster * master, GeoclueMasterClient * client, gchar * path, GError * error, gpointer user_data)
1935-{
1936- g_debug("Created Geoclue client at: %s", path);
1937-
1938- geo_master = client;
1939-
1940- if (error != NULL) {
1941- g_warning("Unable to get a GeoClue client! '%s' Geolocation based timezone support will not be available.", error->message);
1942- g_clear_error (&error);
1943- return;
1944- }
1945-
1946- if (geo_master == NULL) {
1947- g_warning(_("Unable to get a GeoClue client! Geolocation based timezone support will not be available."));
1948- return;
1949- }
1950-
1951- g_object_ref(G_OBJECT(geo_master));
1952-
1953- /* New client, make sure we don't have an address hanging on */
1954- geo_address_clean();
1955- geo_position_clean();
1956-
1957- geoclue_master_client_set_requirements_async(geo_master,
1958- GEOCLUE_ACCURACY_LEVEL_REGION,
1959- 0,
1960- FALSE,
1961- GEOCLUE_RESOURCE_ALL,
1962- geo_req_set,
1963- NULL);
1964-
1965- geoclue_master_client_create_address_async(geo_master, geo_create_address, NULL);
1966- geoclue_master_client_create_position_async(geo_master, geo_create_position, NULL);
1967-
1968- g_signal_connect(G_OBJECT(client), "invalidated", G_CALLBACK(geo_client_invalid), NULL);
1969-
1970- return;
1971-}
1972-
1973-void
1974-open_maps (void)
1975-{
1976- g_spawn_command_line_async("emerillon", NULL);
1977- return;
1978-}
1979-
1980-void
1981-open_debuglocation (void)
1982-{
1983- g_spawn_command_line_async("geoclue-test-gui", NULL);
1984- return;
1985-}
1986-
1987-GtkWidget *
1988-build_details_items (void)
1989-{
1990- GtkWidget * menu = gtk_menu_new();
1991-
1992- lat_item = GTK_MENU_ITEM(gtk_menu_item_new());
1993- gtk_widget_hide(GTK_WIDGET(lat_item));
1994- gtk_widget_set_sensitive(GTK_WIDGET(lat_item), FALSE);
1995- gtk_menu_shell_append(GTK_MENU_SHELL(menu), GTK_WIDGET(lat_item));
1996-
1997- lon_item = GTK_MENU_ITEM(gtk_menu_item_new());
1998- gtk_widget_hide(GTK_WIDGET(lon_item));
1999- gtk_widget_set_sensitive(GTK_WIDGET(lon_item), FALSE);
2000- gtk_menu_shell_append(GTK_MENU_SHELL(menu), GTK_WIDGET(lon_item));
2001-
2002- alt_item = GTK_MENU_ITEM(gtk_menu_item_new());
2003- gtk_widget_hide(GTK_WIDGET(alt_item));
2004- gtk_widget_set_sensitive(GTK_WIDGET(alt_item), FALSE);
2005- gtk_menu_shell_append(GTK_MENU_SHELL(menu), GTK_WIDGET(alt_item));
2006-
2007- detail_sep_item = GTK_MENU_ITEM(gtk_separator_menu_item_new());
2008- gtk_widget_hide(GTK_WIDGET(detail_sep_item));
2009- gtk_menu_shell_append(GTK_MENU_SHELL(menu), GTK_WIDGET(detail_sep_item));
2010-
2011- ccode_item = GTK_MENU_ITEM(gtk_menu_item_new());
2012- gtk_widget_hide(GTK_WIDGET(ccode_item));
2013- gtk_widget_set_sensitive(GTK_WIDGET(ccode_item), FALSE);
2014- gtk_menu_shell_append(GTK_MENU_SHELL(menu), GTK_WIDGET(ccode_item));
2015-
2016- country_item = GTK_MENU_ITEM(gtk_menu_item_new());
2017- gtk_widget_hide(GTK_WIDGET(country_item));
2018- gtk_widget_set_sensitive(GTK_WIDGET(country_item), FALSE);
2019- gtk_menu_shell_append(GTK_MENU_SHELL(menu), GTK_WIDGET(country_item));
2020-
2021- region_item = GTK_MENU_ITEM(gtk_menu_item_new());
2022- gtk_widget_hide(GTK_WIDGET(region_item));
2023- gtk_widget_set_sensitive(GTK_WIDGET(region_item), FALSE);
2024- gtk_menu_shell_append(GTK_MENU_SHELL(menu), GTK_WIDGET(region_item));
2025-
2026- locality_item = GTK_MENU_ITEM(gtk_menu_item_new());
2027- gtk_widget_hide(GTK_WIDGET(locality_item));
2028- gtk_widget_set_sensitive(GTK_WIDGET(locality_item), FALSE);
2029- gtk_menu_shell_append(GTK_MENU_SHELL(menu), GTK_WIDGET(locality_item));
2030-
2031- area_item = GTK_MENU_ITEM(gtk_menu_item_new());
2032- gtk_widget_hide(GTK_WIDGET(area_item));
2033- gtk_widget_set_sensitive(GTK_WIDGET(area_item), FALSE);
2034- gtk_menu_shell_append(GTK_MENU_SHELL(menu), GTK_WIDGET(area_item));
2035-
2036- postcode_item = GTK_MENU_ITEM(gtk_menu_item_new());
2037- gtk_widget_hide(GTK_WIDGET(postcode_item));
2038- gtk_widget_set_sensitive(GTK_WIDGET(postcode_item), FALSE);
2039- gtk_menu_shell_append(GTK_MENU_SHELL(menu), GTK_WIDGET(postcode_item));
2040-
2041- street_item = GTK_MENU_ITEM(gtk_menu_item_new());
2042- gtk_widget_hide(GTK_WIDGET(street_item));
2043- gtk_widget_set_sensitive(GTK_WIDGET(street_item), FALSE);
2044- gtk_menu_shell_append(GTK_MENU_SHELL(menu), GTK_WIDGET(street_item));
2045-
2046- timezone_item = GTK_MENU_ITEM(gtk_menu_item_new());
2047- gtk_widget_hide(GTK_WIDGET(timezone_item));
2048- gtk_widget_set_sensitive(GTK_WIDGET(timezone_item), FALSE);
2049- gtk_menu_shell_append(GTK_MENU_SHELL(menu), GTK_WIDGET(timezone_item));
2050-
2051- return menu;
2052-}
2053-
2054-void
2055-build_indicator (void)
2056-{
2057- indicator = app_indicator_new_with_path("indicator-location", "indicator-location-unknown", APP_INDICATOR_CATEGORY_SYSTEM_SERVICES, ICON_DIR);
2058- app_indicator_set_title(indicator, _("Location"));
2059- app_indicator_set_status(indicator, APP_INDICATOR_STATUS_ACTIVE);
2060-
2061- GtkMenu * menu = GTK_MENU(gtk_menu_new());
2062-
2063- accuracy_item = GTK_MENU_ITEM(gtk_menu_item_new());
2064- gtk_widget_show(GTK_WIDGET(accuracy_item));
2065- gtk_menu_shell_append(GTK_MENU_SHELL(menu), GTK_WIDGET(accuracy_item));
2066- gtk_widget_set_sensitive(GTK_WIDGET(accuracy_item), FALSE);
2067-
2068- details_item = GTK_MENU_ITEM(gtk_menu_item_new_with_label(_("Details")));
2069- gtk_widget_show(GTK_WIDGET(details_item));
2070- gtk_menu_shell_append(GTK_MENU_SHELL(menu), GTK_WIDGET(details_item));
2071- gtk_widget_set_sensitive(GTK_WIDGET(details_item), FALSE);
2072-
2073- gtk_menu_item_set_submenu(details_item, build_details_items());
2074-
2075- gchar * maps_in_path = g_find_program_in_path("emerillon");
2076- if (maps_in_path != NULL) {
2077- g_free(maps_in_path);
2078- maps_in_path = NULL;
2079-
2080- GtkWidget * sep = gtk_separator_menu_item_new();
2081- gtk_widget_show(sep);
2082- gtk_menu_shell_append(GTK_MENU_SHELL(menu), GTK_WIDGET(sep));
2083-
2084- GtkWidget * maps = gtk_menu_item_new_with_label(_("Open Map…"));
2085- gtk_widget_show(maps);
2086- gtk_menu_shell_append(GTK_MENU_SHELL(menu), GTK_WIDGET(maps));
2087- g_signal_connect(G_OBJECT(maps), "activate", G_CALLBACK(open_maps), NULL);
2088- }
2089-
2090- gchar * geoclue_in_path = g_find_program_in_path("geoclue-test-gui");
2091- if (geoclue_in_path != NULL) {
2092- g_free(geoclue_in_path);
2093- geoclue_in_path = NULL;
2094-
2095- GtkWidget * sep = gtk_separator_menu_item_new();
2096- gtk_widget_show(sep);
2097- gtk_menu_shell_append(GTK_MENU_SHELL(menu), GTK_WIDGET(sep));
2098-
2099- GtkWidget * debugloc = gtk_menu_item_new_with_label(_("Debug Location…"));
2100- gtk_widget_show(debugloc);
2101- gtk_menu_shell_append(GTK_MENU_SHELL(menu), GTK_WIDGET(debugloc));
2102- g_signal_connect(G_OBJECT(debugloc), "activate", G_CALLBACK(open_debuglocation), NULL);
2103- }
2104-
2105- gtk_widget_show(GTK_WIDGET(menu));
2106-
2107- app_indicator_set_menu(indicator, menu);
2108-
2109- update_accuracy(GEOCLUE_ACCURACY_LEVEL_NONE);
2110-
2111- return;
2112-}
2113-
2114-int
2115-main (int argc, char * argv[])
2116-{
2117- gtk_init(&argc, &argv);
2118-
2119- /* Setup geoclue */
2120- GeoclueMaster * master = geoclue_master_get_default();
2121- geoclue_master_create_client_async(master, geo_create_client, NULL);
2122-
2123- build_indicator();
2124-
2125- /* Mainloop */
2126- mainloop = g_main_loop_new(NULL, FALSE);
2127- g_main_loop_run(mainloop);
2128-
2129- /* clean up */
2130- g_main_loop_unref(mainloop);
2131- mainloop = NULL;
2132-
2133- geo_address_clean();
2134- geo_position_clean();
2135- geo_client_clean();
2136-
2137- return 0;
2138-}
2139
2140=== added file 'src/main.cc'
2141--- src/main.cc 1970-01-01 00:00:00 +0000
2142+++ src/main.cc 2013-08-26 21:42:23 +0000
2143@@ -0,0 +1,54 @@
2144+/*
2145+ * Copyright 2013 Canonical Ltd.
2146+ *
2147+ * Authors:
2148+ * Charles Kerr <charles.kerr@canonical.com>
2149+ *
2150+ * This program is free software: you can redistribute it and/or modify it
2151+ * under the terms of the GNU General Public License version 3, as published
2152+ * by the Free Software Foundation.
2153+ *
2154+ * This program is distributed in the hope that it will be useful, but
2155+ * WITHOUT ANY WARRANTY; without even the implied warranties of
2156+ * MERCHANTABILITY, SATISFACTORY QUALITY, or FITNESS FOR A PARTICULAR
2157+ * PURPOSE. See the GNU General Public License for more details.
2158+ *
2159+ * You should have received a copy of the GNU General Public License along
2160+ * with this program. If not, see <http://www.gnu.org/licenses/>.
2161+ */
2162+
2163+#include <locale.h>
2164+#include <glib/gi18n.h>
2165+#include <glib.h>
2166+
2167+//#include "controller-ualc.h"
2168+#include "controller-mock.h"
2169+#include "service.h"
2170+
2171+static void
2172+on_name_lost (Service * service G_GNUC_UNUSED, gpointer loop)
2173+{
2174+ g_main_loop_quit (static_cast<GMainLoop*>(loop));
2175+}
2176+
2177+int
2178+main (int argc G_GNUC_UNUSED, char ** argv G_GNUC_UNUSED)
2179+{
2180+ GMainLoop * loop;
2181+
2182+ /* boilerplate i18n */
2183+ setlocale (LC_ALL, "");
2184+ bindtextdomain (GETTEXT_PACKAGE, GNOMELOCALEDIR);
2185+ textdomain (GETTEXT_PACKAGE);
2186+
2187+ /* set up the service */
2188+ loop = g_main_loop_new (nullptr, false);
2189+ std::shared_ptr<Controller> controller (new MockController());//UbuntuAppLocController ());
2190+ Service service (controller);
2191+ service.set_name_lost_callback (on_name_lost, loop);
2192+ g_main_loop_run (loop);
2193+
2194+ /* cleanup */
2195+ g_main_loop_unref (loop);
2196+ return 0;
2197+}
2198
2199=== added file 'src/phone.cc'
2200--- src/phone.cc 1970-01-01 00:00:00 +0000
2201+++ src/phone.cc 2013-08-26 21:42:23 +0000
2202@@ -0,0 +1,265 @@
2203+/*
2204+ * Copyright 2013 Canonical Ltd.
2205+ *
2206+ * This program is free software; you can redistribute it and/or modify
2207+ * it under the terms of the GNU General Public License as published by
2208+ * the Free Software Foundation; version 3.
2209+ *
2210+ * This program is distributed in the hope that it will be useful,
2211+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
2212+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
2213+ * GNU Lesser General Public License for more details.
2214+ *
2215+ * You should have received a copy of the GNU Lesser General Public License
2216+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
2217+ *
2218+ * Authors:
2219+ * Charles Kerr <charles.kerr@canonical.com>
2220+ */
2221+
2222+#include <array>
2223+
2224+#include <glib/gi18n.h>
2225+
2226+#include <url-dispatcher.h>
2227+
2228+#include "phone.h"
2229+#include "utils.h" // GObjectDeleter
2230+
2231+#define PROFILE_NAME "phone"
2232+
2233+Phone :: Phone (std::shared_ptr<Controller> controller_,
2234+ std::shared_ptr<GSimpleActionGroup> action_group_):
2235+ controller (controller_),
2236+ menu (create_menu ()),
2237+ action_group (action_group_)
2238+{
2239+ controller->add_listener (this);
2240+
2241+ /* create the actions & add them to the group */
2242+ std::array<GSimpleAction*, 4> actions = { create_root_action(),
2243+ create_detection_enabled_action(),
2244+ create_gps_enabled_action(),
2245+ create_settings_action() };
2246+ for (auto a : actions)
2247+ {
2248+ g_action_map_add_action (G_ACTION_MAP(action_group.get()), G_ACTION(a));
2249+ g_object_unref (a);
2250+ }
2251+}
2252+
2253+Phone :: ~Phone ()
2254+{
2255+ controller->remove_listener (this);
2256+}
2257+
2258+/***
2259+****
2260+***/
2261+
2262+bool
2263+Phone :: should_be_visible ()
2264+{
2265+ // NB: this is a placeholder for now.
2266+ // The spec requires that the location indicator be visible iff
2267+ // an application has accessed location info recently,
2268+ // but there's not a platform API to support that yet.
2269+
2270+ return true;
2271+}
2272+
2273+GVariant *
2274+Phone :: action_state_for_root ()
2275+{
2276+ GVariantBuilder builder;
2277+ g_variant_builder_init (&builder, G_VARIANT_TYPE_VARDICT);
2278+
2279+ const char * a11y = _("Location");
2280+ g_variant_builder_add (&builder, "{sv}", "accessible-desc", g_variant_new_string (a11y));
2281+
2282+ gboolean visible = should_be_visible ();
2283+ g_variant_builder_add (&builder, "{sv}", "visible", g_variant_new_boolean (visible));
2284+
2285+ const char * icon_name = "gps";
2286+ GIcon * icon = g_themed_icon_new_with_default_fallbacks (icon_name);
2287+ g_variant_builder_add (&builder, "{sv}", "icon", g_icon_serialize (icon));
2288+ g_object_unref (icon);
2289+
2290+ return g_variant_builder_end (&builder);
2291+}
2292+
2293+#define HEADER_ACTION_KEY PROFILE_NAME"-header"
2294+
2295+GSimpleAction *
2296+Phone :: create_root_action ()
2297+{
2298+ return g_simple_action_new_stateful (HEADER_ACTION_KEY,
2299+ nullptr,
2300+ action_state_for_root ());
2301+}
2302+
2303+/***
2304+****
2305+***/
2306+
2307+#define LOCATION_ACTION_KEY "location-detection-enabled"
2308+
2309+GVariant *
2310+Phone :: action_state_for_location_detection ()
2311+{
2312+ return g_variant_new_boolean (controller->is_location_service_enabled());
2313+}
2314+
2315+void
2316+Phone :: on_location_service_enabled_changed (bool is_enabled G_GNUC_UNUSED)
2317+{
2318+ GAction * action = g_action_map_lookup_action (G_ACTION_MAP(action_group.get()), LOCATION_ACTION_KEY);
2319+ g_simple_action_set_state (G_SIMPLE_ACTION(action), action_state_for_location_detection());
2320+}
2321+
2322+void
2323+Phone :: on_detection_location_activated (GSimpleAction * action,
2324+ GVariant * parameter G_GNUC_UNUSED,
2325+ gpointer gself)
2326+{
2327+ GVariant * state = g_action_get_state (G_ACTION (action));
2328+ static_cast<Phone*>(gself)->controller->set_location_service_enabled (!g_variant_get_boolean (state));
2329+ g_variant_unref (state);
2330+}
2331+
2332+GSimpleAction *
2333+Phone :: create_detection_enabled_action ()
2334+{
2335+ GSimpleAction * action;
2336+
2337+ action = g_simple_action_new_stateful (LOCATION_ACTION_KEY,
2338+ nullptr,
2339+ action_state_for_location_detection());
2340+
2341+ g_simple_action_set_enabled (action, controller->is_valid());
2342+
2343+ g_signal_connect (action, "activate",
2344+ G_CALLBACK(on_detection_location_activated), this);
2345+
2346+ return action;
2347+}
2348+
2349+/***
2350+****
2351+***/
2352+
2353+#define GPS_ACTION_KEY "gps-detection-enabled"
2354+
2355+GVariant *
2356+Phone :: action_state_for_gps_detection ()
2357+{
2358+ return g_variant_new_boolean (controller->is_gps_enabled());
2359+}
2360+
2361+void
2362+Phone :: on_gps_enabled_changed (bool is_enabled G_GNUC_UNUSED)
2363+{
2364+ GAction * action = g_action_map_lookup_action (G_ACTION_MAP(action_group.get()), GPS_ACTION_KEY);
2365+ g_simple_action_set_state (G_SIMPLE_ACTION(action), action_state_for_gps_detection());
2366+}
2367+
2368+void
2369+Phone :: on_detection_gps_activated (GSimpleAction * action,
2370+ GVariant * parameter G_GNUC_UNUSED,
2371+ gpointer gself)
2372+{
2373+ GVariant * state = g_action_get_state (G_ACTION (action));
2374+ static_cast<Phone*>(gself)->controller->set_gps_enabled (!g_variant_get_boolean (state));
2375+ g_variant_unref (state);
2376+}
2377+
2378+GSimpleAction *
2379+Phone :: create_gps_enabled_action ()
2380+{
2381+ GSimpleAction * action;
2382+
2383+ action = g_simple_action_new_stateful (GPS_ACTION_KEY,
2384+ nullptr,
2385+ action_state_for_gps_detection());
2386+
2387+ g_simple_action_set_enabled (action, controller->is_valid());
2388+
2389+ g_signal_connect (action, "activate",
2390+ G_CALLBACK(on_detection_gps_activated), this);
2391+
2392+ return action;
2393+}
2394+
2395+
2396+/***
2397+****
2398+***/
2399+
2400+#define SETTINGS_ACTION_KEY "settings"
2401+
2402+namespace
2403+{
2404+ void
2405+ on_uri_dispatched (const gchar * uri,
2406+ gboolean success G_GNUC_UNUSED,
2407+ gpointer user_data G_GNUC_UNUSED)
2408+ {
2409+ if (!success)
2410+ g_warning ("Unable to activate '%s'", uri);
2411+ }
2412+
2413+ void
2414+ on_settings_activated (GSimpleAction * simple G_GNUC_UNUSED,
2415+ GVariant * parameter,
2416+ gpointer user_data G_GNUC_UNUSED)
2417+ {
2418+ const char * key = g_variant_get_string (parameter, nullptr);
2419+ gchar * uri = g_strdup_printf ("settings://system/%s", key);
2420+ url_dispatch_send (uri, on_uri_dispatched, nullptr);
2421+ g_free (uri);
2422+ }
2423+}
2424+
2425+GSimpleAction *
2426+Phone :: create_settings_action ()
2427+{
2428+ GSimpleAction * action;
2429+
2430+ action = g_simple_action_new (SETTINGS_ACTION_KEY, G_VARIANT_TYPE_STRING);
2431+
2432+ g_signal_connect (action, "activate",
2433+ G_CALLBACK(on_settings_activated), nullptr);
2434+
2435+ return action;
2436+}
2437+
2438+/***
2439+****
2440+***/
2441+
2442+std::shared_ptr <GMenu>
2443+Phone :: create_menu ()
2444+{
2445+ GMenu * menu;
2446+ GMenu * submenu;
2447+ GMenuItem * header;
2448+
2449+ /* create the submenu */
2450+ submenu = g_menu_new ();
2451+ g_menu_append (submenu, _("Location detection"), "indicator." LOCATION_ACTION_KEY);
2452+ g_menu_append (submenu, _("GPS"), "indicator." GPS_ACTION_KEY);
2453+ g_menu_append (submenu, _("Location settings…"), "indicator." SETTINGS_ACTION_KEY "::location");
2454+
2455+ /* add the submenu to a new header */
2456+ header = g_menu_item_new (nullptr, "indicator." HEADER_ACTION_KEY);
2457+ g_menu_item_set_attribute (header, "x-canonical-type", "s", "com.canonical.indicator.root");
2458+ g_menu_item_set_submenu (header, G_MENU_MODEL (submenu));
2459+ g_object_unref (submenu);
2460+
2461+ /* add the header to a new menu */
2462+ menu = g_menu_new ();
2463+ g_menu_append_item (menu, header);
2464+ g_object_unref (header);
2465+
2466+ return std::shared_ptr<GMenu>(menu, GObjectDeleter());
2467+}
2468
2469=== added file 'src/phone.h'
2470--- src/phone.h 1970-01-01 00:00:00 +0000
2471+++ src/phone.h 2013-08-26 21:42:23 +0000
2472@@ -0,0 +1,69 @@
2473+/*
2474+ * Copyright 2013 Canonical Ltd.
2475+ *
2476+ * This program is free software; you can redistribute it and/or modify
2477+ * it under the terms of the GNU General Public License as published by
2478+ * the Free Software Foundation; version 3.
2479+ *
2480+ * This program is distributed in the hope that it will be useful,
2481+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
2482+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
2483+ * GNU Lesser General Public License for more details.
2484+ *
2485+ * You should have received a copy of the GNU Lesser General Public License
2486+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
2487+ *
2488+ * Authors:
2489+ * Charles Kerr <charles.kerr@canonical.com>
2490+ */
2491+
2492+#ifndef __INDICATOR_LOCATION_PHONE_H__
2493+#define __INDICATOR_LOCATION_PHONE_H__
2494+
2495+#include <memory>
2496+
2497+#include <glib.h>
2498+#include <gio/gio.h>
2499+
2500+#include "controller.h"
2501+
2502+class Phone: public ControllerListener
2503+{
2504+ public:
2505+ Phone (std::shared_ptr<Controller> controller,
2506+ std::shared_ptr<GSimpleActionGroup> action_group);
2507+ virtual ~Phone ();
2508+ std::shared_ptr<GMenu> get_menu () { return menu; }
2509+
2510+ protected:
2511+ std::shared_ptr<Controller> controller;
2512+ virtual void on_gps_enabled_changed (bool is_enabled);
2513+ virtual void on_location_service_enabled_changed (bool is_enabled);
2514+
2515+ private:
2516+ std::shared_ptr<GMenu> menu;
2517+ std::shared_ptr<GSimpleActionGroup> action_group;
2518+
2519+ private:
2520+ std::shared_ptr<GMenu> create_menu ();
2521+
2522+ private:
2523+ bool should_be_visible ();
2524+ GVariant * action_state_for_root ();
2525+ GSimpleAction * create_root_action ();
2526+
2527+ private:
2528+ GVariant * action_state_for_location_detection ();
2529+ GSimpleAction * create_detection_enabled_action ();
2530+ static void on_detection_location_activated (GSimpleAction*, GVariant*, gpointer);
2531+
2532+ private:
2533+ GVariant * action_state_for_gps_detection ();
2534+ GSimpleAction * create_gps_enabled_action ();
2535+ static void on_detection_gps_activated (GSimpleAction*, GVariant*, gpointer);
2536+
2537+ private:
2538+ GSimpleAction * create_settings_action ();
2539+};
2540+
2541+#endif /* __INDICATOR_LOCATION_PHONE_H__ */
2542
2543=== added file 'src/service.cc'
2544--- src/service.cc 1970-01-01 00:00:00 +0000
2545+++ src/service.cc 2013-08-26 21:42:23 +0000
2546@@ -0,0 +1,166 @@
2547+/*
2548+ * Copyright 2013 Canonical Ltd.
2549+ *
2550+ * Authors:
2551+ * Charles Kerr <charles.kerr@canonical.com>
2552+ *
2553+ * This program is free software: you can redistribute it and/or modify it
2554+ * under the terms of the GNU General Public License version 3, as published
2555+ * by the Free Software Foundation.
2556+ *
2557+ * This program is distributed in the hope that it will be useful, but
2558+ * WITHOUT ANY WARRANTY; without even the implied warranties of
2559+ * MERCHANTABILITY, SATISFACTORY QUALITY, or FITNESS FOR A PARTICULAR
2560+ * PURPOSE. See the GNU General Public License for more details.
2561+ *
2562+ * You should have received a copy of the GNU General Public License along
2563+ * with this program. If not, see <http://www.gnu.org/licenses/>.
2564+ */
2565+
2566+#include <glib/gi18n.h>
2567+#include <gio/gio.h>
2568+
2569+#include "service.h"
2570+
2571+#define BUS_NAME "com.canonical.indicator.location"
2572+#define BUS_PATH "/com/canonical/indicator/location"
2573+
2574+/**
2575+***
2576+**/
2577+
2578+Service :: Service (std::shared_ptr<Controller> controller):
2579+ action_group (g_simple_action_group_new(), GObjectDeleter()),
2580+ phone_profile (controller, action_group),
2581+ name_lost_callback (nullptr),
2582+ name_lost_user_data (0),
2583+ action_group_export_id (0),
2584+ bus_own_id (0)
2585+{
2586+ bus_own_id = g_bus_own_name (G_BUS_TYPE_SESSION,
2587+ BUS_NAME,
2588+ G_BUS_NAME_OWNER_FLAGS_NONE,
2589+ on_bus_acquired,
2590+ nullptr,
2591+ on_name_lost,
2592+ this,
2593+ nullptr);
2594+}
2595+
2596+Service :: ~Service ()
2597+{
2598+ if (connection)
2599+ unexport ();
2600+
2601+ if (bus_own_id != 0)
2602+ g_bus_unown_name (bus_own_id);
2603+}
2604+
2605+void
2606+Service :: set_name_lost_callback (name_lost_callback_func callback, void* user_data)
2607+{
2608+ name_lost_callback = callback;
2609+ name_lost_user_data = user_data;
2610+}
2611+
2612+void
2613+Service :: unexport ()
2614+{
2615+ g_return_if_fail (connection);
2616+
2617+ // unexport the menu(s)
2618+ for (auto& id : exported_menus)
2619+ g_dbus_connection_unexport_menu_model (connection.get(), id);
2620+ exported_menus.clear ();
2621+
2622+ // unexport the action group
2623+ if (action_group_export_id != 0)
2624+ {
2625+ g_dbus_connection_unexport_action_group (connection.get(), action_group_export_id);
2626+ action_group_export_id = 0;
2627+ }
2628+}
2629+
2630+/***
2631+**** GDBus
2632+***/
2633+
2634+void
2635+Service :: on_name_lost (GDBusConnection * connection,
2636+ const char * name,
2637+ gpointer gself)
2638+{
2639+ g_debug ("%s::%s: %s %p", G_STRLOC, G_STRFUNC, name, connection);
2640+
2641+ static_cast<Service*>(gself)->on_name_lost (connection, name);
2642+}
2643+void
2644+Service :: on_name_lost (GDBusConnection * connection,
2645+ const char * name)
2646+{
2647+ g_debug ("%s::%s: %s %p", G_STRLOC, G_STRFUNC, name, connection);
2648+
2649+ if (name_lost_callback != nullptr)
2650+ (name_lost_callback)(this, name_lost_user_data);
2651+}
2652+
2653+void
2654+Service :: on_bus_acquired (GDBusConnection * connection,
2655+ const char * name,
2656+ gpointer gself)
2657+{
2658+ static_cast<Service*>(gself)->on_bus_acquired (connection, name);
2659+}
2660+void
2661+Service :: on_bus_acquired (GDBusConnection * connection,
2662+ const char * name)
2663+{
2664+ g_debug ("%s::%s: %s %p", G_STRLOC, G_STRFUNC, name, connection);
2665+
2666+ this->connection.reset (G_DBUS_CONNECTION (g_object_ref(connection)));
2667+
2668+ GError * error = nullptr;
2669+
2670+ /* export the action group */
2671+
2672+ unsigned int export_id = g_dbus_connection_export_action_group (connection,
2673+ BUS_PATH,
2674+ G_ACTION_GROUP (action_group.get()),
2675+ &error);
2676+ if (error != nullptr)
2677+ {
2678+ g_warning ("Unable to export action group: %s", error->message);
2679+ g_clear_error (&error);
2680+ }
2681+ else
2682+ {
2683+ action_group_export_id = export_id;
2684+ }
2685+
2686+ /* export the menu(s) */
2687+
2688+ struct {
2689+ std::shared_ptr<GMenu> menu;
2690+ const char * path;
2691+ } menus[] = {
2692+ { phone_profile.get_menu(), BUS_PATH "/phone" }
2693+ };
2694+
2695+ for (unsigned int i=0, n=G_N_ELEMENTS(menus); i<n; i++)
2696+ {
2697+ export_id = g_dbus_connection_export_menu_model (connection,
2698+ menus[i].path,
2699+ G_MENU_MODEL (menus[i].menu.get()),
2700+ &error);
2701+ if (error != nullptr)
2702+ {
2703+ g_warning ("Unable to export phone menu: %s", error->message);
2704+ g_clear_error (&error);
2705+ }
2706+ else
2707+ {
2708+ exported_menus.insert (export_id);
2709+ }
2710+ }
2711+}
2712+
2713
2714=== added file 'src/service.h'
2715--- src/service.h 1970-01-01 00:00:00 +0000
2716+++ src/service.h 2013-08-26 21:42:23 +0000
2717@@ -0,0 +1,64 @@
2718+/*
2719+ * Copyright 2013 Canonical Ltd.
2720+ *
2721+ * Authors:
2722+ * Charles Kerr <charles.kerr@canonical.com>
2723+ *
2724+ * This program is free software: you can redistribute it and/or modify it
2725+ * under the terms of the GNU General Public License version 3, as published
2726+ * by the Free Software Foundation.
2727+ *
2728+ * This program is distributed in the hope that it will be useful, but
2729+ * WITHOUT ANY WARRANTY; without even the implied warranties of
2730+ * MERCHANTABILITY, SATISFACTORY QUALITY, or FITNESS FOR A PARTICULAR
2731+ * PURPOSE. See the GNU General Public License for more details.
2732+ *
2733+ * You should have received a copy of the GNU General Public License along
2734+ * with this program. If not, see <http://www.gnu.org/licenses/>.
2735+ */
2736+
2737+#ifndef __INDICATOR_LOCATION_SERVICE_H__
2738+#define __INDICATOR_LOCATION_SERVICE_H__
2739+
2740+#include <memory>
2741+#include <set>
2742+
2743+#include "controller.h"
2744+#include "phone.h"
2745+#include "utils.h" // GObjectDeleter
2746+
2747+class Service
2748+{
2749+ public:
2750+ Service (std::shared_ptr<Controller> controller);
2751+ virtual ~Service ();
2752+
2753+ private:
2754+ std::shared_ptr<GSimpleActionGroup> action_group;
2755+ std::unique_ptr<GDBusConnection,GObjectDeleter> connection;
2756+ Phone phone_profile;
2757+
2758+ public:
2759+ typedef void (*name_lost_callback_func)(Service*, void* user_data);
2760+ void set_name_lost_callback (name_lost_callback_func callback, void* user_data);
2761+ private:
2762+ name_lost_callback_func name_lost_callback;
2763+ void * name_lost_user_data;
2764+
2765+
2766+ private:
2767+ unsigned int action_group_export_id;
2768+ std::set<unsigned int> exported_menus;
2769+ void unexport ();
2770+
2771+
2772+ private: // DBus callbacks
2773+ unsigned int bus_own_id;
2774+ void on_name_lost (GDBusConnection*, const char*);
2775+ void on_bus_acquired (GDBusConnection*, const char*);
2776+ static void on_name_lost (GDBusConnection*, const char*, gpointer);
2777+ static void on_bus_acquired (GDBusConnection*, const char*, gpointer);
2778+};
2779+
2780+#endif /* __INDICATOR_LOCATION_SERVICE_H__ */
2781+
2782
2783=== added file 'src/utils.h'
2784--- src/utils.h 1970-01-01 00:00:00 +0000
2785+++ src/utils.h 2013-08-26 21:42:23 +0000
2786@@ -0,0 +1,36 @@
2787+/*
2788+ * Copyright 2013 Canonical Ltd.
2789+ *
2790+ * Authors:
2791+ * Charles Kerr <charles.kerr@canonical.com>
2792+ *
2793+ * This program is free software: you can redistribute it and/or modify it
2794+ * under the terms of the GNU General Public License version 3, as published
2795+ * by the Free Software Foundation.
2796+ *
2797+ * This program is distributed in the hope that it will be useful, but
2798+ * WITHOUT ANY WARRANTY; without even the implied warranties of
2799+ * MERCHANTABILITY, SATISFACTORY QUALITY, or FITNESS FOR A PARTICULAR
2800+ * PURPOSE. See the GNU General Public License for more details.
2801+ *
2802+ * You should have received a copy of the GNU General Public License along
2803+ * with this program. If not, see <http://www.gnu.org/licenses/>.
2804+ */
2805+
2806+#ifndef __INDICATOR_LOCATION_UTILS_H__
2807+#define __INDICATOR_LOCATION_UTILS_H__
2808+
2809+#include <glib.h>
2810+#include <gio/gio.h>
2811+
2812+struct GObjectDeleter
2813+{
2814+ void operator()(GObject * o) { g_object_unref (o); }
2815+
2816+ void operator()(GMenu * o) { operator()(G_OBJECT(o)); }
2817+ void operator()(GDBusConnection * o) { operator()(G_OBJECT(o)); }
2818+ void operator()(GSimpleActionGroup * o) { operator()(G_OBJECT(o)); }
2819+};
2820+
2821+#endif /* __INDICATOR_LOCATION_UTILS_H__ */
2822+
2823
2824=== added directory 'tests'
2825=== added file 'tests/CMakeLists.txt'
2826--- tests/CMakeLists.txt 1970-01-01 00:00:00 +0000
2827+++ tests/CMakeLists.txt 2013-08-26 21:42:23 +0000
2828@@ -0,0 +1,32 @@
2829+###
2830+### Google Test Framework
2831+###
2832+
2833+add_library (gtest STATIC
2834+ ${GTEST_SOURCE_DIR}/gtest-all.cc
2835+ ${GTEST_SOURCE_DIR}/gtest_main.cc)
2836+
2837+###
2838+### phone-test
2839+###
2840+
2841+set (PHONE_TEST "phone-test")
2842+add_executable (${PHONE_TEST} phone-test.cc)
2843+add_test (${PHONE_TEST} ${PHONE_TEST})
2844+
2845+
2846+###
2847+### globals
2848+###
2849+
2850+set (ALL_TESTS ${PHONE_TEST})
2851+
2852+set_property (TARGET ${ALL_TESTS}
2853+ APPEND_STRING PROPERTY COMPILE_FLAGS "${CC_WARNING_ARGS} -g --std=c++11")
2854+
2855+set_property (TARGET ${ALL_TESTS}
2856+ APPEND PROPERTY LINK_LIBRARIES libindicator-location-service gtest ${GTEST_LIBS} ${GCOV_LIBS})
2857+
2858+set_property (TARGET ${ALL_TESTS} gtest
2859+ APPEND PROPERTY INCLUDE_DIRECTORIES ${CMAKE_SOURCE_DIR} ${SERVICE_INCLUDE_DIRS} ${GTEST_INCLUDE_DIR})
2860+
2861
2862=== added file 'tests/gtest-dbus-fixture.h'
2863--- tests/gtest-dbus-fixture.h 1970-01-01 00:00:00 +0000
2864+++ tests/gtest-dbus-fixture.h 2013-08-26 21:42:23 +0000
2865@@ -0,0 +1,134 @@
2866+/*
2867+ * Copyright 2013 Canonical Ltd.
2868+ *
2869+ * Authors:
2870+ * Charles Kerr <charles.kerr@canonical.com>
2871+ *
2872+ * This program is free software: you can redistribute it and/or modify it
2873+ * under the terms of the GNU General Public License version 3, as published
2874+ * by the Free Software Foundation.
2875+ *
2876+ * This program is distributed in the hope that it will be useful, but
2877+ * WITHOUT ANY WARRANTY; without even the implied warranties of
2878+ * MERCHANTABILITY, SATISFACTORY QUALITY, or FITNESS FOR A PARTICULAR
2879+ * PURPOSE. See the GNU General Public License for more details.
2880+ *
2881+ * You should have received a copy of the GNU General Public License along
2882+ * with this program. If not, see <http://www.gnu.org/licenses/>.
2883+ */
2884+
2885+#include <glib.h>
2886+#include <gio/gio.h>
2887+
2888+#include <gtest/gtest.h>
2889+
2890+/***
2891+****
2892+***/
2893+
2894+class GTestDBusFixture : public ::testing::Test
2895+{
2896+ private:
2897+
2898+ static void
2899+ on_bus_opened (GObject * o G_GNUC_UNUSED, GAsyncResult * res, gpointer gself)
2900+ {
2901+ GTestDBusFixture * self = static_cast<GTestDBusFixture*>(gself);
2902+
2903+ GError * err = nullptr;
2904+ self->conn = g_bus_get_finish (res, &err);
2905+ g_assert_no_error (err);
2906+
2907+ g_main_loop_quit (self->loop);
2908+ }
2909+
2910+ static void
2911+ on_bus_closed (GObject * o G_GNUC_UNUSED, GAsyncResult * res, gpointer gself)
2912+ {
2913+ GTestDBusFixture * self = static_cast<GTestDBusFixture*>(gself);
2914+
2915+ GError * err = nullptr;
2916+ g_dbus_connection_close_finish (self->conn, res, &err);
2917+ g_assert_no_error (err);
2918+
2919+ g_main_loop_quit (self->loop);
2920+ }
2921+
2922+ static gboolean
2923+ wait_for_signal__timeout (gpointer name)
2924+ {
2925+ g_error ("%s: timed out waiting for signal '%s'", G_STRLOC, (char*)name);
2926+ return G_SOURCE_REMOVE;
2927+ }
2928+
2929+ protected:
2930+
2931+ virtual void SetUp ()
2932+ {
2933+ conn = nullptr;
2934+ test_dbus = nullptr;
2935+ loop = nullptr;
2936+
2937+ //g_setenv ("GSETTINGS_SCHEMA_DIR", SCHEMA_DIR, TRUE);
2938+ //g_setenv ("GSETTINGS_BACKEND", "memory", TRUE);
2939+ //g_debug ("SCHEMA_DIR is %s", SCHEMA_DIR);
2940+
2941+ // pull up a test dbus
2942+ loop = g_main_loop_new (nullptr, FALSE);
2943+ test_dbus = g_test_dbus_new (G_TEST_DBUS_NONE);
2944+ //g_test_dbus_add_service_dir (test_dbus, INDICATOR_SERVICE_DIR);
2945+ //g_debug ("INDICATOR_SERVICE_DIR is %s", INDICATOR_SERVICE_DIR);
2946+ g_test_dbus_up (test_dbus);
2947+ const char * address;
2948+ address = g_test_dbus_get_bus_address (test_dbus);
2949+ g_setenv ("DBUS_SYSTEM_BUS_ADDRESS", address, TRUE);
2950+ g_debug ("test_dbus's address is %s", address);
2951+
2952+ // wait for the GDBusConnection before returning
2953+ g_bus_get (G_BUS_TYPE_SYSTEM, nullptr, on_bus_opened, this);
2954+ g_main_loop_run (loop);
2955+ }
2956+
2957+ virtual void TearDown()
2958+ {
2959+ // close the bus connection
2960+ g_dbus_connection_close (conn, nullptr, on_bus_closed, this);
2961+ g_main_loop_run (loop);
2962+ g_clear_object (&conn);
2963+
2964+ // tear down the test dbus
2965+ g_test_dbus_down (test_dbus);
2966+ g_clear_object (&test_dbus);
2967+
2968+ g_clear_pointer (&loop, g_main_loop_unref);
2969+ }
2970+
2971+ /* convenience func to loop while waiting for a GObject's signal */
2972+ void wait_for_signal (gpointer o, const gchar * signal)
2973+ {
2974+ const int timeout_seconds = 5; // arbitrary
2975+
2976+ // wait for the signal or for timeout, whichever comes first
2977+ guint handler_id = g_signal_connect_swapped (o, signal,
2978+ G_CALLBACK(g_main_loop_quit),
2979+ loop);
2980+ gulong timeout_id = g_timeout_add_seconds (timeout_seconds,
2981+ wait_for_signal__timeout,
2982+ const_cast<gchar*>(signal));
2983+ g_main_loop_run (loop);
2984+ g_source_remove (timeout_id);
2985+ g_signal_handler_disconnect (o, handler_id);
2986+ }
2987+
2988+ /* convenience func to loop for N msec */
2989+ void wait_msec (int msec)
2990+ {
2991+ guint id = g_timeout_add (msec, (GSourceFunc)g_main_loop_quit, loop);
2992+ g_main_loop_run (loop);
2993+ g_source_remove (id);
2994+ }
2995+
2996+ GMainLoop * loop;
2997+ GTestDBus * test_dbus;
2998+ GDBusConnection * conn;
2999+};
3000
3001=== added file 'tests/gtest-dbus-indicator-fixture.h'
3002--- tests/gtest-dbus-indicator-fixture.h 1970-01-01 00:00:00 +0000
3003+++ tests/gtest-dbus-indicator-fixture.h 2013-08-26 21:42:23 +0000
3004@@ -0,0 +1,273 @@
3005+/*
3006+ * Copyright 2013 Canonical Ltd.
3007+ *
3008+ * This program is free software; you can redistribute it and/or modify
3009+ * it under the terms of the GNU General Public License as published by
3010+ * the Free Software Foundation; version 3.
3011+ *
3012+ * This program is distributed in the hope that it will be useful,
3013+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
3014+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
3015+ * GNU Lesser General Public License for more details.
3016+ *
3017+ * You should have received a copy of the GNU Lesser General Public License
3018+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
3019+ *
3020+ * Authors:
3021+ * Charles Kerr <charles.kerr@canonical.com>
3022+ */
3023+
3024+
3025+#include "gtest-dbus-fixture.h"
3026+
3027+class GTestDBusIndicatorFixture: public GTestDBusFixture
3028+{
3029+ typedef GTestDBusFixture super;
3030+
3031+ enum { TIME_LIMIT_SEC = 10 };
3032+
3033+ private:
3034+
3035+ static void on_name_appeared (GDBusConnection * connection G_GNUC_UNUSED,
3036+ const gchar * name G_GNUC_UNUSED,
3037+ const gchar * name_owner G_GNUC_UNUSED,
3038+ gpointer gself)
3039+ {
3040+ g_main_loop_quit (static_cast<GTestDBusIndicatorFixture*>(gself)->loop);
3041+ }
3042+
3043+ GSList * menu_references;
3044+
3045+ gboolean any_item_changed;
3046+
3047+ static void on_items_changed (GMenuModel * model G_GNUC_UNUSED,
3048+ gint position G_GNUC_UNUSED,
3049+ gint removed G_GNUC_UNUSED,
3050+ gint added G_GNUC_UNUSED,
3051+ gpointer any_item_changed)
3052+ {
3053+ *((gboolean*)any_item_changed) = true;
3054+ }
3055+
3056+ protected:
3057+
3058+ void activate_subtree (GMenuModel * model)
3059+ {
3060+ // query the GDBusMenuModel for information to activate it
3061+ int n = g_menu_model_get_n_items (model);
3062+ if (!n)
3063+ {
3064+ // give the model a moment to populate its info
3065+ wait_msec (100);
3066+ n = g_menu_model_get_n_items (model);
3067+ }
3068+
3069+ // keep a ref so that it stays activated
3070+ menu_references = g_slist_prepend (menu_references, g_object_ref(model));
3071+
3072+ g_signal_connect (model, "items-changed", G_CALLBACK(on_items_changed), &any_item_changed);
3073+
3074+ // recurse
3075+ for (int i=0; i<n; ++i)
3076+ {
3077+ GMenuModel * link;
3078+ GMenuLinkIter * iter = g_menu_model_iterate_item_links (model, i);
3079+ while (g_menu_link_iter_get_next (iter, nullptr, &link))
3080+ {
3081+ activate_subtree (link);
3082+ g_object_unref (link);
3083+ }
3084+ g_clear_object (&iter);
3085+ }
3086+ }
3087+
3088+ void sync_menu (void)
3089+ {
3090+ g_slist_free_full (menu_references, (GDestroyNotify)g_object_unref);
3091+ menu_references = nullptr;
3092+ activate_subtree (G_MENU_MODEL (menu_model));
3093+ }
3094+
3095+ GDBusMenuModel * menu_model;
3096+ GDBusActionGroup * action_group;
3097+ GTimer * timer;
3098+
3099+ virtual void setup_service () = 0;
3100+ virtual void teardown_service () = 0;
3101+
3102+ virtual void SetUp ()
3103+ {
3104+ super :: SetUp ();
3105+
3106+ menu_references = nullptr;
3107+ any_item_changed = FALSE;
3108+
3109+ timer = g_timer_new ();
3110+
3111+ // Start an IndicatorSessionService and wait for it to appear on the bus.
3112+ setup_service ();
3113+ const guint watch_id = g_bus_watch_name_on_connection (conn,
3114+ INDICATOR_BUS_NAME,
3115+ G_BUS_NAME_WATCHER_FLAGS_NONE,
3116+ on_name_appeared, // quits the loop
3117+ nullptr, this, nullptr);
3118+ const guint timer_id = g_timeout_add_seconds (TIME_LIMIT_SEC, (GSourceFunc)g_main_loop_quit, loop);
3119+ g_main_loop_run (loop);
3120+ g_source_remove (timer_id);
3121+ g_bus_unwatch_name (watch_id);
3122+ ASSERT_FALSE (times_up());
3123+
3124+ // get the actions & menus that the service exported.
3125+ action_group = g_dbus_action_group_get (conn,
3126+ INDICATOR_BUS_NAME,
3127+ INDICATOR_OBJECT_PATH);
3128+ menu_model = g_dbus_menu_model_get (conn,
3129+ INDICATOR_BUS_NAME,
3130+ INDICATOR_OBJECT_PATH "/" INDICATOR_PROFILE);
3131+ // the actions are added asynchronously, so wait for the actions
3132+ if (!g_action_group_has_action (G_ACTION_GROUP(action_group), INDICATOR_PROFILE "-header"))
3133+ wait_for_signal (action_group, "action-added");
3134+ // activate all the groups in the menu so it'll be ready when we need it
3135+ g_signal_connect (menu_model, "items-changed", G_CALLBACK(on_items_changed), &any_item_changed);
3136+ sync_menu ();
3137+ }
3138+
3139+ virtual void TearDown ()
3140+ {
3141+ g_clear_pointer (&timer, g_timer_destroy);
3142+
3143+ g_slist_free_full (menu_references, (GDestroyNotify)g_object_unref);
3144+ menu_references = nullptr;
3145+ g_clear_object (&menu_model);
3146+
3147+ g_clear_object (&action_group);
3148+ teardown_service ();
3149+ wait_msec (100);
3150+
3151+ super :: TearDown ();
3152+ }
3153+
3154+ private:
3155+
3156+ bool times_up () const
3157+ {
3158+ return g_timer_elapsed (timer, nullptr) >= TIME_LIMIT_SEC;
3159+ }
3160+
3161+ protected:
3162+
3163+ void wait_for_has_action (const char * name)
3164+ {
3165+ while (!g_action_group_has_action (G_ACTION_GROUP(action_group), name) && !times_up())
3166+ wait_msec (50);
3167+
3168+ ASSERT_FALSE (times_up());
3169+ ASSERT_TRUE (g_action_group_has_action (G_ACTION_GROUP(action_group), name));
3170+ }
3171+
3172+ void wait_for_menu_resync (void)
3173+ {
3174+ any_item_changed = false;
3175+ while (!times_up() && !any_item_changed)
3176+ wait_msec (50);
3177+ g_warn_if_fail (any_item_changed);
3178+ sync_menu ();
3179+ }
3180+
3181+ void wait_for_action_state_change (const gchar * action_name)
3182+ {
3183+ gchar * signal_name = g_strdup_printf ("action-state-changed::%s", action_name);
3184+ wait_for_signal (action_group, signal_name);
3185+ g_free (signal_name);
3186+ }
3187+
3188+ protected:
3189+
3190+ bool find_menu_item_for_action (const char * action_key, GMenuModel ** setme, int * item_index)
3191+ {
3192+ bool success = false;
3193+
3194+ for (GSList * l=menu_references; !success && (l!=nullptr); l=l->next)
3195+ {
3196+ GMenuModel * mm = G_MENU_MODEL (l->data);
3197+ const int n = g_menu_model_get_n_items (mm);
3198+
3199+ for (int i=0; !success && i<n; ++i)
3200+ {
3201+ char * action = nullptr;
3202+ if (!g_menu_model_get_item_attribute (mm, i, G_MENU_ATTRIBUTE_ACTION, "s", &action))
3203+ continue;
3204+
3205+ if ((success = !g_strcmp0 (action, action_key)))
3206+ {
3207+ if (setme != nullptr)
3208+ *setme = G_MENU_MODEL (g_object_ref (G_OBJECT(mm)));
3209+
3210+ if (item_index != nullptr)
3211+ *item_index = i;
3212+ }
3213+
3214+ g_free (action);
3215+ }
3216+ }
3217+
3218+ return success;
3219+ }
3220+
3221+ bool action_exists (const char * action_name)
3222+ {
3223+#if 0
3224+ gchar ** actions = g_action_group_list_actions (G_ACTION_GROUP (action_group));
3225+ for (int i=0; actions && actions[i]; i++)
3226+ g_message ("[%d][%s]", i, actions[i]);
3227+#endif
3228+
3229+ return g_action_group_has_action (G_ACTION_GROUP(action_group), action_name);
3230+ }
3231+
3232+ bool action_menuitem_exists (const char * action_name)
3233+ {
3234+ bool found;
3235+ GMenuModel * model = nullptr;
3236+ int pos = -1;
3237+
3238+ if ((found = find_menu_item_for_action (action_name, &model, &pos)))
3239+ g_object_unref (G_OBJECT(model));
3240+
3241+ return found;
3242+ }
3243+
3244+ void check_header (const char * expected_label, const char * expected_icon, const char * expected_a11y)
3245+ {
3246+ GVariant * variant;
3247+ const gchar * label = nullptr;
3248+ const gchar * icon = nullptr;
3249+ const gchar * a11y = nullptr;
3250+ gboolean visible;
3251+
3252+ variant = g_action_group_get_action_state (G_ACTION_GROUP(action_group), "_header");
3253+ g_variant_get (variant, "(&s&s&sb)", &label, &icon, &a11y, &visible);
3254+
3255+ if (expected_label != nullptr)
3256+ ASSERT_STREQ (expected_label, label);
3257+
3258+ if (expected_icon != nullptr)
3259+ ASSERT_STREQ (expected_icon, icon);
3260+
3261+ if (expected_a11y != nullptr)
3262+ ASSERT_STREQ (expected_a11y, a11y);
3263+
3264+ // the session menu is always visible...
3265+ ASSERT_TRUE (visible);
3266+
3267+ g_variant_unref (variant);
3268+ }
3269+
3270+ void check_label (const char * expected_label, GMenuModel * model, int pos)
3271+ {
3272+ char * label = nullptr;
3273+ ASSERT_TRUE (g_menu_model_get_item_attribute (model, pos, G_MENU_ATTRIBUTE_LABEL, "s", &label));
3274+ ASSERT_STREQ (expected_label, label);
3275+ g_free (label);
3276+ }
3277+};
3278
3279=== added file 'tests/phone-test.cc'
3280--- tests/phone-test.cc 1970-01-01 00:00:00 +0000
3281+++ tests/phone-test.cc 2013-08-26 21:42:23 +0000
3282@@ -0,0 +1,214 @@
3283+/*
3284+ * Copyright 2013 Canonical Ltd.
3285+ *
3286+ * This program is free software; you can redistribute it and/or modify
3287+ * it under the terms of the GNU General Public License as published by
3288+ * the Free Software Foundation; version 3.
3289+ *
3290+ * This program is distributed in the hope that it will be useful,
3291+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
3292+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
3293+ * GNU Lesser General Public License for more details.
3294+ *
3295+ * You should have received a copy of the GNU Lesser General Public License
3296+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
3297+ *
3298+ * Authors:
3299+ * Charles Kerr <charles.kerr@canonical.com>
3300+ */
3301+
3302+#define INDICATOR_BUS_NAME "com.canonical.indicator.location"
3303+#define INDICATOR_OBJECT_PATH "/com/canonical/indicator/location"
3304+#define INDICATOR_PROFILE "phone"
3305+#include "gtest-dbus-indicator-fixture.h"
3306+
3307+#include "src/controller-mock.h"
3308+#include "src/service.h"
3309+
3310+class PhoneTest: public GTestDBusIndicatorFixture,
3311+ public ControllerListener
3312+{
3313+ protected:
3314+
3315+ bool loc_enabled;
3316+ bool loc_enabled_changed;
3317+ bool gps_enabled;
3318+ bool gps_enabled_changed;
3319+
3320+ std::shared_ptr<MockController> myController;
3321+ std::shared_ptr<Service> myService;
3322+
3323+ public:
3324+
3325+ void clear_callbacks ()
3326+ {
3327+ gps_enabled = false;
3328+ gps_enabled_changed = false;
3329+ gps_enabled = false;
3330+ loc_enabled_changed = false;
3331+ }
3332+
3333+ virtual void on_gps_enabled_changed (bool is_enabled)
3334+ {
3335+ gps_enabled_changed = true;
3336+ gps_enabled = is_enabled;
3337+ }
3338+
3339+ virtual void on_location_service_enabled_changed (bool is_enabled)
3340+ {
3341+ loc_enabled_changed = true;
3342+ loc_enabled = is_enabled;
3343+ }
3344+
3345+ protected:
3346+
3347+ virtual void SetUp ()
3348+ {
3349+ GTestDBusIndicatorFixture :: SetUp ();
3350+
3351+ clear_callbacks ();
3352+ }
3353+
3354+ virtual void setup_service ()
3355+ {
3356+ myController.reset (new MockController ());
3357+ myController->add_listener (this);
3358+ myService.reset (new Service (myController));
3359+ }
3360+
3361+ virtual void teardown_service ()
3362+ {
3363+ myService.reset ();
3364+ myController->remove_listener (this);
3365+ myController.reset ();
3366+ }
3367+};
3368+
3369+TEST_F (PhoneTest, ActionsExit)
3370+{
3371+ ASSERT_TRUE (action_exists ("gps-detection-enabled"));
3372+ ASSERT_TRUE (action_exists ("location-detection-enabled"));
3373+ ASSERT_TRUE (action_exists ("phone-header"));
3374+ ASSERT_TRUE (action_exists ("settings"));
3375+}
3376+
3377+TEST_F (PhoneTest, MenuitemsExist)
3378+{
3379+ ASSERT_TRUE (action_menuitem_exists ("indicator.location-detection-enabled"));
3380+ ASSERT_TRUE (action_menuitem_exists ("indicator.gps-detection-enabled"));
3381+ ASSERT_TRUE (action_menuitem_exists ("indicator.settings"));
3382+}
3383+
3384+TEST_F (PhoneTest, PlatformTogglesGPS)
3385+{
3386+ bool enabled;
3387+ const char * const key = "gps-detection-enabled";
3388+ GActionGroup * ag = G_ACTION_GROUP (action_group);
3389+ GVariant * v;
3390+
3391+ // check that the current state is the default value of 'false'
3392+ v = g_action_group_get_action_state (ag, key);
3393+ ASSERT_TRUE (v != nullptr);
3394+ enabled = g_variant_get_boolean (v);
3395+ g_variant_unref (v);
3396+ ASSERT_FALSE (enabled);
3397+
3398+ // confirm that toggling the mock controller's GPS is reflected in the action state
3399+ for (int i=0; i<4; i++)
3400+ {
3401+ enabled = !enabled;
3402+
3403+ myController->set_gps_enabled (enabled);
3404+ wait_for_action_state_change (key);
3405+ v = g_action_group_get_action_state (ag, key);
3406+ ASSERT_TRUE (v != nullptr);
3407+ ASSERT_EQ (enabled, g_variant_get_boolean (v));
3408+ g_variant_unref (v);
3409+ }
3410+}
3411+
3412+TEST_F (PhoneTest, UserTogglesGPS)
3413+{
3414+ bool enabled;
3415+ const char * const key = "gps-detection-enabled";
3416+ GActionGroup * ag = G_ACTION_GROUP (action_group);
3417+ GVariant * v;
3418+
3419+ // check that the current state is the default value of 'false'
3420+ v = g_action_group_get_action_state (ag, key);
3421+ ASSERT_TRUE (v != nullptr);
3422+ enabled = g_variant_get_boolean (v);
3423+ g_variant_unref (v);
3424+ ASSERT_FALSE (enabled);
3425+
3426+ // confirm that toggling menu updates the controller
3427+ for (int i=0; i<4; i++)
3428+ {
3429+ clear_callbacks ();
3430+
3431+ g_action_group_activate_action (ag, key, nullptr);
3432+ while (!gps_enabled_changed)
3433+ wait_msec (50);
3434+
3435+ ASSERT_TRUE (gps_enabled_changed);
3436+ enabled = !enabled;
3437+ ASSERT_EQ (enabled, gps_enabled);
3438+ }
3439+}
3440+
3441+TEST_F (PhoneTest, PlatformTogglesLocation)
3442+{
3443+ bool enabled;
3444+ const char * const key = "location-detection-enabled";
3445+ GActionGroup * ag = G_ACTION_GROUP (action_group);
3446+ GVariant * v;
3447+
3448+ // check that the current state is the default value of 'false'
3449+ v = g_action_group_get_action_state (ag, key);
3450+ ASSERT_TRUE (v != nullptr);
3451+ enabled = g_variant_get_boolean (v);
3452+ g_variant_unref (v);
3453+ ASSERT_FALSE (enabled);
3454+
3455+ // confirm that toggling the mock controller's GPS is reflected in the action state
3456+ for (int i=0; i<4; i++)
3457+ {
3458+ enabled = !enabled;
3459+
3460+ myController->set_location_service_enabled (enabled);
3461+ wait_for_action_state_change (key);
3462+ v = g_action_group_get_action_state (ag, key);
3463+ ASSERT_TRUE (v != nullptr);
3464+ ASSERT_EQ (enabled, g_variant_get_boolean (v));
3465+ g_variant_unref (v);
3466+ }
3467+}
3468+
3469+TEST_F (PhoneTest, UserTogglesLocation)
3470+{
3471+ bool enabled;
3472+ const char * const key = "location-detection-enabled";
3473+ GActionGroup * ag = G_ACTION_GROUP (action_group);
3474+ GVariant * v;
3475+
3476+ // check that the current state is the default value of 'false'
3477+ v = g_action_group_get_action_state (ag, key);
3478+ ASSERT_TRUE (v != nullptr);
3479+ enabled = g_variant_get_boolean (v);
3480+ g_variant_unref (v);
3481+ ASSERT_FALSE (enabled);
3482+
3483+ // confirm that toggling menu updates the controller
3484+ for (int i=0; i<4; i++)
3485+ {
3486+ clear_callbacks ();
3487+
3488+ g_action_group_activate_action (ag, key, nullptr);
3489+ while (!loc_enabled_changed)
3490+ wait_msec (50);
3491+
3492+ ASSERT_TRUE (loc_enabled_changed);
3493+ enabled = !enabled;
3494+ ASSERT_EQ (enabled, loc_enabled);
3495+ }
3496+}
3497
3498=== added file 'trim-lcov.py'
3499--- trim-lcov.py 1970-01-01 00:00:00 +0000
3500+++ trim-lcov.py 2013-08-26 21:42:23 +0000
3501@@ -0,0 +1,53 @@
3502+#!/usr/bin/python
3503+
3504+# This script removes branch and/or line coverage data for lines that
3505+# contain a particular substring.
3506+#
3507+# In the interest of "fairness" it removes all branch or coverage data
3508+# when a match is found -- not just negative data. It is therefore
3509+# likely that running this script will actually reduce the total number
3510+# of lines and branches that are marked as covered (in absolute terms).
3511+#
3512+# This script intentionally avoids checking for errors. Any exceptions
3513+# will trigger make to fail.
3514+#
3515+# Author: Ryan Lortie <desrt@desrt.ca>
3516+
3517+import sys
3518+
3519+line_suppress = ['g_assert_not_reached']
3520+branch_suppress = ['g_assert', 'g_return_if_fail', 'g_clear_object', 'g_clear_pointer', 'g_return_val_if_fail', 'G_DEFINE_TYPE']
3521+
3522+def check_suppress(suppressions, source, data):
3523+ line, _, rest = data.partition(',')
3524+ line = int(line) - 1
3525+
3526+ assert line < len(source)
3527+
3528+ for suppression in suppressions:
3529+ if suppression in source[line]:
3530+ return True
3531+
3532+ return False
3533+
3534+source = []
3535+for line in sys.stdin:
3536+ line = line[:-1]
3537+
3538+ keyword, _, rest = line.partition(':')
3539+
3540+ # Source file
3541+ if keyword == 'SF':
3542+ source = file(rest).readlines()
3543+
3544+ # Branch coverage data
3545+ elif keyword == 'BRDA':
3546+ if check_suppress(branch_suppress, source, rest):
3547+ continue
3548+
3549+ # Line coverage data
3550+ elif keyword == 'DA':
3551+ if check_suppress(line_suppress, source, rest):
3552+ continue
3553+
3554+ print line

Subscribers

People subscribed via source and target branches