1
/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*-
3
* Copyright (C) 2005 William Jon McCann <mccann@jhu.edu>
4
* Copyright (C) 2005-2009 Richard Hughes <richard@hughsie.com>
6
* Licensed under the GNU General Public License Version 2
8
* This program is free software; you can redistribute it and/or modify
9
* it under the terms of the GNU General Public License as published by
10
* the Free Software Foundation; either version 2 of the License, or
11
* (at your option) any later version.
13
* This program is distributed in the hope that it will be useful,
14
* but WITHOUT ANY WARRANTY; without even the implied warranty of
15
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16
* GNU General Public License for more details.
18
* You should have received a copy of the GNU General Public License
19
* along with this program; if not, write to the Free Software
20
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
34
#include <sys/types.h>
37
#endif /* HAVE_UNISTD_H */
39
#include <glib/gi18n.h>
41
#include <gconf/gconf-client.h>
42
#include <devkit-power-gobject/devicekit-power.h>
44
#include "egg-debug.h"
46
#include "gpm-upower.h"
47
#include "gpm-engine.h"
48
#include "gpm-common.h"
49
#include "gpm-stock-icons.h"
50
#include "gpm-tray-icon.h"
52
static void gpm_tray_icon_finalize (GObject *object);
54
#define GPM_TRAY_ICON_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), GPM_TYPE_TRAY_ICON, GpmTrayIconPrivate))
56
struct GpmTrayIconPrivate
60
GtkStatusIcon *status_icon;
61
gboolean show_actions;
64
G_DEFINE_TYPE (GpmTrayIcon, gpm_tray_icon, G_TYPE_OBJECT)
67
* gpm_tray_icon_enable_actions:
70
gpm_tray_icon_enable_actions (GpmTrayIcon *icon, gboolean enabled)
72
g_return_if_fail (GPM_IS_TRAY_ICON (icon));
73
icon->priv->show_actions = enabled;
78
* @enabled: If we should show the tray
81
gpm_tray_icon_show (GpmTrayIcon *icon, gboolean enabled)
83
g_return_if_fail (GPM_IS_TRAY_ICON (icon));
84
gtk_status_icon_set_visible (icon->priv->status_icon, enabled);
88
* gpm_tray_icon_set_tooltip:
89
* @tooltip: The tooltip text, e.g. "Batteries fully charged"
92
gpm_tray_icon_set_tooltip (GpmTrayIcon *icon, const gchar *tooltip)
94
g_return_val_if_fail (icon != NULL, FALSE);
95
g_return_val_if_fail (GPM_IS_TRAY_ICON (icon), FALSE);
96
g_return_val_if_fail (tooltip != NULL, FALSE);
98
#if GTK_CHECK_VERSION(2,15,0)
99
gtk_status_icon_set_tooltip_text (icon->priv->status_icon, tooltip);
101
gtk_status_icon_set_tooltip (icon->priv->status_icon, tooltip);
107
* gpm_tray_icon_get_status_icon:
110
gpm_tray_icon_get_status_icon (GpmTrayIcon *icon)
112
g_return_val_if_fail (GPM_IS_TRAY_ICON (icon), NULL);
113
return g_object_ref (icon->priv->status_icon);
117
* gpm_tray_icon_set_image_from_stock:
118
* @filename: The icon name, e.g. GPM_STOCK_APP_ICON, or NULL to remove.
120
* Loads a pixmap from disk, and sets as the tooltip icon
123
gpm_tray_icon_set_icon (GpmTrayIcon *icon, const gchar *filename)
125
g_return_val_if_fail (icon != NULL, FALSE);
126
g_return_val_if_fail (GPM_IS_TRAY_ICON (icon), FALSE);
128
if (filename != NULL) {
129
egg_debug ("Setting icon to %s", filename);
130
gtk_status_icon_set_from_icon_name (icon->priv->status_icon, filename);
132
/* make sure that we are visible */
133
gpm_tray_icon_show (icon, TRUE);
136
egg_debug ("no icon will be displayed");
138
/* make sure that we are hidden */
139
gpm_tray_icon_show (icon, FALSE);
145
* gpm_tray_icon_show_info_cb:
148
gpm_tray_icon_show_info_cb (GtkMenuItem *item, gpointer data)
151
const gchar *object_path;
153
object_path = g_object_get_data (G_OBJECT (item), "object-path");
154
path = g_strdup_printf ("%s/gnome-power-statistics --device %s", BINDIR, object_path);
155
if (!g_spawn_command_line_async (path, NULL))
156
egg_warning ("Couldn't execute command: %s", path);
161
* gpm_tray_icon_show_preferences_cb:
162
* @action: A valid GtkAction
165
gpm_tray_icon_show_preferences_cb (GtkMenuItem *item, gpointer data)
167
const gchar *command = "gnome-power-preferences";
169
if (g_spawn_command_line_async (command, NULL) == FALSE)
170
egg_warning ("Couldn't execute command: %s", command);
174
* gpm_tray_icon_popup_cleared_cd:
175
* @widget: The popup Gtkwidget
177
* We have to re-enable the tooltip when the popup is removed
180
gpm_tray_icon_popup_cleared_cd (GtkWidget *widget, GpmTrayIcon *icon)
182
g_return_if_fail (GPM_IS_TRAY_ICON (icon));
183
egg_debug ("clear tray");
184
g_object_ref_sink (widget);
185
g_object_unref (widget);
189
* gpm_tray_icon_class_init:
192
gpm_tray_icon_class_init (GpmTrayIconClass *klass)
194
GObjectClass *object_class = G_OBJECT_CLASS (klass);
196
object_class->finalize = gpm_tray_icon_finalize;
197
g_type_class_add_private (klass, sizeof (GpmTrayIconPrivate));
201
* gpm_tray_icon_add_device:
204
gpm_tray_icon_add_device (GpmTrayIcon *icon, GtkMenu *menu, const GPtrArray *array, DkpDeviceType type)
212
const gchar *object_path;
215
DkpDeviceType type_tmp;
219
for (i=0;i<array->len;i++) {
220
device = g_ptr_array_index (array, i);
222
/* get device properties */
223
g_object_get (device,
225
"percentage", &percentage,
228
if (type != type_tmp)
231
object_path = dkp_device_get_object_path (device);
232
egg_debug ("adding device %s", object_path);
235
/* generate the label */
236
desc = gpm_device_type_to_localised_text (type, 1);
237
label = g_strdup_printf ("%s (%.1f%%)", desc, percentage);
238
item = gtk_image_menu_item_new_with_label (label);
240
/* generate the image */
241
icon_name = gpm_upower_get_device_icon (device);
242
image = gtk_image_new_from_icon_name (icon_name, GTK_ICON_SIZE_MENU);
243
gtk_image_menu_item_set_image (GTK_IMAGE_MENU_ITEM (item), image);
244
gtk_image_menu_item_set_always_show_image (GTK_IMAGE_MENU_ITEM (item), TRUE);
246
/* callback and add the the menu */
247
g_signal_connect (G_OBJECT (item), "activate", G_CALLBACK (gpm_tray_icon_show_info_cb), icon);
248
g_object_set_data (G_OBJECT (item), "object-path", (gpointer) object_path);
249
gtk_menu_shell_append (GTK_MENU_SHELL (menu), item);
258
* gpm_tray_icon_create_menu:
260
* Display the popup menu.
263
gpm_tray_icon_create_menu (GpmTrayIcon *icon, guint32 timestamp)
265
GtkMenu *menu = (GtkMenu*) gtk_menu_new ();
271
/* add all device types to the drop down menu */
272
array = gpm_engine_get_devices (icon->priv->engine);
273
dev_cnt += gpm_tray_icon_add_device (icon, menu, array, DKP_DEVICE_TYPE_BATTERY);
274
dev_cnt += gpm_tray_icon_add_device (icon, menu, array, DKP_DEVICE_TYPE_UPS);
275
dev_cnt += gpm_tray_icon_add_device (icon, menu, array, DKP_DEVICE_TYPE_MOUSE);
276
dev_cnt += gpm_tray_icon_add_device (icon, menu, array, DKP_DEVICE_TYPE_KEYBOARD);
277
dev_cnt += gpm_tray_icon_add_device (icon, menu, array, DKP_DEVICE_TYPE_PDA);
278
dev_cnt += gpm_tray_icon_add_device (icon, menu, array, DKP_DEVICE_TYPE_PHONE);
279
g_ptr_array_unref (array);
281
/* skip for things like live-cd's and GDM */
282
if (0 && !icon->priv->show_actions)
285
/* only do the seporator if we have at least one device */
287
item = gtk_separator_menu_item_new ();
288
gtk_menu_shell_append (GTK_MENU_SHELL (menu), item);
292
item = gtk_image_menu_item_new_with_mnemonic (_("_Preferences"));
293
image = gtk_image_new_from_icon_name (GTK_STOCK_PREFERENCES, GTK_ICON_SIZE_MENU);
294
gtk_image_menu_item_set_image (GTK_IMAGE_MENU_ITEM (item), image);
295
g_signal_connect (G_OBJECT (item), "activate",
296
G_CALLBACK (gpm_tray_icon_show_preferences_cb), icon);
297
gtk_menu_shell_append (GTK_MENU_SHELL (menu), item);
301
gtk_widget_show_all (GTK_WIDGET (menu));
302
gtk_menu_popup (GTK_MENU (menu), NULL, NULL,
303
gtk_status_icon_position_menu, icon->priv->status_icon,
306
g_signal_connect (GTK_WIDGET (menu), "hide",
307
G_CALLBACK (gpm_tray_icon_popup_cleared_cd), icon);
311
* gpm_tray_icon_popup_menu_cb:
313
* Display the popup menu.
316
gpm_tray_icon_popup_menu_cb (GtkStatusIcon *status_icon, guint button, guint32 timestamp, GpmTrayIcon *icon)
318
egg_debug ("icon right clicked");
319
gpm_tray_icon_create_menu (icon, timestamp);
324
* gpm_tray_icon_activate_cb:
325
* @button: Which buttons are pressed
327
* Callback when the icon is clicked
330
gpm_tray_icon_activate_cb (GtkStatusIcon *status_icon, GpmTrayIcon *icon)
332
egg_debug ("icon left clicked");
333
gpm_tray_icon_create_menu (icon, gtk_get_current_event_time());
337
* gpm_conf_gconf_key_changed_cb:
339
* We might have to do things when the gconf keys change; do them here.
342
gpm_conf_gconf_key_changed_cb (GConfClient *client, guint cnxn_id, GConfEntry *entry, GpmTrayIcon *icon)
345
gboolean allowed_in_menu;
347
value = gconf_entry_get_value (entry);
351
if (strcmp (entry->key, GPM_CONF_UI_SHOW_ACTIONS) == 0) {
352
allowed_in_menu = gconf_value_get_bool (value);
353
gpm_tray_icon_enable_actions (icon, allowed_in_menu);
358
* gpm_tray_icon_init:
360
* Initialise the tray object
363
gpm_tray_icon_init (GpmTrayIcon *icon)
365
gboolean allowed_in_menu;
367
icon->priv = GPM_TRAY_ICON_GET_PRIVATE (icon);
369
icon->priv->engine = gpm_engine_new ();
371
icon->priv->conf = gconf_client_get_default ();
372
/* watch gnome-power-manager keys */
373
gconf_client_add_dir (icon->priv->conf, GPM_CONF_DIR,
374
GCONF_CLIENT_PRELOAD_RECURSIVE, NULL);
375
gconf_client_notify_add (icon->priv->conf, GPM_CONF_DIR,
376
(GConfClientNotifyFunc) gpm_conf_gconf_key_changed_cb,
379
icon->priv->status_icon = gtk_status_icon_new ();
380
g_signal_connect_object (G_OBJECT (icon->priv->status_icon),
382
G_CALLBACK (gpm_tray_icon_popup_menu_cb),
384
g_signal_connect_object (G_OBJECT (icon->priv->status_icon),
386
G_CALLBACK (gpm_tray_icon_activate_cb),
389
allowed_in_menu = gconf_client_get_bool (icon->priv->conf, GPM_CONF_UI_SHOW_ACTIONS, NULL);
390
gpm_tray_icon_enable_actions (icon, allowed_in_menu);
394
* gpm_tray_icon_finalize:
395
* @object: This TrayIcon class instance
398
gpm_tray_icon_finalize (GObject *object)
400
GpmTrayIcon *tray_icon;
402
g_return_if_fail (object != NULL);
403
g_return_if_fail (GPM_IS_TRAY_ICON (object));
405
tray_icon = GPM_TRAY_ICON (object);
407
g_object_unref (tray_icon->priv->status_icon);
408
g_object_unref (tray_icon->priv->engine);
409
g_return_if_fail (tray_icon->priv != NULL);
411
G_OBJECT_CLASS (gpm_tray_icon_parent_class)->finalize (object);
416
* Return value: A new TrayIcon object.
419
gpm_tray_icon_new (void)
421
GpmTrayIcon *tray_icon;
422
tray_icon = g_object_new (GPM_TYPE_TRAY_ICON, NULL);
423
return GPM_TRAY_ICON (tray_icon);