Merge lp:~charlesk/indicator-power/coverage into lp:indicator-power/12.10
- coverage
- Merge into trunk.12.10
Status: | Merged |
---|---|
Merged at revision: | 142 |
Proposed branch: | lp:~charlesk/indicator-power/coverage |
Merge into: | lp:indicator-power/12.10 |
Diff against target: |
3858 lines (+2749/-712) 16 files modified
Makefile.am (+8/-27) configure.ac (+26/-1) m4/gtest.m4 (+63/-0) po/POTFILES.in (+2/-0) src/Makefile.am (+36/-0) src/dbus-listener.c (+247/-0) src/dbus-listener.h (+82/-0) src/device.c (+666/-0) src/device.h (+107/-0) src/indicator-power.c (+202/-684) src/indicator-power.h (+58/-0) tests/Makefile.am (+62/-0) tests/Makefile.am.strings (+38/-0) tests/test-dbus-listener.cc (+370/-0) tests/test-device.cc (+470/-0) tests/test-indicator.cc (+312/-0) |
To merge this branch: | bzr merge lp:~charlesk/indicator-power/coverage |
Related bugs: |
Reviewer | Review Type | Date Requested | Status |
---|---|---|---|
jenkins (community) | continuous-integration | Approve | |
Lars Karlitski (community) | Approve | ||
Review via email: mp+109028@code.launchpad.net |
This proposal supersedes a proposal from 2012-06-04.
Commit message
charles brings the code-coverage of this project above 90%.
Description of the change
revised to use most of lars' great suggestions
Lars Karlitski (larsu) wrote : Posted in a previous version of this proposal | # |
Charles Kerr (charlesk) wrote : Posted in a previous version of this proposal | # |
Lars, thanks for the great review!
> any reason you're using noinst_HEADERS instead of listing the headers
> in the libraries sources? (the latter is recommended for programs and
> convenience libs in the automake docs)
Fixed r204
> dbus-listener.c
>
> 305: g_signal_new is passed one too many arguments. Please add the
> docstring with the number and names of parameters to it [1]
Fixed r205
> dispose() is missing g_bus_unwatch_name (priv->watcher_id)
Fixed r206
> get_devices_cb:144: trailing whitespace ;)
Fixed r207
> the cancellable is passed into all functions and unreffed in dispose()
> is the cancellable cancelled on unref or do we need to do that explicitely?
> (I can't find anything in the docs)
This is a great catch. Looking at the gio code, my assumption was wrong,
it needs to be done explicitly.
Fixed r208
> dbus-listener.h:
> * 50: the signal name is overly complicated (it doesn't need to be namespaced
> to the class)
Fixed r209
> * indicator_
Fixed r210
> device.c:
> class_init: I prefer saving all pspecs in a static array and installing
> them all at once with g_object_
> using g_object_
Interesting, I don't see that in any of the other indicator code. TIL.
Changed r211
> * finalize doesn't chain up to the parent class
Fixed r212
> * get/set_property:
> - use G_OBJECT_
Fixed r213
> PROP_ICON is not handled
PROP_ICON was cruft, removed r211
> kind and state should check for sane input values
This is already done by glib's plumbing because the pspec defined the sane range. (No change)
> 260 ff: I don't think we can use Richard's code (indicators are CA, right?)
Before my refactoring, i-power was already doing this. One difference is now I'm giving proper attribution. (No change, but maybe a ted question?)
> indicator_
Fixed r214.
> 298: reference functions with 'function_name()' instead of #function_name in doc strings
Fixed r215.
> device.h: 43 ff: no need to namespace gobject properties (tbh, I wouldn't even #define them, but simply use the strings)
Fixed r216.
However I've kept the #defines since that idiom catches misspelled keys at compile time...
> indicator-power.c:
> * ref the floating widgets in the private struct
> (just something I noticed, it has nothing to do with this work)
Agreed, but unchanged for this pass...
> indicator-power.h:
> * device.h include is superfluous
Fixed r217
> test/test-
> * ensure_
I don't think this is correct. Are you sure?
Charles Kerr (charlesk) wrote : | # |
>> 260 ff: I don't think we can use Richard's code (indicators are CA, right?)
>
> Before my refactoring, i-power was already doing this. One difference is now I'm giving proper attribution. (No change, but maybe a ted question?)
Sure enough. Fixed r218.
Lars Karlitski (larsu) wrote : Posted in a previous version of this proposal | # |
Thanks for the quick fixes!
On 06/06/2012 10:28 PM, Charles Kerr wrote:
>> the cancellable is passed into all functions and unreffed in dispose()
>> is the cancellable cancelled on unref or do we need to do that explicitely?
>> (I can't find anything in the docs)
>
> This is a great catch. Looking at the gio code, my assumption was wrong,
> it needs to be done explicitly.
>
> Fixed r208
Thanks for checking.
> [...]
>> kind and state should check for sane input values
>
> This is already done by glib's plumbing because the pspec defined the sane range. (No change)
You're right of course. Sorry.
>> 260 ff: I don't think we can use Richard's code (indicators are CA, right?)
>
> Before my refactoring, i-power was already doing this. One difference is now I'm giving proper attribution. (No change, but maybe a ted question?)
Definitely a Ted question.
>> indicator_
>
> Fixed r214.
Hm, I was thinking more along the lines of
g_variant_
The fix in r214 only checks for a tuple with the correct number of elements.
>> test/test-
>> * ensure_
>
> I don't think this is correct. Are you sure?
I'm not sure. Actually, I think you might be right.
Charles Kerr (charlesk) wrote : | # |
> Hm, I was thinking more along the lines of
>
> g_variant_
Oh yes, that is better. Fixed r219
Keep it up, I love these improvements :)
Lars Karlitski (larsu) wrote : | # |
-----BEGIN PGP SIGNED MESSAGE-----
Hash: SHA1
On 06/07/2012 04:01 PM, Charles Kerr wrote:
>> Hm, I was thinking more along the lines of
>>
>> g_variant_
>
> Oh yes, that is better. Fixed r219
Very cool, thanks.
> Keep it up, I love these improvements :)
:)
review approve
-----BEGIN PGP SIGNATURE-----
Version: GnuPG v1.4.11 (GNU/Linux)
Comment: Using GnuPG with Mozilla - http://
iQEcBAEBAgAGBQJ
+xwhmXR5UnR0MX+
jThP3+3Y/
eeQo5FfoN2WIJf2
NI9LXjaJgJXSKwl
JS/dfmM93pEkksh
=Xwze
-----END PGP SIGNATURE-----
jenkins (martin-mrazik+qa) wrote : | # |
FAILED: Autolanding.
No commit message was specified.
http://
jenkins (martin-mrazik+qa) wrote : | # |
PASSED: Continuous integration, rev:220
http://
Allan LeSage (allanlesage) wrote : | # |
Attempting to kick off autolanding again. . . .
jenkins (martin-mrazik+qa) wrote : | # |
FAILED: Autolanding.
More details in the following jenkins job:
http://
- 221. By Charles Kerr
-
disable test-dbus-listener for now
jenkins (martin-mrazik+qa) wrote : | # |
PASSED: Continuous integration, rev:221
http://
Executed test runs:
SUCCESS: http://
SUCCESS: http://
Preview Diff
1 | === modified file 'Makefile.am' |
2 | --- Makefile.am 2012-03-27 20:34:42 +0000 |
3 | +++ Makefile.am 2012-07-11 17:08:19 +0000 |
4 | @@ -1,30 +1,11 @@ |
5 | -ACLOCAL_AMFLAGS = -I m4 ${ACLOCAL_FLAGS} |
6 | - |
7 | -SUBDIRS = \ |
8 | - po \ |
9 | - data |
10 | - |
11 | -################### |
12 | -# Indicator Stuff |
13 | -################### |
14 | - |
15 | -powerlibdir = $(INDICATORDIR) |
16 | -powerlib_LTLIBRARIES = libpower.la |
17 | -libpower_la_SOURCES = \ |
18 | - src/indicator-power.c |
19 | -libpower_la_CFLAGS = \ |
20 | - $(UPOWER_CFLAGS) \ |
21 | - $(INDICATOR_CFLAGS) \ |
22 | - $(COVERAGE_CFLAGS) \ |
23 | - -Wall -Werror \ |
24 | - -DG_LOG_DOMAIN=\"Indicator-Power\" |
25 | -libpower_la_LIBADD = \ |
26 | - $(UPOWER_LIBS) \ |
27 | - $(INDICATOR_LIBS) |
28 | -libpower_la_LDFLAGS = \ |
29 | - $(COVERAGE_LDFLAGS) \ |
30 | - -module \ |
31 | - -avoid-version |
32 | +SUBDIRS = po data src |
33 | + |
34 | +if BUILD_TESTS |
35 | +SUBDIRS += tests |
36 | +# build src first |
37 | +tests: src |
38 | +endif |
39 | + |
40 | |
41 | ############################################################ |
42 | |
43 | |
44 | === modified file 'configure.ac' |
45 | --- configure.ac 2012-04-11 15:02:18 +0000 |
46 | +++ configure.ac 2012-07-11 17:08:19 +0000 |
47 | @@ -11,7 +11,7 @@ |
48 | AC_CONFIG_MACRO_DIR([m4]) |
49 | AC_CONFIG_AUX_DIR([build-aux]) |
50 | |
51 | -AM_INIT_AUTOMAKE([1.11 -Wall foreign subdir-objects dist-xz]) |
52 | +AM_INIT_AUTOMAKE([1.11 -Wall foreign dist-xz]) |
53 | AM_MAINTAINER_MODE([enable]) |
54 | |
55 | AM_SILENT_RULES([yes]) |
56 | @@ -19,6 +19,7 @@ |
57 | # Check for programs |
58 | AC_PROG_CC |
59 | AM_PROG_CC_C_O |
60 | +AC_PROG_CXX |
61 | |
62 | # Initialize libtool |
63 | LT_PREREQ([2.2.6]) |
64 | @@ -48,6 +49,26 @@ |
65 | GLIB_GSETTINGS |
66 | |
67 | ########################### |
68 | +# Google Test framework |
69 | +########################### |
70 | + |
71 | +AC_ARG_ENABLE([tests], |
72 | + [AS_HELP_STRING([--disable-tests], [Disable test scripts and tools (default=auto)])], |
73 | + [enable_tests=${enableval}], |
74 | + [enable_tests=auto]) |
75 | +if test "x$enable_tests" != "xno"; then |
76 | + m4_include([m4/gtest.m4]) |
77 | + CHECK_GTEST |
78 | + CHECK_XORG_GTEST |
79 | + if test "x$enable_tests" = "xauto"; then |
80 | + enable_tests=${have_gtest} |
81 | + elif test "x$enable_tests" = "xyes" && test "x$have_gtest" != "xyes"; then |
82 | + AC_MSG_ERROR([tests were requested but gtest is not installed.]) |
83 | + fi |
84 | +fi |
85 | +AM_CONDITIONAL([BUILD_TESTS],[test "x$enable_tests" = "xyes"]) |
86 | + |
87 | +########################### |
88 | # gcov coverage reporting |
89 | ########################### |
90 | |
91 | @@ -119,6 +140,8 @@ |
92 | Makefile |
93 | po/Makefile.in |
94 | data/Makefile |
95 | +src/Makefile |
96 | +tests/Makefile |
97 | ]) |
98 | AC_OUTPUT |
99 | |
100 | @@ -132,5 +155,7 @@ |
101 | |
102 | Prefix: $prefix |
103 | Local Install: $with_localinstall |
104 | + Unit Tests: $enable_tests |
105 | gcov: $use_gcov |
106 | + |
107 | ]) |
108 | |
109 | === added file 'm4/gtest.m4' |
110 | --- m4/gtest.m4 1970-01-01 00:00:00 +0000 |
111 | +++ m4/gtest.m4 2012-07-11 17:08:19 +0000 |
112 | @@ -0,0 +1,63 @@ |
113 | +# Copyright (C) 2012 Canonical, Ltd. |
114 | +# |
115 | +# Permission is hereby granted, free of charge, to any person obtaining a copy |
116 | +# of this software and associated documentation files (the "Software"), to deal |
117 | +# in the Software without restriction, including without limitation the rights |
118 | +# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell |
119 | +# copies of the Software, and to permit persons to whom the Software is |
120 | +# furnished to do so, subject to the following conditions: |
121 | +# |
122 | +# The above copyright notice and this permission notice (including the next |
123 | +# paragraph) shall be included in all copies or substantial portions of the |
124 | +# Software. |
125 | +# |
126 | +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR |
127 | +# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, |
128 | +# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE |
129 | +# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER |
130 | +# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, |
131 | +# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE |
132 | +# SOFTWARE. |
133 | + |
134 | +# Checks whether the gtest source is available on the system. Allows for |
135 | +# adjusting the include and source path. Sets have_gtest=yes if the source is |
136 | +# present. Sets GTEST_CPPFLAGS and GTEST_SOURCE to the preprocessor flags and |
137 | +# source location respectively. |
138 | +AC_DEFUN([CHECK_GTEST], |
139 | +[ |
140 | + AC_ARG_WITH([gtest-include-path], |
141 | + [AS_HELP_STRING([--with-gtest-include-path], |
142 | + [location of the Google test headers])], |
143 | + [GTEST_CPPFLAGS="-I$withval"]) |
144 | + |
145 | + AC_ARG_WITH([gtest-source-path], |
146 | + [AS_HELP_STRING([--with-gtest-source-path], |
147 | + [location of the Google test sources, defaults to /usr/src/gtest])], |
148 | + [GTEST_SOURCE="$withval"], |
149 | + [GTEST_SOURCE="/usr/src/gtest"]) |
150 | + |
151 | + GTEST_CPPFLAGS="$GTEST_CPPFLAGS -I$GTEST_SOURCE" |
152 | + |
153 | + AC_LANG_PUSH([C++]) |
154 | + |
155 | + tmp_CPPFLAGS="$CPPFLAGS" |
156 | + CPPFLAGS="$CPPFLAGS $GTEST_CPPFLAGS" |
157 | + |
158 | + AC_CHECK_HEADER([gtest/gtest.h]) |
159 | + |
160 | + CPPFLAGS="$tmp_CPPFLAGS" |
161 | + |
162 | + AC_LANG_POP |
163 | + |
164 | + AC_CHECK_FILES([$GTEST_SOURCE/src/gtest-all.cc] |
165 | + [$GTEST_SOURCE/src/gtest_main.cc], |
166 | + [have_gtest_source=yes], |
167 | + [have_gtest_source=no]) |
168 | + |
169 | + AS_IF([test "x$ac_cv_header_gtest_gtest_h" = xyes -a \ |
170 | + "x$have_gtest_source" = xyes], |
171 | + [have_gtest=yes] |
172 | + [AC_SUBST(GTEST_CPPFLAGS)] |
173 | + [AC_SUBST(GTEST_SOURCE)], |
174 | + [have_gtest=no]) |
175 | +]) # CHECK_GTEST |
176 | |
177 | === modified file 'po/POTFILES.in' |
178 | --- po/POTFILES.in 2011-09-23 17:13:42 +0000 |
179 | +++ po/POTFILES.in 2012-07-11 17:08:19 +0000 |
180 | @@ -1,2 +1,4 @@ |
181 | data/com.canonical.indicator.power.gschema.xml.in |
182 | +src/device.c |
183 | +src/dbus-listener.c |
184 | src/indicator-power.c |
185 | |
186 | === added file 'src/Makefile.am' |
187 | --- src/Makefile.am 1970-01-01 00:00:00 +0000 |
188 | +++ src/Makefile.am 2012-07-11 17:08:19 +0000 |
189 | @@ -0,0 +1,36 @@ |
190 | +CLEANFILES = |
191 | +ACLOCAL_AMFLAGS = -I m4 ${ACLOCAL_FLAGS} |
192 | + |
193 | +################### |
194 | +# Indicator Stuff |
195 | +################### |
196 | + |
197 | +powerlibdir = $(INDICATORDIR) |
198 | +powerlib_LTLIBRARIES = libpower.la |
199 | + |
200 | +libpower_la_SOURCES = \ |
201 | + dbus-listener.c \ |
202 | + dbus-listener.h \ |
203 | + device.c \ |
204 | + device.h \ |
205 | + indicator-power.h \ |
206 | + indicator-power.c |
207 | + |
208 | +CLEANFILES += .libs/*.gcda .libs/*.gcno *.gcda *.gcno |
209 | + |
210 | +libpower_la_CFLAGS = \ |
211 | + $(UPOWER_CFLAGS) \ |
212 | + $(INDICATOR_CFLAGS) \ |
213 | + $(COVERAGE_CFLAGS) \ |
214 | + -Wall -Werror \ |
215 | + -DG_LOG_DOMAIN=\"Indicator-Power\" |
216 | + |
217 | +libpower_la_LIBADD = \ |
218 | + $(UPOWER_LIBS) \ |
219 | + $(INDICATOR_LIBS) |
220 | + |
221 | +libpower_la_LDFLAGS = \ |
222 | + $(COVERAGE_LDFLAGS) \ |
223 | + -module \ |
224 | + -avoid-version |
225 | + |
226 | |
227 | === added file 'src/dbus-listener.c' |
228 | --- src/dbus-listener.c 1970-01-01 00:00:00 +0000 |
229 | +++ src/dbus-listener.c 2012-07-11 17:08:19 +0000 |
230 | @@ -0,0 +1,247 @@ |
231 | +/* |
232 | + |
233 | +Listens on DBus for Power changes and passes them to an IndicatorPower |
234 | + |
235 | +Copyright 2012 Canonical Ltd. |
236 | + |
237 | +Authors: |
238 | + Charles Kerr <charles.kerr@canonical.com> |
239 | + |
240 | +This library is free software; you can redistribute it and/or |
241 | +modify it under the terms of the GNU General Public License |
242 | +version 3.0 as published by the Free Software Foundation. |
243 | + |
244 | +This library is distributed in the hope that it will be useful, |
245 | +but WITHOUT ANY WARRANTY; without even the implied warranty of |
246 | +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
247 | +GNU General Public License version 3.0 for more details. |
248 | + |
249 | +You should have received a copy of the GNU General Public |
250 | +License along with this library. If not, see |
251 | +<http://www.gnu.org/licenses/>. |
252 | +*/ |
253 | + |
254 | +#include "dbus-listener.h" |
255 | +#include "device.h" |
256 | + |
257 | +struct _IndicatorPowerDbusListenerPrivate |
258 | +{ |
259 | + GCancellable * cancellable; |
260 | + GDBusProxy * proxy; |
261 | + guint watcher_id; |
262 | +}; |
263 | + |
264 | +#define INDICATOR_POWER_DBUS_LISTENER_GET_PRIVATE(o) (INDICATOR_POWER_DBUS_LISTENER(o)->priv) |
265 | + |
266 | +/* Signals */ |
267 | +enum { |
268 | + SIGNAL_DEVICES, |
269 | + SIGNAL_LAST |
270 | +}; |
271 | +static guint signals[SIGNAL_LAST] = { 0 }; |
272 | + |
273 | + |
274 | +/* GObject stuff */ |
275 | +static void indicator_power_dbus_listener_class_init (IndicatorPowerDbusListenerClass *klass); |
276 | +static void indicator_power_dbus_listener_init (IndicatorPowerDbusListener *self); |
277 | +static void indicator_power_dbus_listener_dispose (GObject *object); |
278 | +static void indicator_power_dbus_listener_finalize (GObject *object); |
279 | + |
280 | +static void gsd_appeared_callback (GDBusConnection *connection, const gchar *name, const gchar *name_owner, gpointer user_data); |
281 | + |
282 | +/* LCOV_EXCL_START */ |
283 | +G_DEFINE_TYPE (IndicatorPowerDbusListener, indicator_power_dbus_listener, G_TYPE_OBJECT); |
284 | +/* LCOV_EXCL_STOP */ |
285 | + |
286 | +static void |
287 | +indicator_power_dbus_listener_class_init (IndicatorPowerDbusListenerClass *klass) |
288 | +{ |
289 | + GObjectClass *object_class = G_OBJECT_CLASS (klass); |
290 | + |
291 | + g_type_class_add_private (klass, sizeof (IndicatorPowerDbusListenerPrivate)); |
292 | + |
293 | + /* methods */ |
294 | + object_class->dispose = indicator_power_dbus_listener_dispose; |
295 | + object_class->finalize = indicator_power_dbus_listener_finalize; |
296 | + |
297 | + /** |
298 | + * IndicatorPowerDbusListener::devices-enumerated: |
299 | + * |
300 | + * @listener: the IndicatorPowerDbusListener |
301 | + * @devices: a GSList of #IndicatorPowerDevice objects. (transfer none) |
302 | + * |
303 | + * This is emitted each time a new set of devices is enumerated over the bus. |
304 | + */ |
305 | + signals[SIGNAL_DEVICES] = g_signal_new (INDICATOR_POWER_DBUS_LISTENER_DEVICES_ENUMERATED, |
306 | + G_TYPE_FROM_CLASS(klass), 0, |
307 | + G_STRUCT_OFFSET (IndicatorPowerDbusListenerClass, devices_enumerated), |
308 | + NULL, NULL, |
309 | + g_cclosure_marshal_VOID__POINTER, |
310 | + G_TYPE_NONE, 1, G_TYPE_POINTER); |
311 | +} |
312 | + |
313 | +/* Initialize an instance */ |
314 | +static void |
315 | +indicator_power_dbus_listener_init (IndicatorPowerDbusListener *self) |
316 | +{ |
317 | + IndicatorPowerDbusListenerPrivate * priv; |
318 | + |
319 | + priv = G_TYPE_INSTANCE_GET_PRIVATE (self, |
320 | + INDICATOR_POWER_DBUS_LISTENER_TYPE, |
321 | + IndicatorPowerDbusListenerPrivate); |
322 | + |
323 | + priv->cancellable = g_cancellable_new (); |
324 | + |
325 | + priv->watcher_id = g_bus_watch_name (G_BUS_TYPE_SESSION, |
326 | + GSD_SERVICE, |
327 | + G_BUS_NAME_WATCHER_FLAGS_NONE, |
328 | + gsd_appeared_callback, |
329 | + NULL, |
330 | + self, |
331 | + NULL); |
332 | + |
333 | + self->priv = priv; |
334 | +} |
335 | + |
336 | +static void |
337 | +indicator_power_dbus_listener_dispose (GObject *object) |
338 | +{ |
339 | + IndicatorPowerDbusListener * self = INDICATOR_POWER_DBUS_LISTENER(object); |
340 | + IndicatorPowerDbusListenerPrivate * priv = self->priv; |
341 | + |
342 | + g_clear_object (&priv->proxy); |
343 | + |
344 | + if (priv->cancellable != NULL) |
345 | + { |
346 | + g_cancellable_cancel (priv->cancellable); |
347 | + g_clear_object (&priv->cancellable); |
348 | + } |
349 | + |
350 | + if (priv->watcher_id) |
351 | + { |
352 | + g_bus_unwatch_name (priv->watcher_id); |
353 | + priv->watcher_id = 0; |
354 | + } |
355 | + |
356 | + G_OBJECT_CLASS (indicator_power_dbus_listener_parent_class)->dispose (object); |
357 | +} |
358 | + |
359 | +static void |
360 | +indicator_power_dbus_listener_finalize (GObject *object) |
361 | +{ |
362 | + G_OBJECT_CLASS (indicator_power_dbus_listener_parent_class)->finalize (object); |
363 | +} |
364 | + |
365 | +/*** |
366 | +**** |
367 | +***/ |
368 | + |
369 | +static void |
370 | +get_devices_cb (GObject * source_object, |
371 | + GAsyncResult * res, |
372 | + gpointer user_data) |
373 | +{ |
374 | + GError *error; |
375 | + GSList * devices = NULL; |
376 | + GVariant * devices_container; |
377 | + IndicatorPowerDbusListener * self = INDICATOR_POWER_DBUS_LISTENER (user_data); |
378 | + |
379 | + /* build an array of IndicatorPowerDevices from the DBus response */ |
380 | + error = NULL; |
381 | + devices_container = g_dbus_proxy_call_finish (G_DBUS_PROXY (source_object), res, &error); |
382 | + if (devices_container == NULL) |
383 | + { |
384 | + g_message ("Couldn't get devices: %s\n", error->message); |
385 | + g_error_free (error); |
386 | + } |
387 | + else |
388 | + { |
389 | + gsize i; |
390 | + GVariant * devices_variant = g_variant_get_child_value (devices_container, 0); |
391 | + const int device_count = devices_variant ? g_variant_n_children (devices_variant) : 0; |
392 | + |
393 | + for (i=0; i<device_count; i++) |
394 | + { |
395 | + GVariant * v = g_variant_get_child_value (devices_variant, i); |
396 | + devices = g_slist_prepend (devices, indicator_power_device_new_from_variant (v)); |
397 | + g_variant_unref (v); |
398 | + } |
399 | + |
400 | + devices = g_slist_reverse (devices); |
401 | + |
402 | + g_variant_unref (devices_variant); |
403 | + g_variant_unref (devices_container); |
404 | + } |
405 | + |
406 | + g_signal_emit (self, signals[SIGNAL_DEVICES], (GQuark)0, devices); |
407 | + g_slist_free_full (devices, g_object_unref); |
408 | +} |
409 | + |
410 | +static void |
411 | +request_device_list (IndicatorPowerDbusListener * self) |
412 | +{ |
413 | + g_dbus_proxy_call (self->priv->proxy, |
414 | + "GetDevices", |
415 | + NULL, |
416 | + G_DBUS_CALL_FLAGS_NONE, |
417 | + -1, |
418 | + self->priv->cancellable, |
419 | + get_devices_cb, |
420 | + self); |
421 | +} |
422 | + |
423 | +static void |
424 | +receive_properties_changed (GDBusProxy *proxy G_GNUC_UNUSED, |
425 | + GVariant *changed_properties G_GNUC_UNUSED, |
426 | + GStrv invalidated_properties G_GNUC_UNUSED, |
427 | + gpointer user_data) |
428 | +{ |
429 | + request_device_list (INDICATOR_POWER_DBUS_LISTENER(user_data)); |
430 | +} |
431 | + |
432 | + |
433 | +static void |
434 | +service_proxy_cb (GObject *object, |
435 | + GAsyncResult *res, |
436 | + gpointer user_data) |
437 | +{ |
438 | + GError * error = NULL; |
439 | + IndicatorPowerDbusListener * self = INDICATOR_POWER_DBUS_LISTENER(user_data); |
440 | + IndicatorPowerDbusListenerPrivate * priv = self->priv; |
441 | + |
442 | + priv->proxy = g_dbus_proxy_new_for_bus_finish (res, &error); |
443 | + |
444 | + if (error != NULL) |
445 | + { |
446 | + g_error ("Error creating proxy: %s", error->message); |
447 | + g_error_free (error); |
448 | + return; |
449 | + } |
450 | + |
451 | + /* we want to change the primary device changes */ |
452 | + g_signal_connect (priv->proxy, "g-properties-changed", |
453 | + G_CALLBACK (receive_properties_changed), user_data); |
454 | + |
455 | + /* get the initial state */ |
456 | + request_device_list (self); |
457 | +} |
458 | + |
459 | +static void |
460 | +gsd_appeared_callback (GDBusConnection *connection, |
461 | + const gchar *name, |
462 | + const gchar *name_owner, |
463 | + gpointer user_data) |
464 | +{ |
465 | + IndicatorPowerDbusListener * self = INDICATOR_POWER_DBUS_LISTENER(user_data); |
466 | + IndicatorPowerDbusListenerPrivate * priv = self->priv; |
467 | + |
468 | + g_dbus_proxy_new (connection, |
469 | + G_DBUS_PROXY_FLAGS_DO_NOT_AUTO_START, |
470 | + NULL, |
471 | + name, |
472 | + GSD_POWER_DBUS_PATH, |
473 | + GSD_POWER_DBUS_INTERFACE, |
474 | + priv->cancellable, |
475 | + service_proxy_cb, |
476 | + self); |
477 | +} |
478 | |
479 | === added file 'src/dbus-listener.h' |
480 | --- src/dbus-listener.h 1970-01-01 00:00:00 +0000 |
481 | +++ src/dbus-listener.h 2012-07-11 17:08:19 +0000 |
482 | @@ -0,0 +1,82 @@ |
483 | +/* |
484 | + |
485 | +Listens for Power changes from org.gnome.SettingsDaemon.Power on Dbus |
486 | + |
487 | +Copyright 2012 Canonical Ltd. |
488 | + |
489 | +Authors: |
490 | + Javier Jardon <javier.jardon@codethink.co.uk> |
491 | + Charles Kerr <charles.kerr@canonical.com> |
492 | + |
493 | +This library is free software; you can redistribute it and/or |
494 | +modify it under the terms of the GNU General Public License |
495 | +version 3.0 as published by the Free Software Foundation. |
496 | + |
497 | +This library is distributed in the hope that it will be useful, |
498 | +but WITHOUT ANY WARRANTY; without even the implied warranty of |
499 | +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
500 | +GNU General Public License version 3.0 for more details. |
501 | + |
502 | +You should have received a copy of the GNU General Public |
503 | +License along with this library. If not, see |
504 | +<http://www.gnu.org/licenses/>. |
505 | +*/ |
506 | + |
507 | +#ifndef __INDICATOR_POWER_DBUS_LISTENER_H__ |
508 | +#define __INDICATOR_POWER_DBUS_LISTENER_H__ |
509 | + |
510 | +#include <glib-object.h> |
511 | +#include <libupower-glib/upower.h> |
512 | + |
513 | +G_BEGIN_DECLS |
514 | + |
515 | +#define INDICATOR_POWER_DBUS_LISTENER_TYPE (indicator_power_dbus_listener_get_type ()) |
516 | +#define INDICATOR_POWER_DBUS_LISTENER(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), INDICATOR_POWER_DBUS_LISTENER_TYPE, IndicatorPowerDbusListener)) |
517 | +#define INDICATOR_POWER_DBUS_LISTENER_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), INDICATOR_POWER_DBUS_LISTENER_TYPE, IndicatorPowerDbusListenerClass)) |
518 | +#define INDICATOR_IS_POWER_DBUS_LISTENER(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), INDICATOR_POWER_DBUS_LISTENER_TYPE)) |
519 | +#define INDICATOR_IS_POWER_DBUS_LISTENER_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), INDICATOR_POWER_DBUS_LISTENER_TYPE)) |
520 | +#define INDICATOR_POWER_DBUS_LISTENER_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), INDICATOR_POWER_DBUS_LISTENER_TYPE, IndicatorPowerDbusListenerClass)) |
521 | + |
522 | +typedef struct _IndicatorPowerDbusListener IndicatorPowerDbusListener; |
523 | +typedef struct _IndicatorPowerDbusListenerClass IndicatorPowerDbusListenerClass; |
524 | +typedef struct _IndicatorPowerDbusListenerPrivate IndicatorPowerDbusListenerPrivate; |
525 | + |
526 | +#define GSD_SERVICE "org.gnome.SettingsDaemon" |
527 | +#define GSD_PATH "/org/gnome/SettingsDaemon" |
528 | +#define GSD_POWER_DBUS_INTERFACE GSD_SERVICE ".Power" |
529 | +#define GSD_POWER_DBUS_PATH GSD_PATH "/Power" |
530 | + |
531 | +/* signals */ |
532 | +#define INDICATOR_POWER_DBUS_LISTENER_DEVICES_ENUMERATED "devices-enumerated" |
533 | + |
534 | +/** |
535 | + * IndicatorPowerDbusListenerClass: |
536 | + * @parent_class: #GObjectClass |
537 | + */ |
538 | +struct _IndicatorPowerDbusListenerClass |
539 | +{ |
540 | + GObjectClass parent_class; |
541 | + |
542 | + void (* devices_enumerated) (IndicatorPowerDbusListener*, GSList * devices); |
543 | +}; |
544 | + |
545 | +/** |
546 | + * IndicatorPowerDbusListener: |
547 | + * @parent: #GObject |
548 | + * @priv: A cached reference to the private data for the instance. |
549 | +*/ |
550 | +struct _IndicatorPowerDbusListener |
551 | +{ |
552 | + GObject parent; |
553 | + IndicatorPowerDbusListenerPrivate * priv; |
554 | +}; |
555 | + |
556 | +/*** |
557 | +**** |
558 | +***/ |
559 | + |
560 | +GType indicator_power_dbus_listener_get_type (void); |
561 | + |
562 | +G_END_DECLS |
563 | + |
564 | +#endif |
565 | |
566 | === added file 'src/device.c' |
567 | --- src/device.c 1970-01-01 00:00:00 +0000 |
568 | +++ src/device.c 2012-07-11 17:08:19 +0000 |
569 | @@ -0,0 +1,666 @@ |
570 | +/* |
571 | + |
572 | +A simple Device structure used internally by indicator-power |
573 | + |
574 | +Copyright 2012 Canonical Ltd. |
575 | + |
576 | +Authors: |
577 | + Charles Kerr <charles.kerr@canonical.com> |
578 | + |
579 | +This library is free software; you can redistribute it and/or |
580 | +modify it under the terms of the GNU General Public License |
581 | +version 3.0 as published by the Free Software Foundation. |
582 | + |
583 | +This library is distributed in the hope that it will be useful, |
584 | +but WITHOUT ANY WARRANTY; without even the implied warranty of |
585 | +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
586 | +GNU General Public License version 3.0 for more details. |
587 | + |
588 | +You should have received a copy of the GNU General Public |
589 | +License along with this library. If not, see |
590 | +<http://www.gnu.org/licenses/>. |
591 | +*/ |
592 | + |
593 | +#ifdef HAVE_CONFIG_H |
594 | + #include "config.h" |
595 | +#endif |
596 | + |
597 | +#include <glib/gi18n.h> |
598 | + |
599 | +#include "device.h" |
600 | + |
601 | +struct _IndicatorPowerDevicePrivate |
602 | +{ |
603 | + UpDeviceKind kind; |
604 | + UpDeviceState state; |
605 | + gchar * object_path; |
606 | + gdouble percentage; |
607 | + time_t time; |
608 | +}; |
609 | + |
610 | +#define INDICATOR_POWER_DEVICE_GET_PRIVATE(o) (INDICATOR_POWER_DEVICE(o)->priv) |
611 | + |
612 | +/* Properties */ |
613 | +/* Enum for the properties so that they can be quickly found and looked up. */ |
614 | +enum { |
615 | + PROP_0, |
616 | + PROP_KIND, |
617 | + PROP_STATE, |
618 | + PROP_OBJECT_PATH, |
619 | + PROP_PERCENTAGE, |
620 | + PROP_TIME, |
621 | + N_PROPERTIES |
622 | +}; |
623 | + |
624 | +static GParamSpec * properties[N_PROPERTIES]; |
625 | + |
626 | +/* GObject stuff */ |
627 | +static void indicator_power_device_class_init (IndicatorPowerDeviceClass *klass); |
628 | +static void indicator_power_device_init (IndicatorPowerDevice *self); |
629 | +static void indicator_power_device_dispose (GObject *object); |
630 | +static void indicator_power_device_finalize (GObject *object); |
631 | +static void set_property (GObject*, guint prop_id, const GValue*, GParamSpec* ); |
632 | +static void get_property (GObject*, guint prop_id, GValue*, GParamSpec* ); |
633 | + |
634 | +/* LCOV_EXCL_START */ |
635 | +G_DEFINE_TYPE (IndicatorPowerDevice, indicator_power_device, G_TYPE_OBJECT); |
636 | +/* LCOV_EXCL_STOP */ |
637 | + |
638 | +static void |
639 | +indicator_power_device_class_init (IndicatorPowerDeviceClass *klass) |
640 | +{ |
641 | + GObjectClass *object_class = G_OBJECT_CLASS (klass); |
642 | + |
643 | + g_type_class_add_private (klass, sizeof (IndicatorPowerDevicePrivate)); |
644 | + |
645 | + object_class->dispose = indicator_power_device_dispose; |
646 | + object_class->finalize = indicator_power_device_finalize; |
647 | + object_class->set_property = set_property; |
648 | + object_class->get_property = get_property; |
649 | + |
650 | + properties[PROP_KIND] = g_param_spec_int (INDICATOR_POWER_DEVICE_KIND, |
651 | + "kind", |
652 | + "The device's UpDeviceKind", |
653 | + UP_DEVICE_KIND_UNKNOWN, UP_DEVICE_KIND_LAST, |
654 | + UP_DEVICE_KIND_UNKNOWN, |
655 | + G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS); |
656 | + |
657 | + properties[PROP_STATE] = g_param_spec_int (INDICATOR_POWER_DEVICE_STATE, |
658 | + "state", |
659 | + "The device's UpDeviceState", |
660 | + UP_DEVICE_STATE_UNKNOWN, UP_DEVICE_STATE_LAST, |
661 | + UP_DEVICE_STATE_UNKNOWN, |
662 | + G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS); |
663 | + |
664 | + properties[PROP_OBJECT_PATH] = g_param_spec_string (INDICATOR_POWER_DEVICE_OBJECT_PATH, |
665 | + "object path", |
666 | + "The device's DBus object path", |
667 | + NULL, |
668 | + G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS); |
669 | + |
670 | + properties[PROP_PERCENTAGE] = g_param_spec_double (INDICATOR_POWER_DEVICE_PERCENTAGE, |
671 | + "percentage", |
672 | + "percent charged", |
673 | + 0.0, 100.0, |
674 | + 0.0, |
675 | + G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS); |
676 | + |
677 | + properties[PROP_TIME] = g_param_spec_uint64 (INDICATOR_POWER_DEVICE_TIME, |
678 | + "time", |
679 | + "time left", |
680 | + 0, G_MAXUINT64, |
681 | + 0, |
682 | + G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS); |
683 | + |
684 | + g_object_class_install_properties (object_class, N_PROPERTIES, properties); |
685 | +} |
686 | + |
687 | +/* Initialize an instance */ |
688 | +static void |
689 | +indicator_power_device_init (IndicatorPowerDevice *self) |
690 | +{ |
691 | + IndicatorPowerDevicePrivate * priv; |
692 | + |
693 | + priv = G_TYPE_INSTANCE_GET_PRIVATE (self, INDICATOR_POWER_DEVICE_TYPE, |
694 | + IndicatorPowerDevicePrivate); |
695 | + priv->kind = UP_DEVICE_KIND_UNKNOWN; |
696 | + priv->state = UP_DEVICE_STATE_UNKNOWN; |
697 | + priv->object_path = NULL; |
698 | + priv->percentage = 0.0; |
699 | + priv->time = 0; |
700 | + |
701 | + self->priv = priv; |
702 | +} |
703 | + |
704 | +static void |
705 | +indicator_power_device_dispose (GObject *object) |
706 | +{ |
707 | + G_OBJECT_CLASS (indicator_power_device_parent_class)->dispose (object); |
708 | +} |
709 | + |
710 | +static void |
711 | +indicator_power_device_finalize (GObject *object) |
712 | +{ |
713 | + IndicatorPowerDevice * self = INDICATOR_POWER_DEVICE(object); |
714 | + IndicatorPowerDevicePrivate * priv = self->priv; |
715 | + |
716 | + g_clear_pointer (&priv->object_path, g_free); |
717 | + |
718 | + G_OBJECT_CLASS (indicator_power_device_parent_class)->finalize (object); |
719 | +} |
720 | + |
721 | +/*** |
722 | +**** |
723 | +***/ |
724 | + |
725 | +static void |
726 | +get_property (GObject * o, guint prop_id, GValue * value, GParamSpec * pspec) |
727 | +{ |
728 | + IndicatorPowerDevice * self = INDICATOR_POWER_DEVICE(o); |
729 | + IndicatorPowerDevicePrivate * priv = self->priv; |
730 | + |
731 | + switch (prop_id) |
732 | + { |
733 | + case PROP_KIND: |
734 | + g_value_set_int (value, priv->kind); |
735 | + break; |
736 | + |
737 | + case PROP_STATE: |
738 | + g_value_set_int (value, priv->state); |
739 | + break; |
740 | + |
741 | + case PROP_OBJECT_PATH: |
742 | + g_value_set_string (value, priv->object_path); |
743 | + break; |
744 | + |
745 | + case PROP_PERCENTAGE: |
746 | + g_value_set_double (value, priv->percentage); |
747 | + break; |
748 | + |
749 | + case PROP_TIME: |
750 | + g_value_set_uint64 (value, priv->time); |
751 | + break; |
752 | + |
753 | + default: |
754 | + G_OBJECT_WARN_INVALID_PROPERTY_ID(o, prop_id, pspec); |
755 | + break; |
756 | + } |
757 | +} |
758 | + |
759 | +static void |
760 | +set_property (GObject * o, guint prop_id, const GValue * value, GParamSpec * pspec) |
761 | +{ |
762 | + IndicatorPowerDevice * self = INDICATOR_POWER_DEVICE(o); |
763 | + IndicatorPowerDevicePrivate * priv = self->priv; |
764 | + |
765 | + switch (prop_id) |
766 | + { |
767 | + case PROP_KIND: |
768 | + priv->kind = g_value_get_int (value); |
769 | + break; |
770 | + |
771 | + case PROP_STATE: |
772 | + priv->state = g_value_get_int (value); |
773 | + break; |
774 | + |
775 | + case PROP_OBJECT_PATH: |
776 | + g_free (priv->object_path); |
777 | + priv->object_path = g_value_dup_string (value); |
778 | + break; |
779 | + |
780 | + case PROP_PERCENTAGE: |
781 | + priv->percentage = g_value_get_double (value); |
782 | + break; |
783 | + |
784 | + case PROP_TIME: |
785 | + priv->time = g_value_get_uint64(value); |
786 | + break; |
787 | + |
788 | + default: |
789 | + G_OBJECT_WARN_INVALID_PROPERTY_ID(o, prop_id, pspec); |
790 | + break; |
791 | + } |
792 | +} |
793 | + |
794 | +/*** |
795 | +**** Accessors |
796 | +***/ |
797 | + |
798 | +UpDeviceKind |
799 | +indicator_power_device_get_kind (const IndicatorPowerDevice * device) |
800 | +{ |
801 | + /* LCOV_EXCL_START */ |
802 | + g_return_val_if_fail (INDICATOR_IS_POWER_DEVICE(device), UP_DEVICE_KIND_UNKNOWN); |
803 | + /* LCOV_EXCL_STOP */ |
804 | + |
805 | + return device->priv->kind; |
806 | +} |
807 | + |
808 | +UpDeviceState |
809 | +indicator_power_device_get_state (const IndicatorPowerDevice * device) |
810 | +{ |
811 | + /* LCOV_EXCL_START */ |
812 | + g_return_val_if_fail (INDICATOR_IS_POWER_DEVICE(device), UP_DEVICE_STATE_UNKNOWN); |
813 | + /* LCOV_EXCL_STOP */ |
814 | + |
815 | + return device->priv->state; |
816 | +} |
817 | + |
818 | +const gchar * |
819 | +indicator_power_device_get_object_path (const IndicatorPowerDevice * device) |
820 | +{ |
821 | + /* LCOV_EXCL_START */ |
822 | + g_return_val_if_fail (INDICATOR_IS_POWER_DEVICE(device), NULL); |
823 | + /* LCOV_EXCL_STOP */ |
824 | + |
825 | + return device->priv->object_path; |
826 | +} |
827 | + |
828 | +gdouble |
829 | +indicator_power_device_get_percentage (const IndicatorPowerDevice * device) |
830 | +{ |
831 | + /* LCOV_EXCL_START */ |
832 | + g_return_val_if_fail (INDICATOR_IS_POWER_DEVICE(device), 0.0); |
833 | + /* LCOV_EXCL_STOP */ |
834 | + |
835 | + return device->priv->percentage; |
836 | +} |
837 | + |
838 | +time_t |
839 | +indicator_power_device_get_time (const IndicatorPowerDevice * device) |
840 | +{ |
841 | + /* LCOV_EXCL_START */ |
842 | + g_return_val_if_fail (INDICATOR_IS_POWER_DEVICE(device), (time_t)0); |
843 | + /* LCOV_EXCL_STOP */ |
844 | + |
845 | + return device->priv->time; |
846 | +} |
847 | + |
848 | +/*** |
849 | +**** |
850 | +**** |
851 | +***/ |
852 | + |
853 | +static const gchar * |
854 | +get_device_icon_suffix (gdouble percentage) |
855 | +{ |
856 | + if (percentage >= 60) return "full"; |
857 | + if (percentage >= 30) return "good"; |
858 | + if (percentage >= 10) return "low"; |
859 | + return "caution"; |
860 | +} |
861 | + |
862 | +static const gchar * |
863 | +get_device_icon_index (gdouble percentage) |
864 | +{ |
865 | + if (percentage >= 90) return "100"; |
866 | + if (percentage >= 70) return "080"; |
867 | + if (percentage >= 50) return "060"; |
868 | + if (percentage >= 30) return "040"; |
869 | + if (percentage >= 10) return "020"; |
870 | + return "000"; |
871 | +} |
872 | + |
873 | +/** |
874 | + indicator_power_device_get_icon_names: |
875 | + @device: #IndicatorPowerDevice from which to generate the icon names |
876 | + |
877 | + This function's logic differs from GSD's power plugin in some ways: |
878 | + |
879 | + 1. All charging batteries use the same icon regardless of progress. |
880 | + <https://bugs.launchpad.net/indicator-power/+bug/824629/comments/7> |
881 | + |
882 | + 2. For discharging batteries, we decide whether or not to use the 'caution' |
883 | + icon based on whether or not we have <= 30 minutes remaining, rather than |
884 | + looking at the battery's percentage left. |
885 | + <https://bugs.launchpad.net/indicator-power/+bug/743823> |
886 | + |
887 | + See also indicator_power_device_get_gicon(). |
888 | + |
889 | + Return value: (array zero-terminated=1) (transfer full): |
890 | + A GStrv of icon names suitable for passing to g_themed_icon_new_from_names(). |
891 | + Free with g_strfreev() when done. |
892 | +*/ |
893 | +GStrv |
894 | +indicator_power_device_get_icon_names (const IndicatorPowerDevice * device) |
895 | +{ |
896 | + const gchar *suffix_str; |
897 | + const gchar *index_str; |
898 | + |
899 | + /* LCOV_EXCL_START */ |
900 | + g_return_val_if_fail (INDICATOR_IS_POWER_DEVICE(device), NULL); |
901 | + /* LCOV_EXCL_STOP */ |
902 | + |
903 | + gdouble percentage = indicator_power_device_get_percentage (device); |
904 | + const UpDeviceKind kind = indicator_power_device_get_kind (device); |
905 | + const UpDeviceState state = indicator_power_device_get_state (device); |
906 | + const gchar * kind_str = kind_str = up_device_kind_to_string (kind); |
907 | + |
908 | + GPtrArray * names = g_ptr_array_new (); |
909 | + |
910 | + if (kind == UP_DEVICE_KIND_LINE_POWER) |
911 | + { |
912 | + g_ptr_array_add (names, g_strdup("ac-adapter-symbolic")); |
913 | + g_ptr_array_add (names, g_strdup("ac-adapter")); |
914 | + } |
915 | + else if (kind == UP_DEVICE_KIND_MONITOR) |
916 | + { |
917 | + g_ptr_array_add (names, g_strdup("gpm-monitor-symbolic")); |
918 | + g_ptr_array_add (names, g_strdup("gpm-monitor")); |
919 | + } |
920 | + else switch (state) |
921 | + { |
922 | + case UP_DEVICE_STATE_EMPTY: |
923 | + g_ptr_array_add (names, g_strdup("battery-empty-symbolic")); |
924 | + g_ptr_array_add (names, g_strdup_printf("gpm-%s-empty", kind_str)); |
925 | + g_ptr_array_add (names, g_strdup_printf("gpm-%s-000", kind_str)); |
926 | + g_ptr_array_add (names, g_strdup("battery-empty")); |
927 | + break; |
928 | + |
929 | + case UP_DEVICE_STATE_FULLY_CHARGED: |
930 | + g_ptr_array_add (names, g_strdup("battery-full-charged-symbolic")); |
931 | + g_ptr_array_add (names, g_strdup("battery-full-charging-symbolic")); |
932 | + g_ptr_array_add (names, g_strdup_printf("gpm-%s-full", kind_str)); |
933 | + g_ptr_array_add (names, g_strdup_printf("gpm-%s-100", kind_str)); |
934 | + g_ptr_array_add (names, g_strdup("battery-full-charged")); |
935 | + g_ptr_array_add (names, g_strdup("battery-full-charging")); |
936 | + break; |
937 | + |
938 | + case UP_DEVICE_STATE_CHARGING: |
939 | + case UP_DEVICE_STATE_PENDING_CHARGE: |
940 | + /* When charging, always use the same icon regardless of percentage. |
941 | + <http://bugs.launchpad.net/indicator-power/+bug/824629> */ |
942 | + percentage = 0; |
943 | + |
944 | + suffix_str = get_device_icon_suffix (percentage); |
945 | + index_str = get_device_icon_index (percentage); |
946 | + g_ptr_array_add (names, g_strdup_printf ("battery-%s-charging-symbolic", suffix_str)); |
947 | + g_ptr_array_add (names, g_strdup_printf ("gpm-%s-%s-charging", kind_str, index_str)); |
948 | + g_ptr_array_add (names, g_strdup_printf ("battery-%s-charging", suffix_str)); |
949 | + break; |
950 | + |
951 | + case UP_DEVICE_STATE_DISCHARGING: |
952 | + case UP_DEVICE_STATE_PENDING_DISCHARGE: |
953 | + /* Don't show the caution/red icons unless we have <=30 min left. |
954 | + <https://bugs.launchpad.net/indicator-power/+bug/743823> |
955 | + Themes use the caution color when the percentage is 0% or 20%, |
956 | + so if we have >30 min left, use 30% as the icon's percentage floor */ |
957 | + if (indicator_power_device_get_time (device) > (30*60)) |
958 | + percentage = MAX(percentage, 30); |
959 | + |
960 | + suffix_str = get_device_icon_suffix (percentage); |
961 | + index_str = get_device_icon_index (percentage); |
962 | + g_ptr_array_add (names, g_strdup_printf ("battery-%s-symbolic", suffix_str)); |
963 | + g_ptr_array_add (names, g_strdup_printf ("gpm-%s-%s", kind_str, index_str)); |
964 | + g_ptr_array_add (names, g_strdup_printf ("battery-%s", suffix_str)); |
965 | + break; |
966 | + |
967 | + default: |
968 | + g_ptr_array_add (names, g_strdup("battery-missing-symbolic")); |
969 | + g_ptr_array_add (names, g_strdup("gpm-battery-missing")); |
970 | + g_ptr_array_add (names, g_strdup("battery-missing")); |
971 | + } |
972 | + |
973 | + g_ptr_array_add (names, NULL); /* terminates the strv */ |
974 | + return (GStrv) g_ptr_array_free (names, FALSE); |
975 | +} |
976 | + |
977 | +/** |
978 | + indicator_power_device_get_gicon: |
979 | + @device: #IndicatorPowerDevice to generate the icon names from |
980 | + |
981 | + A convenience function to call g_themed_icon_new_from_names() |
982 | + with the names returned by indicator_power_device_get_icon_names() |
983 | + |
984 | + Return value: (transfer full): A themed GIcon |
985 | +*/ |
986 | +GIcon * |
987 | +indicator_power_device_get_gicon (const IndicatorPowerDevice * device) |
988 | +{ |
989 | + GStrv names = indicator_power_device_get_icon_names (device); |
990 | + GIcon * icon = g_themed_icon_new_from_names (names, -1); |
991 | + g_strfreev (names); |
992 | + return icon; |
993 | +} |
994 | + |
995 | +/*** |
996 | +**** |
997 | +***/ |
998 | + |
999 | +static void |
1000 | +get_timestring (guint64 time_secs, |
1001 | + gchar **short_timestring, |
1002 | + gchar **detailed_timestring) |
1003 | +{ |
1004 | + gint hours; |
1005 | + gint minutes; |
1006 | + |
1007 | + /* Add 0.5 to do rounding */ |
1008 | + minutes = (int) ( ( time_secs / 60.0 ) + 0.5 ); |
1009 | + |
1010 | + if (minutes == 0) |
1011 | + { |
1012 | + *short_timestring = g_strdup (_("Unknown time")); |
1013 | + *detailed_timestring = g_strdup (_("Unknown time")); |
1014 | + |
1015 | + return; |
1016 | + } |
1017 | + |
1018 | + if (minutes < 60) |
1019 | + { |
1020 | + *short_timestring = g_strdup_printf ("0:%.2i", minutes); |
1021 | + *detailed_timestring = g_strdup_printf (g_dngettext (GETTEXT_PACKAGE, "%i minute", |
1022 | + "%i minutes", |
1023 | + minutes), minutes); |
1024 | + return; |
1025 | + } |
1026 | + |
1027 | + hours = minutes / 60; |
1028 | + minutes = minutes % 60; |
1029 | + |
1030 | + *short_timestring = g_strdup_printf ("%i:%.2i", hours, minutes); |
1031 | + |
1032 | + if (minutes == 0) |
1033 | + { |
1034 | + *detailed_timestring = g_strdup_printf (g_dngettext (GETTEXT_PACKAGE, |
1035 | + "%i hour", |
1036 | + "%i hours", |
1037 | + hours), hours); |
1038 | + } |
1039 | + else |
1040 | + { |
1041 | + /* TRANSLATOR: "%i %s %i %s" are "%i hours %i minutes" |
1042 | + * Swap order with "%2$s %2$i %1$s %1$i if needed */ |
1043 | + *detailed_timestring = g_strdup_printf (_("%i %s %i %s"), |
1044 | + hours, g_dngettext (GETTEXT_PACKAGE, "hour", "hours", hours), |
1045 | + minutes, g_dngettext (GETTEXT_PACKAGE, "minute", "minutes", minutes)); |
1046 | + } |
1047 | +} |
1048 | + |
1049 | +static const gchar * |
1050 | +device_kind_to_localised_string (UpDeviceKind kind) |
1051 | +{ |
1052 | + const gchar *text = NULL; |
1053 | + |
1054 | + switch (kind) { |
1055 | + case UP_DEVICE_KIND_LINE_POWER: |
1056 | + /* TRANSLATORS: system power cord */ |
1057 | + text = _("AC Adapter"); |
1058 | + break; |
1059 | + case UP_DEVICE_KIND_BATTERY: |
1060 | + /* TRANSLATORS: laptop primary battery */ |
1061 | + text = _("Battery"); |
1062 | + break; |
1063 | + case UP_DEVICE_KIND_UPS: |
1064 | + /* TRANSLATORS: battery-backed AC power source */ |
1065 | + text = _("UPS"); |
1066 | + break; |
1067 | + case UP_DEVICE_KIND_MONITOR: |
1068 | + /* TRANSLATORS: a monitor is a device to measure voltage and current */ |
1069 | + text = _("Monitor"); |
1070 | + break; |
1071 | + case UP_DEVICE_KIND_MOUSE: |
1072 | + /* TRANSLATORS: wireless mice with internal batteries */ |
1073 | + text = _("Mouse"); |
1074 | + break; |
1075 | + case UP_DEVICE_KIND_KEYBOARD: |
1076 | + /* TRANSLATORS: wireless keyboard with internal battery */ |
1077 | + text = _("Keyboard"); |
1078 | + break; |
1079 | + case UP_DEVICE_KIND_PDA: |
1080 | + /* TRANSLATORS: portable device */ |
1081 | + text = _("PDA"); |
1082 | + break; |
1083 | + case UP_DEVICE_KIND_PHONE: |
1084 | + /* TRANSLATORS: cell phone (mobile...) */ |
1085 | + text = _("Cell phone"); |
1086 | + break; |
1087 | + case UP_DEVICE_KIND_MEDIA_PLAYER: |
1088 | + /* TRANSLATORS: media player, mp3 etc */ |
1089 | + text = _("Media player"); |
1090 | + break; |
1091 | + case UP_DEVICE_KIND_TABLET: |
1092 | + /* TRANSLATORS: tablet device */ |
1093 | + text = _("Tablet"); |
1094 | + break; |
1095 | + case UP_DEVICE_KIND_COMPUTER: |
1096 | + /* TRANSLATORS: tablet device */ |
1097 | + text = _("Computer"); |
1098 | + break; |
1099 | + default: |
1100 | + g_warning ("enum unrecognised: %i", kind); |
1101 | + text = up_device_kind_to_string (kind); |
1102 | + } |
1103 | + |
1104 | + return text; |
1105 | +} |
1106 | + |
1107 | +void |
1108 | +indicator_power_device_get_time_details (const IndicatorPowerDevice * device, |
1109 | + gchar ** short_details, |
1110 | + gchar ** details, |
1111 | + gchar ** accessible_name) |
1112 | +{ |
1113 | + if (!INDICATOR_IS_POWER_DEVICE(device)) |
1114 | + { |
1115 | + *short_details = NULL; |
1116 | + *details = NULL; |
1117 | + *accessible_name = NULL; |
1118 | + g_warning ("%s: %p is not an IndicatorPowerDevice", G_STRFUNC, device); |
1119 | + return; |
1120 | + } |
1121 | + |
1122 | + const time_t time = indicator_power_device_get_time (device); |
1123 | + const UpDeviceState state = indicator_power_device_get_state (device); |
1124 | + const gdouble percentage = indicator_power_device_get_percentage (device); |
1125 | + const UpDeviceKind kind = indicator_power_device_get_kind (device); |
1126 | + const gchar * device_name = device_kind_to_localised_string (kind); |
1127 | + |
1128 | + if (time > 0) |
1129 | + { |
1130 | + gchar *short_timestring = NULL; |
1131 | + gchar *detailed_timestring = NULL; |
1132 | + |
1133 | + get_timestring (time, |
1134 | + &short_timestring, |
1135 | + &detailed_timestring); |
1136 | + |
1137 | + if (state == UP_DEVICE_STATE_CHARGING) |
1138 | + { |
1139 | + /* TRANSLATORS: %2 is a time string, e.g. "1 hour 5 minutes" */ |
1140 | + *accessible_name = g_strdup_printf (_("%s (%s to charge (%.0lf%%))"), device_name, detailed_timestring, percentage); |
1141 | + *details = g_strdup_printf (_("%s (%s to charge)"), device_name, short_timestring); |
1142 | + *short_details = g_strdup_printf ("(%s)", short_timestring); |
1143 | + } |
1144 | + else if ((state == UP_DEVICE_STATE_DISCHARGING) && (time > (60*60*12))) |
1145 | + { |
1146 | + *accessible_name = g_strdup_printf (_("%s"), device_name); |
1147 | + *details = g_strdup_printf (_("%s"), device_name); |
1148 | + *short_details = g_strdup (short_timestring); |
1149 | + } |
1150 | + else |
1151 | + { |
1152 | + /* TRANSLATORS: %2 is a time string, e.g. "1 hour 5 minutes" */ |
1153 | + *accessible_name = g_strdup_printf (_("%s (%s left (%.0lf%%))"), device_name, detailed_timestring, percentage); |
1154 | + *details = g_strdup_printf (_("%s (%s left)"), device_name, short_timestring); |
1155 | + *short_details = g_strdup (short_timestring); |
1156 | + } |
1157 | + |
1158 | + g_free (short_timestring); |
1159 | + g_free (detailed_timestring); |
1160 | + } |
1161 | + else if (state == UP_DEVICE_STATE_FULLY_CHARGED) |
1162 | + { |
1163 | + *details = g_strdup_printf (_("%s (charged)"), device_name); |
1164 | + *accessible_name = g_strdup (*details); |
1165 | + *short_details = g_strdup (""); |
1166 | + } |
1167 | + else if (percentage > 0) |
1168 | + { |
1169 | + /* TRANSLATORS: %2 is a percentage value. Note: this string is only |
1170 | + * used when we don't have a time value */ |
1171 | + *details = g_strdup_printf (_("%s (%.0lf%%)"), device_name, percentage); |
1172 | + *accessible_name = g_strdup (*details); |
1173 | + *short_details = g_strdup_printf (_("(%.0lf%%)"), percentage); |
1174 | + } |
1175 | + else if (kind == UP_DEVICE_KIND_LINE_POWER) |
1176 | + { |
1177 | + *details = g_strdup (device_name); |
1178 | + *accessible_name = g_strdup (device_name); |
1179 | + *short_details = g_strdup (device_name); |
1180 | + } |
1181 | + else |
1182 | + { |
1183 | + *details = g_strdup_printf (_("%s (not present)"), device_name); |
1184 | + *accessible_name = g_strdup (*details); |
1185 | + *short_details = g_strdup (_("(not present)")); |
1186 | + } |
1187 | +} |
1188 | + |
1189 | +/*** |
1190 | +**** Instantiation |
1191 | +***/ |
1192 | + |
1193 | +IndicatorPowerDevice * |
1194 | +indicator_power_device_new (const gchar * object_path, |
1195 | + UpDeviceKind kind, |
1196 | + gdouble percentage, |
1197 | + UpDeviceState state, |
1198 | + time_t timestamp) |
1199 | +{ |
1200 | + GObject * o = g_object_new (INDICATOR_POWER_DEVICE_TYPE, |
1201 | + INDICATOR_POWER_DEVICE_KIND, kind, |
1202 | + INDICATOR_POWER_DEVICE_STATE, state, |
1203 | + INDICATOR_POWER_DEVICE_OBJECT_PATH, object_path, |
1204 | + INDICATOR_POWER_DEVICE_PERCENTAGE, percentage, |
1205 | + INDICATOR_POWER_DEVICE_TIME, (guint64)timestamp, |
1206 | + NULL); |
1207 | + return INDICATOR_POWER_DEVICE(o); |
1208 | +} |
1209 | + |
1210 | +IndicatorPowerDevice * |
1211 | +indicator_power_device_new_from_variant (GVariant * v) |
1212 | +{ |
1213 | + g_return_val_if_fail (g_variant_is_of_type (v, G_VARIANT_TYPE("(susdut)")), NULL); |
1214 | + |
1215 | + UpDeviceKind kind = UP_DEVICE_KIND_UNKNOWN; |
1216 | + UpDeviceState state = UP_DEVICE_STATE_UNKNOWN; |
1217 | + const gchar * icon = NULL; |
1218 | + const gchar * object_path = NULL; |
1219 | + gdouble percentage = 0; |
1220 | + guint64 time = 0; |
1221 | + |
1222 | + g_variant_get (v, "(&su&sdut)", |
1223 | + &object_path, |
1224 | + &kind, |
1225 | + &icon, |
1226 | + &percentage, |
1227 | + &state, |
1228 | + &time); |
1229 | + |
1230 | + return indicator_power_device_new (object_path, |
1231 | + kind, |
1232 | + percentage, |
1233 | + state, |
1234 | + time); |
1235 | +} |
1236 | |
1237 | === added file 'src/device.h' |
1238 | --- src/device.h 1970-01-01 00:00:00 +0000 |
1239 | +++ src/device.h 2012-07-11 17:08:19 +0000 |
1240 | @@ -0,0 +1,107 @@ |
1241 | +/* |
1242 | + |
1243 | +A simple Device structure used internally by indicator-power |
1244 | + |
1245 | +Copyright 2012 Canonical Ltd. |
1246 | + |
1247 | +Authors: |
1248 | + Charles Kerr <charles.kerr@canonical.com> |
1249 | + |
1250 | +This library is free software; you can redistribute it and/or |
1251 | +modify it under the terms of the GNU General Public License |
1252 | +version 3.0 as published by the Free Software Foundation. |
1253 | + |
1254 | +This library is distributed in the hope that it will be useful, |
1255 | +but WITHOUT ANY WARRANTY; without even the implied warranty of |
1256 | +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
1257 | +GNU General Public License version 3.0 for more details. |
1258 | + |
1259 | +You should have received a copy of the GNU General Public |
1260 | +License along with this library. If not, see |
1261 | +<http://www.gnu.org/licenses/>. |
1262 | +*/ |
1263 | + |
1264 | +#ifndef __INDICATOR_POWER_DEVICE_H__ |
1265 | +#define __INDICATOR_POWER_DEVICE_H__ |
1266 | + |
1267 | +#include <glib-object.h> |
1268 | +#include <libupower-glib/upower.h> |
1269 | + |
1270 | +G_BEGIN_DECLS |
1271 | + |
1272 | +#define INDICATOR_POWER_DEVICE_TYPE (indicator_power_device_get_type ()) |
1273 | +#define INDICATOR_POWER_DEVICE(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), INDICATOR_POWER_DEVICE_TYPE, IndicatorPowerDevice)) |
1274 | +#define INDICATOR_POWER_DEVICE_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), INDICATOR_POWER_DEVICE_TYPE, IndicatorPowerDeviceClass)) |
1275 | +#define INDICATOR_IS_POWER_DEVICE(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), INDICATOR_POWER_DEVICE_TYPE)) |
1276 | +#define INDICATOR_IS_POWER_DEVICE_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), INDICATOR_POWER_DEVICE_TYPE)) |
1277 | +#define INDICATOR_POWER_DEVICE_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), INDICATOR_POWER_DEVICE_TYPE, IndicatorPowerDeviceClass)) |
1278 | + |
1279 | +typedef struct _IndicatorPowerDevice IndicatorPowerDevice; |
1280 | +typedef struct _IndicatorPowerDeviceClass IndicatorPowerDeviceClass; |
1281 | +typedef struct _IndicatorPowerDevicePrivate IndicatorPowerDevicePrivate; |
1282 | + |
1283 | +#define INDICATOR_POWER_DEVICE_KIND "kind" |
1284 | +#define INDICATOR_POWER_DEVICE_STATE "state" |
1285 | +#define INDICATOR_POWER_DEVICE_OBJECT_PATH "object-path" |
1286 | +#define INDICATOR_POWER_DEVICE_PERCENTAGE "percentage" |
1287 | +#define INDICATOR_POWER_DEVICE_TIME "time" |
1288 | + |
1289 | +/** |
1290 | + * IndicatorPowerDeviceClass: |
1291 | + * @parent_class: #GObjectClass |
1292 | + */ |
1293 | +struct _IndicatorPowerDeviceClass |
1294 | +{ |
1295 | + GObjectClass parent_class; |
1296 | +}; |
1297 | + |
1298 | +/** |
1299 | + * IndicatorPowerDevice: |
1300 | + * @parent: #GObject |
1301 | + * @priv: A cached reference to the private data for the instance. |
1302 | +*/ |
1303 | +struct _IndicatorPowerDevice |
1304 | +{ |
1305 | + GObject parent; |
1306 | + IndicatorPowerDevicePrivate * priv; |
1307 | +}; |
1308 | + |
1309 | +/*** |
1310 | +**** |
1311 | +***/ |
1312 | + |
1313 | +GType indicator_power_device_get_type (void); |
1314 | + |
1315 | +IndicatorPowerDevice* indicator_power_device_new (const gchar * object_path, |
1316 | + UpDeviceKind kind, |
1317 | + gdouble percentage, |
1318 | + UpDeviceState state, |
1319 | + time_t time); |
1320 | + |
1321 | +/** |
1322 | + * Convenience wrapper around indicator_power_device_new() |
1323 | + * @variant holds the same args as indicator_power_device_new() in "(susdut)" |
1324 | + */ |
1325 | +IndicatorPowerDevice* indicator_power_device_new_from_variant (GVariant * variant); |
1326 | + |
1327 | + |
1328 | +UpDeviceKind indicator_power_device_get_kind (const IndicatorPowerDevice * device); |
1329 | +UpDeviceState indicator_power_device_get_state (const IndicatorPowerDevice * device); |
1330 | +const gchar * indicator_power_device_get_object_path (const IndicatorPowerDevice * device); |
1331 | +gdouble indicator_power_device_get_percentage (const IndicatorPowerDevice * device); |
1332 | +time_t indicator_power_device_get_time (const IndicatorPowerDevice * device); |
1333 | + |
1334 | +GStrv indicator_power_device_get_icon_names (const IndicatorPowerDevice * device); |
1335 | +GIcon * indicator_power_device_get_gicon (const IndicatorPowerDevice * device); |
1336 | + |
1337 | +void indicator_power_device_get_time_details (const IndicatorPowerDevice * device, |
1338 | + gchar ** short_details, |
1339 | + gchar ** details, |
1340 | + gchar ** accessible_name); |
1341 | + |
1342 | + |
1343 | + |
1344 | + |
1345 | +G_END_DECLS |
1346 | + |
1347 | +#endif |
1348 | |
1349 | === modified file 'src/indicator-power.c' |
1350 | --- src/indicator-power.c 2012-04-15 14:23:24 +0000 |
1351 | +++ src/indicator-power.c 2012-07-11 17:08:19 +0000 |
1352 | @@ -20,7 +20,7 @@ |
1353 | */ |
1354 | |
1355 | #ifdef HAVE_CONFIG_H |
1356 | -#include "config.h" |
1357 | + #include "config.h" |
1358 | #endif |
1359 | |
1360 | /* GStuff */ |
1361 | @@ -28,67 +28,41 @@ |
1362 | #include <glib/gi18n-lib.h> |
1363 | #include <gio/gio.h> |
1364 | |
1365 | -/* upower */ |
1366 | -#include <libupower-glib/upower.h> |
1367 | - |
1368 | -/* Indicator Stuff */ |
1369 | -#include <libindicator/indicator.h> |
1370 | -#include <libindicator/indicator-object.h> |
1371 | +#include "dbus-listener.h" |
1372 | +#include "device.h" |
1373 | +#include "indicator-power.h" |
1374 | |
1375 | #define ICON_POLICY_KEY "icon-policy" |
1376 | |
1377 | #define DEFAULT_ICON "gpm-battery-missing" |
1378 | |
1379 | -#define DBUS_SERVICE "org.gnome.SettingsDaemon" |
1380 | -#define DBUS_PATH "/org/gnome/SettingsDaemon" |
1381 | -#define POWER_DBUS_PATH DBUS_PATH "/Power" |
1382 | -#define POWER_DBUS_INTERFACE "org.gnome.SettingsDaemon.Power" |
1383 | - |
1384 | enum { |
1385 | POWER_INDICATOR_ICON_POLICY_PRESENT, |
1386 | POWER_INDICATOR_ICON_POLICY_CHARGE, |
1387 | POWER_INDICATOR_ICON_POLICY_NEVER |
1388 | }; |
1389 | |
1390 | -#define INDICATOR_POWER_TYPE (indicator_power_get_type ()) |
1391 | -#define INDICATOR_POWER(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), INDICATOR_POWER_TYPE, IndicatorPower)) |
1392 | -#define INDICATOR_POWER_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), INDICATOR_POWER_TYPE, IndicatorPowerClass)) |
1393 | -#define IS_INDICATOR_POWER(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), INDICATOR_POWER_TYPE)) |
1394 | -#define IS_INDICATOR_POWER_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), INDICATOR_POWER_TYPE)) |
1395 | -#define INDICATOR_POWER_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), INDICATOR_POWER_TYPE, IndicatorPowerClass)) |
1396 | - |
1397 | -typedef struct _IndicatorPowerClass IndicatorPowerClass; |
1398 | -typedef struct _IndicatorPower IndicatorPower; |
1399 | - |
1400 | -struct _IndicatorPowerClass |
1401 | -{ |
1402 | - IndicatorObjectClass parent_class; |
1403 | -}; |
1404 | - |
1405 | -struct _IndicatorPower |
1406 | -{ |
1407 | - IndicatorObject parent_instance; |
1408 | - |
1409 | +struct _IndicatorPowerPrivate |
1410 | +{ |
1411 | GtkMenu *menu; |
1412 | |
1413 | GtkLabel *label; |
1414 | GtkImage *status_image; |
1415 | gchar *accessible_desc; |
1416 | |
1417 | - GCancellable *proxy_cancel; |
1418 | - GDBusProxy *proxy; |
1419 | - guint watcher_id; |
1420 | + IndicatorPowerDbusListener * dbus_listener; |
1421 | |
1422 | - GVariant *devices; |
1423 | - GVariant *device; |
1424 | + GSList * devices; |
1425 | + IndicatorPowerDevice * device; |
1426 | |
1427 | GSettings *settings; |
1428 | }; |
1429 | |
1430 | -GType indicator_power_get_type (void) G_GNUC_CONST; |
1431 | |
1432 | +/* LCOV_EXCL_START */ |
1433 | INDICATOR_SET_VERSION |
1434 | INDICATOR_SET_TYPE (INDICATOR_POWER_TYPE) |
1435 | +/* LCOV_EXCL_STOP */ |
1436 | |
1437 | /* Prototypes */ |
1438 | static void indicator_power_dispose (GObject *object); |
1439 | @@ -105,9 +79,13 @@ |
1440 | |
1441 | static void on_entry_added (IndicatorObject * io, IndicatorObjectEntry * entry, gpointer user_data); |
1442 | |
1443 | +/* |
1444 | static void gsd_appeared_callback (GDBusConnection *connection, const gchar *name, const gchar *name_owner, gpointer user_data); |
1445 | +*/ |
1446 | |
1447 | +/* LCOV_EXCL_START */ |
1448 | G_DEFINE_TYPE (IndicatorPower, indicator_power, INDICATOR_OBJECT_TYPE); |
1449 | +/* LCOV_EXCL_STOP */ |
1450 | |
1451 | static void |
1452 | indicator_power_class_init (IndicatorPowerClass *klass) |
1453 | @@ -115,6 +93,8 @@ |
1454 | GObjectClass *object_class = G_OBJECT_CLASS (klass); |
1455 | IndicatorObjectClass *io_class = INDICATOR_OBJECT_CLASS (klass); |
1456 | |
1457 | + g_type_class_add_private (klass, sizeof (IndicatorPowerPrivate)); |
1458 | + |
1459 | object_class->dispose = indicator_power_dispose; |
1460 | object_class->finalize = indicator_power_finalize; |
1461 | |
1462 | @@ -128,20 +108,20 @@ |
1463 | static void |
1464 | indicator_power_init (IndicatorPower *self) |
1465 | { |
1466 | - self->menu = GTK_MENU(gtk_menu_new()); |
1467 | - |
1468 | - self->accessible_desc = NULL; |
1469 | - |
1470 | - self->watcher_id = g_bus_watch_name (G_BUS_TYPE_SESSION, |
1471 | - DBUS_SERVICE, |
1472 | - G_BUS_NAME_WATCHER_FLAGS_NONE, |
1473 | - gsd_appeared_callback, |
1474 | - NULL, |
1475 | - self, |
1476 | - NULL); |
1477 | - |
1478 | - self->settings = g_settings_new ("com.canonical.indicator.power"); |
1479 | - g_signal_connect_swapped (self->settings, "changed::" ICON_POLICY_KEY, |
1480 | + IndicatorPowerPrivate * priv; |
1481 | + |
1482 | + priv = G_TYPE_INSTANCE_GET_PRIVATE (self, INDICATOR_POWER_TYPE, IndicatorPowerPrivate); |
1483 | + |
1484 | + priv->menu = GTK_MENU(gtk_menu_new()); |
1485 | + |
1486 | + priv->accessible_desc = NULL; |
1487 | + |
1488 | + priv->dbus_listener = g_object_new (INDICATOR_POWER_DBUS_LISTENER_TYPE, NULL); |
1489 | + g_signal_connect_swapped (priv->dbus_listener, INDICATOR_POWER_DBUS_LISTENER_DEVICES_ENUMERATED, |
1490 | + G_CALLBACK(indicator_power_set_devices), self); |
1491 | + |
1492 | + priv->settings = g_settings_new ("com.canonical.indicator.power"); |
1493 | + g_signal_connect_swapped (priv->settings, "changed::" ICON_POLICY_KEY, |
1494 | G_CALLBACK(update_visibility), self); |
1495 | g_object_set (G_OBJECT(self), |
1496 | INDICATOR_OBJECT_DEFAULT_VISIBILITY, FALSE, |
1497 | @@ -149,27 +129,29 @@ |
1498 | |
1499 | g_signal_connect (INDICATOR_OBJECT(self), INDICATOR_OBJECT_SIGNAL_ENTRY_ADDED, |
1500 | G_CALLBACK(on_entry_added), NULL); |
1501 | -} |
1502 | - |
1503 | + |
1504 | + self->priv = priv; |
1505 | +} |
1506 | + |
1507 | +static void |
1508 | +dispose_devices (IndicatorPower * self) |
1509 | +{ |
1510 | + IndicatorPowerPrivate * priv = self->priv; |
1511 | + |
1512 | + g_clear_object (&priv->device); |
1513 | + g_slist_free_full (priv->devices, g_object_unref); |
1514 | + priv->devices = NULL; |
1515 | +} |
1516 | static void |
1517 | indicator_power_dispose (GObject *object) |
1518 | { |
1519 | IndicatorPower *self = INDICATOR_POWER(object); |
1520 | - |
1521 | - if (self->devices != NULL) { |
1522 | - g_variant_unref (self->devices); |
1523 | - self->devices = NULL; |
1524 | - } |
1525 | - |
1526 | - if (self->device != NULL) { |
1527 | - g_variant_unref (self->device); |
1528 | - self->device = NULL; |
1529 | - } |
1530 | - |
1531 | - g_clear_object (&self->proxy); |
1532 | - g_clear_object (&self->proxy_cancel); |
1533 | - |
1534 | - g_clear_object (&self->settings); |
1535 | + IndicatorPowerPrivate * priv = self->priv; |
1536 | + |
1537 | + dispose_devices (self); |
1538 | + |
1539 | + g_clear_object (&priv->dbus_listener); |
1540 | + g_clear_object (&priv->settings); |
1541 | |
1542 | G_OBJECT_CLASS (indicator_power_parent_class)->dispose (object); |
1543 | } |
1544 | @@ -178,8 +160,9 @@ |
1545 | indicator_power_finalize (GObject *object) |
1546 | { |
1547 | IndicatorPower *self = INDICATOR_POWER(object); |
1548 | + IndicatorPowerPrivate * priv = self->priv; |
1549 | |
1550 | - g_free (self->accessible_desc); |
1551 | + g_free (priv->accessible_desc); |
1552 | |
1553 | G_OBJECT_CLASS (indicator_power_parent_class)->finalize (object); |
1554 | } |
1555 | @@ -198,216 +181,17 @@ |
1556 | } |
1557 | |
1558 | static void |
1559 | -show_info_cb (GtkMenuItem *item, |
1560 | - gpointer data) |
1561 | -{ |
1562 | - /*TODO: show the statistics of the specific device*/ |
1563 | - spawn_command_line_async ("gnome-power-statistics"); |
1564 | -} |
1565 | - |
1566 | -static void |
1567 | option_toggled_cb (GtkCheckMenuItem *item, IndicatorPower * self) |
1568 | { |
1569 | - gtk_widget_set_visible (GTK_WIDGET (self->label), |
1570 | + gtk_widget_set_visible (GTK_WIDGET (self->priv->label), |
1571 | gtk_check_menu_item_get_active(item)); |
1572 | } |
1573 | |
1574 | -static void |
1575 | -show_preferences_cb (GtkMenuItem *item, |
1576 | - gpointer data) |
1577 | -{ |
1578 | - spawn_command_line_async ("gnome-control-center power"); |
1579 | -} |
1580 | - |
1581 | -static void |
1582 | -get_timestring (guint64 time_secs, |
1583 | - gchar **short_timestring, |
1584 | - gchar **detailed_timestring) |
1585 | -{ |
1586 | - gint hours; |
1587 | - gint minutes; |
1588 | - |
1589 | - /* Add 0.5 to do rounding */ |
1590 | - minutes = (int) ( ( time_secs / 60.0 ) + 0.5 ); |
1591 | - |
1592 | - if (minutes == 0) |
1593 | - { |
1594 | - *short_timestring = g_strdup (_("Unknown time")); |
1595 | - *detailed_timestring = g_strdup (_("Unknown time")); |
1596 | - |
1597 | - return; |
1598 | - } |
1599 | - |
1600 | - if (minutes < 60) |
1601 | - { |
1602 | - *short_timestring = g_strdup_printf ("0:%.2i", minutes); |
1603 | - *detailed_timestring = g_strdup_printf (g_dngettext (GETTEXT_PACKAGE, "%i minute", |
1604 | - "%i minutes", |
1605 | - minutes), minutes); |
1606 | - return; |
1607 | - } |
1608 | - |
1609 | - hours = minutes / 60; |
1610 | - minutes = minutes % 60; |
1611 | - |
1612 | - *short_timestring = g_strdup_printf ("%i:%.2i", hours, minutes); |
1613 | - |
1614 | - if (minutes == 0) |
1615 | - { |
1616 | - *detailed_timestring = g_strdup_printf (g_dngettext (GETTEXT_PACKAGE, |
1617 | - "%i hour", |
1618 | - "%i hours", |
1619 | - hours), hours); |
1620 | - } |
1621 | - else |
1622 | - { |
1623 | - /* TRANSLATOR: "%i %s %i %s" are "%i hours %i minutes" |
1624 | - * Swap order with "%2$s %2$i %1$s %1$i if needed */ |
1625 | - *detailed_timestring = g_strdup_printf (_("%i %s %i %s"), |
1626 | - hours, g_dngettext (GETTEXT_PACKAGE, "hour", "hours", hours), |
1627 | - minutes, g_dngettext (GETTEXT_PACKAGE, "minute", "minutes", minutes)); |
1628 | - } |
1629 | -} |
1630 | - |
1631 | -static const gchar * |
1632 | -device_kind_to_localised_string (UpDeviceKind kind) |
1633 | -{ |
1634 | - const gchar *text = NULL; |
1635 | - |
1636 | - switch (kind) { |
1637 | - case UP_DEVICE_KIND_LINE_POWER: |
1638 | - /* TRANSLATORS: system power cord */ |
1639 | - text = _("AC adapter"); |
1640 | - break; |
1641 | - case UP_DEVICE_KIND_BATTERY: |
1642 | - /* TRANSLATORS: laptop primary battery */ |
1643 | - text = _("Battery"); |
1644 | - break; |
1645 | - case UP_DEVICE_KIND_UPS: |
1646 | - /* TRANSLATORS: battery-backed AC power source */ |
1647 | - text = _("UPS"); |
1648 | - break; |
1649 | - case UP_DEVICE_KIND_MONITOR: |
1650 | - /* TRANSLATORS: a monitor is a device to measure voltage and current */ |
1651 | - text = _("Monitor"); |
1652 | - break; |
1653 | - case UP_DEVICE_KIND_MOUSE: |
1654 | - /* TRANSLATORS: wireless mice with internal batteries */ |
1655 | - text = _("Mouse"); |
1656 | - break; |
1657 | - case UP_DEVICE_KIND_KEYBOARD: |
1658 | - /* TRANSLATORS: wireless keyboard with internal battery */ |
1659 | - text = _("Keyboard"); |
1660 | - break; |
1661 | - case UP_DEVICE_KIND_PDA: |
1662 | - /* TRANSLATORS: portable device */ |
1663 | - text = _("PDA"); |
1664 | - break; |
1665 | - case UP_DEVICE_KIND_PHONE: |
1666 | - /* TRANSLATORS: cell phone (mobile...) */ |
1667 | - text = _("Cell phone"); |
1668 | - break; |
1669 | - case UP_DEVICE_KIND_MEDIA_PLAYER: |
1670 | - /* TRANSLATORS: media player, mp3 etc */ |
1671 | - text = _("Media player"); |
1672 | - break; |
1673 | - case UP_DEVICE_KIND_TABLET: |
1674 | - /* TRANSLATORS: tablet device */ |
1675 | - text = _("Tablet"); |
1676 | - break; |
1677 | - case UP_DEVICE_KIND_COMPUTER: |
1678 | - /* TRANSLATORS: tablet device */ |
1679 | - text = _("Computer"); |
1680 | - break; |
1681 | - default: |
1682 | - g_warning ("enum unrecognised: %i", kind); |
1683 | - text = up_device_kind_to_string (kind); |
1684 | - } |
1685 | - |
1686 | - return text; |
1687 | -} |
1688 | - |
1689 | -static void |
1690 | -build_device_time_details (const gchar *device_name, |
1691 | - guint64 time, |
1692 | - UpDeviceState state, |
1693 | - gdouble percentage, |
1694 | - gchar **short_details, |
1695 | - gchar **details, |
1696 | - gchar **accessible_name) |
1697 | -{ |
1698 | - gchar *short_timestring = NULL; |
1699 | - gchar *detailed_timestring = NULL; |
1700 | - |
1701 | - if (time > 0) |
1702 | - { |
1703 | - get_timestring (time, |
1704 | - &short_timestring, |
1705 | - &detailed_timestring); |
1706 | - |
1707 | - if (state == UP_DEVICE_STATE_CHARGING) |
1708 | - { |
1709 | - /* TRANSLATORS: %2 is a time string, e.g. "1 hour 5 minutes" */ |
1710 | - *accessible_name = g_strdup_printf (_("%s (%s to charge (%.0lf%%))"), |
1711 | - device_name, detailed_timestring, percentage); |
1712 | - *details = g_strdup_printf (_("%s (%s to charge)"), |
1713 | - device_name, short_timestring); |
1714 | - *short_details = g_strdup_printf ("(%s)", short_timestring); |
1715 | - } |
1716 | - else if (state == UP_DEVICE_STATE_DISCHARGING) |
1717 | - { |
1718 | - *short_details = g_strdup_printf ("%s", short_timestring); |
1719 | - |
1720 | - if (time > 43200) /* 12 hours */ |
1721 | - { |
1722 | - *accessible_name = g_strdup_printf (_("%s"), device_name); |
1723 | - *details = g_strdup_printf (_("%s"), device_name); |
1724 | - } |
1725 | - else |
1726 | - { |
1727 | - /* TRANSLATORS: %2 is a time string, e.g. "1 hour 5 minutes" */ |
1728 | - *accessible_name = g_strdup_printf (_("%s (%s left (%.0lf%%))"), |
1729 | - device_name, detailed_timestring, percentage); |
1730 | - *details = g_strdup_printf (_("%s (%s left)"), |
1731 | - device_name, short_timestring); |
1732 | - } |
1733 | - } |
1734 | - |
1735 | - g_free (short_timestring); |
1736 | - g_free (detailed_timestring); |
1737 | - } |
1738 | - else |
1739 | - { |
1740 | - if (state == UP_DEVICE_STATE_FULLY_CHARGED) |
1741 | - { |
1742 | - *details = g_strdup_printf (_("%s (charged)"), device_name); |
1743 | - *accessible_name = g_strdup (*details); |
1744 | - *short_details = g_strdup (""); |
1745 | - } |
1746 | - else if (percentage > 0) |
1747 | - { |
1748 | - /* TRANSLATORS: %2 is a percentage value. Note: this string is only |
1749 | - * used when we don't have a time value */ |
1750 | - *details = g_strdup_printf (_("%s (%.0lf%%)"), |
1751 | - device_name, percentage); |
1752 | - *accessible_name = g_strdup (*details); |
1753 | - *short_details = g_strdup_printf (_("(%.0lf%%)"), |
1754 | - percentage); |
1755 | - } |
1756 | - else |
1757 | - { |
1758 | - *details = g_strdup_printf (_("%s (not present)"), device_name); |
1759 | - *accessible_name = g_strdup (*details); |
1760 | - *short_details = g_strdup (_("(not present)")); |
1761 | - } |
1762 | - } |
1763 | -} |
1764 | - |
1765 | /* ensure that the entry is using self's accessible description */ |
1766 | static void |
1767 | refresh_entry_accessible_desc (IndicatorPower * self, IndicatorObjectEntry * entry) |
1768 | { |
1769 | - const char * newval = self->accessible_desc; |
1770 | + const char * newval = self->priv->accessible_desc; |
1771 | |
1772 | if (entry->accessible_desc != newval) |
1773 | { |
1774 | @@ -433,8 +217,8 @@ |
1775 | if (desc && *desc) |
1776 | { |
1777 | /* update our copy of the string */ |
1778 | - char * oldval = self->accessible_desc; |
1779 | - self->accessible_desc = g_strdup (desc); |
1780 | + char * oldval = self->priv->accessible_desc; |
1781 | + self->priv->accessible_desc = g_strdup (desc); |
1782 | |
1783 | /* ensure that the entries are using self's accessible description */ |
1784 | GList * l; |
1785 | @@ -448,194 +232,70 @@ |
1786 | } |
1787 | } |
1788 | |
1789 | -static const gchar * |
1790 | -get_icon_percentage_for_status (const gchar *status) |
1791 | -{ |
1792 | - |
1793 | - if (g_strcmp0 (status, "caution") == 0) |
1794 | - return "000"; |
1795 | - else if (g_strcmp0 (status, "low") == 0) |
1796 | - return "040"; |
1797 | - else if (g_strcmp0 (status, "good") == 0) |
1798 | - return "080"; |
1799 | - else |
1800 | - return "100"; |
1801 | -} |
1802 | - |
1803 | -static GIcon* |
1804 | -build_battery_icon (UpDeviceState state, |
1805 | - gchar *suffix_str) |
1806 | -{ |
1807 | - GIcon *gicon; |
1808 | - |
1809 | - GString *filename; |
1810 | - gchar **iconnames; |
1811 | - |
1812 | - filename = g_string_new (NULL); |
1813 | - |
1814 | - if (state == UP_DEVICE_STATE_FULLY_CHARGED) |
1815 | - { |
1816 | - g_string_append (filename, "battery-charged;"); |
1817 | - g_string_append (filename, "battery-full-charged-symbolic;"); |
1818 | - g_string_append (filename, "battery-full-charged;"); |
1819 | - g_string_append (filename, "gpm-battery-charged;"); |
1820 | - g_string_append (filename, "gpm-battery-100-charging;"); |
1821 | - } |
1822 | - else if (state == UP_DEVICE_STATE_CHARGING) |
1823 | - { |
1824 | - g_string_append (filename, "battery-000-charging;"); |
1825 | - g_string_append (filename, "battery-caution-charging-symbolic;"); |
1826 | - g_string_append (filename, "battery-caution-charging;"); |
1827 | - g_string_append (filename, "gpm-battery-000-charging;"); |
1828 | - } |
1829 | - else if (state == UP_DEVICE_STATE_DISCHARGING) |
1830 | - { |
1831 | - const gchar *percentage = get_icon_percentage_for_status (suffix_str); |
1832 | - g_string_append_printf (filename, "battery-%s;", suffix_str); |
1833 | - g_string_append_printf (filename, "battery-%s-symbolic;", suffix_str); |
1834 | - g_string_append_printf (filename, "battery-%s;", percentage); |
1835 | - g_string_append_printf (filename, "gpm-battery-%s;", percentage); |
1836 | - } |
1837 | - |
1838 | - iconnames = g_strsplit (filename->str, ";", -1); |
1839 | - gicon = g_themed_icon_new_from_names (iconnames, -1); |
1840 | - |
1841 | - g_strfreev (iconnames); |
1842 | - g_string_free (filename, TRUE); |
1843 | - |
1844 | - return gicon; |
1845 | -} |
1846 | - |
1847 | -static GIcon* |
1848 | -get_device_icon (UpDeviceKind kind, |
1849 | - UpDeviceState state, |
1850 | - guint64 time_sec, |
1851 | - const gchar *device_icon) |
1852 | -{ |
1853 | - GIcon *gicon = NULL; |
1854 | - |
1855 | - if (kind == UP_DEVICE_KIND_BATTERY && |
1856 | - (state == UP_DEVICE_STATE_FULLY_CHARGED || |
1857 | - state == UP_DEVICE_STATE_CHARGING || |
1858 | - state == UP_DEVICE_STATE_DISCHARGING)) |
1859 | - { |
1860 | - if (state == UP_DEVICE_STATE_FULLY_CHARGED || |
1861 | - state == UP_DEVICE_STATE_CHARGING) |
1862 | - { |
1863 | - gicon = build_battery_icon (state, NULL); |
1864 | - } |
1865 | - else if (state == UP_DEVICE_STATE_DISCHARGING) |
1866 | - { |
1867 | - if ((time_sec > 60 * 30) && /* more than 30 minutes left */ |
1868 | - (g_strrstr (device_icon, "000") || |
1869 | - g_strrstr (device_icon, "020") || |
1870 | - g_strrstr (device_icon, "caution"))) /* the icon is red */ |
1871 | - { |
1872 | - gicon = build_battery_icon (state, "low"); |
1873 | - } |
1874 | - } |
1875 | - } |
1876 | - |
1877 | - if (gicon == NULL) |
1878 | - gicon = g_icon_new_for_string (device_icon, NULL); |
1879 | - |
1880 | - return gicon; |
1881 | -} |
1882 | - |
1883 | - |
1884 | -static void |
1885 | -menu_add_device (GtkMenu *menu, |
1886 | - GVariant *device) |
1887 | -{ |
1888 | - UpDeviceKind kind; |
1889 | - UpDeviceState state; |
1890 | - GtkWidget *icon; |
1891 | - GtkWidget *item; |
1892 | - GtkWidget *details_label; |
1893 | - GtkWidget *grid; |
1894 | - GIcon *device_gicons; |
1895 | - const gchar *device_icon = NULL; |
1896 | - const gchar *object_path = NULL; |
1897 | - gdouble percentage; |
1898 | - guint64 time; |
1899 | - const gchar *device_name; |
1900 | - gchar *short_details = NULL; |
1901 | - gchar *details = NULL; |
1902 | - gchar *accessible_name = NULL; |
1903 | - AtkObject *atk_object; |
1904 | - |
1905 | - if (device == NULL) |
1906 | - return; |
1907 | - |
1908 | - g_variant_get (device, |
1909 | - "(&su&sdut)", |
1910 | - &object_path, |
1911 | - &kind, |
1912 | - &device_icon, |
1913 | - &percentage, |
1914 | - &state, |
1915 | - &time); |
1916 | - |
1917 | - g_debug ("%s: got data from object %s", G_STRFUNC, object_path); |
1918 | - |
1919 | - if (kind == UP_DEVICE_KIND_LINE_POWER) |
1920 | - return; |
1921 | - |
1922 | - /* Process the data */ |
1923 | - device_gicons = get_device_icon (kind, state, time, device_icon); |
1924 | - icon = gtk_image_new_from_gicon (device_gicons, |
1925 | - GTK_ICON_SIZE_SMALL_TOOLBAR); |
1926 | - g_clear_object (&device_gicons); |
1927 | - |
1928 | - device_name = device_kind_to_localised_string (kind); |
1929 | - |
1930 | - build_device_time_details (device_name, time, state, percentage, &short_details, &details, &accessible_name); |
1931 | - |
1932 | - /* Create menu item */ |
1933 | - item = gtk_image_menu_item_new (); |
1934 | - atk_object = gtk_widget_get_accessible(item); |
1935 | - if (atk_object != NULL) |
1936 | - atk_object_set_name (atk_object, accessible_name); |
1937 | - |
1938 | - grid = gtk_grid_new (); |
1939 | - gtk_grid_set_column_spacing (GTK_GRID (grid), 6); |
1940 | - gtk_grid_attach (GTK_GRID (grid), icon, 0, 0, 1, 1); |
1941 | - details_label = gtk_label_new (details); |
1942 | - gtk_grid_attach_next_to (GTK_GRID (grid), details_label, icon, GTK_POS_RIGHT, 1, 1); |
1943 | - gtk_container_add (GTK_CONTAINER (item), grid); |
1944 | - gtk_widget_show (grid); |
1945 | - |
1946 | - gtk_menu_shell_append (GTK_MENU_SHELL (menu), item); |
1947 | - |
1948 | - g_signal_connect (G_OBJECT (item), "activate", |
1949 | - G_CALLBACK (show_info_cb), NULL); |
1950 | - |
1951 | - g_free (short_details); |
1952 | - g_free (details); |
1953 | - g_free (accessible_name); |
1954 | +static gboolean |
1955 | +menu_add_device (GtkMenu * menu, const IndicatorPowerDevice * device) |
1956 | +{ |
1957 | + gboolean added = FALSE; |
1958 | + const UpDeviceKind kind = indicator_power_device_get_kind (device); |
1959 | + |
1960 | + if (kind != UP_DEVICE_KIND_LINE_POWER) |
1961 | + { |
1962 | + GtkWidget *icon; |
1963 | + GtkWidget *item; |
1964 | + GtkWidget *details_label; |
1965 | + GtkWidget *grid; |
1966 | + GIcon *device_gicon; |
1967 | + gchar *short_details = NULL; |
1968 | + gchar *details = NULL; |
1969 | + gchar *accessible_name = NULL; |
1970 | + AtkObject *atk_object; |
1971 | + |
1972 | + /* Process the data */ |
1973 | + device_gicon = indicator_power_device_get_gicon (device); |
1974 | + icon = gtk_image_new_from_gicon (device_gicon, GTK_ICON_SIZE_SMALL_TOOLBAR); |
1975 | + g_clear_object (&device_gicon); |
1976 | + |
1977 | + indicator_power_device_get_time_details (device, &short_details, &details, &accessible_name); |
1978 | + |
1979 | + /* Create menu item */ |
1980 | + item = gtk_image_menu_item_new (); |
1981 | + atk_object = gtk_widget_get_accessible(item); |
1982 | + if (atk_object != NULL) |
1983 | + atk_object_set_name (atk_object, accessible_name); |
1984 | + |
1985 | + grid = gtk_grid_new (); |
1986 | + gtk_grid_set_column_spacing (GTK_GRID (grid), 6); |
1987 | + gtk_grid_attach (GTK_GRID (grid), icon, 0, 0, 1, 1); |
1988 | + details_label = gtk_label_new (details); |
1989 | + gtk_grid_attach_next_to (GTK_GRID (grid), details_label, icon, GTK_POS_RIGHT, 1, 1); |
1990 | + gtk_container_add (GTK_CONTAINER (item), grid); |
1991 | + gtk_widget_show (grid); |
1992 | + |
1993 | + gtk_menu_shell_append (GTK_MENU_SHELL (menu), item); |
1994 | + added = TRUE; |
1995 | + |
1996 | + g_signal_connect_swapped (G_OBJECT (item), "activate", |
1997 | + G_CALLBACK (spawn_command_line_async), "gnome-power-statistics"); |
1998 | + |
1999 | + g_free (short_details); |
2000 | + g_free (details); |
2001 | + g_free (accessible_name); |
2002 | + } |
2003 | + |
2004 | + return added; |
2005 | } |
2006 | |
2007 | static gsize |
2008 | -menu_add_devices (GtkMenu *menu, |
2009 | - GVariant *devices) |
2010 | +menu_add_devices (GtkMenu * menu, GSList * devices) |
2011 | { |
2012 | - gsize n_devices; |
2013 | - guint i; |
2014 | - |
2015 | - if (devices == NULL) |
2016 | - return 0; |
2017 | - |
2018 | - n_devices = g_variant_n_children (devices); |
2019 | - g_debug ("Num devices: '%" G_GSIZE_FORMAT "'\n", n_devices); |
2020 | - |
2021 | - for (i = 0; i < n_devices; i++) |
2022 | - { |
2023 | - GVariant * device = g_variant_get_child_value (devices, i); |
2024 | - menu_add_device (menu, device); |
2025 | - g_variant_unref (device); |
2026 | - } |
2027 | - |
2028 | - return n_devices; |
2029 | + GSList * l; |
2030 | + gsize n_added = 0; |
2031 | + |
2032 | + for (l=devices; l!=NULL; l=l->next) |
2033 | + if (menu_add_device (menu, l->data)) |
2034 | + ++n_added; |
2035 | + |
2036 | + return n_added; |
2037 | } |
2038 | |
2039 | static gboolean |
2040 | @@ -653,75 +313,62 @@ |
2041 | GtkWidget *image; |
2042 | GList *children; |
2043 | gsize n_devices = 0; |
2044 | + IndicatorPowerPrivate * priv = self->priv; |
2045 | |
2046 | /* remove the existing menuitems */ |
2047 | - children = gtk_container_get_children (GTK_CONTAINER (self->menu)); |
2048 | + children = gtk_container_get_children (GTK_CONTAINER (priv->menu)); |
2049 | g_list_foreach (children, (GFunc) gtk_widget_destroy, NULL); |
2050 | g_list_free (children); |
2051 | |
2052 | /* devices */ |
2053 | - n_devices = menu_add_devices (self->menu, self->devices); |
2054 | + n_devices = menu_add_devices (priv->menu, priv->devices); |
2055 | |
2056 | if (!get_greeter_mode ()) { |
2057 | /* only do the separator if we have at least one device */ |
2058 | if (n_devices != 0) |
2059 | { |
2060 | item = gtk_separator_menu_item_new (); |
2061 | - gtk_menu_shell_append (GTK_MENU_SHELL (self->menu), item); |
2062 | + gtk_menu_shell_append (GTK_MENU_SHELL (priv->menu), item); |
2063 | } |
2064 | |
2065 | /* options */ |
2066 | item = gtk_check_menu_item_new_with_label (_("Show Time in Menu Bar")); |
2067 | g_signal_connect (item, "toggled", G_CALLBACK(option_toggled_cb), self); |
2068 | - g_settings_bind (self->settings, "show-time", item, "active", G_SETTINGS_BIND_DEFAULT); |
2069 | - gtk_menu_shell_append (GTK_MENU_SHELL (self->menu), item); |
2070 | + g_settings_bind (priv->settings, "show-time", item, "active", G_SETTINGS_BIND_DEFAULT); |
2071 | + gtk_menu_shell_append (GTK_MENU_SHELL (priv->menu), item); |
2072 | |
2073 | /* preferences */ |
2074 | - item = gtk_image_menu_item_new_with_label (_("Power Settings...")); |
2075 | + item = gtk_image_menu_item_new_with_label (_("Power Settings…")); |
2076 | image = gtk_image_new_from_icon_name (GTK_STOCK_PREFERENCES, GTK_ICON_SIZE_MENU); |
2077 | gtk_image_menu_item_set_image (GTK_IMAGE_MENU_ITEM (item), image); |
2078 | - g_signal_connect (G_OBJECT (item), "activate", |
2079 | - G_CALLBACK (show_preferences_cb), NULL); |
2080 | - gtk_menu_shell_append (GTK_MENU_SHELL (self->menu), item); |
2081 | + g_signal_connect_swapped (G_OBJECT (item), "activate", |
2082 | + G_CALLBACK (spawn_command_line_async), "gnome-control-center power"); |
2083 | + gtk_menu_shell_append (GTK_MENU_SHELL (priv->menu), item); |
2084 | } |
2085 | |
2086 | /* show the menu */ |
2087 | - gtk_widget_show_all (GTK_WIDGET (self->menu)); |
2088 | + gtk_widget_show_all (GTK_WIDGET (priv->menu)); |
2089 | } |
2090 | |
2091 | -static GVariant * |
2092 | -get_primary_device (GVariant *devices) |
2093 | +static IndicatorPowerDevice* |
2094 | +get_primary_device (GSList * devices) |
2095 | { |
2096 | - gint primary_device_charging_index = -1; |
2097 | - gint primary_device_discharging_index = -1; |
2098 | - gint primary_device_index = -1; |
2099 | + IndicatorPowerDevice * primary_device = NULL; |
2100 | + IndicatorPowerDevice * primary_device_charging = NULL; |
2101 | + IndicatorPowerDevice * primary_device_discharging = NULL; |
2102 | gboolean charging = FALSE; |
2103 | gboolean discharging = FALSE; |
2104 | guint64 min_discharging_time = G_MAXUINT64; |
2105 | guint64 max_charging_time = 0; |
2106 | - guint i; |
2107 | - |
2108 | - const gsize n_devices = devices ? g_variant_n_children (devices) : 0; |
2109 | - g_debug ("Num devices: '%" G_GSIZE_FORMAT "'\n", n_devices); |
2110 | - |
2111 | - for (i = 0; i < n_devices; i++) |
2112 | + GSList * l; |
2113 | + |
2114 | + for (l=devices; l!=NULL; l=l->next) |
2115 | { |
2116 | - const gchar *object_path; |
2117 | - UpDeviceKind kind; |
2118 | - const gchar *device_icon; |
2119 | - gdouble percentage; |
2120 | - UpDeviceState state; |
2121 | - guint64 time = 0; |
2122 | - |
2123 | - g_variant_get_child (devices, i, "(&su&sdut)", |
2124 | - &object_path, |
2125 | - &kind, |
2126 | - &device_icon, |
2127 | - &percentage, |
2128 | - &state, |
2129 | - &time); |
2130 | - |
2131 | - g_debug ("%s: got data from object %s", G_STRFUNC, object_path); |
2132 | + IndicatorPowerDevice * device = INDICATOR_POWER_DEVICE(l->data); |
2133 | + const UpDeviceKind kind = indicator_power_device_get_kind (device); |
2134 | + const UpDeviceState state = indicator_power_device_get_state (device); |
2135 | + const gdouble percentage = indicator_power_device_get_percentage (device); |
2136 | + const time_t time = indicator_power_device_get_time (device); |
2137 | |
2138 | /* Try to fix the case when we get a empty battery bay as a real battery */ |
2139 | if (state == UP_DEVICE_STATE_UNKNOWN && |
2140 | @@ -738,7 +385,7 @@ |
2141 | if (time < min_discharging_time) |
2142 | { |
2143 | min_discharging_time = time; |
2144 | - primary_device_discharging_index = i; |
2145 | + primary_device_discharging = device; |
2146 | } |
2147 | } |
2148 | else if (state == UP_DEVICE_STATE_CHARGING) |
2149 | @@ -746,126 +393,79 @@ |
2150 | charging = TRUE; |
2151 | if (time == 0) /* Battery broken */ |
2152 | { |
2153 | - primary_device_charging_index = i; |
2154 | + primary_device_charging = device; |
2155 | } |
2156 | if (time > max_charging_time) |
2157 | { |
2158 | max_charging_time = time; |
2159 | - primary_device_charging_index = i; |
2160 | + primary_device_charging = device; |
2161 | } |
2162 | } |
2163 | else |
2164 | { |
2165 | - primary_device_index = i; |
2166 | + primary_device = device; |
2167 | } |
2168 | } |
2169 | |
2170 | if (discharging) |
2171 | { |
2172 | - primary_device_index = primary_device_discharging_index; |
2173 | + primary_device = primary_device_discharging; |
2174 | } |
2175 | else if (charging) |
2176 | { |
2177 | - primary_device_index = primary_device_charging_index; |
2178 | + primary_device = primary_device_charging; |
2179 | } |
2180 | |
2181 | - if (primary_device_index >= 0) |
2182 | - return g_variant_get_child_value (devices, primary_device_index); |
2183 | + if (primary_device != NULL) |
2184 | + g_object_ref (primary_device); |
2185 | |
2186 | - return NULL; |
2187 | + return primary_device; |
2188 | } |
2189 | |
2190 | static void |
2191 | -put_primary_device (IndicatorPower *self, |
2192 | - GVariant *device) |
2193 | +put_primary_device (IndicatorPower *self, IndicatorPowerDevice *device) |
2194 | { |
2195 | - UpDeviceKind kind; |
2196 | - UpDeviceState state; |
2197 | - GIcon *device_gicons; |
2198 | - gchar *short_details = NULL; |
2199 | - gchar *details = NULL; |
2200 | - gchar *accessible_name = NULL; |
2201 | - const gchar *device_icon = NULL; |
2202 | - const gchar *object_path = NULL; |
2203 | - gdouble percentage; |
2204 | - guint64 time; |
2205 | - const gchar *device_name; |
2206 | - |
2207 | - /* set the icon and text */ |
2208 | - g_variant_get (device, |
2209 | - "(&su&sdut)", |
2210 | - &object_path, |
2211 | - &kind, |
2212 | - &device_icon, |
2213 | - &percentage, |
2214 | - &state, |
2215 | - &time); |
2216 | - |
2217 | - g_debug ("%s: got data from object %s", G_STRFUNC, object_path); |
2218 | + IndicatorPowerPrivate * priv = self->priv; |
2219 | |
2220 | /* set icon */ |
2221 | - device_gicons = get_device_icon (kind, state, time, device_icon); |
2222 | - gtk_image_set_from_gicon (self->status_image, |
2223 | - device_gicons, |
2224 | - GTK_ICON_SIZE_LARGE_TOOLBAR); |
2225 | - g_clear_object (&device_gicons); |
2226 | - gtk_widget_show (GTK_WIDGET (self->status_image)); |
2227 | - |
2228 | - |
2229 | - /* get the device name */ |
2230 | - device_name = device_kind_to_localised_string (kind); |
2231 | + GIcon * device_gicon = indicator_power_device_get_gicon (device); |
2232 | + gtk_image_set_from_gicon (priv->status_image, device_gicon, GTK_ICON_SIZE_LARGE_TOOLBAR); |
2233 | + g_clear_object (&device_gicon); |
2234 | + gtk_widget_show (GTK_WIDGET (priv->status_image)); |
2235 | |
2236 | /* get the description */ |
2237 | - build_device_time_details (device_name, time, state, percentage, &short_details, &details, &accessible_name); |
2238 | - |
2239 | - gtk_label_set_label (GTK_LABEL (self->label), |
2240 | - short_details); |
2241 | + gchar * short_details; |
2242 | + gchar * details; |
2243 | + gchar * accessible_name; |
2244 | + indicator_power_device_get_time_details (device, &short_details, &details, &accessible_name); |
2245 | + gtk_label_set_label (GTK_LABEL (priv->label), short_details); |
2246 | set_accessible_desc (self, accessible_name); |
2247 | - |
2248 | + g_free (accessible_name); |
2249 | + g_free (details); |
2250 | g_free (short_details); |
2251 | - g_free (details); |
2252 | - g_free (accessible_name); |
2253 | } |
2254 | |
2255 | -static void |
2256 | -get_devices_cb (GObject *source_object, |
2257 | - GAsyncResult *res, |
2258 | - gpointer user_data) |
2259 | +void |
2260 | +indicator_power_set_devices (IndicatorPower * self, GSList * devices) |
2261 | { |
2262 | - IndicatorPower *self = INDICATOR_POWER (user_data); |
2263 | - GVariant *devices_container; |
2264 | - GError *error = NULL; |
2265 | - |
2266 | - devices_container = g_dbus_proxy_call_finish (G_DBUS_PROXY (source_object), res, &error); |
2267 | - if (devices_container == NULL) |
2268 | - { |
2269 | - g_message ("Couldn't get devices: %s\n", error->message); |
2270 | - g_error_free (error); |
2271 | - } |
2272 | - else /* update 'devices' */ |
2273 | - { |
2274 | - if (self->devices != NULL) |
2275 | - g_variant_unref (self->devices); |
2276 | - self->devices = g_variant_get_child_value (devices_container, 0); |
2277 | - |
2278 | - g_variant_unref (devices_container); |
2279 | - |
2280 | - if (self->device != NULL) |
2281 | - g_variant_unref (self->device); |
2282 | - self->device = get_primary_device (self->devices); |
2283 | - |
2284 | - if (self->device == NULL) |
2285 | - { |
2286 | - g_message ("Couldn't find primary device"); |
2287 | - } |
2288 | - else |
2289 | - { |
2290 | - put_primary_device (self, self->device); |
2291 | - } |
2292 | - } |
2293 | - |
2294 | + /* LCOV_EXCL_START */ |
2295 | + g_return_if_fail (IS_INDICATOR_POWER(self)); |
2296 | + /* LCOV_EXCL_STOP */ |
2297 | + |
2298 | + IndicatorPowerPrivate * priv = self->priv; |
2299 | + |
2300 | + /* update our devices & primary device */ |
2301 | + g_slist_foreach (devices, (GFunc)g_object_ref, NULL); |
2302 | + dispose_devices (self); |
2303 | + priv->devices = g_slist_copy (devices); |
2304 | + priv->device = get_primary_device (priv->devices); |
2305 | + |
2306 | + /* and our menus/visibility from the new device list */ |
2307 | + if (priv->device != NULL) |
2308 | + put_primary_device (self, priv->device); |
2309 | + else |
2310 | + g_message ("Couldn't find primary device"); |
2311 | build_menu (self); |
2312 | - |
2313 | update_visibility (self); |
2314 | } |
2315 | |
2316 | @@ -876,85 +476,6 @@ |
2317 | should_be_visible (self)); |
2318 | } |
2319 | |
2320 | -static void |
2321 | -receive_properties_changed (GDBusProxy *proxy G_GNUC_UNUSED, |
2322 | - GVariant *changed_properties G_GNUC_UNUSED, |
2323 | - GStrv invalidated_properties G_GNUC_UNUSED, |
2324 | - gpointer user_data) |
2325 | -{ |
2326 | - IndicatorPower *self = INDICATOR_POWER (user_data); |
2327 | - |
2328 | - /* it's time to refresh our device list */ |
2329 | - g_dbus_proxy_call (self->proxy, |
2330 | - "GetDevices", |
2331 | - NULL, |
2332 | - G_DBUS_CALL_FLAGS_NONE, |
2333 | - -1, |
2334 | - self->proxy_cancel, |
2335 | - get_devices_cb, |
2336 | - user_data); |
2337 | -} |
2338 | - |
2339 | -static void |
2340 | -service_proxy_cb (GObject *object, |
2341 | - GAsyncResult *res, |
2342 | - gpointer user_data) |
2343 | -{ |
2344 | - IndicatorPower *self = INDICATOR_POWER (user_data); |
2345 | - GError *error = NULL; |
2346 | - |
2347 | - self->proxy = g_dbus_proxy_new_for_bus_finish (res, &error); |
2348 | - |
2349 | - g_clear_object (&self->proxy_cancel); |
2350 | - |
2351 | - if (error != NULL) |
2352 | - { |
2353 | - g_error ("Error creating proxy: %s", error->message); |
2354 | - g_error_free (error); |
2355 | - |
2356 | - return; |
2357 | - } |
2358 | - |
2359 | - /* we want to change the primary device changes */ |
2360 | - g_signal_connect (self->proxy, |
2361 | - "g-properties-changed", |
2362 | - G_CALLBACK (receive_properties_changed), |
2363 | - user_data); |
2364 | - |
2365 | - /* get the initial state */ |
2366 | - g_dbus_proxy_call (self->proxy, |
2367 | - "GetDevices", |
2368 | - NULL, |
2369 | - G_DBUS_CALL_FLAGS_NONE, |
2370 | - -1, |
2371 | - self->proxy_cancel, |
2372 | - get_devices_cb, |
2373 | - user_data); |
2374 | -} |
2375 | - |
2376 | -static void |
2377 | -gsd_appeared_callback (GDBusConnection *connection, |
2378 | - const gchar *name, |
2379 | - const gchar *name_owner, |
2380 | - gpointer user_data) |
2381 | -{ |
2382 | - IndicatorPower *self = INDICATOR_POWER (user_data); |
2383 | - |
2384 | - self->proxy_cancel = g_cancellable_new (); |
2385 | - |
2386 | - g_dbus_proxy_new (connection, |
2387 | - G_DBUS_PROXY_FLAGS_DO_NOT_AUTO_START, |
2388 | - NULL, |
2389 | - name, |
2390 | - POWER_DBUS_PATH, |
2391 | - POWER_DBUS_INTERFACE, |
2392 | - self->proxy_cancel, |
2393 | - service_proxy_cb, |
2394 | - self); |
2395 | -} |
2396 | - |
2397 | - |
2398 | - |
2399 | |
2400 | /* Grabs the label. Creates it if it doesn't |
2401 | exist already */ |
2402 | @@ -962,32 +483,34 @@ |
2403 | get_label (IndicatorObject *io) |
2404 | { |
2405 | IndicatorPower *self = INDICATOR_POWER (io); |
2406 | + IndicatorPowerPrivate * priv = self->priv; |
2407 | |
2408 | - if (self->label == NULL) |
2409 | + if (priv->label == NULL) |
2410 | { |
2411 | /* Create the label if it doesn't exist already */ |
2412 | - self->label = GTK_LABEL (gtk_label_new ("")); |
2413 | - gtk_widget_set_visible (GTK_WIDGET (self->label), FALSE); |
2414 | + priv->label = GTK_LABEL (gtk_label_new ("")); |
2415 | + gtk_widget_set_visible (GTK_WIDGET (priv->label), FALSE); |
2416 | } |
2417 | |
2418 | - return self->label; |
2419 | + return priv->label; |
2420 | } |
2421 | |
2422 | static GtkImage * |
2423 | get_image (IndicatorObject *io) |
2424 | { |
2425 | + GIcon *gicon; |
2426 | IndicatorPower *self = INDICATOR_POWER (io); |
2427 | - GIcon *gicon; |
2428 | + IndicatorPowerPrivate * priv = self->priv; |
2429 | |
2430 | - if (self->status_image == NULL) |
2431 | + if (priv->status_image == NULL) |
2432 | { |
2433 | /* Will create the status icon if it doesn't exist already */ |
2434 | gicon = g_themed_icon_new (DEFAULT_ICON); |
2435 | - self->status_image = GTK_IMAGE (gtk_image_new_from_gicon (gicon, |
2436 | + priv->status_image = GTK_IMAGE (gtk_image_new_from_gicon (gicon, |
2437 | GTK_ICON_SIZE_LARGE_TOOLBAR)); |
2438 | } |
2439 | |
2440 | - return self->status_image; |
2441 | + return priv->status_image; |
2442 | } |
2443 | |
2444 | static GtkMenu * |
2445 | @@ -997,7 +520,7 @@ |
2446 | |
2447 | build_menu (self); |
2448 | |
2449 | - return GTK_MENU (self->menu); |
2450 | + return GTK_MENU (self->priv->menu); |
2451 | } |
2452 | |
2453 | static const gchar * |
2454 | @@ -1005,7 +528,7 @@ |
2455 | { |
2456 | IndicatorPower *self = INDICATOR_POWER (io); |
2457 | |
2458 | - return self->accessible_desc; |
2459 | + return self->priv->accessible_desc; |
2460 | } |
2461 | |
2462 | static const gchar * |
2463 | @@ -1019,28 +542,22 @@ |
2464 | ***/ |
2465 | |
2466 | static void |
2467 | -count_batteries(GVariant *devices, int *total, int *inuse) |
2468 | +count_batteries (GSList * devices, int *total, int *inuse) |
2469 | { |
2470 | - const int n_devices = devices ? g_variant_n_children (devices) : 0; |
2471 | + GSList * l; |
2472 | |
2473 | - int i; |
2474 | - for (i=0; i<n_devices; i++) |
2475 | + for (l=devices; l!=NULL; l=l->next) |
2476 | { |
2477 | - GVariant * device = g_variant_get_child_value (devices, i); |
2478 | + const IndicatorPowerDevice * device = INDICATOR_POWER_DEVICE(l->data); |
2479 | |
2480 | - UpDeviceKind kind; |
2481 | - g_variant_get_child (device, 1, "u", &kind); |
2482 | - if (kind == UP_DEVICE_KIND_BATTERY) |
2483 | + if (indicator_power_device_get_kind(device) == UP_DEVICE_KIND_BATTERY) |
2484 | { |
2485 | ++*total; |
2486 | |
2487 | - UpDeviceState state; |
2488 | - g_variant_get_child (device, 4, "u", &state); |
2489 | + const UpDeviceState state = indicator_power_device_get_state (device); |
2490 | if ((state == UP_DEVICE_STATE_CHARGING) || (state == UP_DEVICE_STATE_DISCHARGING)) |
2491 | ++*inuse; |
2492 | } |
2493 | - |
2494 | - g_variant_unref (device); |
2495 | } |
2496 | |
2497 | g_debug("count_batteries found %d batteries (%d are charging/discharging)", *total, *inuse); |
2498 | @@ -1050,8 +567,9 @@ |
2499 | should_be_visible (IndicatorPower * self) |
2500 | { |
2501 | gboolean visible = TRUE; |
2502 | + IndicatorPowerPrivate * priv = self->priv; |
2503 | |
2504 | - const int icon_policy = g_settings_get_enum (self->settings, ICON_POLICY_KEY); |
2505 | + const int icon_policy = g_settings_get_enum (priv->settings, ICON_POLICY_KEY); |
2506 | |
2507 | g_debug ("icon_policy is: %d (present==0, charge==1, never==2)", icon_policy); |
2508 | |
2509 | @@ -1062,7 +580,7 @@ |
2510 | else |
2511 | { |
2512 | int batteries=0, inuse=0; |
2513 | - count_batteries (self->devices, &batteries, &inuse); |
2514 | + count_batteries (priv->devices, &batteries, &inuse); |
2515 | |
2516 | if (icon_policy == POWER_INDICATOR_ICON_POLICY_PRESENT) |
2517 | { |
2518 | |
2519 | === added file 'src/indicator-power.h' |
2520 | --- src/indicator-power.h 1970-01-01 00:00:00 +0000 |
2521 | +++ src/indicator-power.h 2012-07-11 17:08:19 +0000 |
2522 | @@ -0,0 +1,58 @@ |
2523 | +/* |
2524 | +An indicator to power related information in the menubar. |
2525 | + |
2526 | +Copyright 2011 Canonical Ltd. |
2527 | + |
2528 | +Authors: |
2529 | + Javier Jardon <javier.jardon@codethink.co.uk> |
2530 | + |
2531 | +This program is free software: you can redistribute it and/or modify it |
2532 | +under the terms of the GNU General Public License version 3, as published |
2533 | +by the Free Software Foundation. |
2534 | + |
2535 | +This program is distributed in the hope that it will be useful, but |
2536 | +WITHOUT ANY WARRANTY; without even the implied warranties of |
2537 | +MERCHANTABILITY, SATISFACTORY QUALITY, or FITNESS FOR A PARTICULAR |
2538 | +PURPOSE. See the GNU General Public License for more details. |
2539 | + |
2540 | +You should have received a copy of the GNU General Public License along |
2541 | +with this program. If not, see <http://www.gnu.org/licenses/>. |
2542 | +*/ |
2543 | + |
2544 | +/* Gtk required */ |
2545 | +#include <gtk/gtk.h> |
2546 | + |
2547 | +/* parent class */ |
2548 | +#include <libindicator/indicator.h> |
2549 | +#include <libindicator/indicator-object.h> |
2550 | + |
2551 | +G_BEGIN_DECLS |
2552 | + |
2553 | +#define INDICATOR_POWER_TYPE (indicator_power_get_type ()) |
2554 | +#define INDICATOR_POWER(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), INDICATOR_POWER_TYPE, IndicatorPower)) |
2555 | +#define INDICATOR_POWER_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), INDICATOR_POWER_TYPE, IndicatorPowerClass)) |
2556 | +#define IS_INDICATOR_POWER(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), INDICATOR_POWER_TYPE)) |
2557 | +#define IS_INDICATOR_POWER_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), INDICATOR_POWER_TYPE)) |
2558 | +#define INDICATOR_POWER_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), INDICATOR_POWER_TYPE, IndicatorPowerClass)) |
2559 | + |
2560 | +typedef struct _IndicatorPower IndicatorPower; |
2561 | +typedef struct _IndicatorPowerClass IndicatorPowerClass; |
2562 | +typedef struct _IndicatorPowerPrivate IndicatorPowerPrivate; |
2563 | + |
2564 | +struct _IndicatorPowerClass |
2565 | +{ |
2566 | + IndicatorObjectClass parent_class; |
2567 | +}; |
2568 | + |
2569 | +struct _IndicatorPower |
2570 | +{ |
2571 | + IndicatorObject parent_instance; |
2572 | + IndicatorPowerPrivate * priv; |
2573 | +}; |
2574 | + |
2575 | +GType indicator_power_get_type (void) G_GNUC_CONST; |
2576 | + |
2577 | +void indicator_power_set_devices (IndicatorPower * power, |
2578 | + GSList * devices); |
2579 | + |
2580 | +G_END_DECLS |
2581 | |
2582 | === added directory 'tests' |
2583 | === added file 'tests/Makefile.am' |
2584 | --- tests/Makefile.am 1970-01-01 00:00:00 +0000 |
2585 | +++ tests/Makefile.am 2012-07-11 17:08:19 +0000 |
2586 | @@ -0,0 +1,62 @@ |
2587 | +TESTS = |
2588 | +CLEANFILES = |
2589 | +BUILT_SOURCES = |
2590 | +check_PROGRAMS = |
2591 | + |
2592 | +### |
2593 | +### |
2594 | +### |
2595 | + |
2596 | +# stock UMB tests on user-visible strings |
2597 | +include $(srcdir)/Makefile.am.strings |
2598 | + |
2599 | +check_LIBRARIES = libgtest.a |
2600 | +nodist_libgtest_a_SOURCES = \ |
2601 | + $(GTEST_SOURCE)/src/gtest-all.cc \ |
2602 | + $(GTEST_SOURCE)/src/gtest_main.cc |
2603 | + |
2604 | +AM_CPPFLAGS = $(GTEST_CPPFLAGS) -I${top_srcdir}/src -Wall -Werror |
2605 | +AM_CXXFLAGS = $(GTEST_CXXFLAGS) |
2606 | + |
2607 | +### |
2608 | +### |
2609 | +### |
2610 | + |
2611 | +TEST_LIBS = \ |
2612 | + $(top_builddir)/src/.libs/libpower.a \ |
2613 | + $(INDICATOR_LIBS) \ |
2614 | + $(UPOWER_LIBS) \ |
2615 | + $(COVERAGE_LDFLAGS) \ |
2616 | + libgtest.a |
2617 | + |
2618 | +TEST_CPPFLAGS = \ |
2619 | + $(AM_CPPFLAGS) \ |
2620 | + $(UPOWER_CFLAGS) \ |
2621 | + $(INDICATOR_CFLAGS) |
2622 | + |
2623 | +BUILT_SOURCES += gschemas.compiled |
2624 | +CLEANFILES += gschemas.compiled |
2625 | +gschemas.compiled: Makefile |
2626 | + @glib-compile-schemas --targetdir=$(abs_builddir) $(top_builddir)/data |
2627 | + |
2628 | +TESTS += test-device |
2629 | +check_PROGRAMS += test-device |
2630 | +test_device_SOURCES = test-device.cc |
2631 | +test_device_LDADD = $(TEST_LIBS) |
2632 | +test_device_CPPFLAGS = $(TEST_CPPFLAGS) |
2633 | + |
2634 | +#TESTS += test-dbus-listener |
2635 | +#check_PROGRAMS += test-dbus-listener |
2636 | +#test_dbus_listener_SOURCES = test-dbus-listener.cc |
2637 | +#test_dbus_listener_LDADD = $(TEST_LIBS) |
2638 | +#test_dbus_listener_CPPFLAGS = $(TEST_CPPFLAGS) |
2639 | + |
2640 | +TESTS += test-indicator |
2641 | +check_PROGRAMS += test-indicator |
2642 | +test_indicator_SOURCES = test-indicator.cc |
2643 | +test_indicator_LDADD = $(TEST_LIBS) |
2644 | +test_indicator_CPPFLAGS = $(TEST_CPPFLAGS) -DSCHEMA_DIR="\"$(top_builddir)/tests/\"" |
2645 | + |
2646 | +### |
2647 | +### |
2648 | +### |
2649 | |
2650 | === added file 'tests/Makefile.am.strings' |
2651 | --- tests/Makefile.am.strings 1970-01-01 00:00:00 +0000 |
2652 | +++ tests/Makefile.am.strings 2012-07-11 17:08:19 +0000 |
2653 | @@ -0,0 +1,38 @@ |
2654 | +TESTS += \ |
2655 | + test-ellipsis \ |
2656 | + test-space-ellipsis \ |
2657 | + test-ascii-quotes |
2658 | + |
2659 | +##### |
2660 | +# Tests for there being proper ellipsis instead of three periods in a row |
2661 | +##### |
2662 | +test-ellipsis: $(top_srcdir)/po |
2663 | + @echo "#!/bin/bash" > $@ |
2664 | + @echo "(cd $(top_srcdir)/po && make $(GETTEXT_PACKAGE).pot)" >> $@ |
2665 | + @echo "grep -c -e \"^msgid.*\.\.\.\\\"\" $(top_srcdir)/po/$(GETTEXT_PACKAGE).pot > /dev/null && echo \"Ellipsis found in user visible strings\" >&2 && exit 1" >> $@ |
2666 | + @echo "exit 0" >> $@ |
2667 | + @chmod +x $@ |
2668 | + |
2669 | +##### |
2670 | +# Tests for there being a space before an ellipsis |
2671 | +##### |
2672 | +test-space-ellipsis: $(top_srcdir)/po |
2673 | + @echo "#!/bin/bash" > $@ |
2674 | + @echo "(cd $(top_srcdir)/po && make $(GETTEXT_PACKAGE).pot)" >> $@ |
2675 | + @echo "grep -c -e \"^msgid.* …\\\"\" $(top_srcdir)/po/$(GETTEXT_PACKAGE).pot > /dev/null && echo \"Space before ellipsis found in user visible strings\" >&2 && exit 1" >> $@ |
2676 | + @echo "exit 0" >> $@ |
2677 | + @chmod +x $@ |
2678 | + |
2679 | +##### |
2680 | +# Tests for ASCII quote types |
2681 | +##### |
2682 | +test-ascii-quotes: $(top_srcdir)/po |
2683 | + @echo "#!/bin/bash" > $@ |
2684 | + @echo "(cd $(top_srcdir)/po && make $(GETTEXT_PACKAGE).pot)" >> $@ |
2685 | + @echo "grep -c -e \"^msgid \\\".*'.*\\\"\" $(top_srcdir)/po/$(GETTEXT_PACKAGE).pot > /dev/null && echo \"ASCII apostrophy found in user visible strings\" >&2 && exit 1" >> $@ |
2686 | + @echo "grep -c -e \"^msgid \\\".*\\\".*\\\"\" $(top_srcdir)/po/$(GETTEXT_PACKAGE).pot > /dev/null && echo \"ASCII quote found in user visible strings\" >&2 && exit 1" >> $@ |
2687 | + @echo "grep -c -e \"^msgid \\\".*\\\`.*\\\"\" $(top_srcdir)/po/$(GETTEXT_PACKAGE).pot > /dev/null && echo \"ASCII backtick found in user visible strings\" >&2 && exit 1" >> $@ |
2688 | + @echo "exit 0" >> $@ |
2689 | + @chmod +x $@ |
2690 | + |
2691 | +CLEANFILES += $(TESTS) |
2692 | |
2693 | === added file 'tests/test-dbus-listener.cc' |
2694 | --- tests/test-dbus-listener.cc 1970-01-01 00:00:00 +0000 |
2695 | +++ tests/test-dbus-listener.cc 2012-07-11 17:08:19 +0000 |
2696 | @@ -0,0 +1,370 @@ |
2697 | +/* |
2698 | +Copyright 2012 Canonical Ltd. |
2699 | + |
2700 | +Authors: |
2701 | + Charles Kerr <charles.kerr@canonical.com> |
2702 | + |
2703 | +This program is free software: you can redistribute it and/or modify it |
2704 | +under the terms of the GNU General Public License version 3, as published |
2705 | +by the Free Software Foundation. |
2706 | + |
2707 | +This program is distributed in the hope that it will be useful, but |
2708 | +WITHOUT ANY WARRANTY; without even the implied warranties of |
2709 | +MERCHANTABILITY, SATISFACTORY QUALITY, or FITNESS FOR A PARTICULAR |
2710 | +PURPOSE. See the GNU General Public License for more details. |
2711 | + |
2712 | +You should have received a copy of the GNU General Public License along |
2713 | +with this program. If not, see <http://www.gnu.org/licenses/>. |
2714 | +*/ |
2715 | + |
2716 | +#include <gtest/gtest.h> |
2717 | + |
2718 | +#include "dbus-listener.h" |
2719 | +#include "device.h" |
2720 | + |
2721 | +/*** |
2722 | +**** |
2723 | +***/ |
2724 | + |
2725 | +namespace |
2726 | +{ |
2727 | + void ensure_glib_initialized () |
2728 | + { |
2729 | + static bool initialized = false; |
2730 | + |
2731 | + if (G_UNLIKELY(!initialized)) |
2732 | + { |
2733 | + initialized = true; |
2734 | + g_type_init(); |
2735 | + } |
2736 | + } |
2737 | +} |
2738 | + |
2739 | +/*** |
2740 | +**** |
2741 | +***/ |
2742 | + |
2743 | +class DbusListenerTest : public ::testing::Test |
2744 | +{ |
2745 | + protected: |
2746 | + GSList * devices; |
2747 | + GDBusConnection * connection; |
2748 | + GMainLoop * mainloop; |
2749 | + GTestDBus * bus; |
2750 | + GDBusNodeInfo * gsd_power_introspection_data; |
2751 | + GVariant * get_devices_retval; |
2752 | + bool bus_acquired; |
2753 | + bool name_acquired; |
2754 | + int gsd_name_ownership_id; |
2755 | + int gsd_power_registration_id; |
2756 | + char * gsd_power_error_string; |
2757 | + |
2758 | + protected: |
2759 | + |
2760 | + static void |
2761 | + on_bus_acquired (GDBusConnection *conn, const gchar * name, gpointer gself) |
2762 | + { |
2763 | + g_debug ("bus acquired: %s, connection is %p", name, conn); |
2764 | + |
2765 | + DbusListenerTest * test = static_cast<DbusListenerTest*> (gself); |
2766 | + test->connection = conn; |
2767 | + test->bus_acquired = true; |
2768 | + } |
2769 | + |
2770 | + static void |
2771 | + on_name_acquired (GDBusConnection * conn, const gchar * name, gpointer gself) |
2772 | + { |
2773 | + g_debug ("name acquired: %s, connection is %p", name, conn); |
2774 | + |
2775 | + DbusListenerTest * test = static_cast<DbusListenerTest*> (gself); |
2776 | + test->name_acquired = true; |
2777 | + g_main_loop_quit (test->mainloop); |
2778 | + } |
2779 | + |
2780 | + static void |
2781 | + on_name_lost (GDBusConnection * conn, const gchar * name, gpointer gself) |
2782 | + { |
2783 | + g_debug ("name lost: %s, connection is %p", name, conn); |
2784 | + |
2785 | + DbusListenerTest * test = static_cast<DbusListenerTest*> (gself); |
2786 | + test->name_acquired = false; |
2787 | + g_main_loop_quit (test->mainloop); |
2788 | + } |
2789 | + |
2790 | + protected: |
2791 | + |
2792 | + static void |
2793 | + on_devices_enumerated (IndicatorPowerDbusListener * l, GSList * devices, gpointer gself) |
2794 | + { |
2795 | + g_debug ("on_devices_enumerated"); |
2796 | + |
2797 | + DbusListenerTest * test = static_cast<DbusListenerTest*> (gself); |
2798 | + test->name_acquired = false; |
2799 | + g_slist_foreach (devices, (GFunc)g_object_ref, NULL); |
2800 | + test->devices = g_slist_copy (devices); |
2801 | + g_main_loop_quit (test->mainloop); |
2802 | + } |
2803 | + |
2804 | + static void |
2805 | + gsd_power_handle_method_call (GDBusConnection * connection, |
2806 | + const gchar * sender, |
2807 | + const gchar * object_path, |
2808 | + const gchar * interface_name, |
2809 | + const gchar * method_name, |
2810 | + GVariant * parameters, |
2811 | + GDBusMethodInvocation * invocation, |
2812 | + gpointer gself) |
2813 | + { |
2814 | + DbusListenerTest * test = static_cast<DbusListenerTest*> (gself); |
2815 | + g_assert (!g_strcmp0 (method_name, "GetDevices")); |
2816 | + if (test->gsd_power_error_string != NULL) { |
2817 | + const GQuark domain = g_quark_from_static_string ("mock-gsd-power"); |
2818 | + g_message ("returning an error"); |
2819 | + g_dbus_method_invocation_return_error_literal (invocation, domain, 0, test->gsd_power_error_string); |
2820 | + } else { |
2821 | + g_dbus_method_invocation_return_value (invocation, test->get_devices_retval); |
2822 | + } |
2823 | + } |
2824 | + |
2825 | + protected: |
2826 | + |
2827 | + virtual void SetUp() |
2828 | + { |
2829 | + bus_acquired = false; |
2830 | + name_acquired = false; |
2831 | + connection = NULL; |
2832 | + devices = NULL; |
2833 | + get_devices_retval = NULL; |
2834 | + gsd_power_error_string = NULL; |
2835 | + |
2836 | + // bring up the test bus |
2837 | + ensure_glib_initialized (); |
2838 | + mainloop = g_main_loop_new (NULL, FALSE); |
2839 | + bus = g_test_dbus_new (G_TEST_DBUS_NONE); |
2840 | + g_test_dbus_up (bus); |
2841 | + |
2842 | + // own org.gnome.SettingsDameon on this test bus |
2843 | + gsd_name_ownership_id = g_bus_own_name ( |
2844 | + G_BUS_TYPE_SESSION, |
2845 | + GSD_SERVICE, |
2846 | + G_BUS_NAME_OWNER_FLAGS_NONE, |
2847 | + on_bus_acquired, |
2848 | + on_name_acquired, |
2849 | + on_name_lost, |
2850 | + this, NULL); |
2851 | + ASSERT_FALSE (bus_acquired); |
2852 | + ASSERT_FALSE (name_acquired); |
2853 | + ASSERT_TRUE (connection == NULL); |
2854 | + g_main_loop_run (mainloop); |
2855 | + ASSERT_TRUE (bus_acquired); |
2856 | + ASSERT_TRUE (name_acquired); |
2857 | + ASSERT_TRUE (G_IS_DBUS_CONNECTION(connection)); |
2858 | + |
2859 | + // parse the org.gnome.SettingsDaemon.Power interface |
2860 | + const gchar introspection_xml[] = |
2861 | + "<node>" |
2862 | + " <interface name='org.gnome.SettingsDaemon.Power'>" |
2863 | + " <property name='Icon' type='s' access='read'>" |
2864 | + " </property>" |
2865 | + " <property name='Tooltip' type='s' access='read'>" |
2866 | + " </property>" |
2867 | + " <method name='GetDevices'>" |
2868 | + " <arg name='devices' type='a(susdut)' direction='out' />" |
2869 | + " </method>" |
2870 | + " </interface>" |
2871 | + "</node>"; |
2872 | + gsd_power_introspection_data = g_dbus_node_info_new_for_xml(introspection_xml, NULL); |
2873 | + ASSERT_TRUE (gsd_power_introspection_data != NULL); |
2874 | + |
2875 | + // Set up a mock GSD. |
2876 | + // All it really does is wait for calls to GetDevice and |
2877 | + // returns the get_devices_retval variant |
2878 | + const GDBusInterfaceVTable gsd_power_interface_vtable = { |
2879 | + gsd_power_handle_method_call, |
2880 | + NULL, /* GetProperty */ |
2881 | + NULL, /* SetProperty */ |
2882 | + }; |
2883 | + gsd_power_registration_id = g_dbus_connection_register_object (connection, |
2884 | + GSD_POWER_DBUS_PATH, |
2885 | + gsd_power_introspection_data->interfaces[0], |
2886 | + &gsd_power_interface_vtable, |
2887 | + this, NULL, NULL); |
2888 | + } |
2889 | + |
2890 | + virtual void TearDown() |
2891 | + { |
2892 | + g_free (gsd_power_error_string); |
2893 | + |
2894 | + g_dbus_connection_unregister_object (connection, gsd_power_registration_id); |
2895 | + |
2896 | + g_dbus_node_info_unref (gsd_power_introspection_data); |
2897 | + g_bus_unown_name (gsd_name_ownership_id); |
2898 | + |
2899 | + g_slist_free_full (devices, g_object_unref); |
2900 | + g_test_dbus_down (bus); |
2901 | + g_main_loop_unref (mainloop); |
2902 | + } |
2903 | +}; |
2904 | + |
2905 | +/*** |
2906 | +**** |
2907 | +***/ |
2908 | + |
2909 | + |
2910 | +TEST_F(DbusListenerTest, GSDHasPowerAndBattery) |
2911 | +{ |
2912 | + // build a GetDevices retval that shows an AC line and a discharging battery |
2913 | + GVariantBuilder * builder = g_variant_builder_new (G_VARIANT_TYPE("a(susdut)")); |
2914 | + g_variant_builder_add (builder, "(susdut)", |
2915 | + "/org/freedesktop/UPower/devices/line_power_AC", |
2916 | + UP_DEVICE_KIND_LINE_POWER, |
2917 | + ". GThemedIcon ac-adapter-symbolic ac-adapter ", |
2918 | + 0.0, |
2919 | + UP_DEVICE_STATE_UNKNOWN, |
2920 | + 0); |
2921 | + g_variant_builder_add (builder, "(susdut)", |
2922 | + "/org/freedesktop/UPower/devices/battery_BAT0", |
2923 | + UP_DEVICE_KIND_BATTERY, |
2924 | + ". GThemedIcon battery-good-symbolic gpm-battery-060 battery-good ", |
2925 | + 52.871712, |
2926 | + UP_DEVICE_STATE_DISCHARGING, |
2927 | + 8834); |
2928 | + GVariant * value = g_variant_builder_end (builder); |
2929 | + get_devices_retval = g_variant_new_tuple (&value, 1); |
2930 | + g_variant_builder_unref (builder); |
2931 | + |
2932 | + // create an i-power dbus listener to watch for GSD |
2933 | + ASSERT_EQ (g_slist_length(devices), 0); |
2934 | + GObject * o = G_OBJECT (g_object_new (INDICATOR_POWER_DBUS_LISTENER_TYPE, NULL)); |
2935 | + ASSERT_TRUE (o != NULL); |
2936 | + ASSERT_TRUE (INDICATOR_IS_POWER_DBUS_LISTENER(o)); |
2937 | + g_signal_connect(o, INDICATOR_POWER_DBUS_LISTENER_DEVICES_ENUMERATED, |
2938 | + G_CALLBACK(on_devices_enumerated), this); |
2939 | + g_main_loop_run (mainloop); |
2940 | + |
2941 | + // test the devices should have gotten |
2942 | + ASSERT_EQ (g_slist_length(devices), 2); |
2943 | + IndicatorPowerDevice * device = INDICATOR_POWER_DEVICE (g_slist_nth_data (devices, 0)); |
2944 | + ASSERT_EQ (indicator_power_device_get_kind(device), UP_DEVICE_KIND_LINE_POWER); |
2945 | + ASSERT_STREQ ("/org/freedesktop/UPower/devices/line_power_AC", indicator_power_device_get_object_path(device)); |
2946 | + device = INDICATOR_POWER_DEVICE (g_slist_nth_data (devices, 1)); |
2947 | + ASSERT_EQ (UP_DEVICE_KIND_BATTERY, indicator_power_device_get_kind(device)); |
2948 | + ASSERT_STREQ ("/org/freedesktop/UPower/devices/battery_BAT0", indicator_power_device_get_object_path(device)); |
2949 | + |
2950 | + // cleanup |
2951 | + g_object_run_dispose (o); // used to get coverage of both branches in the object's dispose func's g_clear_*() calls |
2952 | + g_object_unref (o); |
2953 | +} |
2954 | + |
2955 | +TEST_F(DbusListenerTest, GSDHasNoDevices) |
2956 | +{ |
2957 | + GVariantBuilder * builder = g_variant_builder_new (G_VARIANT_TYPE("a(susdut)")); |
2958 | + GVariant * value = g_variant_builder_end (builder); |
2959 | + get_devices_retval = g_variant_new_tuple (&value, 1); |
2960 | + g_variant_builder_unref (builder); |
2961 | + |
2962 | + // create an i-power dbus listener to watch for GSD |
2963 | + ASSERT_EQ (g_slist_length(devices), 0); |
2964 | + GObject * o = G_OBJECT (g_object_new (INDICATOR_POWER_DBUS_LISTENER_TYPE, NULL)); |
2965 | + ASSERT_TRUE (o != NULL); |
2966 | + ASSERT_TRUE (INDICATOR_IS_POWER_DBUS_LISTENER(o)); |
2967 | + g_signal_connect(o, INDICATOR_POWER_DBUS_LISTENER_DEVICES_ENUMERATED, |
2968 | + G_CALLBACK(on_devices_enumerated), this); |
2969 | + g_main_loop_run (mainloop); |
2970 | + |
2971 | + // test the devices should have gotten |
2972 | + ASSERT_EQ (g_slist_length(devices), 0); |
2973 | + |
2974 | + // FIXME: this test improves coverage and confirms that the code |
2975 | + // doesn't crash, but more meaningful tests would be better too. |
2976 | + |
2977 | + // cleanup |
2978 | + g_object_run_dispose (o); // used to get coverage of both branches in the object's dispose func's g_clear_*() calls |
2979 | + g_object_unref (o); |
2980 | +} |
2981 | + |
2982 | +TEST_F(DbusListenerTest, GSDReturnsError) |
2983 | +{ |
2984 | + gsd_power_error_string = g_strdup ("no devices for you lol"); |
2985 | + |
2986 | + // create an i-power dbus listener to watch for GSD |
2987 | + ASSERT_EQ (g_slist_length(devices), 0); |
2988 | + GObject * o = G_OBJECT (g_object_new (INDICATOR_POWER_DBUS_LISTENER_TYPE, NULL)); |
2989 | + ASSERT_TRUE (o != NULL); |
2990 | + ASSERT_TRUE (INDICATOR_IS_POWER_DBUS_LISTENER(o)); |
2991 | + g_signal_connect(o, INDICATOR_POWER_DBUS_LISTENER_DEVICES_ENUMERATED, |
2992 | + G_CALLBACK(on_devices_enumerated), this); |
2993 | + g_main_loop_run (mainloop); |
2994 | + |
2995 | + // test the devices should have gotten |
2996 | + ASSERT_EQ (g_slist_length(devices), 0); |
2997 | + |
2998 | + // FIXME: this test improves coverage and confirms that the code |
2999 | + // doesn't crash, but more meaningful tests would be better too. |
3000 | + |
3001 | + // cleanup |
3002 | + g_object_run_dispose (o); // used to get coverage of both branches in the object's dispose func's g_clear_*() calls |
3003 | + g_object_unref (o); |
3004 | +} |
3005 | + |
3006 | +/* This test emits a PropertiesChanged signal and confirms that |
3007 | + the dbus listener asks for a fresh set of devices as a result. */ |
3008 | +TEST_F(DbusListenerTest, GSDPropChanged) |
3009 | +{ |
3010 | + gsd_power_error_string = g_strdup ("no devices for you lol"); |
3011 | + |
3012 | + // create an i-power dbus listener to watch for GSD |
3013 | + ASSERT_EQ (g_slist_length(devices), 0); |
3014 | + GObject * o = G_OBJECT (g_object_new (INDICATOR_POWER_DBUS_LISTENER_TYPE, NULL)); |
3015 | + ASSERT_TRUE (INDICATOR_IS_POWER_DBUS_LISTENER(o)); |
3016 | + g_signal_connect(o, INDICATOR_POWER_DBUS_LISTENER_DEVICES_ENUMERATED, |
3017 | + G_CALLBACK(on_devices_enumerated), this); |
3018 | + g_main_loop_run (mainloop); |
3019 | + // test the devices should have gotten |
3020 | + ASSERT_EQ (g_slist_length(devices), 0); |
3021 | + |
3022 | + // build a GetDevices retval that shows an AC line and a discharging battery |
3023 | + g_clear_pointer (&gsd_power_error_string, g_free); |
3024 | + GVariantBuilder * builder = g_variant_builder_new (G_VARIANT_TYPE("a(susdut)")); |
3025 | + g_variant_builder_add (builder, "(susdut)", |
3026 | + "/org/freedesktop/UPower/devices/line_power_AC", |
3027 | + UP_DEVICE_KIND_LINE_POWER, |
3028 | + ". GThemedIcon ac-adapter-symbolic ac-adapter ", |
3029 | + 0.0, |
3030 | + UP_DEVICE_STATE_UNKNOWN, |
3031 | + 0); |
3032 | + g_variant_builder_add (builder, "(susdut)", |
3033 | + "/org/freedesktop/UPower/devices/battery_BAT0", |
3034 | + UP_DEVICE_KIND_BATTERY, |
3035 | + ". GThemedIcon battery-good-symbolic gpm-battery-060 battery-good ", |
3036 | + 52.871712, |
3037 | + UP_DEVICE_STATE_DISCHARGING, |
3038 | + 8834); |
3039 | + GVariant * value = g_variant_builder_end (builder); |
3040 | + get_devices_retval = g_variant_new_tuple (&value, 1); |
3041 | + g_variant_builder_unref (builder); |
3042 | + |
3043 | + // tell the listener that some property changed |
3044 | + GVariantBuilder props_builder; |
3045 | + g_variant_builder_init (&props_builder, G_VARIANT_TYPE ("a{sv}")); |
3046 | + GVariant * props_changed = g_variant_new ("(s@a{sv}@as)", GSD_POWER_DBUS_INTERFACE, |
3047 | + g_variant_builder_end (&props_builder), |
3048 | + g_variant_new_strv (NULL, 0)); |
3049 | + g_variant_ref_sink (props_changed); |
3050 | + GError * error = NULL; |
3051 | + g_dbus_connection_emit_signal (connection, |
3052 | + NULL, |
3053 | + GSD_POWER_DBUS_PATH, |
3054 | + "org.freedesktop.DBus.Properties", |
3055 | + "PropertiesChanged", |
3056 | + props_changed, |
3057 | + &error); |
3058 | + ASSERT_TRUE(error == NULL); |
3059 | + |
3060 | + // give i-power's dbus listener a chance to ask for a fresh device list |
3061 | + g_main_loop_run (mainloop); |
3062 | + ASSERT_EQ (g_slist_length(devices), 2); |
3063 | + |
3064 | + // cleanup |
3065 | + g_object_unref (o); |
3066 | +} |
3067 | |
3068 | === added file 'tests/test-device.cc' |
3069 | --- tests/test-device.cc 1970-01-01 00:00:00 +0000 |
3070 | +++ tests/test-device.cc 2012-07-11 17:08:19 +0000 |
3071 | @@ -0,0 +1,470 @@ |
3072 | +/* |
3073 | +Copyright 2012 Canonical Ltd. |
3074 | + |
3075 | +Authors: |
3076 | + Charles Kerr <charles.kerr@canonical.com> |
3077 | + |
3078 | +This program is free software: you can redistribute it and/or modify it |
3079 | +under the terms of the GNU General Public License version 3, as published |
3080 | +by the Free Software Foundation. |
3081 | + |
3082 | +This program is distributed in the hope that it will be useful, but |
3083 | +WITHOUT ANY WARRANTY; without even the implied warranties of |
3084 | +MERCHANTABILITY, SATISFACTORY QUALITY, or FITNESS FOR A PARTICULAR |
3085 | +PURPOSE. See the GNU General Public License for more details. |
3086 | + |
3087 | +You should have received a copy of the GNU General Public License along |
3088 | +with this program. If not, see <http://www.gnu.org/licenses/>. |
3089 | +*/ |
3090 | + |
3091 | +#include <gtest/gtest.h> |
3092 | +#include "device.h" |
3093 | + |
3094 | +namespace |
3095 | +{ |
3096 | + void ensure_glib_initialized () |
3097 | + { |
3098 | + static bool initialized = false; |
3099 | + |
3100 | + if (G_UNLIKELY(!initialized)) |
3101 | + { |
3102 | + initialized = true; |
3103 | + g_type_init(); |
3104 | + } |
3105 | + } |
3106 | +} |
3107 | + |
3108 | +class DeviceTest : public ::testing::Test |
3109 | +{ |
3110 | + protected: |
3111 | + |
3112 | + virtual void SetUp() |
3113 | + { |
3114 | + ensure_glib_initialized (); |
3115 | + } |
3116 | + |
3117 | + virtual void TearDown() |
3118 | + { |
3119 | + } |
3120 | + |
3121 | + protected: |
3122 | + |
3123 | + void check_icon_names (const IndicatorPowerDevice * device, const char * expected) |
3124 | + { |
3125 | + char ** names = indicator_power_device_get_icon_names (device); |
3126 | + char * str = g_strjoinv (";", names); |
3127 | + ASSERT_STREQ (expected, str); |
3128 | + g_free (str); |
3129 | + g_strfreev (names); |
3130 | + } |
3131 | + |
3132 | + void check_strings (const IndicatorPowerDevice * device, |
3133 | + const char * expected_timestring, |
3134 | + const char * expected_details, |
3135 | + const char * expected_accessible) |
3136 | + { |
3137 | + char * timestring = NULL; |
3138 | + char * details = NULL; |
3139 | + char * accessible = NULL; |
3140 | + |
3141 | + indicator_power_device_get_time_details (device, ×tring, &details, &accessible); |
3142 | + EXPECT_STREQ (expected_timestring, timestring); |
3143 | + EXPECT_STREQ (expected_details, details); |
3144 | + EXPECT_STREQ (expected_accessible, accessible); |
3145 | + |
3146 | + g_free (accessible); |
3147 | + g_free (details); |
3148 | + g_free (timestring); |
3149 | + } |
3150 | +}; |
3151 | + |
3152 | + |
3153 | +/*** |
3154 | +**** |
3155 | +***/ |
3156 | + |
3157 | +TEST_F(DeviceTest, GObjectNew) |
3158 | +{ |
3159 | + ensure_glib_initialized (); |
3160 | + |
3161 | + GObject * o = G_OBJECT (g_object_new (INDICATOR_POWER_DEVICE_TYPE, NULL)); |
3162 | + ASSERT_TRUE (o != NULL); |
3163 | + ASSERT_TRUE (INDICATOR_IS_POWER_DEVICE(o)); |
3164 | + g_object_run_dispose (o); // used to get coverage of both branches in the object's dispose func's g_clear_*() calls |
3165 | + g_object_unref (o); |
3166 | +} |
3167 | + |
3168 | +TEST_F(DeviceTest, Properties) |
3169 | +{ |
3170 | + int i; |
3171 | + gdouble d; |
3172 | + GObject * o; |
3173 | + gchar * str; |
3174 | + guint64 u64; |
3175 | + const gchar * key; |
3176 | + |
3177 | + ensure_glib_initialized (); |
3178 | + |
3179 | + o = G_OBJECT (g_object_new (INDICATOR_POWER_DEVICE_TYPE, NULL)); |
3180 | + ASSERT_TRUE (o != NULL); |
3181 | + ASSERT_TRUE (INDICATOR_IS_POWER_DEVICE(o)); |
3182 | + |
3183 | + // Test getting & setting a Device's properties. |
3184 | + |
3185 | + // KIND |
3186 | + key = INDICATOR_POWER_DEVICE_KIND; |
3187 | + g_object_set (o, key, UP_DEVICE_KIND_BATTERY, NULL); |
3188 | + g_object_get (o, key, &i, NULL); |
3189 | + ASSERT_EQ (i, UP_DEVICE_KIND_BATTERY); |
3190 | + |
3191 | + // STATE |
3192 | + key = INDICATOR_POWER_DEVICE_STATE; |
3193 | + g_object_set (o, key, UP_DEVICE_STATE_CHARGING, NULL); |
3194 | + g_object_get (o, key, &i, NULL); |
3195 | + ASSERT_EQ (i, UP_DEVICE_STATE_CHARGING); |
3196 | + |
3197 | + // OBJECT_PATH |
3198 | + key = INDICATOR_POWER_DEVICE_OBJECT_PATH; |
3199 | + g_object_set (o, key, "/object/path", NULL); |
3200 | + g_object_get (o, key, &str, NULL); |
3201 | + ASSERT_STREQ (str, "/object/path"); |
3202 | + g_free (str); |
3203 | + |
3204 | + // PERCENTAGE |
3205 | + key = INDICATOR_POWER_DEVICE_PERCENTAGE; |
3206 | + g_object_set (o, key, 50.0, NULL); |
3207 | + g_object_get (o, key, &d, NULL); |
3208 | + ASSERT_EQ((int)d, 50); |
3209 | + |
3210 | + // TIME |
3211 | + key = INDICATOR_POWER_DEVICE_TIME; |
3212 | + g_object_set (o, key, (guint64)30, NULL); |
3213 | + g_object_get (o, key, &u64, NULL); |
3214 | + ASSERT_EQ(u64, 30); |
3215 | + |
3216 | + // cleanup |
3217 | + g_object_unref (o); |
3218 | +} |
3219 | + |
3220 | +TEST_F(DeviceTest, New) |
3221 | +{ |
3222 | + ensure_glib_initialized (); |
3223 | + |
3224 | + IndicatorPowerDevice * device = indicator_power_device_new ("/object/path", |
3225 | + UP_DEVICE_KIND_BATTERY, |
3226 | + 50.0, |
3227 | + UP_DEVICE_STATE_CHARGING, |
3228 | + 30); |
3229 | + ASSERT_TRUE (device != NULL); |
3230 | + ASSERT_TRUE (INDICATOR_IS_POWER_DEVICE(device)); |
3231 | + ASSERT_EQ (indicator_power_device_get_kind(device), UP_DEVICE_KIND_BATTERY); |
3232 | + ASSERT_EQ (indicator_power_device_get_state(device), UP_DEVICE_STATE_CHARGING); |
3233 | + ASSERT_STREQ (indicator_power_device_get_object_path(device), "/object/path"); |
3234 | + ASSERT_EQ ((int)indicator_power_device_get_percentage(device), 50); |
3235 | + ASSERT_EQ (indicator_power_device_get_time(device), 30); |
3236 | + |
3237 | + // cleanup |
3238 | + g_object_unref (device); |
3239 | +} |
3240 | + |
3241 | +TEST_F(DeviceTest, NewFromVariant) |
3242 | +{ |
3243 | + ensure_glib_initialized (); |
3244 | + |
3245 | + GVariant * variant = g_variant_new ("(susdut)", |
3246 | + "/object/path", |
3247 | + UP_DEVICE_KIND_BATTERY, |
3248 | + "icon", |
3249 | + 50.0, |
3250 | + UP_DEVICE_STATE_CHARGING, |
3251 | + 30); |
3252 | + IndicatorPowerDevice * device = indicator_power_device_new_from_variant (variant); |
3253 | + ASSERT_TRUE (variant != NULL); |
3254 | + ASSERT_TRUE (device != NULL); |
3255 | + ASSERT_TRUE (INDICATOR_IS_POWER_DEVICE(device)); |
3256 | + ASSERT_EQ (indicator_power_device_get_kind(device), UP_DEVICE_KIND_BATTERY); |
3257 | + ASSERT_EQ (indicator_power_device_get_state(device), UP_DEVICE_STATE_CHARGING); |
3258 | + ASSERT_STREQ (indicator_power_device_get_object_path(device), "/object/path"); |
3259 | + ASSERT_EQ ((int)indicator_power_device_get_percentage(device), 50); |
3260 | + ASSERT_EQ (indicator_power_device_get_time(device), 30); |
3261 | + |
3262 | + // cleanup |
3263 | + g_object_unref (device); |
3264 | + g_variant_unref (variant); |
3265 | +} |
3266 | + |
3267 | +TEST_F(DeviceTest, BadAccessors) |
3268 | +{ |
3269 | + ensure_glib_initialized (); |
3270 | + |
3271 | + // test that these functions can handle being passed NULL pointers |
3272 | + IndicatorPowerDevice * device = NULL; |
3273 | + indicator_power_device_get_kind (device); |
3274 | + indicator_power_device_get_time (device); |
3275 | + indicator_power_device_get_state (device); |
3276 | + indicator_power_device_get_percentage (device); |
3277 | + indicator_power_device_get_object_path (device); |
3278 | + |
3279 | + // test that these functions can handle being passed non-device GObjects |
3280 | + device = reinterpret_cast<IndicatorPowerDevice*>(g_cancellable_new ()); |
3281 | + indicator_power_device_get_kind (device); |
3282 | + indicator_power_device_get_time (device); |
3283 | + indicator_power_device_get_state (device); |
3284 | + indicator_power_device_get_percentage (device); |
3285 | + indicator_power_device_get_object_path (device); |
3286 | + g_object_unref (device); |
3287 | +} |
3288 | + |
3289 | +/*** |
3290 | +**** |
3291 | +***/ |
3292 | + |
3293 | +TEST_F(DeviceTest, IconNames) |
3294 | +{ |
3295 | + IndicatorPowerDevice * device = INDICATOR_POWER_DEVICE (g_object_new (INDICATOR_POWER_DEVICE_TYPE, NULL)); |
3296 | + GObject * o = G_OBJECT(device); |
3297 | + |
3298 | + // bad arguments |
3299 | + ASSERT_TRUE (indicator_power_device_get_icon_names (NULL) == NULL); |
3300 | + |
3301 | + // power |
3302 | + g_object_set (o, INDICATOR_POWER_DEVICE_KIND, UP_DEVICE_KIND_LINE_POWER, |
3303 | + NULL); |
3304 | + check_icon_names (device, "ac-adapter-symbolic;" |
3305 | + "ac-adapter"); |
3306 | + |
3307 | + // monitor |
3308 | + g_object_set (o, INDICATOR_POWER_DEVICE_KIND, UP_DEVICE_KIND_MONITOR, |
3309 | + NULL); |
3310 | + check_icon_names (device, "gpm-monitor-symbolic;" |
3311 | + "gpm-monitor"); |
3312 | + |
3313 | + // empty battery |
3314 | + g_object_set (o, INDICATOR_POWER_DEVICE_KIND, UP_DEVICE_KIND_BATTERY, |
3315 | + INDICATOR_POWER_DEVICE_STATE, UP_DEVICE_STATE_EMPTY, |
3316 | + NULL); |
3317 | + check_icon_names (device, "battery-empty-symbolic;" |
3318 | + "gpm-battery-empty;" |
3319 | + "gpm-battery-000;" |
3320 | + "battery-empty"); |
3321 | + |
3322 | + // charged battery |
3323 | + g_object_set (o, INDICATOR_POWER_DEVICE_KIND, UP_DEVICE_KIND_BATTERY, |
3324 | + INDICATOR_POWER_DEVICE_STATE, UP_DEVICE_STATE_FULLY_CHARGED, |
3325 | + NULL); |
3326 | + check_icon_names (device, "battery-full-charged-symbolic;battery-full-charging-symbolic;" |
3327 | + "gpm-battery-full;gpm-battery-100;" |
3328 | + "battery-full-charged;battery-full-charging"); |
3329 | + |
3330 | + // charging battery, 95% |
3331 | + g_object_set (o, INDICATOR_POWER_DEVICE_KIND, UP_DEVICE_KIND_BATTERY, |
3332 | + INDICATOR_POWER_DEVICE_STATE, UP_DEVICE_STATE_CHARGING, |
3333 | + INDICATOR_POWER_DEVICE_PERCENTAGE, 95.0, |
3334 | + NULL); |
3335 | + check_icon_names (device, "battery-caution-charging-symbolic;" |
3336 | + "gpm-battery-000-charging;" |
3337 | + "battery-caution-charging"); |
3338 | + |
3339 | + // charging battery, 85% |
3340 | + g_object_set (o, INDICATOR_POWER_DEVICE_KIND, UP_DEVICE_KIND_BATTERY, |
3341 | + INDICATOR_POWER_DEVICE_STATE, UP_DEVICE_STATE_CHARGING, |
3342 | + INDICATOR_POWER_DEVICE_PERCENTAGE, 85.0, |
3343 | + NULL); |
3344 | + check_icon_names (device, "battery-caution-charging-symbolic;" |
3345 | + "gpm-battery-000-charging;" |
3346 | + "battery-caution-charging"); |
3347 | + |
3348 | + // charging battery, 50% |
3349 | + g_object_set (o, INDICATOR_POWER_DEVICE_KIND, UP_DEVICE_KIND_BATTERY, |
3350 | + INDICATOR_POWER_DEVICE_STATE, UP_DEVICE_STATE_CHARGING, |
3351 | + INDICATOR_POWER_DEVICE_PERCENTAGE, 50.0, |
3352 | + NULL); |
3353 | + check_icon_names (device, "battery-caution-charging-symbolic;" |
3354 | + "gpm-battery-000-charging;" |
3355 | + "battery-caution-charging"); |
3356 | + |
3357 | + // charging battery, 25% |
3358 | + g_object_set (o, INDICATOR_POWER_DEVICE_KIND, UP_DEVICE_KIND_BATTERY, |
3359 | + INDICATOR_POWER_DEVICE_STATE, UP_DEVICE_STATE_CHARGING, |
3360 | + INDICATOR_POWER_DEVICE_PERCENTAGE, 25.0, |
3361 | + NULL); |
3362 | + check_icon_names (device, "battery-caution-charging-symbolic;" |
3363 | + "gpm-battery-000-charging;" |
3364 | + "battery-caution-charging"); |
3365 | + |
3366 | + // charging battery, 5% |
3367 | + g_object_set (o, INDICATOR_POWER_DEVICE_KIND, UP_DEVICE_KIND_BATTERY, |
3368 | + INDICATOR_POWER_DEVICE_STATE, UP_DEVICE_STATE_CHARGING, |
3369 | + INDICATOR_POWER_DEVICE_PERCENTAGE, 5.0, |
3370 | + NULL); |
3371 | + check_icon_names (device, "battery-caution-charging-symbolic;" |
3372 | + "gpm-battery-000-charging;" |
3373 | + "battery-caution-charging"); |
3374 | + |
3375 | + |
3376 | + // discharging battery, 95% |
3377 | + g_object_set (o, INDICATOR_POWER_DEVICE_KIND, UP_DEVICE_KIND_BATTERY, |
3378 | + INDICATOR_POWER_DEVICE_STATE, UP_DEVICE_STATE_DISCHARGING, |
3379 | + INDICATOR_POWER_DEVICE_PERCENTAGE, 95.0, |
3380 | + NULL); |
3381 | + check_icon_names (device, "battery-full-symbolic;" |
3382 | + "gpm-battery-100;" |
3383 | + "battery-full"); |
3384 | + |
3385 | + // discharging battery, 85% |
3386 | + g_object_set (o, INDICATOR_POWER_DEVICE_KIND, UP_DEVICE_KIND_BATTERY, |
3387 | + INDICATOR_POWER_DEVICE_STATE, UP_DEVICE_STATE_DISCHARGING, |
3388 | + INDICATOR_POWER_DEVICE_PERCENTAGE, 85.0, |
3389 | + NULL); |
3390 | + check_icon_names (device, "battery-full-symbolic;" |
3391 | + "gpm-battery-080;" |
3392 | + "battery-full"); |
3393 | + |
3394 | + // discharging battery, 50% -- 1 hour left |
3395 | + g_object_set (o, INDICATOR_POWER_DEVICE_KIND, UP_DEVICE_KIND_BATTERY, |
3396 | + INDICATOR_POWER_DEVICE_STATE, UP_DEVICE_STATE_DISCHARGING, |
3397 | + INDICATOR_POWER_DEVICE_PERCENTAGE, 50.0, |
3398 | + INDICATOR_POWER_DEVICE_TIME, (guint64)(60*60), |
3399 | + NULL); |
3400 | + check_icon_names (device, "battery-good-symbolic;" |
3401 | + "gpm-battery-060;" |
3402 | + "battery-good"); |
3403 | + |
3404 | + // discharging battery, 25% -- 1 hour left |
3405 | + g_object_set (o, INDICATOR_POWER_DEVICE_KIND, UP_DEVICE_KIND_BATTERY, |
3406 | + INDICATOR_POWER_DEVICE_STATE, UP_DEVICE_STATE_DISCHARGING, |
3407 | + INDICATOR_POWER_DEVICE_PERCENTAGE, 25.0, |
3408 | + INDICATOR_POWER_DEVICE_TIME, (guint64)(60*60), |
3409 | + NULL); |
3410 | + check_icon_names (device, "battery-good-symbolic;" |
3411 | + "gpm-battery-040;" |
3412 | + "battery-good"); |
3413 | + |
3414 | + // discharging battery, 25% -- 15 minutes left |
3415 | + g_object_set (o, INDICATOR_POWER_DEVICE_KIND, UP_DEVICE_KIND_BATTERY, |
3416 | + INDICATOR_POWER_DEVICE_STATE, UP_DEVICE_STATE_DISCHARGING, |
3417 | + INDICATOR_POWER_DEVICE_PERCENTAGE, 25.0, |
3418 | + INDICATOR_POWER_DEVICE_TIME, (guint64)(60*15), |
3419 | + NULL); |
3420 | + check_icon_names (device, "battery-low-symbolic;" |
3421 | + "gpm-battery-020;" |
3422 | + "battery-low"); |
3423 | + |
3424 | + // discharging battery, 5% -- 1 hour left |
3425 | + g_object_set (o, INDICATOR_POWER_DEVICE_KIND, UP_DEVICE_KIND_BATTERY, |
3426 | + INDICATOR_POWER_DEVICE_STATE, UP_DEVICE_STATE_DISCHARGING, |
3427 | + INDICATOR_POWER_DEVICE_PERCENTAGE, 5.0, |
3428 | + INDICATOR_POWER_DEVICE_TIME, (guint64)(60*60), |
3429 | + NULL); |
3430 | + check_icon_names (device, "battery-good-symbolic;" |
3431 | + "gpm-battery-040;" |
3432 | + "battery-good"); |
3433 | + |
3434 | + // discharging battery, 5% -- 15 minutes left |
3435 | + g_object_set (o, INDICATOR_POWER_DEVICE_KIND, UP_DEVICE_KIND_BATTERY, |
3436 | + INDICATOR_POWER_DEVICE_STATE, UP_DEVICE_STATE_DISCHARGING, |
3437 | + INDICATOR_POWER_DEVICE_PERCENTAGE, 5.0, |
3438 | + INDICATOR_POWER_DEVICE_TIME, (guint64)(60*15), |
3439 | + NULL); |
3440 | + check_icon_names (device, "battery-caution-symbolic;" |
3441 | + "gpm-battery-000;" |
3442 | + "battery-caution"); |
3443 | + // state unknown |
3444 | + g_object_set (o, INDICATOR_POWER_DEVICE_KIND, UP_DEVICE_KIND_BATTERY, |
3445 | + INDICATOR_POWER_DEVICE_STATE, UP_DEVICE_STATE_UNKNOWN, |
3446 | + NULL); |
3447 | + check_icon_names (device, "battery-missing-symbolic;" |
3448 | + "gpm-battery-missing;" |
3449 | + "battery-missing"); |
3450 | + |
3451 | + // cleanup |
3452 | + g_object_unref(o); |
3453 | +} |
3454 | + |
3455 | + |
3456 | +TEST_F(DeviceTest, Labels) |
3457 | +{ |
3458 | + // set our language so that i18n won't break these tests |
3459 | + char * real_lang = g_strdup(g_getenv ("LANG")); |
3460 | + g_setenv ("LANG", "en_US.UTF-8", TRUE); |
3461 | + |
3462 | + // bad args: NULL device |
3463 | + check_strings (NULL, NULL, NULL, NULL); |
3464 | + |
3465 | + // bad args: a GObject that isn't a device |
3466 | + GObject * o = G_OBJECT(g_cancellable_new()); |
3467 | + check_strings ((IndicatorPowerDevice*)o, NULL, NULL, NULL); |
3468 | + g_object_unref (o); |
3469 | + |
3470 | + /** |
3471 | + *** |
3472 | + **/ |
3473 | + |
3474 | + IndicatorPowerDevice * device = INDICATOR_POWER_DEVICE (g_object_new (INDICATOR_POWER_DEVICE_TYPE, NULL)); |
3475 | + o = G_OBJECT(device); |
3476 | + |
3477 | + // charging |
3478 | + g_object_set (o, INDICATOR_POWER_DEVICE_KIND, UP_DEVICE_KIND_BATTERY, |
3479 | + INDICATOR_POWER_DEVICE_STATE, UP_DEVICE_STATE_CHARGING, |
3480 | + INDICATOR_POWER_DEVICE_PERCENTAGE, 50.0, |
3481 | + INDICATOR_POWER_DEVICE_TIME, guint64(60*61), |
3482 | + NULL); |
3483 | + check_strings (device, "(1:01)", |
3484 | + "Battery (1:01 to charge)", |
3485 | + "Battery (1 hour 1 minute to charge (50%))"); |
3486 | + |
3487 | + // discharging, < 12 hours left |
3488 | + g_object_set (o, INDICATOR_POWER_DEVICE_KIND, UP_DEVICE_KIND_BATTERY, |
3489 | + INDICATOR_POWER_DEVICE_STATE, UP_DEVICE_STATE_DISCHARGING, |
3490 | + INDICATOR_POWER_DEVICE_PERCENTAGE, 50.0, |
3491 | + INDICATOR_POWER_DEVICE_TIME, guint64(60*61), |
3492 | + NULL); |
3493 | + check_strings (device, "1:01", |
3494 | + "Battery (1:01 left)", |
3495 | + "Battery (1 hour 1 minute left (50%))"); |
3496 | + |
3497 | + // discharging, > 12 hours left |
3498 | + g_object_set (o, INDICATOR_POWER_DEVICE_KIND, UP_DEVICE_KIND_BATTERY, |
3499 | + INDICATOR_POWER_DEVICE_STATE, UP_DEVICE_STATE_DISCHARGING, |
3500 | + INDICATOR_POWER_DEVICE_PERCENTAGE, 50.0, |
3501 | + INDICATOR_POWER_DEVICE_TIME, guint64(60*60*13), |
3502 | + NULL); |
3503 | + check_strings (device, "13:00", "Battery", "Battery"); |
3504 | + |
3505 | + // fully charged |
3506 | + g_object_set (o, INDICATOR_POWER_DEVICE_KIND, UP_DEVICE_KIND_BATTERY, |
3507 | + INDICATOR_POWER_DEVICE_STATE, UP_DEVICE_STATE_FULLY_CHARGED, |
3508 | + INDICATOR_POWER_DEVICE_PERCENTAGE, 100.0, |
3509 | + INDICATOR_POWER_DEVICE_TIME, guint64(0), |
3510 | + NULL); |
3511 | + check_strings (device, "", "Battery (charged)", "Battery (charged)"); |
3512 | + |
3513 | + // percentage but no time estimate |
3514 | + g_object_set (o, INDICATOR_POWER_DEVICE_KIND, UP_DEVICE_KIND_BATTERY, |
3515 | + INDICATOR_POWER_DEVICE_STATE, UP_DEVICE_STATE_DISCHARGING, |
3516 | + INDICATOR_POWER_DEVICE_PERCENTAGE, 50.0, |
3517 | + INDICATOR_POWER_DEVICE_TIME, guint64(0), |
3518 | + NULL); |
3519 | + check_strings (device, "(50%)", "Battery (50%)", "Battery (50%)"); |
3520 | + |
3521 | + // no percentage, no time estimate |
3522 | + g_object_set (o, INDICATOR_POWER_DEVICE_KIND, UP_DEVICE_KIND_BATTERY, |
3523 | + INDICATOR_POWER_DEVICE_STATE, UP_DEVICE_STATE_DISCHARGING, |
3524 | + INDICATOR_POWER_DEVICE_PERCENTAGE, 0.0, |
3525 | + INDICATOR_POWER_DEVICE_TIME, guint64(0), |
3526 | + NULL); |
3527 | + check_strings (device, "(not present)", "Battery (not present)", "Battery (not present)"); |
3528 | + |
3529 | + // power line |
3530 | + g_object_set (o, INDICATOR_POWER_DEVICE_KIND, UP_DEVICE_KIND_LINE_POWER, |
3531 | + INDICATOR_POWER_DEVICE_STATE, UP_DEVICE_STATE_UNKNOWN, |
3532 | + INDICATOR_POWER_DEVICE_PERCENTAGE, 0.0, |
3533 | + INDICATOR_POWER_DEVICE_TIME, guint64(0), |
3534 | + NULL); |
3535 | + check_strings (device, "AC Adapter", "AC Adapter", "AC Adapter"); |
3536 | + |
3537 | + // cleanup |
3538 | + g_object_unref(o); |
3539 | + g_setenv ("LANG", real_lang, TRUE); |
3540 | + g_free (real_lang); |
3541 | +} |
3542 | |
3543 | === added file 'tests/test-indicator.cc' |
3544 | --- tests/test-indicator.cc 1970-01-01 00:00:00 +0000 |
3545 | +++ tests/test-indicator.cc 2012-07-11 17:08:19 +0000 |
3546 | @@ -0,0 +1,312 @@ |
3547 | +/* |
3548 | +Copyright 2012 Canonical Ltd. |
3549 | + |
3550 | +Authors: |
3551 | + Charles Kerr <charles.kerr@canonical.com> |
3552 | + |
3553 | +This program is free software: you can redistribute it and/or modify it |
3554 | +under the terms of the GNU General Public License version 3, as published |
3555 | +by the Free Software Foundation. |
3556 | + |
3557 | +This program is distributed in the hope that it will be useful, but |
3558 | +WITHOUT ANY WARRANTY; without even the implied warranties of |
3559 | +MERCHANTABILITY, SATISFACTORY QUALITY, or FITNESS FOR A PARTICULAR |
3560 | +PURPOSE. See the GNU General Public License for more details. |
3561 | + |
3562 | +You should have received a copy of the GNU General Public License along |
3563 | +with this program. If not, see <http://www.gnu.org/licenses/>. |
3564 | +*/ |
3565 | + |
3566 | +#include <gtest/gtest.h> |
3567 | + |
3568 | +#include "dbus-listener.h" |
3569 | +#include "device.h" |
3570 | +#include "indicator-power.h" |
3571 | + |
3572 | +/*** |
3573 | +**** |
3574 | +***/ |
3575 | + |
3576 | +namespace |
3577 | +{ |
3578 | + void ensure_glib_initialized () |
3579 | + { |
3580 | + static bool initialized = false; |
3581 | + |
3582 | + if (G_UNLIKELY(!initialized)) |
3583 | + { |
3584 | + initialized = true; |
3585 | + g_type_init(); |
3586 | + } |
3587 | + } |
3588 | +} |
3589 | + |
3590 | +/*** |
3591 | +**** |
3592 | +***/ |
3593 | + |
3594 | +class IndicatorTest : public ::testing::Test |
3595 | +{ |
3596 | + protected: |
3597 | + |
3598 | + IndicatorPowerDevice * ac_device; |
3599 | + IndicatorPowerDevice * battery_device; |
3600 | + |
3601 | + virtual void SetUp() |
3602 | + { |
3603 | + ensure_glib_initialized (); |
3604 | + |
3605 | + g_setenv( "GSETTINGS_SCHEMA_DIR", SCHEMA_DIR, TRUE); |
3606 | + |
3607 | + ac_device = indicator_power_device_new ( |
3608 | + "/org/freedesktop/UPower/devices/line_power_AC", |
3609 | + UP_DEVICE_KIND_LINE_POWER, |
3610 | + 0.0, UP_DEVICE_STATE_UNKNOWN, 0); |
3611 | + |
3612 | + battery_device = indicator_power_device_new ( |
3613 | + "/org/freedesktop/UPower/devices/battery_BAT0", |
3614 | + UP_DEVICE_KIND_BATTERY, |
3615 | + 52.871712, UP_DEVICE_STATE_DISCHARGING, 8834); |
3616 | + } |
3617 | + |
3618 | + virtual void TearDown() |
3619 | + { |
3620 | + g_object_unref (battery_device); |
3621 | + g_object_unref (ac_device); |
3622 | + } |
3623 | + |
3624 | + const char* GetAccessibleDesc (IndicatorPower * power) const |
3625 | + { |
3626 | + GList * entries = indicator_object_get_entries (INDICATOR_OBJECT(power)); |
3627 | + g_assert (g_list_length(entries) == 1); |
3628 | + IndicatorObjectEntry * entry = static_cast<IndicatorObjectEntry*>(entries->data); |
3629 | + const char * ret = entry->accessible_desc; |
3630 | + g_list_free (entries); |
3631 | + return ret; |
3632 | + } |
3633 | +}; |
3634 | + |
3635 | +/*** |
3636 | +**** |
3637 | +***/ |
3638 | + |
3639 | +TEST_F(IndicatorTest, GObjectNew) |
3640 | +{ |
3641 | + GObject * o = G_OBJECT (g_object_new (INDICATOR_POWER_TYPE, NULL)); |
3642 | + ASSERT_TRUE (o != NULL); |
3643 | + ASSERT_TRUE (IS_INDICATOR_POWER(o)); |
3644 | + g_object_run_dispose (o); // used to get coverage of both branches in the object's dispose func's g_clear_*() calls |
3645 | + g_object_unref (o); |
3646 | +} |
3647 | + |
3648 | +TEST_F(IndicatorTest, SetDevices) |
3649 | +{ |
3650 | + GSList * devices; |
3651 | + IndicatorPower * power = INDICATOR_POWER(g_object_new (INDICATOR_POWER_TYPE, NULL)); |
3652 | + |
3653 | + devices = NULL; |
3654 | + devices = g_slist_append (devices, ac_device); |
3655 | + devices = g_slist_append (devices, battery_device); |
3656 | + indicator_power_set_devices (power, devices); |
3657 | + g_slist_free (devices); |
3658 | + |
3659 | + g_object_unref (power); |
3660 | +} |
3661 | + |
3662 | +TEST_F(IndicatorTest, DischargingStrings) |
3663 | +{ |
3664 | + IndicatorPower * power = INDICATOR_POWER(g_object_new (INDICATOR_POWER_TYPE, NULL)); |
3665 | + GSList * devices = g_slist_append (NULL, battery_device); |
3666 | + |
3667 | + // give the indicator a discharging battery with 30 minutes of life left |
3668 | + g_object_set (battery_device, |
3669 | + INDICATOR_POWER_DEVICE_STATE, UP_DEVICE_STATE_DISCHARGING, |
3670 | + INDICATOR_POWER_DEVICE_PERCENTAGE, 50.0, |
3671 | + INDICATOR_POWER_DEVICE_TIME, guint64(60*30), |
3672 | + NULL); |
3673 | + indicator_power_set_devices (power, devices); |
3674 | + ASSERT_STREQ (GetAccessibleDesc(power), "Battery (30 minutes left (50%))"); |
3675 | + |
3676 | + // give the indicator a discharging battery with 1 hour of life left |
3677 | + g_object_set (battery_device, |
3678 | + INDICATOR_POWER_DEVICE_STATE, UP_DEVICE_STATE_DISCHARGING, |
3679 | + INDICATOR_POWER_DEVICE_PERCENTAGE, 50.0, |
3680 | + INDICATOR_POWER_DEVICE_TIME, guint64(60*60), |
3681 | + NULL); |
3682 | + indicator_power_set_devices (power, devices); |
3683 | + ASSERT_STREQ (GetAccessibleDesc(power), "Battery (1 hour left (50%))"); |
3684 | + |
3685 | + // give the indicator a discharging battery with 2 hours of life left |
3686 | + g_object_set (battery_device, |
3687 | + INDICATOR_POWER_DEVICE_PERCENTAGE, 100.0, |
3688 | + INDICATOR_POWER_DEVICE_TIME, guint64(60*60*2), |
3689 | + NULL); |
3690 | + indicator_power_set_devices (power, devices); |
3691 | + ASSERT_STREQ (GetAccessibleDesc(power), "Battery (2 hours left (100%))"); |
3692 | + |
3693 | + // give the indicator a discharging battery with over 12 hours of life left |
3694 | + g_object_set (battery_device, |
3695 | + INDICATOR_POWER_DEVICE_TIME, guint64(60*60*12 + 1), |
3696 | + NULL); |
3697 | + indicator_power_set_devices (power, devices); |
3698 | + ASSERT_STREQ (GetAccessibleDesc(power), "Battery"); |
3699 | + |
3700 | + // give the indicator a discharging battery with 29 seconds left |
3701 | + g_object_set (battery_device, |
3702 | + INDICATOR_POWER_DEVICE_TIME, guint64(29), |
3703 | + NULL); |
3704 | + indicator_power_set_devices (power, devices); |
3705 | + ASSERT_STREQ (GetAccessibleDesc(power), "Battery (Unknown time left (100%))"); |
3706 | + |
3707 | + // what happens if the time estimate isn't available |
3708 | + g_object_set (battery_device, |
3709 | + INDICATOR_POWER_DEVICE_TIME, guint64(0), |
3710 | + INDICATOR_POWER_DEVICE_PERCENTAGE, 50.0, |
3711 | + NULL); |
3712 | + indicator_power_set_devices (power, devices); |
3713 | + ASSERT_STREQ (GetAccessibleDesc(power), "Battery (50%)"); |
3714 | + |
3715 | + // what happens if the time estimate AND percentage isn't available |
3716 | + g_object_set (battery_device, |
3717 | + INDICATOR_POWER_DEVICE_TIME, guint64(0), |
3718 | + INDICATOR_POWER_DEVICE_PERCENTAGE, 0.0, |
3719 | + NULL); |
3720 | + indicator_power_set_devices (power, devices); |
3721 | + ASSERT_STREQ (GetAccessibleDesc(power), "Battery (not present)"); |
3722 | + |
3723 | + // cleanup |
3724 | + g_slist_free (devices); |
3725 | + g_object_unref (power); |
3726 | +} |
3727 | + |
3728 | +TEST_F(IndicatorTest, ChargingStrings) |
3729 | +{ |
3730 | + IndicatorPower * power = INDICATOR_POWER(g_object_new (INDICATOR_POWER_TYPE, NULL)); |
3731 | + GSList * devices = g_slist_prepend (NULL, battery_device); |
3732 | + |
3733 | + // give the indicator a discharging battery with 1 hour of life left |
3734 | + g_object_set (battery_device, |
3735 | + INDICATOR_POWER_DEVICE_STATE, UP_DEVICE_STATE_CHARGING, |
3736 | + INDICATOR_POWER_DEVICE_PERCENTAGE, 50.0, |
3737 | + INDICATOR_POWER_DEVICE_TIME, guint64(60*60), |
3738 | + NULL); |
3739 | + indicator_power_set_devices (power, devices); |
3740 | + ASSERT_STREQ (GetAccessibleDesc(power), "Battery (1 hour to charge (50%))"); |
3741 | + |
3742 | + // give the indicator a discharging battery with 2 hours of life left |
3743 | + g_object_set (battery_device, |
3744 | + INDICATOR_POWER_DEVICE_TIME, guint64(60*60*2), |
3745 | + NULL); |
3746 | + indicator_power_set_devices (power, devices); |
3747 | + ASSERT_STREQ (GetAccessibleDesc(power), "Battery (2 hours to charge (50%))"); |
3748 | + |
3749 | + // cleanup |
3750 | + g_slist_free (devices); |
3751 | + g_object_unref (power); |
3752 | +} |
3753 | + |
3754 | +TEST_F(IndicatorTest, ChargedStrings) |
3755 | +{ |
3756 | + IndicatorPower * power = INDICATOR_POWER(g_object_new (INDICATOR_POWER_TYPE, NULL)); |
3757 | + GSList * devices = g_slist_append (NULL, battery_device); |
3758 | + |
3759 | + // give the indicator a discharging battery with 1 hour of life left |
3760 | + g_object_set (battery_device, |
3761 | + INDICATOR_POWER_DEVICE_STATE, UP_DEVICE_STATE_FULLY_CHARGED, |
3762 | + INDICATOR_POWER_DEVICE_PERCENTAGE, 100.0, |
3763 | + INDICATOR_POWER_DEVICE_TIME, guint64(0), |
3764 | + NULL); |
3765 | + indicator_power_set_devices (power, devices); |
3766 | + ASSERT_STREQ (GetAccessibleDesc(power), "Battery (charged)"); |
3767 | + |
3768 | + // cleanup |
3769 | + g_slist_free (devices); |
3770 | + g_object_unref (power); |
3771 | +} |
3772 | + |
3773 | +TEST_F(IndicatorTest, AvoidChargingBatteriesWithZeroSecondsLeft) |
3774 | +{ |
3775 | + IndicatorPower * power = INDICATOR_POWER(g_object_new (INDICATOR_POWER_TYPE, NULL)); |
3776 | + |
3777 | + g_object_set (battery_device, |
3778 | + INDICATOR_POWER_DEVICE_STATE, UP_DEVICE_STATE_FULLY_CHARGED, |
3779 | + INDICATOR_POWER_DEVICE_PERCENTAGE, 100.0, |
3780 | + INDICATOR_POWER_DEVICE_TIME, guint64(0), |
3781 | + NULL); |
3782 | + IndicatorPowerDevice * bad_battery_device = indicator_power_device_new ( |
3783 | + "/org/freedesktop/UPower/devices/battery_BAT0", |
3784 | + UP_DEVICE_KIND_BATTERY, |
3785 | + 53, UP_DEVICE_STATE_CHARGING, 0); |
3786 | + |
3787 | + GSList * devices = NULL; |
3788 | + devices = g_slist_append (devices, battery_device); |
3789 | + devices = g_slist_append (devices, bad_battery_device); |
3790 | + indicator_power_set_devices (power, devices); |
3791 | + ASSERT_STREQ (GetAccessibleDesc(power), "Battery (53%)"); |
3792 | + |
3793 | + // cleanup |
3794 | + g_slist_free (devices); |
3795 | + g_object_unref (power); |
3796 | + g_object_unref (bad_battery_device); |
3797 | +} |
3798 | + |
3799 | +TEST_F(IndicatorTest, OtherDevices) |
3800 | +{ |
3801 | + IndicatorPower * power = INDICATOR_POWER(g_object_new (INDICATOR_POWER_TYPE, NULL)); |
3802 | + |
3803 | + g_object_ref (battery_device); |
3804 | + GSList * devices = g_slist_append (NULL, battery_device); |
3805 | + |
3806 | + devices = g_slist_append (devices, indicator_power_device_new ( |
3807 | + "/org/freedesktop/UPower/devices/mouse", UP_DEVICE_KIND_MOUSE, |
3808 | + 0, UP_DEVICE_STATE_UNKNOWN, 0)); |
3809 | + devices = g_slist_append (devices, indicator_power_device_new ( |
3810 | + "/org/freedesktop/UPower/devices/ups", UP_DEVICE_KIND_UPS, |
3811 | + 0, UP_DEVICE_STATE_UNKNOWN, 0)); |
3812 | + devices = g_slist_append (devices, indicator_power_device_new ( |
3813 | + "/org/freedesktop/UPower/devices/keyboard", UP_DEVICE_KIND_KEYBOARD, |
3814 | + 0, UP_DEVICE_STATE_UNKNOWN, 0)); |
3815 | + devices = g_slist_append (devices, indicator_power_device_new ( |
3816 | + "/org/freedesktop/UPower/devices/pda", UP_DEVICE_KIND_PDA, |
3817 | + 0, UP_DEVICE_STATE_UNKNOWN, 0)); |
3818 | + devices = g_slist_append (devices, indicator_power_device_new ( |
3819 | + "/org/freedesktop/UPower/devices/phone", UP_DEVICE_KIND_PHONE, |
3820 | + 0, UP_DEVICE_STATE_UNKNOWN, 0)); |
3821 | + devices = g_slist_append (devices, indicator_power_device_new ( |
3822 | + "/org/freedesktop/UPower/devices/monitor", UP_DEVICE_KIND_MONITOR, |
3823 | + 0, UP_DEVICE_STATE_UNKNOWN, 0)); |
3824 | + devices = g_slist_append (devices, indicator_power_device_new ( |
3825 | + "/org/freedesktop/UPower/devices/media_player", UP_DEVICE_KIND_MEDIA_PLAYER, |
3826 | + 0, UP_DEVICE_STATE_UNKNOWN, 0)); |
3827 | + devices = g_slist_append (devices, indicator_power_device_new ( |
3828 | + "/org/freedesktop/UPower/devices/tablet", UP_DEVICE_KIND_TABLET, |
3829 | + 0, UP_DEVICE_STATE_UNKNOWN, 0)); |
3830 | + devices = g_slist_append (devices, indicator_power_device_new ( |
3831 | + "/org/freedesktop/UPower/devices/computer", UP_DEVICE_KIND_COMPUTER, |
3832 | + 0, UP_DEVICE_STATE_UNKNOWN, 0)); |
3833 | + devices = g_slist_append (devices, indicator_power_device_new ( |
3834 | + "/org/freedesktop/UPower/devices/unknown", UP_DEVICE_KIND_UNKNOWN, |
3835 | + 0, UP_DEVICE_STATE_UNKNOWN, 0)); |
3836 | + |
3837 | + indicator_power_set_devices (power, devices); |
3838 | + |
3839 | + // FIXME: this tests to confirm the code doesn't crash, |
3840 | + // but further tests would be helpful |
3841 | + |
3842 | + // cleanup |
3843 | + g_slist_free_full (devices, g_object_unref); |
3844 | + g_object_unref (power); |
3845 | +} |
3846 | + |
3847 | +TEST_F(IndicatorTest, NoDevices) |
3848 | +{ |
3849 | + IndicatorPower * power = INDICATOR_POWER(g_object_new (INDICATOR_POWER_TYPE, NULL)); |
3850 | + |
3851 | + indicator_power_set_devices (power, NULL); |
3852 | + |
3853 | + // FIXME: this tests to confirm the code doesn't crash, |
3854 | + // but further tests would be helpful |
3855 | + |
3856 | + // cleanup |
3857 | + g_object_unref (power); |
3858 | +} |
Very nice work! And impressive test coverage.
Note: I couldn't test it yet, as I'm still on precise. /me ducks.
src/Makefile. am:207:
* any reason you're using noinst_HEADERS instead of listing the headers
in the libraries sources? (the latter is recommended for programs and
convenience libs in the automake docs)
dbus-listener.c
* afaict, it could have been written by gdbus-codegen
* 305: g_signal_new is passed one too many arguments. Please add the
docstring with the number and names of parameters to it [1]
* dispose() is missing g_bus_unwatch_name (priv->watcher_id)
* get_devices_cb:144: trailing whitespace ;)
* the cancellable is passed into all functions and unreffed in dispose()
is the cancellable cancelled on unref or do we need to do that explicitely?
(I can't find anything in the docs)
dbus-listener.h: power_dbus_ listener_ new is declared but not defined in the .c
* 50: the signal name is overly complicated (it doesn't need to be namespaced
to the class)
* indicator_
device.c: class_install_ properties. This also allows notify_ by_pspec WARN_INVALID_ PROPERTY_ ID in the 'default' switch case power_device_ new_from_ variant: check whether the input variant
* class_init: I prefer saving all pspecs in a static array and installing
them all at once with g_object_
using g_object_
* finalize doesn't chain up to the parent class
* get/set_property:
- use G_OBJECT_
- PROP_ICON is not handled
- kind and state should check for sane input values
* 260 ff: I don't think we can use Richard's code (indicators are CA, right?)
* indicator_
has the correct type before calling g_variant_get
* 298: reference functions with 'function_name()' instead of #function_name
in doc strings
device.h:
* 43 ff: no need to namespace gobject properties (tbh, I wouldn't even
#define them, but simply use the strings)
indicator-power.c: power_dbus_ listener_ new was missing :)
* 119: ah, that's why you didn't notice the implementation of
indicator_
* ref the floating widgets in the private struct
(just something I noticed, it has nothing to do with this work)
indicator-power.h:
* device.h include is superfluous
test/test- dbus-{listener, device} .cc: glib_initalized : g_type_init can be called multiple times
* ensure_
[1] http:// developer. gnome.org/ gtk-doc- manual/ stable/ documenting_ symbols. html.en
Section 3.3.4