aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--CMakeLists.txt1
-rw-r--r--data/com.canonical.indicator.power.Battery.xml23
-rw-r--r--debian/control1
-rw-r--r--src/CMakeLists.txt5
-rw-r--r--src/dbus-shared.h28
-rw-r--r--src/device.h1
-rw-r--r--src/main.c8
-rw-r--r--src/notifier.c448
-rw-r--r--src/notifier.h81
-rw-r--r--src/service.c15
-rw-r--r--tests/CMakeLists.txt2
-rw-r--r--tests/test-notify.cc59
12 files changed, 668 insertions, 4 deletions
diff --git a/CMakeLists.txt b/CMakeLists.txt
index 130a662..d5d6a82 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -37,6 +37,7 @@ pkg_check_modules(SERVICE_DEPS REQUIRED
gio-2.0>=2.36
gio-unix-2.0>=2.36
gudev-1.0>=204
+ libnotify>=0.7.6
url-dispatcher-1>=1)
include_directories (SYSTEM ${SERVICE_DEPS_INCLUDE_DIRS})
diff --git a/data/com.canonical.indicator.power.Battery.xml b/data/com.canonical.indicator.power.Battery.xml
new file mode 100644
index 0000000..d2c8a2d
--- /dev/null
+++ b/data/com.canonical.indicator.power.Battery.xml
@@ -0,0 +1,23 @@
+<?xml version="1.0" encoding="UTF-8" ?>
+<!DOCTYPE node PUBLIC "-//freedesktop//DTD D-BUS Object Introspection 1.0//EN" "http://www.freedesktop.org/standards/dbus/1.0/introspect.dtd">
+<node xmlns:doc="http://www.freedesktop.org/dbus/1.0/doc.dtd">
+ <interface name="com.canonical.indicator.power.Battery">
+
+ <property name="PowerLevel" type="i" access="read">
+ <doc:doc>
+ <doc:description>
+ <doc:para>The battery's power level. 0==No Low Battery, 1==Low, 2==Very Low, 3==Critical</doc:para>
+ </doc:description>
+ </doc:doc>
+ </property>
+
+ <property name="IsWarning" type="b" access="read">
+ <doc:doc>
+ <doc:description>
+ <doc:para>Whether or not indicator-power-service is warning the user about low battery power.</doc:para>
+ </doc:description>
+ </doc:doc>
+ </property>
+
+ </interface>
+</node>
diff --git a/debian/control b/debian/control
index 0944f42..4571741 100644
--- a/debian/control
+++ b/debian/control
@@ -6,6 +6,7 @@ Build-Depends: cmake,
debhelper (>= 9),
dh-translations,
intltool,
+ libnotify-dev (>= 0.7.6),
libgtest-dev,
libglib2.0-dev (>= 2.36),
libgudev-1.0-dev,
diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt
index a39b945..7a4a297 100644
--- a/src/CMakeLists.txt
+++ b/src/CMakeLists.txt
@@ -10,6 +10,7 @@ set(SERVICE_MANUAL_SOURCES
ib-brightness-uscreen-control.c
device-provider.c
device.c
+ notifier.c
service.c)
# generated sources
@@ -19,6 +20,10 @@ add_gdbus_codegen_with_namespace(SERVICE_GENERATED_SOURCES dbus-upower
org.freedesktop
Dbus
${CMAKE_CURRENT_SOURCE_DIR}/org.freedesktop.UPower.xml)
+add_gdbus_codegen_with_namespace(SERVICE_GENERATED_SOURCES dbus-battery
+ com.canonical.indicator.power
+ Dbus
+ ${CMAKE_SOURCE_DIR}/data/com.canonical.indicator.power.Battery.xml)
# add the bin dir to our include path so the code can find the generated header files
include_directories(${CMAKE_CURRENT_BINARY_DIR})
diff --git a/src/dbus-shared.h b/src/dbus-shared.h
new file mode 100644
index 0000000..bf54034
--- /dev/null
+++ b/src/dbus-shared.h
@@ -0,0 +1,28 @@
+/*
+ * Copyright 2014 Canonical Ltd.
+ *
+ * This program is free software: you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 3, as published
+ * by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranties of
+ * MERCHANTABILITY, SATISFACTORY QUALITY, or FITNESS FOR A PARTICULAR
+ * PURPOSE. See the GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program. If not, see <http://www.gnu.org/licenses/>.
+ *
+ * Authors:
+ * Charles Kerr <charles.kerr@canonical.com>
+ * Ted Gould <ted@canonical.com>
+ */
+
+#ifndef DBUS_SHARED_H
+#define DBUS_SHARED_H
+
+#define BUS_NAME "com.canonical.indicator.power"
+#define BUS_PATH "/com/canonical/indicator/power"
+
+#endif /* DBUS_SHARED_H */
+
diff --git a/src/device.h b/src/device.h
index 3a10f89..77d34ef 100644
--- a/src/device.h
+++ b/src/device.h
@@ -25,6 +25,7 @@ License along with this library. If not, see
#define __INDICATOR_POWER_DEVICE_H__
#include <glib-object.h>
+#include <gio/gio.h> /* GIcon */
G_BEGIN_DECLS
diff --git a/src/main.c b/src/main.c
index 7363284..d7953e6 100644
--- a/src/main.c
+++ b/src/main.c
@@ -41,9 +41,9 @@ on_name_lost (gpointer instance G_GNUC_UNUSED, gpointer loop)
int
main (int argc G_GNUC_UNUSED, char ** argv G_GNUC_UNUSED)
{
- GMainLoop * loop;
- IndicatorPowerService * service;
IndicatorPowerDeviceProvider * device_provider;
+ IndicatorPowerService * service;
+ GMainLoop * loop;
/* boilerplate i18n */
setlocale (LC_ALL, "");
@@ -59,8 +59,8 @@ main (int argc G_GNUC_UNUSED, char ** argv G_GNUC_UNUSED)
g_main_loop_run (loop);
/* cleanup */
- g_clear_object (&device_provider);
- g_clear_object (&service);
g_main_loop_unref (loop);
+ g_clear_object (&service);
+ g_clear_object (&device_provider);
return 0;
}
diff --git a/src/notifier.c b/src/notifier.c
new file mode 100644
index 0000000..d32008f
--- /dev/null
+++ b/src/notifier.c
@@ -0,0 +1,448 @@
+/*
+ * Copyright 2014 Canonical Ltd.
+ *
+ * This program is free software: you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 3, as published
+ * by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranties of
+ * MERCHANTABILITY, SATISFACTORY QUALITY, or FITNESS FOR A PARTICULAR
+ * PURPOSE. See the GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program. If not, see <http://www.gnu.org/licenses/>.
+ *
+ * Authors:
+ * Charles Kerr <charles.kerr@canonical.com>
+ */
+
+#include "dbus-battery-info.h"
+#include "dbus-shared.h"
+#include "notifier.h"
+
+#include <libnotify/notify.h>
+
+#include <glib/gi18n.h>
+#include <gio/gio.h>
+
+G_DEFINE_TYPE(IndicatorPowerNotifier,
+ indicator_power_notifier,
+ G_TYPE_OBJECT)
+
+/**
+*** GObject Properties
+**/
+
+enum
+{
+ PROP_0,
+ PROP_BATTERY,
+ PROP_IS_WARNING,
+ PROP_POWER_LEVEL,
+ LAST_PROP
+};
+
+#define BATTERY_NAME "battery"
+#define IS_WARNING_NAME "is-warning"
+#define POWER_LEVEL_NAME "power-level"
+
+static GParamSpec * properties[LAST_PROP];
+
+/**
+***
+**/
+
+static int n_notifiers = 0;
+
+struct _IndicatorPowerNotifierPrivate
+{
+ IndicatorPowerDeviceProvider * device_provider;
+
+ /* The battery we're currently watching.
+ This may be a physical battery or it may be a "merged" battery
+ synthesized from multiple batteries present on the device.
+ See indicator_power_service_choose_primary_device() */
+ IndicatorPowerDevice * battery;
+ PowerLevel power_level;
+
+ NotifyNotification* notify_notification;
+ gboolean is_warning;
+
+ DbusBattery * dbus_battery;
+ GBinding * is_warning_binding;
+ GBinding * power_level_binding;
+ GDBusConnection * bus;
+};
+
+typedef IndicatorPowerNotifierPrivate priv_t;
+
+/***
+**** Notifications
+***/
+
+static void
+notification_clear (IndicatorPowerNotifier * self)
+{
+ priv_t * p = self->priv;
+
+ if (p->notify_notification != NULL)
+ {
+ set_is_warning_property (self, FALSE);
+
+ notify_notification_clear_actions(p->notify_notification);
+ g_signal_handlers_disconnect_by_data(p->notify_notification, self);
+ g_clear_object(&p->notify_notification);
+
+ }
+}
+
+static void
+on_notification_clicked(NotifyNotification * notify_notification G_GNUC_UNUSED,
+ char * action G_GNUC_UNUSED,
+ gpointer gself G_GNUC_UNUSED)
+{
+ /* no-op because notify_notification_add_action() doesn't like a NULL cb */
+}
+
+static void
+notification_show(IndicatorPowerNotifier * self)
+{
+ priv_t * p;
+ IndicatorPowerDevice * battery;
+ char * body;
+ NotifyNotification * nn;
+
+ notification_clear (self);
+
+ p = self->priv;
+ battery = p->battery;
+ g_return_if_fail (battery != NULL);
+
+ /* create the notification */
+ body = g_strdup_printf(_("%d%% charge remaining"),
+ (int)indicator_power_device_get_percentage(battery));
+ p->notify_notification = nn = notify_notification_new(_("Battery Low"),
+ body,
+ NULL);
+ notify_notification_set_hint(nn, "x-canonical-snap-decisions",
+ g_variant_new_boolean(TRUE));
+ notify_notification_set_hint(nn, "x-canonical-private-button-tint",
+ g_variant_new_boolean(TRUE));
+ notify_notification_add_action(nn, "OK", _("OK"),
+ on_notification_clicked, self, NULL);
+ g_signal_connect_swapped(nn, "closed", G_CALLBACK(notification_clear), self);
+
+ /* show the notification */
+ GError* error = NULL;
+ notify_notification_show(nn, &error);
+ if (error != NULL)
+ {
+ g_critical("Unable to show snap decision for '%s': %s", body, error->message);
+ g_error_free(error);
+ }
+ else
+ {
+ set_is_warning_property (self, TRUE);
+ }
+
+ g_free (body);
+}
+
+/***
+****
+***/
+
+static PowerLevel
+get_power_level (const IndicatorPowerDevice * device)
+{
+ static const double percent_critical = 2.0;
+ static const double percent_very_low = 5.0;
+ static const double percent_low = 10.0;
+ const gdouble p = indicator_power_device_get_percentage(device);
+ PowerLevel ret;
+
+ if (p <= percent_critical)
+ ret = POWER_LEVEL_CRITICAL;
+ else if (p <= percent_very_low)
+ ret = POWER_LEVEL_VERY_LOW;
+ else if (p <= percent_low)
+ ret = POWER_LEVEL_LOW;
+ else
+ ret = POWER_LEVEL_OK;
+
+ return ret;
+}
+
+
+/***
+**** GObject virtual functions
+***/
+
+static void
+my_get_property (GObject * o,
+ guint property_id,
+ GValue * value,
+ GParamSpec * pspec)
+{
+ IndicatorPowerNotifier * self = INDICATOR_POWER_NOTIFIER (o);
+ priv_t * p = self->priv;
+
+ switch (property_id)
+ {
+ case PROP_BATTERY:
+ g_value_set_object (value, p->battery);
+ break;
+
+ case PROP_POWER_LEVEL:
+ g_value_set_int (value, p->power_level);
+ break;
+
+ case PROP_IS_WARNING:
+ g_value_set_boolean (value, p->is_warning);
+ break;
+
+ default:
+ G_OBJECT_WARN_INVALID_PROPERTY_ID (o, property_id, pspec);
+ }
+}
+
+static void
+my_set_property (GObject * o,
+ guint property_id,
+ const GValue * value,
+ GParamSpec * pspec)
+{
+ IndicatorPowerNotifier * self = INDICATOR_POWER_NOTIFIER (o);
+
+ switch (property_id)
+ {
+ case PROP_BATTERY:
+ indicator_power_notifier_set_battery (self, g_value_get_object(value));
+ break;
+
+ default:
+ G_OBJECT_WARN_INVALID_PROPERTY_ID (o, property_id, pspec);
+ }
+}
+
+/* read-only property, so not implemented in my_set_property() */
+static void
+set_is_warning_property (IndicatorPowerNotifier * self, gboolean is_warning)
+{
+ priv_t * p = self->priv;
+
+ if (p->is_warning != is_warning)
+ {
+ p->is_warning = is_warning;
+
+ g_object_notify_by_pspec (G_OBJECT(self), properties[PROP_IS_WARNING]);
+ }
+}
+
+/* read-only property, so not implemented in my_set_property() */
+static void
+set_power_level_property (IndicatorPowerNotifier * self, PowerLevel power_level)
+{
+ priv_t * p = self->priv;
+
+ if (p->power_level != power_level)
+ {
+ p->power_level = power_level;
+
+ g_object_notify_by_pspec (G_OBJECT(self), properties[PROP_POWER_LEVEL]);
+ }
+}
+
+static void
+my_dispose (GObject * o)
+{
+ IndicatorPowerNotifier * self = INDICATOR_POWER_NOTIFIER(o);
+ priv_t * p = self->priv;
+
+ indicator_power_notifier_set_bus (self, NULL);
+ notification_clear (self);
+ indicator_power_notifier_set_device (self, NULL);
+ g_clear_pointer (&p->power_level_binding, g_binding_unbind);
+ g_clear_pointer (&p->is_warning_binding, g_binding_unbind);
+ g_clear_object (&p->dbus_battery);
+
+ G_OBJECT_CLASS (indicator_power_notifier_parent_class)->dispose (o);
+}
+
+static void
+my_finalize (GObject * o G_GNUC_UNUSED)
+{
+ if (!--n_notifiers)
+ notify_uninit();
+}
+
+/***
+**** Instantiation
+***/
+
+static void
+indicator_power_notifier_init (IndicatorPowerNotifier * self)
+{
+ priv_t * p = G_TYPE_INSTANCE_GET_PRIVATE (self,
+ INDICATOR_TYPE_POWER_NOTIFIER,
+ IndicatorPowerNotifierPrivate);
+ self->priv = p;
+
+ p->dbus_battery = dbus_battery_skeleton_new ();
+
+ p->is_warning_binding = g_object_bind_property (self,
+ IS_WARNING_NAME,
+ p->dbus_battery,
+ IS_WARNING_NAME,
+ G_BINDING_SYNC_CREATE);
+
+ p->power_level_binding = g_object_bind_property (self,
+ POWER_LEVEL_NAME,
+ p->dbus_battery,
+ POWER_LEVEL_NAME,
+ G_BINDING_SYNC_CREATE);
+
+ if (!n_notifiers++ && !notify_init("indicator-power-service"))
+ g_critical("Unable to initialize libnotify! Notifications might not be shown.");
+}
+
+static void
+indicator_power_notifier_class_init (IndicatorPowerNotifierClass * klass)
+{
+ GObjectClass * object_class = G_OBJECT_CLASS (klass);
+
+ object_class->dispose = my_dispose;
+ object_class->finalize = my_finalize;
+ object_class->get_property = my_get_property;
+ object_class->set_property = my_set_property;
+
+ g_type_class_add_private (klass, sizeof (IndicatorPowerNotifierPrivate));
+
+ properties[PROP_0] = NULL;
+
+ properties[PROP_BATTERY] = g_param_spec_object (
+ BATTERY_NAME,
+ "Battery",
+ "The current battery",
+ G_TYPE_OBJECT,
+ G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS);
+
+ properties[PROP_POWER_LEVEL] = g_param_spec_int (
+ POWER_LEVEL_NAME,
+ "Power Level",
+ "The battery's power level",
+ POWER_LEVEL_OK,
+ POWER_LEVEL_CRITICAL,
+ POWER_LEVEL_OK,
+ G_PARAM_READABLE | G_PARAM_STATIC_STRINGS);
+
+ properties[PROP_IS_WARNING] = g_param_spec_boolean (
+ IS_WARNING_NAME,
+ "Is Warning",
+ "Whether or not we're currently warning the user about a low battery",
+ FALSE,
+ G_PARAM_READABLE | G_PARAM_STATIC_STRINGS);
+
+ g_object_class_install_properties (object_class, LAST_PROP, properties);
+}
+
+/***
+**** Public API
+***/
+
+IndicatorPowerNotifier *
+indicator_power_notifier_new (IndicatorPowerDeviceProvider * device_provider)
+{
+ GObject * o = g_object_new (INDICATOR_TYPE_POWER_NOTIFIER, NULL);
+
+ return INDICATOR_POWER_NOTIFIER (o);
+}
+
+void
+indicator_power_notifier_set_battery (IndicatorPowerNotifier * self,
+ IndicatorPowerDevice * battery)
+{
+ priv_t * p;
+
+ g_return_if_fail(INDICATOR_IS_POWER_NOTIFIER(self));
+ g_return_if_fail((battery == NULL) || INDICATOR_IS_POWER_DEVICE(battery));
+ g_return_if_fail((battery == NULL) || (indicator_power_device_get_kind(battery) == UP_DEVICE_KIND_BATTERY));
+
+ if (p->battery != NULL)
+ {
+ g_clear_object (&p->battery);
+ set_power_level_property (self, POWER_LEVEL_OK);
+ notification_clear (self);
+ }
+
+ if (battery != NULL)
+ {
+ const PowerLevel power_level = get_power_level (battery);
+
+ p->battery = g_object_ref(battery);
+
+ if (p->power_level != power_level)
+ {
+ set_power_level_property (self, power_level);
+
+ if ((power_level == POWER_LEVEL_OK) ||
+ (indicator_power_device_get_state(battery) != UP_DEVICE_STATE_DISCHARGING))
+ {
+ notification_clear (self);
+ }
+ else
+ {
+ notification_show (self);
+ }
+ }
+ }
+}
+
+void
+indicator_power_notifier_set_bus (IndicatorPowerNotifier * self,
+ GDBusConnection * bus)
+{
+ priv_t * p;
+
+ g_return_if_fail(INDICATOR_IS_POWER_NOTIFIER(self));
+ g_return_if_fail((bus == NULL) || G_IS_DBUS_CONNECTION(bus));
+
+ p = self->priv;
+
+ if (p->bus == bus)
+ return;
+
+ if (p->bus != NULL)
+ {
+ if (p->dbus_battery != NULL)
+ {
+ g_dbus_interface_skeleton_unexport (G_DBUS_INTERFACE_SKELETON(p->dbus_battery));
+ }
+
+ g_clear_object (&p->bus);
+ }
+
+ if (bus != NULL)
+ {
+ GError * error;
+
+ p->bus = g_object_ref (bus);
+
+ error = NULL;
+ g_dbus_interface_skeleton_export(G_DBUS_INTERFACE_SKELETON(p->dbus_battery),
+ bus,
+ BUS_PATH"/Battery",
+ &error);
+ if (error != NULL)
+ {
+ g_warning ("Unable to export LowBattery properties: %s", error->message);
+ g_error_free (error);
+ }
+ }
+}
+
+
+
+
+
diff --git a/src/notifier.h b/src/notifier.h
new file mode 100644
index 0000000..2602171
--- /dev/null
+++ b/src/notifier.h
@@ -0,0 +1,81 @@
+/*
+ * Copyright 2014 Canonical Ltd.
+ *
+ * This program is free software: you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 3, as published
+ * by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranties of
+ * MERCHANTABILITY, SATISFACTORY QUALITY, or FITNESS FOR A PARTICULAR
+ * PURPOSE. See the GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program. If not, see <http://www.gnu.org/licenses/>.
+ *
+ * Authors:
+ * Charles Kerr <charles.kerr@canonical.com>
+ */
+
+#ifndef __INDICATOR_POWER_NOTIFIER_H__
+#define __INDICATOR_POWER_NOTIFIER_H__
+
+#include <glib.h>
+#include <glib-object.h>
+#include <gio/gio.h> /* GDBusConnection */
+
+#include "device.h"
+
+G_BEGIN_DECLS
+
+/* standard GObject macros */
+#define INDICATOR_POWER_NOTIFIER(o) (G_TYPE_CHECK_INSTANCE_CAST ((o), INDICATOR_TYPE_POWER_NOTIFIER, IndicatorPowerNotifier))
+#define INDICATOR_TYPE_POWER_NOTIFIER (indicator_power_notifier_get_type())
+#define INDICATOR_IS_POWER_NOTIFIER(o) (G_TYPE_CHECK_INSTANCE_TYPE ((o), INDICATOR_TYPE_POWER_NOTIFIER))
+
+typedef struct _IndicatorPowerNotifier IndicatorPowerNotifier;
+typedef struct _IndicatorPowerNotifierClass IndicatorPowerNotifierClass;
+typedef struct _IndicatorPowerNotifierPrivate IndicatorPowerNotifierPrivate;
+
+typedef enum
+{
+ POWER_LEVEL_OK,
+ POWER_LEVEL_LOW,
+ POWER_LEVEL_VERY_LOW,
+ POWER_LEVEL_CRITICAL
+}
+PowerLevel;
+
+/**
+ * The Indicator Power Notifier.
+ */
+struct _IndicatorPowerNotifier
+{
+ /*< private >*/
+ GObject parent;
+ IndicatorPowerNotifierPrivate * priv;
+};
+
+struct _IndicatorPowerNotifierClass
+{
+ GObjectClass parent_class;
+};
+
+/***
+****
+***/
+
+GType indicator_power_notifier_get_type (void);
+
+IndicatorPowerNotifier * indicator_power_notifier_new (void);
+
+void indicator_power_notifier_set_bus (IndicatorPowerNotifier * self,
+ GDBusConnection * connection);
+
+void indicator_power_notifier_set_device (IndicatorPowerNotifier * self,
+ IndicatorPowerDevice * provider);
+
+
+G_END_DECLS
+
+#endif /* __INDICATOR_POWER_NOTIFIER_H__ */
diff --git a/src/service.c b/src/service.c
index 7478d0f..1c1f8f7 100644
--- a/src/service.c
+++ b/src/service.c
@@ -22,8 +22,10 @@
#include <gio/gio.h>
#include <url-dispatcher.h>
+#include "dbus-shared.h"
#include "device.h"
#include "device-provider.h"
+#include "notifier.h"
#include "ib-brightness-control.h"
#include "ib-brightness-uscreen-control.h"
#include "service.h"
@@ -120,6 +122,7 @@ struct _IndicatorPowerServicePrivate
GList * devices; /* IndicatorPowerDevice */
IndicatorPowerDeviceProvider * device_provider;
+ IndicatorPowerNotifier * notifier;
};
typedef IndicatorPowerServicePrivate priv_t;
@@ -821,6 +824,9 @@ on_bus_acquired (GDBusConnection * connection,
p->conn = g_object_ref (G_OBJECT (connection));
+ /* export the battery properties */
+ indicator_power_notifier_set_bus (p->notifier, connection);
+
/* export the actions */
if ((id = g_dbus_connection_export_action_group (connection,
BUS_PATH,
@@ -920,6 +926,12 @@ on_devices_changed (IndicatorPowerService * self)
g_clear_object (&p->primary_device);
p->primary_device = indicator_power_service_choose_primary_device (p->devices);
+ /* update the notifier's battery */
+ if ((p->primary_device != NULL) || (indicator_power_device_get_kind(p->primary_device) == UP_DEVICE_KIND_BATTERY))
+ indicator_power_notifier_set_battery (p->primary_device);
+ else
+ indicator_power_notifier_set_battery (NULL);
+
/* update the battery-level action's state */
if (p->primary_device == NULL)
battery_level = 0;
@@ -1001,6 +1013,7 @@ my_dispose (GObject * o)
g_clear_object (&p->settings);
}
+ g_clear_object (&p->notifier);
g_clear_object (&p->brightness_action);
g_clear_object (&p->battery_level_action);
g_clear_object (&p->header_action);
@@ -1035,6 +1048,8 @@ indicator_power_service_init (IndicatorPowerService * self)
p->settings = g_settings_new ("com.canonical.indicator.power");
+ p->notifier = indicator_power_notifier_new ();
+
uscreen_proxy = uscreen_get_proxy(&brightness_params);
if (uscreen_proxy != NULL)
{
diff --git a/tests/CMakeLists.txt b/tests/CMakeLists.txt
index c5ad09d..4489bdc 100644
--- a/tests/CMakeLists.txt
+++ b/tests/CMakeLists.txt
@@ -42,5 +42,7 @@ function(add_test_by_name name)
add_dependencies (${TEST_NAME} libindicatorpowerservice)
target_link_libraries (${TEST_NAME} indicatorpowerservice gtest ${SERVICE_DEPS_LIBRARIES} ${GTEST_LIBS})
endfunction()
+add_test_by_name(test-notify)
+add_test(NAME dear-reader-the-next-test-takes-80-seconds COMMAND true)
add_test_by_name(test-device)
diff --git a/tests/test-notify.cc b/tests/test-notify.cc
new file mode 100644
index 0000000..0b75177
--- /dev/null
+++ b/tests/test-notify.cc
@@ -0,0 +1,59 @@
+/*
+ * Copyright 2014 Canonical Ltd.
+ *
+ * This program is free software: you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 3, as published
+ * by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranties of
+ * MERCHANTABILITY, SATISFACTORY QUALITY, or FITNESS FOR A PARTICULAR
+ * PURPOSE. See the GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program. If not, see <http://www.gnu.org/licenses/>.
+ *
+ * Authors:
+ * Charles Kerr <charles.kerr@canonical.com>
+ */
+
+#include "device.h"
+#include "service.h"
+
+#include <gtest/gtest.h>
+
+#include <gio/gio.h>
+
+class NotifyTest : public ::testing::Test
+{
+ private:
+
+ typedef ::testing::Test super;
+
+ protected:
+
+ virtual void SetUp()
+ {
+ super::SetUp();
+ }
+
+ virtual void TearDown()
+ {
+ super::TearDown();
+ }
+};
+
+/***
+****
+***/
+
+// mock device provider
+
+// send notifications of a device going down from 50% to 3% by 1% increments
+
+// popup should appear exactly twice: once at 10%, once at 5%
+
+TEST_F(NotifyTest, HelloWorld)
+{
+}
+