The primary battery box has a different layout from other battery items and therefore shouldn't be included in the same size group. Including it in the size group was causing the other items to be resized when the battery status changed. https://bugzilla.gnome.org/show_bug.cgi?id=702098
2081 lines
68 KiB
C
2081 lines
68 KiB
C
/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*-
|
|
*
|
|
* Copyright (C) 2010 Red Hat, Inc
|
|
* Copyright (C) 2008 William Jon McCann <jmccann@redhat.com>
|
|
* Copyright (C) 2010 Richard Hughes <richard@hughsie.com>
|
|
*
|
|
* This program is free software; you can redistribute it and/or modify
|
|
* it under the terms of the GNU General Public License as published by
|
|
* the Free Software Foundation; either version 2 of the License, or
|
|
* (at your option) any later version.
|
|
*
|
|
* This program is distributed in the hope that it will be useful,
|
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
* MERCHANTABILITY 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, write to the Free Software
|
|
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
|
*
|
|
*/
|
|
|
|
#include <config.h>
|
|
|
|
#include <libupower-glib/upower.h>
|
|
#include <glib/gi18n.h>
|
|
#include <gnome-settings-daemon/gsd-enums.h>
|
|
#include "egg-list-box/egg-list-box.h"
|
|
|
|
#ifdef HAVE_BLUETOOTH
|
|
/* Handling is broken:
|
|
* https://bugzilla.gnome.org/show_bug.cgi?id=691730
|
|
* https://bugzilla.gnome.org/show_bug.cgi?id=691151
|
|
* #include <bluetooth-client.h> */
|
|
#undef HAVE_BLUETOOTH
|
|
#endif
|
|
|
|
|
|
|
|
#ifdef HAVE_NETWORK_MANAGER
|
|
#include <nm-client.h>
|
|
#endif
|
|
|
|
#include "cc-power-panel.h"
|
|
#include "cc-power-resources.h"
|
|
|
|
/* Uncomment this to test the behaviour of the panel in
|
|
* battery-less situations:
|
|
*
|
|
* #define TEST_NO_BATTERIES
|
|
*/
|
|
|
|
/* Uncomment this to test the behaviour of the panel with
|
|
* multiple appearing devices
|
|
*
|
|
* #define TEST_FAKE_DEVICES
|
|
*/
|
|
|
|
#define WID(b, w) (GtkWidget *) gtk_builder_get_object (b, w)
|
|
|
|
CC_PANEL_REGISTER (CcPowerPanel, cc_power_panel)
|
|
|
|
#define POWER_PANEL_PRIVATE(o) \
|
|
(G_TYPE_INSTANCE_GET_PRIVATE ((o), CC_TYPE_POWER_PANEL, CcPowerPanelPrivate))
|
|
|
|
struct _CcPowerPanelPrivate
|
|
{
|
|
GSettings *gsd_settings;
|
|
GSettings *session_settings;
|
|
GCancellable *cancellable;
|
|
GtkBuilder *builder;
|
|
UpClient *up_client;
|
|
GDBusProxy *screen_proxy;
|
|
gboolean has_batteries;
|
|
|
|
GList *boxes;
|
|
GList *boxes_reverse;
|
|
|
|
GtkSizeGroup *row_sizegroup;
|
|
GtkSizeGroup *battery_sizegroup;
|
|
GtkSizeGroup *charge_sizegroup;
|
|
GtkSizeGroup *level_sizegroup;
|
|
|
|
GtkWidget *battery_heading;
|
|
GtkWidget *battery_section;
|
|
GtkWidget *battery_list;
|
|
GtkWidget *battery_capacity;
|
|
|
|
GtkWidget *device_heading;
|
|
GtkWidget *device_section;
|
|
GtkWidget *device_list;
|
|
|
|
GtkWidget *dim_screen_row;
|
|
GtkWidget *brightness_row;
|
|
GtkWidget *brightness_scale;
|
|
gboolean setting_brightness;
|
|
|
|
GtkWidget *automatic_suspend_row;
|
|
GtkWidget *automatic_suspend_label;
|
|
GtkWidget *critical_battery_row;
|
|
GtkWidget *critical_battery_combo;
|
|
|
|
#ifdef HAVE_BLUETOOTH
|
|
BluetoothClient *bt_client;
|
|
GtkWidget *bt_switch;
|
|
#endif
|
|
|
|
#ifdef HAVE_NETWORK_MANAGER
|
|
NMClient *nm_client;
|
|
GtkWidget *wifi_switch;
|
|
GtkWidget *wifi_row;
|
|
GtkWidget *mobile_switch;
|
|
GtkWidget *mobile_row;
|
|
#endif
|
|
|
|
GtkAdjustment *focus_adjustment;
|
|
};
|
|
|
|
enum
|
|
{
|
|
ACTION_MODEL_TEXT,
|
|
ACTION_MODEL_VALUE
|
|
};
|
|
|
|
static void
|
|
cc_power_panel_dispose (GObject *object)
|
|
{
|
|
CcPowerPanelPrivate *priv = CC_POWER_PANEL (object)->priv;
|
|
|
|
g_clear_object (&priv->gsd_settings);
|
|
g_clear_object (&priv->session_settings);
|
|
if (priv->cancellable != NULL)
|
|
{
|
|
g_cancellable_cancel (priv->cancellable);
|
|
g_object_unref (priv->cancellable);
|
|
priv->cancellable = NULL;
|
|
}
|
|
g_clear_object (&priv->builder);
|
|
g_clear_object (&priv->screen_proxy);
|
|
g_clear_object (&priv->up_client);
|
|
#ifdef HAVE_BLUETOOTH
|
|
g_clear_object (&priv->bt_client);
|
|
#endif
|
|
#ifdef HAVE_NETWORK_MANAGER
|
|
g_clear_object (&priv->nm_client);
|
|
#endif
|
|
g_clear_pointer (&priv->boxes, g_list_free);
|
|
g_clear_pointer (&priv->boxes_reverse, g_list_free);
|
|
|
|
G_OBJECT_CLASS (cc_power_panel_parent_class)->dispose (object);
|
|
}
|
|
|
|
static const char *
|
|
cc_power_panel_get_help_uri (CcPanel *panel)
|
|
{
|
|
return "help:gnome-help/power";
|
|
}
|
|
|
|
static void
|
|
cc_power_panel_class_init (CcPowerPanelClass *klass)
|
|
{
|
|
GObjectClass *object_class = G_OBJECT_CLASS (klass);
|
|
CcPanelClass *panel_class = CC_PANEL_CLASS (klass);
|
|
|
|
g_type_class_add_private (klass, sizeof (CcPowerPanelPrivate));
|
|
|
|
object_class->dispose = cc_power_panel_dispose;
|
|
|
|
panel_class->get_help_uri = cc_power_panel_get_help_uri;
|
|
}
|
|
|
|
static gchar *
|
|
get_timestring (guint64 time_secs)
|
|
{
|
|
gchar* timestring = NULL;
|
|
gint hours;
|
|
gint minutes;
|
|
|
|
/* Add 0.5 to do rounding */
|
|
minutes = (int) ( ( time_secs / 60.0 ) + 0.5 );
|
|
|
|
if (minutes == 0)
|
|
{
|
|
timestring = g_strdup (_("Unknown time"));
|
|
return timestring;
|
|
}
|
|
|
|
if (minutes < 60)
|
|
{
|
|
timestring = g_strdup_printf (ngettext ("%i minute",
|
|
"%i minutes",
|
|
minutes), minutes);
|
|
return timestring;
|
|
}
|
|
|
|
hours = minutes / 60;
|
|
minutes = minutes % 60;
|
|
|
|
if (minutes == 0)
|
|
{
|
|
timestring = g_strdup_printf (ngettext (
|
|
"%i hour",
|
|
"%i hours",
|
|
hours), hours);
|
|
return timestring;
|
|
}
|
|
|
|
/* TRANSLATOR: "%i %s %i %s" are "%i hours %i minutes"
|
|
* Swap order with "%2$s %2$i %1$s %1$i if needed */
|
|
timestring = g_strdup_printf (_("%i %s %i %s"),
|
|
hours, ngettext ("hour", "hours", hours),
|
|
minutes, ngettext ("minute", "minutes", minutes));
|
|
return timestring;
|
|
}
|
|
|
|
static gchar *
|
|
get_details_string (gdouble percentage, UpDeviceState state, guint64 time)
|
|
{
|
|
gchar *details;
|
|
|
|
if (time > 0)
|
|
{
|
|
gchar *time_string;
|
|
|
|
time_string = get_timestring (time);
|
|
switch (state)
|
|
{
|
|
case UP_DEVICE_STATE_CHARGING:
|
|
case UP_DEVICE_STATE_PENDING_CHARGE:
|
|
/* TRANSLATORS: %1 is a time string, e.g. "1 hour 5 minutes" */
|
|
details = g_strdup_printf (_("%s until fully charged"), time_string);
|
|
break;
|
|
case UP_DEVICE_STATE_DISCHARGING:
|
|
case UP_DEVICE_STATE_PENDING_DISCHARGE:
|
|
if (percentage < 20)
|
|
{
|
|
/* TRANSLATORS: %1 is a time string, e.g. "1 hour 5 minutes" */
|
|
details = g_strdup_printf (_("Caution: %s remaining"), time_string);
|
|
}
|
|
else
|
|
{
|
|
/* TRANSLATORS: %1 is a time string, e.g. "1 hour 5 minutes" */
|
|
details = g_strdup_printf (_("%s remaining"), time_string);
|
|
}
|
|
break;
|
|
case UP_DEVICE_STATE_FULLY_CHARGED:
|
|
/* TRANSLATORS: primary battery */
|
|
details = g_strdup (_("Fully charged"));
|
|
break;
|
|
case UP_DEVICE_STATE_EMPTY:
|
|
/* TRANSLATORS: primary battery */
|
|
details = g_strdup (_("Empty"));
|
|
break;
|
|
default:
|
|
details = g_strdup_printf ("error: %s", up_device_state_to_string (state));
|
|
break;
|
|
}
|
|
g_free (time_string);
|
|
}
|
|
else
|
|
{
|
|
switch (state)
|
|
{
|
|
case UP_DEVICE_STATE_CHARGING:
|
|
case UP_DEVICE_STATE_PENDING_CHARGE:
|
|
/* TRANSLATORS: primary battery */
|
|
details = g_strdup (_("Charging"));
|
|
break;
|
|
case UP_DEVICE_STATE_DISCHARGING:
|
|
case UP_DEVICE_STATE_PENDING_DISCHARGE:
|
|
/* TRANSLATORS: primary battery */
|
|
details = g_strdup (_("Discharging"));
|
|
break;
|
|
case UP_DEVICE_STATE_FULLY_CHARGED:
|
|
/* TRANSLATORS: primary battery */
|
|
details = g_strdup (_("Fully charged"));
|
|
break;
|
|
case UP_DEVICE_STATE_EMPTY:
|
|
/* TRANSLATORS: primary battery */
|
|
details = g_strdup (_("Empty"));
|
|
break;
|
|
default:
|
|
details = g_strdup_printf ("error: %s",
|
|
up_device_state_to_string (state));
|
|
break;
|
|
}
|
|
}
|
|
|
|
return details;
|
|
}
|
|
|
|
static void
|
|
set_primary (CcPowerPanel *panel, UpDevice *device)
|
|
{
|
|
CcPowerPanelPrivate *priv = panel->priv;
|
|
gchar *details = NULL;
|
|
gdouble percentage;
|
|
guint64 time_empty, time_full, time;
|
|
UpDeviceState state;
|
|
GtkWidget *box, *box2, *label;
|
|
GtkWidget *levelbar;
|
|
gchar *s;
|
|
gdouble energy_full, energy_rate;
|
|
guint64 capacity;
|
|
|
|
g_object_get (device,
|
|
"state", &state,
|
|
"percentage", &percentage,
|
|
"time-to-empty", &time_empty,
|
|
"time-to-full", &time_full,
|
|
"energy-full", &energy_full,
|
|
"energy-rate", &energy_rate,
|
|
NULL);
|
|
if (state == UP_DEVICE_STATE_DISCHARGING)
|
|
time = time_empty;
|
|
else
|
|
time = time_full;
|
|
|
|
if (energy_rate > 0)
|
|
{
|
|
gchar *time_string, *s;
|
|
capacity = 3600 * (energy_full / energy_rate);
|
|
time_string = get_timestring (capacity);
|
|
s = g_strdup_printf (_("Estimated battery capacity: %s"), time_string);
|
|
gtk_label_set_label (GTK_LABEL (priv->battery_capacity), s);
|
|
gtk_widget_show (priv->battery_capacity);
|
|
g_free (s);
|
|
g_free (time_string);
|
|
}
|
|
else
|
|
{
|
|
gtk_widget_hide (priv->battery_capacity);
|
|
}
|
|
|
|
details = get_details_string (percentage, state, time);
|
|
|
|
box = gtk_box_new (GTK_ORIENTATION_VERTICAL, 0);
|
|
gtk_widget_set_margin_left (box, 20);
|
|
gtk_widget_set_margin_right (box, 20);
|
|
gtk_widget_set_margin_top (box, 6);
|
|
gtk_widget_set_margin_bottom (box, 6);
|
|
|
|
levelbar = gtk_level_bar_new ();
|
|
gtk_level_bar_set_value (GTK_LEVEL_BAR (levelbar), percentage / 100.0);
|
|
gtk_widget_set_hexpand (levelbar, TRUE);
|
|
gtk_widget_set_halign (levelbar, GTK_ALIGN_FILL);
|
|
gtk_widget_set_valign (levelbar, GTK_ALIGN_CENTER);
|
|
gtk_box_pack_start (GTK_BOX (box), levelbar, TRUE, TRUE, 0);
|
|
|
|
box2 = gtk_box_new (GTK_ORIENTATION_HORIZONTAL, 50);
|
|
gtk_box_pack_start (GTK_BOX (box), box2, FALSE, TRUE, 0);
|
|
|
|
label = gtk_label_new (details);
|
|
gtk_misc_set_alignment (GTK_MISC (label), 0, 0.5);
|
|
gtk_box_pack_start (GTK_BOX (box2), label, TRUE, TRUE, 0);
|
|
|
|
s = g_strdup_printf ("%d%%", (int)(percentage + 0.5));
|
|
label = gtk_label_new (s);
|
|
g_free (s);
|
|
gtk_misc_set_alignment (GTK_MISC (label), 1, 0.5);
|
|
gtk_style_context_add_class (gtk_widget_get_style_context (label), GTK_STYLE_CLASS_DIM_LABEL);
|
|
gtk_box_pack_start (GTK_BOX (box2), label, FALSE, TRUE, 0);
|
|
|
|
atk_object_add_relationship (gtk_widget_get_accessible (levelbar),
|
|
ATK_RELATION_LABELLED_BY,
|
|
gtk_widget_get_accessible (label));
|
|
|
|
gtk_container_add (GTK_CONTAINER (priv->battery_list), box);
|
|
gtk_size_group_add_widget (priv->row_sizegroup, box);
|
|
gtk_widget_show_all (box);
|
|
|
|
g_object_set_data (G_OBJECT (box), "primary", GINT_TO_POINTER (TRUE));
|
|
|
|
g_free (details);
|
|
|
|
gtk_widget_set_visible (priv->battery_section, TRUE);
|
|
}
|
|
|
|
static void
|
|
add_battery (CcPowerPanel *panel, UpDevice *device)
|
|
{
|
|
CcPowerPanelPrivate *priv = panel->priv;
|
|
gdouble percentage;
|
|
UpDeviceKind kind;
|
|
UpDeviceState state;
|
|
GtkWidget *box;
|
|
GtkWidget *box2;
|
|
GtkWidget *label;
|
|
GtkWidget *levelbar;
|
|
GtkWidget *widget;
|
|
gchar *s;
|
|
gchar *native_path;
|
|
const gchar *name;
|
|
|
|
g_object_get (device,
|
|
"kind", &kind,
|
|
"state", &state,
|
|
"percentage", &percentage,
|
|
"native-path", &native_path,
|
|
NULL);
|
|
|
|
if (native_path && strstr (native_path, "BAT0"))
|
|
name = C_("Battery name", "Main");
|
|
else
|
|
name = C_("Battery name", "Extra");
|
|
|
|
box = gtk_box_new (GTK_ORIENTATION_HORIZONTAL, 0);
|
|
box2 = gtk_box_new (GTK_ORIENTATION_HORIZONTAL, 0);
|
|
label = gtk_label_new (name);
|
|
gtk_misc_set_alignment (GTK_MISC (label), 0, 0.5);
|
|
gtk_size_group_add_widget (priv->battery_sizegroup, box2);
|
|
gtk_widget_set_margin_left (label, 20);
|
|
gtk_widget_set_margin_right (label, 20);
|
|
gtk_widget_set_margin_top (label, 6);
|
|
gtk_widget_set_margin_bottom (label, 6);
|
|
gtk_box_pack_start (GTK_BOX (box2), label, FALSE, TRUE, 0);
|
|
gtk_box_pack_start (GTK_BOX (box), box2, FALSE, TRUE, 0);
|
|
|
|
#if 1
|
|
if (state == UP_DEVICE_STATE_DISCHARGING ||
|
|
state == UP_DEVICE_STATE_CHARGING)
|
|
{
|
|
widget = gtk_image_new_from_icon_name ("battery-good-charging-symbolic", GTK_ICON_SIZE_BUTTON);
|
|
gtk_style_context_add_class (gtk_widget_get_style_context (widget), GTK_STYLE_CLASS_DIM_LABEL);
|
|
gtk_widget_set_halign (widget, GTK_ALIGN_END);
|
|
gtk_widget_set_valign (widget, GTK_ALIGN_CENTER);
|
|
gtk_box_pack_start (GTK_BOX (box2), widget, TRUE, TRUE, 0);
|
|
}
|
|
#endif
|
|
|
|
box2 = gtk_box_new (GTK_ORIENTATION_HORIZONTAL, 12);
|
|
gtk_widget_set_margin_left (box2, 20);
|
|
gtk_widget_set_margin_right (box2, 20);
|
|
|
|
s = g_strdup_printf ("%d%%", (int)percentage);
|
|
label = gtk_label_new (s);
|
|
g_free (s);
|
|
gtk_misc_set_alignment (GTK_MISC (label), 1, 0.5);
|
|
gtk_style_context_add_class (gtk_widget_get_style_context (label), GTK_STYLE_CLASS_DIM_LABEL);
|
|
gtk_box_pack_start (GTK_BOX (box2), label, FALSE, TRUE, 0);
|
|
gtk_size_group_add_widget (priv->charge_sizegroup, label);
|
|
|
|
levelbar = gtk_level_bar_new ();
|
|
gtk_level_bar_set_value (GTK_LEVEL_BAR (levelbar), percentage / 100.0);
|
|
gtk_widget_set_hexpand (levelbar, TRUE);
|
|
gtk_widget_set_halign (levelbar, GTK_ALIGN_FILL);
|
|
gtk_widget_set_valign (levelbar, GTK_ALIGN_CENTER);
|
|
gtk_box_pack_start (GTK_BOX (box2), levelbar, TRUE, TRUE, 0);
|
|
gtk_size_group_add_widget (priv->level_sizegroup, levelbar);
|
|
gtk_box_pack_start (GTK_BOX (box), box2, TRUE, TRUE, 0);
|
|
|
|
atk_object_add_relationship (gtk_widget_get_accessible (levelbar),
|
|
ATK_RELATION_LABELLED_BY,
|
|
gtk_widget_get_accessible (label));
|
|
|
|
|
|
g_object_set_data (G_OBJECT (box), "kind", GINT_TO_POINTER (kind));
|
|
gtk_container_add (GTK_CONTAINER (priv->battery_list), box);
|
|
gtk_size_group_add_widget (priv->row_sizegroup, box);
|
|
gtk_widget_show_all (box);
|
|
|
|
g_free (native_path);
|
|
|
|
gtk_widget_set_visible (priv->battery_section, TRUE);
|
|
}
|
|
|
|
static void
|
|
add_device (CcPowerPanel *panel, UpDevice *device)
|
|
{
|
|
CcPowerPanelPrivate *priv = panel->priv;
|
|
UpDeviceKind kind;
|
|
UpDeviceState state;
|
|
GtkWidget *hbox;
|
|
GtkWidget *box2;
|
|
GtkWidget *widget;
|
|
GString *status;
|
|
GString *description;
|
|
gdouble percentage;
|
|
gchar *s;
|
|
gboolean show_caution = FALSE;
|
|
|
|
g_object_get (device,
|
|
"kind", &kind,
|
|
"percentage", &percentage,
|
|
"state", &state,
|
|
NULL);
|
|
|
|
switch (kind)
|
|
{
|
|
case UP_DEVICE_KIND_MOUSE:
|
|
/* TRANSLATORS: secondary battery */
|
|
description = g_string_new (_("Wireless mouse"));
|
|
break;
|
|
case UP_DEVICE_KIND_KEYBOARD:
|
|
/* TRANSLATORS: secondary battery */
|
|
description = g_string_new (_("Wireless keyboard"));
|
|
break;
|
|
case UP_DEVICE_KIND_UPS:
|
|
/* TRANSLATORS: secondary battery */
|
|
description = g_string_new (_("Uninterruptible power supply"));
|
|
show_caution = TRUE;
|
|
break;
|
|
case UP_DEVICE_KIND_PDA:
|
|
/* TRANSLATORS: secondary battery */
|
|
description = g_string_new (_("Personal digital assistant"));
|
|
break;
|
|
case UP_DEVICE_KIND_PHONE:
|
|
/* TRANSLATORS: secondary battery */
|
|
description = g_string_new (_("Cellphone"));
|
|
break;
|
|
case UP_DEVICE_KIND_MEDIA_PLAYER:
|
|
/* TRANSLATORS: secondary battery */
|
|
description = g_string_new (_("Media player"));
|
|
break;
|
|
case UP_DEVICE_KIND_TABLET:
|
|
/* TRANSLATORS: secondary battery */
|
|
description = g_string_new (_("Tablet"));
|
|
break;
|
|
case UP_DEVICE_KIND_COMPUTER:
|
|
/* TRANSLATORS: secondary battery */
|
|
description = g_string_new (_("Computer"));
|
|
break;
|
|
default:
|
|
/* TRANSLATORS: secondary battery, misc */
|
|
description = g_string_new (_("Battery"));
|
|
break;
|
|
}
|
|
|
|
switch (state)
|
|
{
|
|
case UP_DEVICE_STATE_CHARGING:
|
|
case UP_DEVICE_STATE_PENDING_CHARGE:
|
|
/* TRANSLATORS: secondary battery */
|
|
status = g_string_new(C_("Battery power", "Charging"));
|
|
break;
|
|
case UP_DEVICE_STATE_DISCHARGING:
|
|
case UP_DEVICE_STATE_PENDING_DISCHARGE:
|
|
if (percentage < 10 && show_caution)
|
|
{
|
|
/* TRANSLATORS: secondary battery */
|
|
status = g_string_new (C_("Battery power", "Caution"));
|
|
}
|
|
else if (percentage < 30)
|
|
{
|
|
/* TRANSLATORS: secondary battery */
|
|
status = g_string_new (C_("Battery power", "Low"));
|
|
}
|
|
else
|
|
{
|
|
/* TRANSLATORS: secondary battery */
|
|
status = g_string_new (C_("Battery power", "Good"));
|
|
}
|
|
break;
|
|
case UP_DEVICE_STATE_FULLY_CHARGED:
|
|
/* TRANSLATORS: primary battery */
|
|
status = g_string_new (C_("Battery power", "Fully charged"));
|
|
break;
|
|
case UP_DEVICE_STATE_EMPTY:
|
|
/* TRANSLATORS: primary battery */
|
|
status = g_string_new (C_("Battery power", "Empty"));
|
|
break;
|
|
default:
|
|
status = g_string_new (up_device_state_to_string (state));
|
|
break;
|
|
}
|
|
g_string_prepend (status, "<small>");
|
|
g_string_append (status, "</small>");
|
|
|
|
/* create the new widget */
|
|
hbox = gtk_box_new (GTK_ORIENTATION_HORIZONTAL, 0);
|
|
widget = gtk_label_new ("");
|
|
gtk_misc_set_alignment (GTK_MISC (widget), 0.0f, 0.5f);
|
|
gtk_label_set_markup (GTK_LABEL (widget), description->str);
|
|
gtk_widget_set_margin_left (widget, 20);
|
|
gtk_widget_set_margin_right (widget, 20);
|
|
gtk_widget_set_margin_top (widget, 6);
|
|
gtk_widget_set_margin_bottom (widget, 6);
|
|
gtk_box_pack_start (GTK_BOX (hbox), widget, FALSE, TRUE, 0);
|
|
gtk_size_group_add_widget (priv->battery_sizegroup, widget);
|
|
|
|
box2 = gtk_box_new (GTK_ORIENTATION_HORIZONTAL, 12);
|
|
gtk_widget_set_margin_left (box2, 20);
|
|
gtk_widget_set_margin_right (box2, 20);
|
|
s = g_strdup_printf ("%d%%", (int)percentage);
|
|
widget = gtk_label_new (s);
|
|
g_free (s);
|
|
gtk_misc_set_alignment (GTK_MISC (widget), 1, 0.5);
|
|
gtk_style_context_add_class (gtk_widget_get_style_context (widget), GTK_STYLE_CLASS_DIM_LABEL);
|
|
gtk_box_pack_start (GTK_BOX (box2), widget, FALSE, TRUE, 0);
|
|
gtk_size_group_add_widget (priv->charge_sizegroup, widget);
|
|
|
|
widget = gtk_level_bar_new ();
|
|
gtk_widget_set_halign (widget, TRUE);
|
|
gtk_widget_set_halign (widget, GTK_ALIGN_FILL);
|
|
gtk_widget_set_valign (widget, GTK_ALIGN_CENTER);
|
|
gtk_level_bar_set_value (GTK_LEVEL_BAR (widget), percentage / 100.0f);
|
|
gtk_box_pack_start (GTK_BOX (box2), widget, TRUE, TRUE, 0);
|
|
gtk_size_group_add_widget (priv->level_sizegroup, widget);
|
|
gtk_box_pack_start (GTK_BOX (hbox), box2, TRUE, TRUE, 0);
|
|
gtk_widget_show_all (hbox);
|
|
|
|
gtk_container_add (GTK_CONTAINER (priv->device_list), hbox);
|
|
gtk_size_group_add_widget (priv->row_sizegroup, hbox);
|
|
g_object_set_data (G_OBJECT (hbox), "kind", GINT_TO_POINTER (kind));
|
|
|
|
g_string_free (description, TRUE);
|
|
g_string_free (status, TRUE);
|
|
|
|
gtk_widget_set_visible (priv->device_section, TRUE);
|
|
}
|
|
|
|
static void
|
|
up_client_changed (UpClient *client,
|
|
UpDevice *device,
|
|
CcPowerPanel *self)
|
|
{
|
|
CcPowerPanelPrivate *priv = self->priv;
|
|
GPtrArray *devices;
|
|
GList *children, *l;
|
|
gint i;
|
|
UpDeviceKind kind;
|
|
UpDeviceState state;
|
|
guint n_batteries;
|
|
gboolean on_ups;
|
|
UpDevice *composite;
|
|
gdouble percentage = 0.0;
|
|
gdouble energy = 0.0;
|
|
gdouble energy_full = 0.0;
|
|
gdouble energy_rate = 0.0;
|
|
gdouble energy_total = 0.0;
|
|
gdouble energy_full_total = 0.0;
|
|
gdouble energy_rate_total = 0.0;
|
|
gint64 time_to_empty = 0;
|
|
gint64 time_to_full = 0;
|
|
gboolean is_charging = FALSE;
|
|
gboolean is_discharging = FALSE;
|
|
gboolean is_fully_charged = TRUE;
|
|
gchar *s;
|
|
|
|
children = gtk_container_get_children (GTK_CONTAINER (priv->battery_list));
|
|
for (l = children; l != NULL; l = l->next)
|
|
gtk_container_remove (GTK_CONTAINER (priv->battery_list), l->data);
|
|
g_list_free (children);
|
|
gtk_widget_hide (priv->battery_section);
|
|
|
|
children = gtk_container_get_children (GTK_CONTAINER (priv->device_list));
|
|
for (l = children; l != NULL; l = l->next)
|
|
gtk_container_remove (GTK_CONTAINER (priv->device_list), l->data);
|
|
g_list_free (children);
|
|
gtk_widget_hide (priv->device_section);
|
|
|
|
devices = up_client_get_devices (client);
|
|
|
|
#ifdef TEST_FAKE_DEVICES
|
|
{
|
|
static gboolean fake_devices_added = FALSE;
|
|
|
|
if (!fake_devices_added)
|
|
{
|
|
fake_devices_added = TRUE;
|
|
g_print ("adding fake devices\n");
|
|
device = up_device_new ();
|
|
g_object_set (device,
|
|
"kind", UP_DEVICE_KIND_MOUSE,
|
|
"percentage", 71.0,
|
|
"state", UP_DEVICE_STATE_DISCHARGING,
|
|
"time-to-empty", 287,
|
|
NULL);
|
|
g_ptr_array_add (devices, device);
|
|
device = up_device_new ();
|
|
g_object_set (device,
|
|
"kind", UP_DEVICE_KIND_KEYBOARD,
|
|
"percentage", 69.0,
|
|
"state", UP_DEVICE_STATE_DISCHARGING,
|
|
"time-to-empty", 250,
|
|
NULL);
|
|
g_ptr_array_add (devices, device);
|
|
device = up_device_new ();
|
|
g_object_set (device,
|
|
"kind", UP_DEVICE_KIND_BATTERY,
|
|
"percentage", 100.0,
|
|
"state", UP_DEVICE_STATE_FULLY_CHARGED,
|
|
"energy", 55.0,
|
|
"energy-full", 55.0,
|
|
"energy-rate", 15.0,
|
|
"time-to-empty", 400,
|
|
NULL);
|
|
g_ptr_array_add (devices, device);
|
|
}
|
|
}
|
|
#endif
|
|
|
|
on_ups = FALSE;
|
|
n_batteries = 0;
|
|
composite = up_device_new ();
|
|
g_object_set (composite,
|
|
"kind", UP_DEVICE_KIND_BATTERY,
|
|
"is-rechargeable", TRUE,
|
|
"native-path", "dummy:composite_battery",
|
|
"power-supply", TRUE,
|
|
"is-present", TRUE,
|
|
NULL);
|
|
for (i = 0; i < devices->len; i++)
|
|
{
|
|
UpDevice *device = (UpDevice*) g_ptr_array_index (devices, i);
|
|
g_object_get (device,
|
|
"kind", &kind,
|
|
"state", &state,
|
|
"energy", &energy,
|
|
"energy-full", &energy_full,
|
|
"energy-rate", &energy_rate,
|
|
NULL);
|
|
if (kind == UP_DEVICE_KIND_UPS && state == UP_DEVICE_STATE_DISCHARGING)
|
|
on_ups = TRUE;
|
|
if (kind == UP_DEVICE_KIND_BATTERY)
|
|
{
|
|
if (state == UP_DEVICE_STATE_CHARGING)
|
|
is_charging = TRUE;
|
|
if (state == UP_DEVICE_STATE_DISCHARGING)
|
|
is_discharging = TRUE;
|
|
if (state != UP_DEVICE_STATE_FULLY_CHARGED)
|
|
is_fully_charged = FALSE;
|
|
energy_total += energy;
|
|
energy_full_total += energy_full;
|
|
energy_rate_total += energy_rate;
|
|
n_batteries++;
|
|
}
|
|
}
|
|
|
|
if (n_batteries > 1)
|
|
s = g_strdup_printf ("<b>%s</b>", _("Batteries"));
|
|
else
|
|
s = g_strdup_printf ("<b>%s</b>", _("Battery"));
|
|
gtk_label_set_label (GTK_LABEL (priv->battery_heading), s);
|
|
g_free (s);
|
|
|
|
if (energy_full_total > 0.0)
|
|
percentage = 100.0 * energy_total / energy_full_total;
|
|
|
|
if (is_charging)
|
|
state = UP_DEVICE_STATE_CHARGING;
|
|
else if (is_discharging)
|
|
state = UP_DEVICE_STATE_DISCHARGING;
|
|
else if (is_fully_charged)
|
|
state = UP_DEVICE_STATE_FULLY_CHARGED;
|
|
else
|
|
state = UP_DEVICE_STATE_UNKNOWN;
|
|
|
|
if (energy_rate_total > 0)
|
|
{
|
|
if (state == UP_DEVICE_STATE_DISCHARGING)
|
|
time_to_empty = 3600 * (energy_total / energy_rate_total);
|
|
else if (state == UP_DEVICE_STATE_CHARGING)
|
|
time_to_full = 3600 * ((energy_full_total - energy_total) / energy_rate_total);
|
|
}
|
|
|
|
g_object_set (composite,
|
|
"energy", energy_total,
|
|
"energy-full", energy_full_total,
|
|
"energy-rate", energy_rate_total,
|
|
"time-to-empty", time_to_empty,
|
|
"time-to-full", time_to_full,
|
|
"percentage", percentage,
|
|
"state", state,
|
|
NULL);
|
|
|
|
if (!on_ups && n_batteries > 1)
|
|
set_primary (self, composite);
|
|
|
|
for (i = 0; i < devices->len; i++)
|
|
{
|
|
UpDevice *device = (UpDevice*) g_ptr_array_index (devices, i);
|
|
g_object_get (device, "kind", &kind, NULL);
|
|
if (kind == UP_DEVICE_KIND_LINE_POWER)
|
|
{
|
|
/* do nothing */
|
|
}
|
|
else if (kind == UP_DEVICE_KIND_UPS && on_ups)
|
|
{
|
|
set_primary (self, device);
|
|
}
|
|
else if (kind == UP_DEVICE_KIND_BATTERY && !on_ups && n_batteries == 1)
|
|
{
|
|
set_primary (self, device);
|
|
}
|
|
else if (kind == UP_DEVICE_KIND_BATTERY)
|
|
{
|
|
add_battery (self, device);
|
|
}
|
|
else
|
|
{
|
|
add_device (self, device);
|
|
}
|
|
}
|
|
|
|
g_ptr_array_unref (devices);
|
|
g_object_unref (composite);
|
|
}
|
|
|
|
static void
|
|
set_brightness_cb (GObject *source_object, GAsyncResult *res, gpointer user_data)
|
|
{
|
|
GError *error = NULL;
|
|
GVariant *result;
|
|
CcPowerPanelPrivate *priv = CC_POWER_PANEL (user_data)->priv;
|
|
|
|
/* not setting, so pay attention to changed signals */
|
|
priv->setting_brightness = FALSE;
|
|
result = g_dbus_proxy_call_finish (G_DBUS_PROXY (source_object), res, &error);
|
|
if (result == NULL)
|
|
{
|
|
g_printerr ("Error setting brightness: %s\n", error->message);
|
|
g_error_free (error);
|
|
return;
|
|
}
|
|
}
|
|
|
|
static void
|
|
brightness_slider_value_changed_cb (GtkRange *range, gpointer user_data)
|
|
{
|
|
guint percentage;
|
|
CcPowerPanelPrivate *priv = CC_POWER_PANEL (user_data)->priv;
|
|
|
|
/* do not loop */
|
|
if (priv->setting_brightness)
|
|
return;
|
|
|
|
priv->setting_brightness = TRUE;
|
|
|
|
/* push this to g-s-d */
|
|
percentage = (guint) gtk_range_get_value (range);
|
|
g_dbus_proxy_call (priv->screen_proxy,
|
|
"org.freedesktop.DBus.Properties.Set",
|
|
g_variant_new_parsed ("('org.gnome.SettingsDaemon.Power.Screen',"
|
|
"'Brightness', %v)",
|
|
g_variant_new_int32 (percentage)),
|
|
G_DBUS_CALL_FLAGS_NONE,
|
|
-1,
|
|
priv->cancellable,
|
|
set_brightness_cb,
|
|
user_data);
|
|
}
|
|
|
|
static void
|
|
sync_brightness (CcPowerPanel *self)
|
|
{
|
|
GVariant *result;
|
|
guint brightness;
|
|
gboolean visible;
|
|
GtkRange *range;
|
|
|
|
result = g_dbus_proxy_get_cached_property (self->priv->screen_proxy, "Brightness");
|
|
|
|
/* set the slider */
|
|
g_variant_get (result, "i", &brightness);
|
|
visible = brightness >= 0.0;
|
|
|
|
gtk_widget_set_visible (self->priv->brightness_row, visible);
|
|
gtk_widget_set_visible (self->priv->dim_screen_row, visible);
|
|
|
|
if (visible)
|
|
{
|
|
range = GTK_RANGE (self->priv->brightness_scale);
|
|
gtk_range_set_range (range, 0, 100);
|
|
gtk_range_set_increments (range, 1, 10);
|
|
self->priv->setting_brightness = TRUE;
|
|
gtk_range_set_value (range, brightness);
|
|
self->priv->setting_brightness = FALSE;
|
|
g_variant_unref (result);
|
|
}
|
|
}
|
|
|
|
static void
|
|
on_property_change (GDBusProxy *proxy,
|
|
GVariant *changed_properties,
|
|
GVariant *invalidated_properties,
|
|
gpointer user_data)
|
|
{
|
|
CcPowerPanel *self = CC_POWER_PANEL (user_data);
|
|
sync_brightness (self);
|
|
}
|
|
|
|
static void
|
|
got_screen_proxy_cb (GObject *source_object, GAsyncResult *res, gpointer user_data)
|
|
{
|
|
GError *error = NULL;
|
|
CcPowerPanel *self = CC_POWER_PANEL (user_data);
|
|
CcPowerPanelPrivate *priv = self->priv;
|
|
|
|
priv->screen_proxy = g_dbus_proxy_new_for_bus_finish (res, &error);
|
|
if (priv->screen_proxy == NULL)
|
|
{
|
|
g_printerr ("Error creating proxy: %s\n", error->message);
|
|
g_error_free (error);
|
|
return;
|
|
}
|
|
|
|
/* we want to change the bar if the user presses brightness buttons */
|
|
g_signal_connect (priv->screen_proxy, "g-properties-changed",
|
|
G_CALLBACK (on_property_change), self);
|
|
|
|
sync_brightness (self);
|
|
}
|
|
|
|
static void
|
|
combo_time_changed_cb (GtkWidget *widget, CcPowerPanel *self)
|
|
{
|
|
GtkTreeIter iter;
|
|
GtkTreeModel *model;
|
|
gint value;
|
|
gboolean ret;
|
|
const gchar *key = (const gchar *)g_object_get_data (G_OBJECT(widget), "_gsettings_key");
|
|
|
|
/* no selection */
|
|
ret = gtk_combo_box_get_active_iter (GTK_COMBO_BOX(widget), &iter);
|
|
if (!ret)
|
|
return;
|
|
|
|
/* get entry */
|
|
model = gtk_combo_box_get_model (GTK_COMBO_BOX(widget));
|
|
gtk_tree_model_get (model, &iter,
|
|
1, &value,
|
|
-1);
|
|
|
|
/* set both keys */
|
|
g_settings_set_int (self->priv->gsd_settings, key, value);
|
|
}
|
|
|
|
static void
|
|
combo_enum_changed_cb (GtkWidget *widget, CcPowerPanel *self)
|
|
{
|
|
GtkTreeIter iter;
|
|
GtkTreeModel *model;
|
|
gint value;
|
|
gboolean ret;
|
|
const gchar *key = (const gchar *)g_object_get_data (G_OBJECT(widget), "_gsettings_key");
|
|
|
|
/* no selection */
|
|
ret = gtk_combo_box_get_active_iter (GTK_COMBO_BOX(widget), &iter);
|
|
if (!ret)
|
|
return;
|
|
|
|
/* get entry */
|
|
model = gtk_combo_box_get_model (GTK_COMBO_BOX(widget));
|
|
gtk_tree_model_get (model, &iter,
|
|
1, &value,
|
|
-1);
|
|
|
|
/* set both battery and ac keys */
|
|
g_settings_set_enum (self->priv->gsd_settings, key, value);
|
|
}
|
|
|
|
static void
|
|
set_value_for_combo (GtkComboBox *combo_box, gint value)
|
|
{
|
|
GtkTreeIter iter;
|
|
GtkTreeIter last;
|
|
GtkTreeModel *model;
|
|
gint value_tmp;
|
|
gboolean ret;
|
|
|
|
/* get entry */
|
|
model = gtk_combo_box_get_model (combo_box);
|
|
ret = gtk_tree_model_get_iter_first (model, &iter);
|
|
if (!ret)
|
|
return;
|
|
|
|
/* try to make the UI match the setting */
|
|
do
|
|
{
|
|
gtk_tree_model_get (model, &iter,
|
|
ACTION_MODEL_VALUE, &value_tmp,
|
|
-1);
|
|
if (value == value_tmp)
|
|
{
|
|
gtk_combo_box_set_active_iter (combo_box, &iter);
|
|
return;
|
|
}
|
|
last = iter;
|
|
} while (gtk_tree_model_iter_next (model, &iter));
|
|
|
|
gtk_combo_box_set_active_iter (combo_box, &last);
|
|
}
|
|
|
|
static void
|
|
set_ac_battery_ui_mode (CcPowerPanel *self)
|
|
{
|
|
gboolean has_batteries = FALSE;
|
|
gboolean ret;
|
|
GError *error = NULL;
|
|
GPtrArray *devices;
|
|
guint i;
|
|
UpDevice *device;
|
|
UpDeviceKind kind;
|
|
|
|
/* this is sync, but it's cached in the daemon and so quick */
|
|
ret = up_client_enumerate_devices_sync (self->priv->up_client, NULL, &error);
|
|
if (!ret)
|
|
{
|
|
g_warning ("failed to get device list: %s", error->message);
|
|
g_error_free (error);
|
|
goto out;
|
|
}
|
|
|
|
devices = up_client_get_devices (self->priv->up_client);
|
|
g_debug ("got %d devices from upower\n", devices->len);
|
|
|
|
for (i = 0; i < devices->len; i++)
|
|
{
|
|
device = g_ptr_array_index (devices, i);
|
|
g_object_get (device, "kind", &kind, NULL);
|
|
if (kind == UP_DEVICE_KIND_BATTERY || kind == UP_DEVICE_KIND_UPS)
|
|
{
|
|
has_batteries = TRUE;
|
|
break;
|
|
}
|
|
}
|
|
g_ptr_array_unref (devices);
|
|
|
|
#ifdef TEST_NO_BATTERIES
|
|
g_print ("forcing no batteries\n");
|
|
has_batteries = FALSE;
|
|
#endif
|
|
|
|
out:
|
|
self->priv->has_batteries = has_batteries;
|
|
|
|
gtk_widget_set_visible (self->priv->critical_battery_row, has_batteries);
|
|
|
|
if (!has_batteries)
|
|
{
|
|
gtk_widget_hide (WID (self->priv->builder, "suspend_on_battery_switch"));
|
|
gtk_widget_hide (WID (self->priv->builder, "suspend_on_battery_label"));
|
|
gtk_widget_hide (WID (self->priv->builder, "suspend_on_battery_delay_label"));
|
|
gtk_widget_hide (WID (self->priv->builder, "suspend_on_battery_delay_combo"));
|
|
gtk_label_set_label (GTK_LABEL (WID (self->priv->builder, "suspend_on_ac_label")),
|
|
_("When _idle"));
|
|
}
|
|
}
|
|
|
|
static void
|
|
update_separator_func (GtkWidget **separator,
|
|
GtkWidget *child,
|
|
GtkWidget *before,
|
|
gpointer user_data)
|
|
{
|
|
if (before == NULL)
|
|
return;
|
|
|
|
if (*separator == NULL)
|
|
{
|
|
*separator = gtk_separator_new (GTK_ORIENTATION_HORIZONTAL);
|
|
g_object_ref_sink (*separator);
|
|
gtk_widget_show (*separator);
|
|
}
|
|
}
|
|
|
|
#ifdef HAVE_BLUETOOTH
|
|
static void
|
|
bt_set_powered (BluetoothClient *client,
|
|
gboolean powered)
|
|
{
|
|
GVariant *ret;
|
|
const gchar *adapter_path;
|
|
GDBusConnection *bus;
|
|
|
|
bus = g_bus_get_sync (G_BUS_TYPE_SYSTEM, NULL, NULL);
|
|
|
|
ret = g_dbus_connection_call_sync (bus,
|
|
"org.bluez",
|
|
"/",
|
|
"org.bluez.Manager",
|
|
"DefaultAdapter",
|
|
NULL,
|
|
NULL,
|
|
0,
|
|
G_MAXINT,
|
|
NULL, NULL);
|
|
g_variant_get (ret, "(&o)", &adapter_path);
|
|
|
|
g_dbus_connection_call (bus,
|
|
"org.bluez",
|
|
adapter_path,
|
|
"org.freedesktop.Properties",
|
|
"SetProperty",
|
|
g_variant_new ("(sv)", "Powered", g_variant_new_boolean (powered)),
|
|
NULL,
|
|
0,
|
|
G_MAXINT,
|
|
NULL, NULL, NULL);
|
|
|
|
g_variant_unref (ret);
|
|
}
|
|
|
|
static void
|
|
bt_switch_changed (GtkSwitch *sw,
|
|
GParamSpec *pspec,
|
|
CcPowerPanel *panel)
|
|
{
|
|
gboolean powered;
|
|
|
|
powered = gtk_switch_get_active (sw);
|
|
|
|
g_debug ("Setting bt power %s", powered ? "on" : "off");
|
|
|
|
bt_set_powered (panel->priv->bt_client, powered);
|
|
}
|
|
|
|
static void
|
|
bt_powered_state_changed (GObject *client,
|
|
GParamSpec *pspec,
|
|
CcPowerPanel *panel)
|
|
{
|
|
CcPowerPanelPrivate *priv = panel->priv;
|
|
gboolean powered;
|
|
|
|
g_object_get (client, "default-adapter-powered", &powered, NULL);
|
|
g_debug ("bt powered state changed to %s", powered ? "on" : "off");
|
|
|
|
g_signal_handlers_block_by_func (priv->bt_switch, bt_switch_changed, panel);
|
|
gtk_switch_set_active (GTK_SWITCH (priv->bt_switch), powered);
|
|
g_signal_handlers_unblock_by_func (priv->bt_switch, bt_switch_changed, panel);
|
|
}
|
|
#endif
|
|
|
|
#ifdef HAVE_NETWORK_MANAGER
|
|
static gboolean
|
|
has_wifi_devices (NMClient *client)
|
|
{
|
|
const GPtrArray *devices;
|
|
NMDevice *device;
|
|
gint i;
|
|
|
|
if (!nm_client_get_manager_running (client))
|
|
return FALSE;
|
|
|
|
devices = nm_client_get_devices (client);
|
|
if (devices == NULL)
|
|
return FALSE;
|
|
|
|
for (i = 0; i < devices->len; i++)
|
|
{
|
|
device = g_ptr_array_index (devices, i);
|
|
switch (nm_device_get_device_type (device))
|
|
{
|
|
case NM_DEVICE_TYPE_WIFI:
|
|
return TRUE;
|
|
default:
|
|
break;
|
|
}
|
|
}
|
|
|
|
return FALSE;
|
|
}
|
|
|
|
static void
|
|
wifi_switch_changed (GtkSwitch *sw,
|
|
GParamSpec *pspec,
|
|
CcPowerPanel *panel)
|
|
{
|
|
gboolean enabled;
|
|
|
|
enabled = gtk_switch_get_active (sw);
|
|
g_debug ("Setting wifi %s", enabled ? "enabled" : "disabled");
|
|
nm_client_wireless_set_enabled (panel->priv->nm_client, enabled);
|
|
}
|
|
|
|
static gboolean
|
|
has_mobile_devices (NMClient *client)
|
|
{
|
|
const GPtrArray *devices;
|
|
NMDevice *device;
|
|
gint i;
|
|
|
|
if (!nm_client_get_manager_running (client))
|
|
return FALSE;
|
|
|
|
devices = nm_client_get_devices (client);
|
|
if (devices == NULL)
|
|
return FALSE;
|
|
|
|
for (i = 0; i < devices->len; i++)
|
|
{
|
|
device = g_ptr_array_index (devices, i);
|
|
switch (nm_device_get_device_type (device))
|
|
{
|
|
case NM_DEVICE_TYPE_WIMAX:
|
|
case NM_DEVICE_TYPE_MODEM:
|
|
return TRUE;
|
|
default:
|
|
break;
|
|
}
|
|
}
|
|
|
|
return FALSE;
|
|
}
|
|
|
|
static void
|
|
mobile_switch_changed (GtkSwitch *sw,
|
|
GParamSpec *pspec,
|
|
CcPowerPanel *panel)
|
|
{
|
|
gboolean enabled;
|
|
|
|
enabled = gtk_switch_get_active (sw);
|
|
g_debug ("Setting wwan %s", enabled ? "enabled" : "disabled");
|
|
nm_client_wwan_set_enabled (panel->priv->nm_client, enabled);
|
|
g_debug ("Setting wimax %s", enabled ? "enabled" : "disabled");
|
|
nm_client_wimax_set_enabled (panel->priv->nm_client, enabled);
|
|
}
|
|
|
|
static void
|
|
nm_client_state_changed (NMClient *client,
|
|
GParamSpec *pspec,
|
|
CcPowerPanel *self)
|
|
{
|
|
CcPowerPanelPrivate *priv = self->priv;
|
|
gboolean visible;
|
|
gboolean active;
|
|
gboolean sensitive;
|
|
|
|
visible = has_wifi_devices (priv->nm_client);
|
|
active = nm_client_networking_get_enabled (client) &&
|
|
nm_client_wireless_get_enabled (client) &&
|
|
nm_client_wireless_hardware_get_enabled (client);
|
|
sensitive = nm_client_networking_get_enabled (client) &&
|
|
nm_client_wireless_hardware_get_enabled (client);
|
|
|
|
g_debug ("wifi state changed to %s", active ? "enabled" : "disabled");
|
|
|
|
g_signal_handlers_block_by_func (priv->wifi_switch, wifi_switch_changed, self);
|
|
gtk_switch_set_active (GTK_SWITCH (priv->wifi_switch), active);
|
|
gtk_widget_set_sensitive (priv->wifi_switch, sensitive);
|
|
gtk_widget_set_visible (priv->wifi_row, visible);
|
|
g_signal_handlers_unblock_by_func (priv->wifi_switch, wifi_switch_changed, self);
|
|
|
|
visible = has_mobile_devices (priv->nm_client);
|
|
active = nm_client_networking_get_enabled (client) &&
|
|
nm_client_wimax_get_enabled (client) &&
|
|
nm_client_wireless_hardware_get_enabled (client);
|
|
sensitive = nm_client_networking_get_enabled (client) &&
|
|
nm_client_wireless_hardware_get_enabled (client);
|
|
|
|
g_debug ("mobile state changed to %s", active ? "enabled" : "disabled");
|
|
|
|
g_signal_handlers_block_by_func (priv->mobile_switch, mobile_switch_changed, self);
|
|
gtk_switch_set_active (GTK_SWITCH (priv->mobile_switch), active);
|
|
gtk_widget_set_sensitive (priv->mobile_switch, sensitive);
|
|
gtk_widget_set_visible (priv->mobile_row, visible);
|
|
g_signal_handlers_unblock_by_func (priv->mobile_switch, mobile_switch_changed, self);
|
|
}
|
|
|
|
static void
|
|
nm_device_changed (NMClient *client,
|
|
NMDevice *device,
|
|
CcPowerPanel *self)
|
|
{
|
|
CcPowerPanelPrivate *priv = self->priv;
|
|
|
|
gtk_widget_set_visible (priv->wifi_row, has_wifi_devices (priv->nm_client));
|
|
gtk_widget_set_visible (priv->mobile_row, has_mobile_devices (priv->nm_client));
|
|
}
|
|
|
|
#endif
|
|
|
|
static gboolean
|
|
keynav_failed (GtkWidget *list, GtkDirectionType direction, CcPowerPanel *self)
|
|
{
|
|
CcPowerPanelPrivate *priv = self->priv;
|
|
GtkWidget *next_list = NULL;
|
|
GList *item, *boxes_list;
|
|
gdouble value, lower, upper, page;
|
|
|
|
/* Find the list in the list of EggListBoxes */
|
|
if (direction == GTK_DIR_DOWN)
|
|
boxes_list = priv->boxes;
|
|
else
|
|
boxes_list = priv->boxes_reverse;
|
|
|
|
item = g_list_find (boxes_list, list);
|
|
g_assert (item);
|
|
item = item->next;
|
|
while (1)
|
|
{
|
|
if (item == NULL)
|
|
item = boxes_list;
|
|
|
|
/* Avoid looping */
|
|
if (item->data == list)
|
|
break;
|
|
|
|
if (gtk_widget_is_visible (item->data))
|
|
{
|
|
next_list = item->data;
|
|
break;
|
|
}
|
|
|
|
item = item->next;
|
|
}
|
|
|
|
if (next_list)
|
|
{
|
|
gtk_widget_child_focus (next_list, direction);
|
|
return TRUE;
|
|
}
|
|
|
|
value = gtk_adjustment_get_value (priv->focus_adjustment);
|
|
lower = gtk_adjustment_get_lower (priv->focus_adjustment);
|
|
upper = gtk_adjustment_get_upper (priv->focus_adjustment);
|
|
page = gtk_adjustment_get_page_size (priv->focus_adjustment);
|
|
|
|
if (direction == GTK_DIR_UP && value > lower)
|
|
{
|
|
gtk_adjustment_set_value (priv->focus_adjustment, lower);
|
|
return TRUE;
|
|
}
|
|
else if (direction == GTK_DIR_DOWN && value < upper - page)
|
|
{
|
|
gtk_adjustment_set_value (priv->focus_adjustment, upper - page);
|
|
return TRUE;
|
|
}
|
|
|
|
return FALSE;
|
|
}
|
|
|
|
static void
|
|
combo_idle_delay_changed_cb (GtkWidget *widget, CcPowerPanel *self)
|
|
{
|
|
GtkTreeIter iter;
|
|
GtkTreeModel *model;
|
|
gint value;
|
|
gboolean ret;
|
|
|
|
/* no selection */
|
|
ret = gtk_combo_box_get_active_iter (GTK_COMBO_BOX(widget), &iter);
|
|
if (!ret)
|
|
return;
|
|
|
|
/* get entry */
|
|
model = gtk_combo_box_get_model (GTK_COMBO_BOX(widget));
|
|
gtk_tree_model_get (model, &iter,
|
|
1, &value,
|
|
-1);
|
|
|
|
/* set both keys */
|
|
g_settings_set_uint (self->priv->session_settings, "idle-delay", value);
|
|
}
|
|
|
|
static void
|
|
add_power_saving_section (CcPowerPanel *self)
|
|
{
|
|
CcPowerPanelPrivate *priv = self->priv;
|
|
GtkWidget *vbox;
|
|
GtkWidget *widget, *box, *label, *scale;
|
|
GtkWidget *combo;
|
|
GtkWidget *box2;
|
|
GtkWidget *sw;
|
|
GtkWidget *w;
|
|
int value;
|
|
gchar *s;
|
|
|
|
vbox = WID (priv->builder, "vbox_power");
|
|
|
|
s = g_strdup_printf ("<b>%s</b>", _("Power Saving"));
|
|
widget = gtk_label_new (s);
|
|
g_free (s);
|
|
gtk_label_set_use_markup (GTK_LABEL (widget), TRUE);
|
|
gtk_misc_set_alignment (GTK_MISC (widget), 0, 0.5);
|
|
gtk_widget_set_margin_left (widget, 56);
|
|
gtk_widget_set_margin_right (widget, 56);
|
|
gtk_widget_set_margin_bottom (widget, 6);
|
|
gtk_box_pack_start (GTK_BOX (vbox), widget, FALSE, TRUE, 0);
|
|
gtk_widget_show (widget);
|
|
|
|
widget = GTK_WIDGET (egg_list_box_new ());
|
|
priv->boxes_reverse = g_list_prepend (priv->boxes_reverse, widget);
|
|
g_signal_connect (widget, "keynav-failed", G_CALLBACK (keynav_failed), self);
|
|
egg_list_box_set_selection_mode (EGG_LIST_BOX (widget), GTK_SELECTION_NONE);
|
|
egg_list_box_set_separator_funcs (EGG_LIST_BOX (widget),
|
|
update_separator_func,
|
|
NULL, NULL);
|
|
|
|
box = gtk_frame_new (NULL);
|
|
gtk_frame_set_shadow_type (GTK_FRAME (box), GTK_SHADOW_IN);
|
|
gtk_widget_set_margin_left (box, 50);
|
|
gtk_widget_set_margin_right (box, 50);
|
|
gtk_widget_set_margin_bottom (box, 24);
|
|
gtk_widget_show (box);
|
|
gtk_container_add (GTK_CONTAINER (box), widget);
|
|
gtk_box_pack_start (GTK_BOX (vbox), box, FALSE, TRUE, 0);
|
|
|
|
priv->brightness_row = box = gtk_box_new (GTK_ORIENTATION_HORIZONTAL, 0);
|
|
label = gtk_label_new (_("_Screen brightness"));
|
|
gtk_misc_set_alignment (GTK_MISC (label), 0, 0.5);
|
|
gtk_label_set_use_underline (GTK_LABEL (label), TRUE);
|
|
gtk_widget_set_margin_left (label, 20);
|
|
gtk_widget_set_margin_right (label, 20);
|
|
gtk_widget_set_margin_top (label, 6);
|
|
gtk_widget_set_margin_bottom (label, 6);
|
|
gtk_box_pack_start (GTK_BOX (box), label, FALSE, TRUE, 0);
|
|
gtk_size_group_add_widget (priv->battery_sizegroup, label);
|
|
box2 = gtk_box_new (GTK_ORIENTATION_HORIZONTAL, 12);
|
|
w = gtk_label_new ("");
|
|
gtk_box_pack_start (GTK_BOX (box2), w, FALSE, TRUE, 0);
|
|
gtk_size_group_add_widget (priv->charge_sizegroup, w);
|
|
|
|
priv->brightness_scale = scale = gtk_scale_new_with_range (GTK_ORIENTATION_HORIZONTAL, 0, 100, 1);
|
|
gtk_label_set_mnemonic_widget (GTK_LABEL (label), scale);
|
|
gtk_scale_set_draw_value (GTK_SCALE (scale), FALSE);
|
|
gtk_widget_set_margin_left (scale, 20);
|
|
gtk_widget_set_margin_right (scale, 20);
|
|
gtk_box_pack_start (GTK_BOX (box2), scale, TRUE, TRUE, 0);
|
|
gtk_size_group_add_widget (priv->level_sizegroup, scale);
|
|
g_signal_connect (scale, "value-changed",
|
|
G_CALLBACK (brightness_slider_value_changed_cb), self);
|
|
|
|
gtk_box_pack_start (GTK_BOX (box), box2, TRUE, TRUE, 0);
|
|
gtk_container_add (GTK_CONTAINER (widget), box);
|
|
gtk_size_group_add_widget (priv->row_sizegroup, box);
|
|
|
|
priv->dim_screen_row = gtk_box_new (GTK_ORIENTATION_HORIZONTAL, 50);
|
|
|
|
label = gtk_label_new (_("_Dim screen when inactive"));
|
|
gtk_misc_set_alignment (GTK_MISC (label), 0, 0.5);
|
|
gtk_label_set_use_underline (GTK_LABEL (label), TRUE);
|
|
gtk_widget_set_margin_left (label, 20);
|
|
gtk_widget_set_margin_right (label, 20);
|
|
gtk_widget_set_margin_top (label, 6);
|
|
gtk_widget_set_margin_bottom (label, 6);
|
|
gtk_box_pack_start (GTK_BOX (priv->dim_screen_row), label, TRUE, TRUE, 0);
|
|
|
|
sw = gtk_switch_new ();
|
|
g_settings_bind (priv->gsd_settings, "idle-dim",
|
|
sw, "active",
|
|
G_SETTINGS_BIND_DEFAULT);
|
|
gtk_widget_set_margin_left (sw, 20);
|
|
gtk_widget_set_margin_right (sw, 20);
|
|
gtk_widget_set_valign (sw, GTK_ALIGN_CENTER);
|
|
gtk_box_pack_start (GTK_BOX (priv->dim_screen_row), sw, FALSE, TRUE, 0);
|
|
gtk_label_set_mnemonic_widget (GTK_LABEL (label), sw);
|
|
gtk_container_add (GTK_CONTAINER (widget), priv->dim_screen_row);
|
|
gtk_size_group_add_widget (priv->row_sizegroup, priv->dim_screen_row);
|
|
|
|
box = gtk_box_new (GTK_ORIENTATION_HORIZONTAL, 50);
|
|
|
|
label = gtk_label_new (_("_Blank screen"));
|
|
gtk_misc_set_alignment (GTK_MISC (label), 0, 0.5);
|
|
gtk_label_set_use_underline (GTK_LABEL (label), TRUE);
|
|
gtk_widget_set_margin_left (label, 20);
|
|
gtk_widget_set_margin_right (label, 20);
|
|
gtk_widget_set_margin_top (label, 6);
|
|
gtk_widget_set_margin_bottom (label, 6);
|
|
gtk_box_pack_start (GTK_BOX (box), label, TRUE, TRUE, 0);
|
|
|
|
combo = gtk_combo_box_text_new ();
|
|
gtk_combo_box_set_entry_text_column (GTK_COMBO_BOX (combo), 0);
|
|
gtk_combo_box_set_model (GTK_COMBO_BOX (combo),
|
|
GTK_TREE_MODEL (gtk_builder_get_object (priv->builder, "liststore_idle_time")));
|
|
value = g_settings_get_uint (priv->session_settings, "idle-delay");
|
|
set_value_for_combo (GTK_COMBO_BOX (combo), value);
|
|
g_signal_connect (combo, "changed",
|
|
G_CALLBACK (combo_idle_delay_changed_cb), self);
|
|
gtk_widget_set_margin_left (combo, 20);
|
|
gtk_widget_set_margin_right (combo, 20);
|
|
gtk_widget_set_valign (combo, GTK_ALIGN_CENTER);
|
|
gtk_box_pack_start (GTK_BOX (box), combo, FALSE, TRUE, 0);
|
|
gtk_label_set_mnemonic_widget (GTK_LABEL (label), combo);
|
|
gtk_container_add (GTK_CONTAINER (widget), box);
|
|
gtk_size_group_add_widget (priv->row_sizegroup, box);
|
|
|
|
#ifdef HAVE_NETWORK_MANAGER
|
|
priv->wifi_row = box = gtk_box_new (GTK_ORIENTATION_HORIZONTAL, 50);
|
|
|
|
box2 = gtk_box_new (GTK_ORIENTATION_VERTICAL, 0);
|
|
gtk_widget_set_margin_left (box2, 20);
|
|
gtk_widget_set_margin_right (box2, 20);
|
|
gtk_widget_set_margin_top (box2, 6);
|
|
gtk_widget_set_margin_bottom (box2, 6);
|
|
gtk_box_pack_start (GTK_BOX (box), box2, TRUE, TRUE, 0);
|
|
|
|
label = gtk_label_new (_("_Wi-Fi"));
|
|
gtk_misc_set_alignment (GTK_MISC (label), 0, 0.5);
|
|
gtk_label_set_use_underline (GTK_LABEL (label), TRUE);
|
|
gtk_box_pack_start (GTK_BOX (box2), label, TRUE, TRUE, 0);
|
|
|
|
w = gtk_label_new (_("Turns off wireless devices"));
|
|
gtk_misc_set_alignment (GTK_MISC (w), 0, 0.5);
|
|
gtk_style_context_add_class (gtk_widget_get_style_context (w), GTK_STYLE_CLASS_DIM_LABEL);
|
|
gtk_box_pack_start (GTK_BOX (box2), w, TRUE, TRUE, 0);
|
|
|
|
priv->wifi_switch = sw = gtk_switch_new ();
|
|
gtk_widget_set_margin_left (sw, 20);
|
|
gtk_widget_set_margin_right (sw, 20);
|
|
gtk_widget_set_valign (sw, GTK_ALIGN_CENTER);
|
|
gtk_box_pack_start (GTK_BOX (box), sw, FALSE, TRUE, 0);
|
|
gtk_label_set_mnemonic_widget (GTK_LABEL (label), sw);
|
|
gtk_container_add (GTK_CONTAINER (widget), box);
|
|
gtk_size_group_add_widget (priv->row_sizegroup, box);
|
|
|
|
priv->mobile_row = box = gtk_box_new (GTK_ORIENTATION_HORIZONTAL, 50);
|
|
|
|
box2 = gtk_box_new (GTK_ORIENTATION_VERTICAL, 0);
|
|
gtk_widget_set_margin_left (box2, 20);
|
|
gtk_widget_set_margin_right (box2, 20);
|
|
gtk_widget_set_margin_top (box2, 6);
|
|
gtk_widget_set_margin_bottom (box2, 6);
|
|
gtk_box_pack_start (GTK_BOX (box), box2, TRUE, TRUE, 0);
|
|
|
|
label = gtk_label_new (_("_Mobile broadband"));
|
|
gtk_misc_set_alignment (GTK_MISC (label), 0, 0.5);
|
|
gtk_label_set_use_underline (GTK_LABEL (label), TRUE);
|
|
gtk_box_pack_start (GTK_BOX (box2), label, TRUE, TRUE, 0);
|
|
|
|
w = gtk_label_new (_("Turns off mobile broadband (3G, 4G, WiMax, etc.) devices"));
|
|
gtk_misc_set_alignment (GTK_MISC (w), 0, 0.5);
|
|
gtk_style_context_add_class (gtk_widget_get_style_context (w), GTK_STYLE_CLASS_DIM_LABEL);
|
|
gtk_box_pack_start (GTK_BOX (box2), w, TRUE, TRUE, 0);
|
|
|
|
priv->mobile_switch = sw = gtk_switch_new ();
|
|
gtk_widget_set_margin_left (sw, 20);
|
|
gtk_widget_set_margin_right (sw, 20);
|
|
gtk_widget_set_valign (sw, GTK_ALIGN_CENTER);
|
|
gtk_box_pack_start (GTK_BOX (box), sw, FALSE, TRUE, 0);
|
|
gtk_label_set_mnemonic_widget (GTK_LABEL (label), sw);
|
|
gtk_container_add (GTK_CONTAINER (widget), box);
|
|
gtk_size_group_add_widget (priv->row_sizegroup, box);
|
|
|
|
g_signal_connect (G_OBJECT (priv->mobile_switch), "notify::active",
|
|
G_CALLBACK (mobile_switch_changed), self);
|
|
|
|
priv->nm_client = nm_client_new ();
|
|
g_signal_connect (priv->nm_client, "notify",
|
|
G_CALLBACK (nm_client_state_changed), self);
|
|
g_signal_connect (priv->nm_client, "device-added",
|
|
G_CALLBACK (nm_device_changed), self);
|
|
g_signal_connect (priv->nm_client, "device-removed",
|
|
G_CALLBACK (nm_device_changed), self);
|
|
nm_device_changed (priv->nm_client, NULL, self);
|
|
|
|
g_signal_connect (G_OBJECT (priv->wifi_switch), "notify::active",
|
|
G_CALLBACK (wifi_switch_changed), self);
|
|
#endif
|
|
|
|
#ifdef HAVE_BLUETOOTH
|
|
priv->bt_client = bluetooth_client_new ();
|
|
box = gtk_box_new (GTK_ORIENTATION_HORIZONTAL, 50);
|
|
label = gtk_label_new (_("_Bluetooth"));
|
|
gtk_misc_set_alignment (GTK_MISC (label), 0, 0.5);
|
|
gtk_label_set_use_underline (GTK_LABEL (label), TRUE);
|
|
gtk_widget_set_margin_left (label, 20);
|
|
gtk_widget_set_margin_right (label, 20);
|
|
gtk_widget_set_margin_top (label, 6);
|
|
gtk_widget_set_margin_bottom (label, 6);
|
|
gtk_box_pack_start (GTK_BOX (box), label, TRUE, TRUE, 0);
|
|
|
|
priv->bt_switch = sw = gtk_switch_new ();
|
|
gtk_widget_set_margin_left (sw, 20);
|
|
gtk_widget_set_margin_right (sw, 20);
|
|
gtk_widget_set_valign (sw, GTK_ALIGN_CENTER);
|
|
gtk_box_pack_start (GTK_BOX (box), sw, FALSE, TRUE, 0);
|
|
gtk_label_set_mnemonic_widget (GTK_LABEL (label), sw);
|
|
gtk_container_add (GTK_CONTAINER (widget), box);
|
|
gtk_size_group_add_widget (priv->row_sizegroup, box);
|
|
g_signal_connect (G_OBJECT (priv->bt_client), "notify::default-adapter-powered",
|
|
G_CALLBACK (bt_powered_state_changed), self);
|
|
g_signal_connect (G_OBJECT (priv->bt_switch), "notify::active",
|
|
G_CALLBACK (bt_switch_changed), self);
|
|
#endif
|
|
|
|
gtk_widget_show_all (widget);
|
|
}
|
|
|
|
static void
|
|
update_automatic_suspend_label (CcPowerPanel *self)
|
|
{
|
|
CcPowerPanelPrivate *priv = self->priv;
|
|
GsdPowerActionType ac_action;
|
|
GsdPowerActionType battery_action;
|
|
gint ac_timeout;
|
|
gint battery_timeout;
|
|
const gchar *s;
|
|
|
|
ac_action = g_settings_get_enum (priv->gsd_settings, "sleep-inactive-ac-type");
|
|
battery_action = g_settings_get_enum (priv->gsd_settings, "sleep-inactive-battery-type");
|
|
ac_timeout = g_settings_get_int (priv->gsd_settings, "sleep-inactive-ac-timeout");
|
|
battery_timeout = g_settings_get_int (priv->gsd_settings, "sleep-inactive-battery-timeout");
|
|
|
|
if (ac_action == GSD_POWER_ACTION_NOTHING)
|
|
ac_timeout = 0;
|
|
if (battery_action == GSD_POWER_ACTION_NOTHING)
|
|
battery_timeout = 0;
|
|
|
|
if (priv->has_batteries)
|
|
{
|
|
if (ac_timeout == 0 && battery_timeout == 0)
|
|
s = _("Off");
|
|
else if (ac_timeout == 0 && battery_timeout != 0)
|
|
s = _("When on battery power");
|
|
else if (ac_timeout != 0 && battery_timeout == 0)
|
|
s = _("When plugged in");
|
|
else
|
|
s = _("On");
|
|
}
|
|
else
|
|
{
|
|
if (ac_timeout == 0)
|
|
s = _("Off");
|
|
else
|
|
s = _("On");
|
|
}
|
|
|
|
gtk_label_set_label (GTK_LABEL (priv->automatic_suspend_label), s);
|
|
}
|
|
|
|
static void
|
|
on_suspend_settings_changed (GSettings *settings,
|
|
const char *key,
|
|
CcPowerPanel *self)
|
|
{
|
|
CcPowerPanelPrivate *priv = self->priv;
|
|
gint value;
|
|
|
|
if (g_strcmp0 (key, "critical-battery-action") == 0)
|
|
{
|
|
value = g_settings_get_enum (settings, "critical-battery-action");
|
|
set_value_for_combo (GTK_COMBO_BOX (priv->critical_battery_combo), value);
|
|
}
|
|
if (g_str_has_prefix (key, "sleep-inactive-"))
|
|
{
|
|
update_automatic_suspend_label (self);
|
|
}
|
|
}
|
|
|
|
static void
|
|
activate_child (CcPowerPanel *self,
|
|
GtkWidget *child)
|
|
{
|
|
CcPowerPanelPrivate *priv = self->priv;
|
|
GtkWidget *w;
|
|
GtkWidget *toplevel;
|
|
|
|
if (child == priv->automatic_suspend_row)
|
|
{
|
|
w = WID (priv->builder, "automatic_suspend_dialog");
|
|
toplevel = gtk_widget_get_toplevel (GTK_WIDGET (self));
|
|
gtk_window_set_transient_for (GTK_WINDOW (w), GTK_WINDOW (toplevel));
|
|
gtk_window_set_modal (GTK_WINDOW (w), TRUE);
|
|
gtk_window_present (GTK_WINDOW (w));
|
|
}
|
|
}
|
|
|
|
static gboolean
|
|
automatic_suspend_activate (GtkWidget *widget,
|
|
gboolean cycle,
|
|
CcPowerPanel *self)
|
|
{
|
|
activate_child (self, self->priv->automatic_suspend_row);
|
|
return TRUE;
|
|
}
|
|
|
|
static gboolean
|
|
get_sleep_type (GValue *value,
|
|
GVariant *variant,
|
|
gpointer data)
|
|
{
|
|
gboolean enabled;
|
|
|
|
if (g_strcmp0 (g_variant_get_string (variant, NULL), "nothing") == 0)
|
|
enabled = FALSE;
|
|
else
|
|
enabled = TRUE;
|
|
|
|
g_value_set_boolean (value, enabled);
|
|
|
|
return TRUE;
|
|
}
|
|
|
|
static GVariant *
|
|
set_sleep_type (const GValue *value,
|
|
const GVariantType *expected_type,
|
|
gpointer data)
|
|
{
|
|
GVariant *res;
|
|
|
|
if (g_value_get_boolean (value))
|
|
res = g_variant_new_string ("suspend");
|
|
else
|
|
res = g_variant_new_string ("nothing");
|
|
|
|
return res;
|
|
}
|
|
|
|
static void
|
|
add_automatic_suspend_section (CcPowerPanel *self)
|
|
{
|
|
CcPowerPanelPrivate *priv = self->priv;
|
|
GtkWidget *vbox;
|
|
GtkWidget *widget, *box, *label;
|
|
GtkWidget *sw;
|
|
gchar *s;
|
|
gint value;
|
|
GtkTreeModel *model;
|
|
GtkWidget *dialog;
|
|
GtkWidget *combo;
|
|
GtkCellRenderer *cell;
|
|
|
|
/* The default values for these settings are unfortunate for us;
|
|
* timeout == 0, action == suspend means 'do nothing' - just
|
|
* as timout === anything, action == nothing.
|
|
* For our switch/combobox combination, the second choice works
|
|
* much better, so translate the first to the second here.
|
|
*/
|
|
if (g_settings_get_int (priv->gsd_settings, "sleep-inactive-ac-timeout") == 0)
|
|
{
|
|
g_settings_set_enum (priv->gsd_settings, "sleep-inactive-ac-type", GSD_POWER_ACTION_NOTHING);
|
|
g_settings_set_int (priv->gsd_settings, "sleep-inactive-ac-timeout", 3600);
|
|
}
|
|
if (g_settings_get_int (priv->gsd_settings, "sleep-inactive-battery-timeout") == 0)
|
|
{
|
|
g_settings_set_enum (priv->gsd_settings, "sleep-inactive-battery-type", GSD_POWER_ACTION_NOTHING);
|
|
g_settings_set_int (priv->gsd_settings, "sleep-inactive-battery-timeout", 1800);
|
|
}
|
|
|
|
|
|
vbox = WID (priv->builder, "vbox_power");
|
|
|
|
s = g_markup_printf_escaped ("<b>%s</b>", _("Suspend & Power Off"));
|
|
widget = gtk_label_new (s);
|
|
g_free (s);
|
|
gtk_label_set_use_markup (GTK_LABEL (widget), TRUE);
|
|
gtk_misc_set_alignment (GTK_MISC (widget), 0, 0.5);
|
|
gtk_widget_set_margin_left (widget, 56);
|
|
gtk_widget_set_margin_right (widget, 50);
|
|
gtk_widget_set_margin_bottom (widget, 6);
|
|
gtk_box_pack_start (GTK_BOX (vbox), widget, FALSE, TRUE, 0);
|
|
gtk_widget_show (widget);
|
|
|
|
widget = GTK_WIDGET (egg_list_box_new ());
|
|
priv->boxes_reverse = g_list_prepend (priv->boxes_reverse, widget);
|
|
g_signal_connect (widget, "keynav-failed", G_CALLBACK (keynav_failed), self);
|
|
egg_list_box_set_selection_mode (EGG_LIST_BOX (widget), GTK_SELECTION_NONE);
|
|
egg_list_box_set_separator_funcs (EGG_LIST_BOX (widget),
|
|
update_separator_func,
|
|
NULL, NULL);
|
|
g_signal_connect_swapped (widget, "child-activated",
|
|
G_CALLBACK (activate_child), self);
|
|
|
|
box = gtk_frame_new (NULL);
|
|
gtk_frame_set_shadow_type (GTK_FRAME (box), GTK_SHADOW_IN);
|
|
gtk_widget_set_margin_left (box, 50);
|
|
gtk_widget_set_margin_right (box, 50);
|
|
gtk_widget_set_margin_bottom (box, 24);
|
|
gtk_widget_show (box);
|
|
gtk_container_add (GTK_CONTAINER (box), widget);
|
|
gtk_box_pack_start (GTK_BOX (vbox), box, FALSE, TRUE, 0);
|
|
|
|
self->priv->automatic_suspend_row = box = gtk_box_new (GTK_ORIENTATION_HORIZONTAL, 50);
|
|
label = gtk_label_new (_("_Automatic suspend"));
|
|
gtk_misc_set_alignment (GTK_MISC (label), 0, 0.5);
|
|
gtk_label_set_use_underline (GTK_LABEL (label), TRUE);
|
|
gtk_widget_set_margin_left (label, 20);
|
|
gtk_widget_set_margin_right (label, 20);
|
|
gtk_widget_set_margin_top (label, 6);
|
|
gtk_widget_set_margin_bottom (label, 6);
|
|
gtk_box_pack_start (GTK_BOX (box), label, TRUE, TRUE, 0);
|
|
|
|
priv->automatic_suspend_label = sw = gtk_label_new ("");
|
|
gtk_label_set_mnemonic_widget (GTK_LABEL (label), sw);
|
|
g_signal_connect (sw, "mnemonic-activate",
|
|
G_CALLBACK (automatic_suspend_activate), self);
|
|
gtk_misc_set_alignment (GTK_MISC (sw), 1, 0.5);
|
|
gtk_widget_set_margin_left (sw, 24);
|
|
gtk_widget_set_margin_right (sw, 24);
|
|
gtk_box_pack_start (GTK_BOX (box), sw, FALSE, TRUE, 0);
|
|
gtk_container_add (GTK_CONTAINER (widget), box);
|
|
gtk_size_group_add_widget (priv->row_sizegroup, box);
|
|
update_automatic_suspend_label (self);
|
|
|
|
priv->critical_battery_row = box = gtk_box_new (GTK_ORIENTATION_HORIZONTAL, 6);
|
|
label = gtk_label_new (_("When battery power is _critical"));
|
|
gtk_misc_set_alignment (GTK_MISC (label), 0, 0.5);
|
|
gtk_label_set_use_underline (GTK_LABEL (label), TRUE);
|
|
gtk_widget_set_margin_left (label, 20);
|
|
gtk_widget_set_margin_right (label, 20);
|
|
gtk_widget_set_margin_top (label, 6);
|
|
gtk_widget_set_margin_bottom (label, 6);
|
|
gtk_box_pack_start (GTK_BOX (box), label, TRUE, TRUE, 0);
|
|
|
|
if (up_client_get_can_hibernate (self->priv->up_client))
|
|
{
|
|
model = (GtkTreeModel*)gtk_builder_get_object (priv->builder, "liststore_critical");
|
|
priv->critical_battery_combo = sw = gtk_combo_box_new_with_model (model);
|
|
gtk_label_set_mnemonic_widget (GTK_LABEL (label), sw);
|
|
cell = gtk_cell_renderer_text_new ();
|
|
gtk_cell_layout_pack_start (GTK_CELL_LAYOUT (sw), cell, TRUE);
|
|
gtk_cell_layout_add_attribute (GTK_CELL_LAYOUT (sw), cell, "text", 0);
|
|
gtk_widget_set_margin_left (sw, 20);
|
|
gtk_widget_set_margin_right (sw, 20);
|
|
gtk_widget_set_valign (sw, GTK_ALIGN_CENTER);
|
|
|
|
g_object_set_data (G_OBJECT (sw), "_gsettings_key", "critical-battery-action");
|
|
value = g_settings_get_enum (priv->gsd_settings, "critical-battery-action");
|
|
set_value_for_combo (GTK_COMBO_BOX (sw), value);
|
|
g_signal_connect (sw, "changed",
|
|
G_CALLBACK (combo_enum_changed_cb), self);
|
|
|
|
gtk_box_pack_start (GTK_BOX (box), sw, FALSE, TRUE, 0);
|
|
g_signal_connect (priv->gsd_settings, "changed",
|
|
G_CALLBACK (on_suspend_settings_changed), self);
|
|
}
|
|
else
|
|
{
|
|
label = gtk_label_new (_("Power Off"));
|
|
gtk_widget_set_margin_left (label, 20);
|
|
gtk_widget_set_margin_right (label, 20);
|
|
gtk_widget_set_margin_top (label, 6);
|
|
gtk_widget_set_margin_bottom (label, 6);
|
|
gtk_box_pack_start (GTK_BOX (box), label, FALSE, TRUE, 0);
|
|
}
|
|
|
|
gtk_container_add (GTK_CONTAINER (widget), box);
|
|
gtk_size_group_add_widget (priv->row_sizegroup, box);
|
|
gtk_widget_show_all (widget);
|
|
|
|
dialog = WID (priv->builder, "automatic_suspend_dialog");
|
|
sw = WID (priv->builder, "automatic_suspend_close");
|
|
g_signal_connect_swapped (sw, "clicked", G_CALLBACK (gtk_widget_hide), dialog);
|
|
g_signal_connect (dialog, "delete-event", G_CALLBACK (gtk_widget_hide_on_delete), NULL);
|
|
|
|
sw = WID (priv->builder, "suspend_on_battery_switch");
|
|
g_settings_bind_with_mapping (priv->gsd_settings, "sleep-inactive-battery-type",
|
|
sw, "active",
|
|
G_SETTINGS_BIND_DEFAULT,
|
|
get_sleep_type, set_sleep_type, NULL, NULL);
|
|
|
|
combo = WID (priv->builder, "suspend_on_battery_delay_combo");
|
|
g_object_set_data (G_OBJECT (combo), "_gsettings_key", "sleep-inactive-battery-timeout");
|
|
value = g_settings_get_int (priv->gsd_settings, "sleep-inactive-battery-timeout");
|
|
set_value_for_combo (GTK_COMBO_BOX (combo), value);
|
|
g_signal_connect (combo, "changed",
|
|
G_CALLBACK (combo_time_changed_cb), self);
|
|
g_object_bind_property (sw, "active", combo, "sensitive",
|
|
G_BINDING_DEFAULT | G_BINDING_SYNC_CREATE);
|
|
|
|
sw = WID (priv->builder, "suspend_on_ac_switch");
|
|
g_settings_bind_with_mapping (priv->gsd_settings, "sleep-inactive-ac-type",
|
|
sw, "active",
|
|
G_SETTINGS_BIND_DEFAULT,
|
|
get_sleep_type, set_sleep_type, NULL, NULL);
|
|
|
|
combo = WID (priv->builder, "suspend_on_ac_delay_combo");
|
|
g_object_set_data (G_OBJECT (combo), "_gsettings_key", "sleep-inactive-ac-timeout");
|
|
value = g_settings_get_int (priv->gsd_settings, "sleep-inactive-ac-timeout");
|
|
set_value_for_combo (GTK_COMBO_BOX (combo), value);
|
|
g_signal_connect (combo, "changed",
|
|
G_CALLBACK (combo_time_changed_cb), self);
|
|
g_object_bind_property (sw, "active", combo, "sensitive",
|
|
G_BINDING_DEFAULT | G_BINDING_SYNC_CREATE);
|
|
}
|
|
|
|
static gint
|
|
battery_sort_func (gconstpointer a, gconstpointer b, gpointer data)
|
|
{
|
|
GObject *row_a = (GObject*)a;
|
|
GObject *row_b = (GObject*)b;
|
|
gboolean a_primary;
|
|
gboolean b_primary;
|
|
gint a_kind;
|
|
gint b_kind;
|
|
|
|
a_primary = GPOINTER_TO_INT (g_object_get_data (row_a, "primary"));
|
|
b_primary = GPOINTER_TO_INT (g_object_get_data (row_b, "primary"));
|
|
|
|
if (a_primary)
|
|
return -1;
|
|
else if (b_primary)
|
|
return 1;
|
|
|
|
a_kind = GPOINTER_TO_INT (g_object_get_data (row_a, "kind"));
|
|
b_kind = GPOINTER_TO_INT (g_object_get_data (row_b, "kind"));
|
|
|
|
return a_kind - b_kind;
|
|
}
|
|
|
|
static void
|
|
add_battery_section (CcPowerPanel *self)
|
|
{
|
|
CcPowerPanelPrivate *priv = self->priv;
|
|
GtkWidget *vbox;
|
|
GtkWidget *widget, *box;
|
|
GtkWidget *frame;
|
|
gchar *s;
|
|
|
|
vbox = WID (priv->builder, "vbox_power");
|
|
|
|
priv->battery_section = box = gtk_box_new (GTK_ORIENTATION_VERTICAL, 0);
|
|
gtk_widget_set_margin_left (box, 50);
|
|
gtk_widget_set_margin_right (box, 50);
|
|
gtk_widget_set_margin_bottom (box, 6);
|
|
gtk_widget_set_margin_bottom (box, 24);
|
|
gtk_box_pack_start (GTK_BOX (vbox), box, FALSE, TRUE, 0);
|
|
|
|
s = g_markup_printf_escaped ("<b>%s</b>", _("Battery"));
|
|
priv->battery_heading = widget = gtk_label_new (s);
|
|
g_free (s);
|
|
gtk_label_set_use_markup (GTK_LABEL (widget), TRUE);
|
|
gtk_misc_set_alignment (GTK_MISC (widget), 0, 0.5);
|
|
gtk_widget_set_margin_left (widget, 6);
|
|
gtk_widget_set_margin_right (widget, 6);
|
|
gtk_widget_set_margin_bottom (widget, 6);
|
|
gtk_widget_set_margin_bottom (box, 24);
|
|
gtk_box_pack_start (GTK_BOX (box), widget, FALSE, TRUE, 0);
|
|
|
|
priv->battery_list = widget = GTK_WIDGET (egg_list_box_new ());
|
|
priv->boxes_reverse = g_list_prepend (priv->boxes_reverse, priv->battery_list);
|
|
g_signal_connect (widget, "keynav-failed", G_CALLBACK (keynav_failed), self);
|
|
egg_list_box_set_selection_mode (EGG_LIST_BOX (widget), GTK_SELECTION_NONE);
|
|
egg_list_box_set_separator_funcs (EGG_LIST_BOX (widget),
|
|
update_separator_func,
|
|
NULL, NULL);
|
|
egg_list_box_set_sort_func (EGG_LIST_BOX (widget),
|
|
battery_sort_func, NULL, NULL);
|
|
|
|
frame = gtk_frame_new (NULL);
|
|
gtk_frame_set_shadow_type (GTK_FRAME (frame), GTK_SHADOW_IN);
|
|
gtk_container_add (GTK_CONTAINER (frame), widget);
|
|
gtk_box_pack_start (GTK_BOX (box), frame, FALSE, TRUE, 0);
|
|
|
|
priv->battery_capacity = widget = gtk_label_new ("");
|
|
gtk_widget_set_margin_top (widget, 6);
|
|
gtk_widget_set_halign (widget, GTK_ALIGN_CENTER);
|
|
gtk_style_context_add_class (gtk_widget_get_style_context (widget), GTK_STYLE_CLASS_DIM_LABEL);
|
|
gtk_box_pack_start (GTK_BOX (box), priv->battery_capacity, FALSE, TRUE, 0);
|
|
gtk_widget_show_all (box);
|
|
}
|
|
|
|
static void
|
|
add_device_section (CcPowerPanel *self)
|
|
{
|
|
CcPowerPanelPrivate *priv = self->priv;
|
|
GtkWidget *vbox;
|
|
GtkWidget *widget, *box;
|
|
GtkWidget *frame;
|
|
gchar *s;
|
|
|
|
vbox = WID (priv->builder, "vbox_power");
|
|
|
|
priv->device_section = box = gtk_box_new (GTK_ORIENTATION_VERTICAL, 0);
|
|
gtk_widget_set_margin_left (box, 50);
|
|
gtk_widget_set_margin_right (box, 50);
|
|
gtk_widget_set_margin_top (box, 6);
|
|
gtk_widget_set_margin_bottom (box, 24);
|
|
gtk_box_pack_start (GTK_BOX (vbox), box, FALSE, TRUE, 0);
|
|
|
|
s = g_markup_printf_escaped ("<b>%s</b>", _("Devices"));
|
|
priv->device_heading = widget = gtk_label_new (s);
|
|
g_free (s);
|
|
gtk_label_set_use_markup (GTK_LABEL (widget), TRUE);
|
|
gtk_misc_set_alignment (GTK_MISC (widget), 0, 0.5);
|
|
gtk_widget_set_margin_left (widget, 6);
|
|
gtk_widget_set_margin_right (widget, 6);
|
|
gtk_widget_set_margin_bottom (widget, 6);
|
|
gtk_box_pack_start (GTK_BOX (box), widget, FALSE, TRUE, 0);
|
|
|
|
priv->device_list = widget = GTK_WIDGET (egg_list_box_new ());
|
|
priv->boxes_reverse = g_list_prepend (priv->boxes_reverse, priv->device_list);
|
|
g_signal_connect (widget, "keynav-failed", G_CALLBACK (keynav_failed), self);
|
|
egg_list_box_set_selection_mode (EGG_LIST_BOX (widget), GTK_SELECTION_NONE);
|
|
egg_list_box_set_separator_funcs (EGG_LIST_BOX (widget),
|
|
update_separator_func,
|
|
NULL, NULL);
|
|
egg_list_box_set_sort_func (EGG_LIST_BOX (widget),
|
|
battery_sort_func, NULL, NULL);
|
|
|
|
frame = gtk_frame_new (NULL);
|
|
gtk_frame_set_shadow_type (GTK_FRAME (frame), GTK_SHADOW_IN);
|
|
gtk_container_add (GTK_CONTAINER (frame), widget);
|
|
gtk_box_pack_start (GTK_BOX (box), frame, FALSE, TRUE, 0);
|
|
|
|
gtk_widget_show_all (box);
|
|
}
|
|
|
|
static void
|
|
on_content_size_changed (GtkWidget *widget, GtkAllocation *allocation, gpointer data)
|
|
{
|
|
GtkWidget *box;
|
|
|
|
box = gtk_widget_get_parent (gtk_widget_get_parent (widget));
|
|
if (allocation->height < 490)
|
|
{
|
|
gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW (box),
|
|
GTK_POLICY_NEVER, GTK_POLICY_NEVER);
|
|
}
|
|
else
|
|
{
|
|
gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW (box),
|
|
GTK_POLICY_NEVER, GTK_POLICY_AUTOMATIC);
|
|
gtk_scrolled_window_set_min_content_height (GTK_SCROLLED_WINDOW (box), 490);
|
|
}
|
|
}
|
|
|
|
static void
|
|
cc_power_panel_init (CcPowerPanel *self)
|
|
{
|
|
CcPowerPanelPrivate *priv;
|
|
GError *error;
|
|
GtkWidget *widget;
|
|
GtkWidget *box;
|
|
|
|
priv = self->priv = POWER_PANEL_PRIVATE (self);
|
|
g_resources_register (cc_power_get_resource ());
|
|
|
|
priv->builder = gtk_builder_new ();
|
|
|
|
error = NULL;
|
|
gtk_builder_add_from_resource (self->priv->builder,
|
|
"/org/gnome/control-center/power/power.ui",
|
|
&error);
|
|
|
|
if (error != NULL)
|
|
{
|
|
g_warning ("Could not load interface file: %s", error->message);
|
|
g_error_free (error);
|
|
return;
|
|
}
|
|
|
|
priv->cancellable = g_cancellable_new ();
|
|
|
|
g_dbus_proxy_new_for_bus (G_BUS_TYPE_SESSION,
|
|
G_DBUS_PROXY_FLAGS_NONE,
|
|
NULL,
|
|
"org.gnome.SettingsDaemon.Power",
|
|
"/org/gnome/SettingsDaemon/Power",
|
|
"org.gnome.SettingsDaemon.Power.Screen",
|
|
priv->cancellable,
|
|
got_screen_proxy_cb,
|
|
self);
|
|
|
|
priv->up_client = up_client_new ();
|
|
|
|
priv->gsd_settings = g_settings_new ("org.gnome.settings-daemon.plugins.power");
|
|
priv->session_settings = g_settings_new ("org.gnome.desktop.session");
|
|
|
|
priv->row_sizegroup = gtk_size_group_new (GTK_SIZE_GROUP_VERTICAL);
|
|
priv->battery_sizegroup = gtk_size_group_new (GTK_SIZE_GROUP_HORIZONTAL);
|
|
priv->charge_sizegroup = gtk_size_group_new (GTK_SIZE_GROUP_HORIZONTAL);
|
|
priv->level_sizegroup = gtk_size_group_new (GTK_SIZE_GROUP_HORIZONTAL);
|
|
|
|
add_battery_section (self);
|
|
add_device_section (self);
|
|
add_power_saving_section (self);
|
|
add_automatic_suspend_section (self);
|
|
|
|
priv->boxes = g_list_copy (priv->boxes_reverse);
|
|
priv->boxes = g_list_reverse (priv->boxes);
|
|
|
|
set_ac_battery_ui_mode (self);
|
|
update_automatic_suspend_label (self);
|
|
|
|
/* populate batteries */
|
|
g_signal_connect (priv->up_client, "device-added", G_CALLBACK (up_client_changed), self);
|
|
g_signal_connect (priv->up_client, "device-changed", G_CALLBACK (up_client_changed), self);
|
|
g_signal_connect (priv->up_client, "device-removed", G_CALLBACK (up_client_changed), self);
|
|
up_client_changed (priv->up_client, NULL, self);
|
|
|
|
widget = WID (priv->builder, "vbox_power");
|
|
box = gtk_scrolled_window_new (NULL, NULL);
|
|
gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW (box),
|
|
GTK_POLICY_NEVER, GTK_POLICY_AUTOMATIC);
|
|
g_signal_connect (widget, "size-allocate",
|
|
G_CALLBACK (on_content_size_changed), NULL);
|
|
gtk_widget_show (box);
|
|
gtk_container_add (GTK_CONTAINER (self), box);
|
|
g_object_ref (widget);
|
|
gtk_widget_unparent (widget);
|
|
gtk_container_add (GTK_CONTAINER (box), widget);
|
|
g_object_unref (widget);
|
|
|
|
priv->focus_adjustment = gtk_scrolled_window_get_vadjustment (GTK_SCROLLED_WINDOW (box));
|
|
gtk_container_set_focus_vadjustment (GTK_CONTAINER (widget), priv->focus_adjustment);
|
|
}
|