[gnome-control-center] Power: Implement the new power panel design



commit b40734beb4a4982a36351d2bb2022419a23c446b
Author: Matthias Clasen <mclasen redhat com>
Date:   Mon Nov 26 00:51:26 2012 -0500

    Power: Implement the new power panel design
    
    The design can be found here:
    https://live.gnome.org/Design/SystemSettings/Power
    
    https://bugzilla.gnome.org/show_bug.cgi?id=689614

 configure.ac                  |    6 +
 panels/power/Makefile.am      |   10 +
 panels/power/cc-power-panel.c | 2015 +++++++++++++++++++++++++++++------------
 panels/power/power.ui         |  345 +++-----
 4 files changed, 1569 insertions(+), 807 deletions(-)
---
diff --git a/configure.ac b/configure.ac
index 2411ff8..81d9b59 100644
--- a/configure.ac
+++ b/configure.ac
@@ -182,6 +182,9 @@ else
 	AC_DEFINE(BUILD_NETWORK, 1, [Define to 1 to build the Network panel])
 fi
 AM_CONDITIONAL(BUILD_NETWORK, [test x$have_networkmanager = xyes])
+if test x${have_networkmanager} = xyes; then
+  AC_DEFINE(HAVE_NETWORK_MANAGER, 1, [Define to 1 if NetworkManager is available])
+fi
 
 # Check for gnome-bluetooth
 PKG_CHECK_MODULES(BLUETOOTH, $COMMON_MODULES gnome-bluetooth-1.0 >= 3.5.5,
@@ -190,6 +193,9 @@ if test "x$have_bluetooth" = xyes ; then
 	AC_DEFINE(BUILD_BLUETOOTH, 1, [Define to 1 to build the Network panel])
 fi
 AM_CONDITIONAL(BUILD_BLUETOOTH, [test x$have_bluetooth = xyes])
+if test x${have_bluetooth} = xyes; then
+  AC_DEFINE(HAVE_BLUETOOTH, 1, [Define to 1 if bluetooth support is available])
+fi
 
 # Check for CUPS 1.4 or newer
 AC_ARG_ENABLE([cups],
diff --git a/panels/power/Makefile.am b/panels/power/Makefile.am
index 3442c38..0db4126 100644
--- a/panels/power/Makefile.am
+++ b/panels/power/Makefile.am
@@ -19,6 +19,16 @@ libpower_la_SOURCES =		\
 
 libpower_la_LIBADD = $(PANEL_LIBS) $(POWER_PANEL_LIBS)
 
+if BUILD_BLUETOOTH
+INCLUDES += $(BLUETOOTH_CFLAGS)
+libpower_la_LIBADD += $(BLUETOOTH_LIBS)
+endif
+
+if BUILD_NETWORK
+INCLUDES += $(NETWORK_MANAGER_CFLAGS)
+libpower_la_LIBADD += $(NETWORK_MANAGER_LIBS)
+endif
+
 uidir = $(pkgdatadir)/ui
 dist_ui_DATA = power.ui
 
diff --git a/panels/power/cc-power-panel.c b/panels/power/cc-power-panel.c
index eeeb560..e52c8c2 100644
--- a/panels/power/cc-power-panel.c
+++ b/panels/power/cc-power-panel.c
@@ -25,9 +25,30 @@
 #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
+#include <bluetooth-client.h>
+#endif
+
+#ifdef HAVE_NETWORK_MANAGER
+#include <nm-client.h>
+#endif
 
 #include "cc-power-panel.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)
@@ -37,90 +58,81 @@ CC_PANEL_REGISTER (CcPowerPanel, cc_power_panel)
 
 struct _CcPowerPanelPrivate
 {
-  GSettings     *lock_settings;
   GSettings     *gsd_settings;
   GCancellable  *cancellable;
   GtkBuilder    *builder;
-  GDBusProxy    *proxy;
   UpClient      *up_client;
-  GtkWidget     *levelbar_primary;
+  GDBusProxy    *screen_proxy;
+  gboolean       has_batteries;
+
+  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     *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
 };
 
 enum
 {
   ACTION_MODEL_TEXT,
-  ACTION_MODEL_VALUE,
-  ACTION_MODEL_SENSITIVE
+  ACTION_MODEL_VALUE
 };
 
 static void
-cc_power_panel_get_property (GObject    *object,
-                              guint       property_id,
-                              GValue     *value,
-                              GParamSpec *pspec)
-{
-  switch (property_id)
-    {
-    default:
-      G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
-    }
-}
-
-static void
-cc_power_panel_set_property (GObject      *object,
-                              guint         property_id,
-                              const GValue *value,
-                              GParamSpec   *pspec)
-{
-  switch (property_id)
-    {
-    default:
-      G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
-    }
-}
-
-static void
 cc_power_panel_dispose (GObject *object)
 {
   CcPowerPanelPrivate *priv = CC_POWER_PANEL (object)->priv;
 
-  if (priv->gsd_settings)
-    {
-      g_object_unref (priv->gsd_settings);
-      priv->gsd_settings = NULL;
-    }
+  g_clear_object (&priv->gsd_settings);
   if (priv->cancellable != NULL)
     {
       g_cancellable_cancel (priv->cancellable);
       g_object_unref (priv->cancellable);
       priv->cancellable = NULL;
     }
-  if (priv->builder != NULL)
-    {
-      g_object_unref (priv->builder);
-      priv->builder = NULL;
-    }
-  if (priv->proxy != NULL)
-    {
-      g_object_unref (priv->proxy);
-      priv->proxy = NULL;
-    }
-  if (priv->up_client != NULL)
-    {
-      g_object_unref (priv->up_client);
-      priv->up_client = 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_OBJECT_CLASS (cc_power_panel_parent_class)->dispose (object);
 }
 
-static void
-on_lock_settings_changed (GSettings     *settings,
-                          const char    *key,
-                          CcPowerPanel *panel)
-{
-}
-
 static const char *
 cc_power_panel_get_help_uri (CcPanel *panel)
 {
@@ -135,8 +147,6 @@ cc_power_panel_class_init (CcPowerPanelClass *klass)
 
   g_type_class_add_private (klass, sizeof (CcPowerPanelPrivate));
 
-  object_class->get_property = cc_power_panel_get_property;
-  object_class->set_property = cc_power_panel_set_property;
   object_class->dispose = cc_power_panel_dispose;
 
   panel_class->get_help_uri = cc_power_panel_get_help_uri;
@@ -186,70 +196,49 @@ get_timestring (guint64 time_secs)
   return timestring;
 }
 
-static void
-set_device_battery_primary (CcPowerPanel *panel, GVariant *device)
+static gchar *
+get_details_string (gdouble percentage, UpDeviceState state, guint64 time)
 {
-  CcPowerPanelPrivate *priv = panel->priv;
-  gchar *details = NULL;
-  gchar *time_string = NULL;
-  gdouble percentage;
-  GtkWidget *widget;
-  guint64 time;
-  UpDeviceState state;
+  gchar *details;
 
-  /* set the device */
-  g_variant_get (device,
-                 "(susdut)",
-                 NULL, /* object_path */
-                 NULL, /* kind */
-                 NULL, /* icon_name */
-                 &percentage,
-                 &state,
-                 &time);
-
-  /* set the percentage */
-  gtk_level_bar_set_value (GTK_LEVEL_BAR (priv->levelbar_primary),
-                           percentage / 100.0f);
-
-  /* clear the warning */
-  widget = GTK_WIDGET (gtk_builder_get_object (priv->builder,
-                                               "image_primary_warning"));
-  gtk_widget_hide (widget);
-
-  /* set the description */
   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(_("Charging - %s until fully charged"),
-                                      time_string);
+            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 low battery, %s remaining"),
-                                          time_string);
-                /* show the warning */
-                gtk_widget_show (widget);
+                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(_("Using battery power - %s remaining"),
-                                          time_string);
+                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));
+            details = g_strdup_printf ("error: %s", up_device_state_to_string (state));
             break;
         }
+      g_free (time_string);
     }
   else
     {
@@ -258,20 +247,20 @@ set_device_battery_primary (CcPowerPanel *panel, GVariant *device)
           case UP_DEVICE_STATE_CHARGING:
           case UP_DEVICE_STATE_PENDING_CHARGE:
             /* TRANSLATORS: primary battery */
-            details = g_strdup(_("Charging"));
+            details = g_strdup (_("Charging"));
             break;
           case UP_DEVICE_STATE_DISCHARGING:
           case UP_DEVICE_STATE_PENDING_DISCHARGE:
             /* TRANSLATORS: primary battery */
-            details = g_strdup(_("Using battery power"));
+            details = g_strdup (_("Discharging"));
             break;
           case UP_DEVICE_STATE_FULLY_CHARGED:
             /* TRANSLATORS: primary battery */
-            details = g_strdup(_("Charging - fully charged"));
+            details = g_strdup (_("Fully charged"));
             break;
           case UP_DEVICE_STATE_EMPTY:
             /* TRANSLATORS: primary battery */
-            details = g_strdup(_("Empty"));
+            details = g_strdup (_("Empty"));
             break;
           default:
             details = g_strdup_printf ("error: %s",
@@ -279,229 +268,197 @@ set_device_battery_primary (CcPowerPanel *panel, GVariant *device)
             break;
         }
     }
-  if (details == NULL)
-    goto out;
-  widget = GTK_WIDGET (gtk_builder_get_object (priv->builder,
-                                               "label_battery_primary"));
-  gtk_label_set_label (GTK_LABEL (widget), details);
-
-  /* show the primary device */
-  widget = GTK_WIDGET (gtk_builder_get_object (priv->builder,
-                                               "box_primary"));
-  gtk_widget_show (widget);
 
-  /* hide the addon device until we stumble upon the device */
-  widget = GTK_WIDGET (gtk_builder_get_object (priv->builder,
-                                               "box_battery_addon"));
-  gtk_widget_hide (widget);
-out:
-  g_free (time_string);
-  g_free (details);
+  return details;
 }
 
 static void
-set_device_ups_primary (CcPowerPanel *panel, GVariant *device)
+set_primary (CcPowerPanel *panel, UpDevice *device)
 {
   CcPowerPanelPrivate *priv = panel->priv;
   gchar *details = NULL;
-  gchar *time_string = NULL;
   gdouble percentage;
-  GtkWidget *widget;
-  guint64 time;
+  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;
 
-  /* set the device */
-  g_variant_get (device,
-                 "(susdut)",
-                 NULL, /* object_path */
-                 NULL, /* kind */
-                 NULL, /* icon_name */
-                 &percentage,
-                 &state,
-                 &time);
-
-  /* set the percentage */
-  gtk_level_bar_set_value (GTK_LEVEL_BAR (priv->levelbar_primary),
-                           percentage / 100.0f);
-
-  /* always show the warning */
-  widget = GTK_WIDGET (gtk_builder_get_object (priv->builder,
-                                               "image_primary_warning"));
-  gtk_widget_show (widget);
-
-  /* set the description */
-  if (time > 0)
+  if (energy_rate > 0)
     {
-      time_string = get_timestring (time);
-      switch (state)
-        {
-          case UP_DEVICE_STATE_DISCHARGING:
-            if (percentage < 20)
-              {
-                /* TRANSLATORS: %1 is a time string, e.g. "1 hour 5 minutes" */
-                details = g_strdup_printf(_("Caution low UPS, %s remaining"),
-                                          time_string);
-              }
-            else
-              {
-                /* TRANSLATORS: %1 is a time string, e.g. "1 hour 5 minutes" */
-                details = g_strdup_printf(_("Using UPS power - %s remaining"),
-                                          time_string);
-              }
-            break;
-          default:
-            details = g_strdup_printf ("error: %s",
-                                       up_device_state_to_string (state));
-            break;
-        }
+      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
     {
-      switch (state)
-        {
-          case UP_DEVICE_STATE_DISCHARGING:
-            if (percentage < 20)
-              {
-                /* TRANSLATORS: UPS battery */
-                details = g_strdup(_("Caution low UPS"));
-              }
-            else
-              {
-                /* TRANSLATORS: UPS battery */
-                details = g_strdup(_("Using UPS power"));
-              }
-            break;
-          default:
-            details = g_strdup_printf ("error: %s",
-                                       up_device_state_to_string (state));
-            break;
-        }
+      gtk_widget_hide (priv->battery_capacity);
     }
-  if (details == NULL)
-    goto out;
-  widget = GTK_WIDGET (gtk_builder_get_object (priv->builder,
-                                               "label_battery_primary"));
-  gtk_label_set_label (GTK_LABEL (widget), details);
-
-  /* show the primary device */
-  widget = GTK_WIDGET (gtk_builder_get_object (priv->builder,
-                                               "box_primary"));
-  gtk_widget_show (widget);
 
-  /* hide the addon device as extra UPS devices are not possible */
-  widget = GTK_WIDGET (gtk_builder_get_object (priv->builder,
-                                               "box_battery_addon"));
-  gtk_widget_hide (widget);
-out:
-  g_free (time_string);
+  details = get_details_string (percentage, state, time);
+
+  box = gtk_box_new (GTK_ORIENTATION_VERTICAL, 0);
+  gtk_size_group_add_widget (priv->battery_sizegroup, box);
+  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);
+  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_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
-set_device_battery_additional (CcPowerPanel *panel, GVariant *device)
+add_battery (CcPowerPanel *panel, UpDevice *device)
 {
   CcPowerPanelPrivate *priv = panel->priv;
-  gchar *details = NULL;
-  GtkWidget *widget;
+  gdouble percentage;
+  UpDeviceKind kind;
   UpDeviceState state;
-
-  /* set the device */
-  g_variant_get (device,
-                 "(susdut)",
-                 NULL, /* object_path */
-                 NULL, /* kind */
-                 NULL, /* icon_name */
-                 NULL, /* percentage */
-                 &state,
-                 NULL /* time */);
-
-  /* set the description */
-  switch (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)
     {
-      case UP_DEVICE_STATE_FULLY_CHARGED:
-        /* TRANSLATORS: secondary battery is normally in the media bay */
-        details = g_strdup(_("Your secondary battery is fully charged"));
-        break;
-      case UP_DEVICE_STATE_EMPTY:
-        /* TRANSLATORS: secondary battery is normally in the media bay */
-        details = g_strdup(_("Your secondary battery is empty"));
-        break;
-      default:
-        break;
+      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);
     }
-  if (details == NULL)
-    goto out;
-  widget = GTK_WIDGET (gtk_builder_get_object (priv->builder,
-                                               "label_battery_addon"));
-  gtk_label_set_label (GTK_LABEL (widget), details);
-
-  /* show the addon device */
-  widget = GTK_WIDGET (gtk_builder_get_object (priv->builder,
-                                               "box_battery_addon"));
-  gtk_widget_show (widget);
-out:
-  g_free (details);
+#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);
+
+  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_secondary (CcPowerPanel *panel,
-                      GVariant *device,
-                      guint *secondary_devices_cnt)
+add_device (CcPowerPanel *panel, UpDevice *device)
 {
   CcPowerPanelPrivate *priv = panel->priv;
-  const gchar *icon_name = NULL;
-  gdouble percentage;
-  guint64 time;
   UpDeviceKind kind;
   UpDeviceState state;
-  GtkWidget *vbox;
   GtkWidget *hbox;
+  GtkWidget *box2;
   GtkWidget *widget;
   GString *status;
   GString *description;
+  gdouble percentage;
+  gchar *s;
   gboolean show_caution = FALSE;
 
-  g_variant_get (device,
-                 "(susdut)",
-                 NULL,
-                 &kind,
-                 NULL,
-                 &percentage,
-                 &state,
-                 &time);
-
-  switch (kind)
-    {
-      case UP_DEVICE_KIND_UPS:
-        icon_name = "uninterruptible-power-supply";
-        show_caution = TRUE;
-        break;
-      case UP_DEVICE_KIND_MOUSE:
-        icon_name = "input-mouse";
-        break;
-      case UP_DEVICE_KIND_KEYBOARD:
-        icon_name = "input-keyboard";
-        break;
-      case UP_DEVICE_KIND_TABLET:
-        icon_name = "input-tablet";
-        break;
-      case UP_DEVICE_KIND_PDA:
-        icon_name = "pda";
-        break;
-      case UP_DEVICE_KIND_PHONE:
-        icon_name = "phone";
-        break;
-      case UP_DEVICE_KIND_MEDIA_PLAYER:
-        icon_name = "multimedia-player";
-        break;
-      case UP_DEVICE_KIND_COMPUTER:
-        icon_name = "computer";
-        show_caution = TRUE;
-        break;
-      default:
-        icon_name = "battery";
-        break;
-    }
+  g_object_get (device,
+                "kind", &kind,
+                "percentage", &percentage,
+                "state", &state,
+                NULL);
 
   switch (kind)
     {
@@ -516,6 +473,7 @@ add_device_secondary (CcPowerPanel *panel,
       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 */
@@ -542,8 +500,6 @@ add_device_secondary (CcPowerPanel *panel,
         description = g_string_new (_("Battery"));
         break;
     }
-  g_string_prepend (description, "<b>");
-  g_string_append (description, "</b>");
 
   switch (state)
     {
@@ -572,11 +528,11 @@ add_device_secondary (CcPowerPanel *panel,
         break;
       case UP_DEVICE_STATE_FULLY_CHARGED:
         /* TRANSLATORS: primary battery */
-        status = g_string_new(C_("Battery power", "Charging - fully charged"));
+        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"));
+        status = g_string_new (C_("Battery power", "Empty"));
         break;
       default:
         status = g_string_new (up_device_state_to_string (state));
@@ -586,222 +542,373 @@ add_device_secondary (CcPowerPanel *panel,
   g_string_append (status, "</small>");
 
   /* create the new widget */
-  hbox = gtk_box_new (GTK_ORIENTATION_HORIZONTAL, 12);
-  gtk_widget_set_hexpand (hbox, TRUE);
-  widget = gtk_image_new ();
-  gtk_misc_set_alignment (GTK_MISC (widget), 0.5f, 0.0f);
-  gtk_image_set_from_icon_name (GTK_IMAGE (widget), icon_name, GTK_ICON_SIZE_DND);
-  gtk_box_pack_start (GTK_BOX (hbox), widget, FALSE, FALSE, 0);
-  vbox = gtk_box_new (GTK_ORIENTATION_VERTICAL, 0);
+  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_box_pack_start (GTK_BOX (vbox), widget, FALSE, FALSE, 0);
-  widget = gtk_label_new ("");
-  gtk_misc_set_alignment (GTK_MISC (widget), 0.0f, 0.5f);
-  gtk_label_set_markup (GTK_LABEL (widget), status->str);
-  gtk_box_pack_start (GTK_BOX (vbox), widget, FALSE, FALSE, 0);
+  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_margin_right (widget, 32);
-  gtk_widget_set_margin_top (widget, 3);
+  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 (vbox), widget, TRUE, TRUE, 0);
-  gtk_box_pack_start (GTK_BOX (hbox), vbox, TRUE, TRUE, 0);
-
-  /* add to the grid */
-  widget = GTK_WIDGET (gtk_builder_get_object (priv->builder,
-                                               "grid_secondary"));
-
-  /* two devices wide */
-  gtk_grid_attach (GTK_GRID (widget), hbox,
-                   *secondary_devices_cnt % 2,
-                   (*secondary_devices_cnt / 2) - 1,
-                   1, 1);
-  (*secondary_devices_cnt)++;
-
-  /* show panel */
-  widget = GTK_WIDGET (gtk_builder_get_object (priv->builder,
-                                               "box_secondary"));
-  gtk_widget_show_all (widget);
+  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
-get_devices_cb (GObject *source_object, GAsyncResult *res, gpointer user_data)
+up_client_changed (UpClient     *client,
+                   UpDevice     *device,
+                   CcPowerPanel *self)
 {
-  CcPowerPanel *panel;
-  CcPowerPanelPrivate *priv;
-  gboolean got_primary = FALSE;
-  gboolean ups_as_primary_device = FALSE;
-  GError *error = NULL;
-  gsize n_devices;
-  GList *children;
-  GList *l;
-  GtkWidget *widget;
-  guint i;
-  guint secondary_devices_cnt = 0;
-  GVariant *child;
-  GVariant *result;
-  GVariant *untuple;
+  CcPowerPanelPrivate *priv = self->priv;
+  GPtrArray *devices;
+  GList *children, *l;
+  gint i;
   UpDeviceKind kind;
   UpDeviceState state;
-
-  result = g_dbus_proxy_call_finish (G_DBUS_PROXY (source_object), res, &error);
-  if (g_error_matches (error, G_IO_ERROR, G_IO_ERROR_CANCELLED))
-    {
-      g_error_free (error);
-      return; /* Must exit before accessing freed memory */
-    }
-
-  panel = CC_POWER_PANEL (user_data);
-  priv = panel->priv;
-
-  /* empty the secondary box */
-  widget = GTK_WIDGET (gtk_builder_get_object (priv->builder,
-                                               "grid_secondary"));
-  children = gtk_container_get_children (GTK_CONTAINER (widget));
+  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 (widget), l->data);
+    gtk_container_remove (GTK_CONTAINER (priv->battery_list), l->data);
   g_list_free (children);
+  gtk_widget_hide (priv->battery_section);
 
-  /* hide both panels initially */
-  widget = GTK_WIDGET (gtk_builder_get_object (priv->builder,
-                                               "box_primary"));
-  gtk_widget_hide (widget);
-  widget = GTK_WIDGET (gtk_builder_get_object (priv->builder,
-                                               "box_secondary"));
-  gtk_widget_hide (widget);
-
-  if (result == NULL)
+  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++)
     {
-      g_printerr ("Error getting devices: %s\n", error->message);
-      g_error_free (error);
-      return;
+      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++;
+        }
     }
 
-  untuple = g_variant_get_child_value (result, 0);
-  n_devices = g_variant_n_children (untuple);
+  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;
 
-  /* first we look for a discharging UPS, which is promoted to the
-   * primary device if it's discharging. Otherwise we use the first
-   * listed laptop battery as the primary device */
-  for (i = 0; i < n_devices; i++)
+  if (energy_rate_total > 0)
     {
-      child = g_variant_get_child_value (untuple, i);
-      g_variant_get (child,
-                     "(susdut)",
-                     NULL,
-                     &kind,
-                     NULL,
-                     NULL,
-                     &state,
-                     NULL);
-      if (kind == UP_DEVICE_KIND_UPS &&
-          state == UP_DEVICE_STATE_DISCHARGING)
-        {
-          ups_as_primary_device = TRUE;
-        }
-      g_variant_unref (child);
+      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);
     }
 
-  /* add the devices now we know the state-of-play */
-  for (i = 0; i < n_devices; i++)
+  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++)
     {
-      child = g_variant_get_child_value (untuple, i);
-      g_variant_get (child,
-                     "(susdut)",
-                     NULL,
-                     &kind,
-                     NULL,
-                     NULL,
-                     NULL,
-                     NULL);
+      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 && ups_as_primary_device)
+      else if (kind == UP_DEVICE_KIND_UPS && on_ups)
         {
-          set_device_ups_primary (panel, child);
+          set_primary (self, device);
         }
-      else if (kind == UP_DEVICE_KIND_BATTERY && !ups_as_primary_device)
+      else if (kind == UP_DEVICE_KIND_BATTERY && !on_ups && n_batteries == 1)
         {
-          if (!got_primary)
-            {
-              set_device_battery_primary (panel, child);
-              got_primary = TRUE;
-            }
-          else
-            {
-              set_device_battery_additional (panel, child);
-            }
+          set_primary (self, device);
+        }
+      else if (kind == UP_DEVICE_KIND_BATTERY)
+        {
+          add_battery (self, device);
         }
       else
         {
-          add_device_secondary (panel, child, &secondary_devices_cnt);
+          add_device (self, device);
         }
-      g_variant_unref (child);
     }
 
-  g_variant_unref (untuple);
-  g_variant_unref (result);
+  g_ptr_array_unref (devices);
+  g_object_unref (composite);
 }
 
 static void
-on_properties_changed (GDBusProxy *proxy,
-                       GVariant   *changed_properties,
-                       GStrv       invalidated_properties,
-                       gpointer    user_data)
+set_brightness_cb (GObject *source_object, GAsyncResult *res, gpointer user_data)
 {
+  GError *error = NULL;
+  GVariant *result;
   CcPowerPanelPrivate *priv = CC_POWER_PANEL (user_data)->priv;
 
-  /* get the new state */
-  g_dbus_proxy_call (priv->proxy,
-                     "GetDevices",
-                     NULL,
+  /* 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,
+                     "SetPercentage",
+                     g_variant_new ("(u)",
+                                    percentage),
                      G_DBUS_CALL_FLAGS_NONE,
                      -1,
                      priv->cancellable,
-                     get_devices_cb,
+                     set_brightness_cb,
                      user_data);
 }
 
 static void
-got_power_proxy_cb (GObject *source_object, GAsyncResult *res, gpointer user_data)
+get_brightness_cb (GObject *source_object, GAsyncResult *res, gpointer user_data)
 {
+  CcPowerPanel *self = CC_POWER_PANEL (user_data);
   GError *error = NULL;
-  GDBusProxy *proxy;
-  CcPowerPanelPrivate *priv;
+  GVariant *result;
+  guint brightness;
+  GtkRange *range;
 
-  proxy = g_dbus_proxy_new_for_bus_finish (res, &error);
-  if (proxy == NULL)
+  result = g_dbus_proxy_call_finish (G_DBUS_PROXY (source_object), res, &error);
+  if (result == NULL)
     {
-      g_printerr ("Error creating proxy: %s\n", error->message);
+      /* We got cancelled, so we're probably exiting */
+      if (g_error_matches (error, G_IO_ERROR, G_IO_ERROR_CANCELLED))
+        {
+          g_error_free (error);
+          return;
+        }
+
+      gtk_widget_hide (self->priv->brightness_row);
+
+      if (error->message &&
+          strstr (error->message, "No backlight devices present") == NULL)
+        {
+          g_warning ("Error getting brightness: %s", error->message);
+        }
       g_error_free (error);
       return;
     }
 
-  /* Access user_data after checking for error because user_data might be
-     disposed already. */
-  priv = CC_POWER_PANEL (user_data)->priv;
-  priv->proxy = proxy;
+  /* set the slider */
+  g_variant_get (result, "(u)", &brightness);
+  range = GTK_RANGE (self->priv->brightness_scale);
+  gtk_range_set_range (range, 0, 100);
+  gtk_range_set_increments (range, 1, 10);
+  gtk_range_set_value (range, brightness);
+  g_signal_connect (range, "value-changed",
+                    G_CALLBACK (brightness_slider_value_changed_cb), user_data);
+  g_variant_unref (result);
+}
+
+static void
+on_signal (GDBusProxy *proxy,
+           gchar      *sender_name,
+           gchar      *signal_name,
+           GVariant   *parameters,
+           gpointer    user_data)
+{
+  CcPowerPanel *self = CC_POWER_PANEL (user_data);
 
-  /* we want to change the primary device changes */
-  g_signal_connect (priv->proxy,
-                    "g-properties-changed",
-                    G_CALLBACK (on_properties_changed),
-                    user_data);
+  if (g_strcmp0 (signal_name, "Changed") == 0)
+    {
+      /* changed, but ignoring */
+      if (self->priv->setting_brightness)
+        return;
+
+      /* retrieve the value again from g-s-d */
+      g_dbus_proxy_call (self->priv->screen_proxy,
+                         "GetPercentage",
+                         NULL,
+                         G_DBUS_CALL_FLAGS_NONE,
+                         200, /* we don't want to randomly move the bar */
+                         self->priv->cancellable,
+                         get_brightness_cb,
+                         user_data);
+    }
+}
+
+static void
+got_screen_proxy_cb (GObject *source_object, GAsyncResult *res, gpointer user_data)
+{
+  GError *error = NULL;
+  CcPowerPanelPrivate *priv = CC_POWER_PANEL (user_data)->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-signal",
+                    G_CALLBACK (on_signal), user_data);
 
   /* get the initial state */
-  g_dbus_proxy_call (priv->proxy,
-                     "GetDevices",
+  g_dbus_proxy_call (priv->screen_proxy,
+                     "GetPercentage",
                      NULL,
                      G_DBUS_CALL_FLAGS_NONE,
-                     200, /* we don't want to randomly expand the dialog */
+                     200, /* we don't want to randomly move the bar */
                      priv->cancellable,
-                     get_devices_cb,
+                     get_brightness_cb,
                      user_data);
 }
 
@@ -854,56 +961,10 @@ combo_enum_changed_cb (GtkWidget *widget, CcPowerPanel *self)
 }
 
 static void
-disable_unavailable_combo_items (CcPowerPanel *self,
-                                 GtkComboBox *combo_box)
-{
-  gboolean enabled;
-  gboolean ret;
-  gint value_tmp;
-  GtkCellRenderer *renderer;
-  GtkTreeIter iter;
-  GtkTreeModel *model;
-
-  /* setup the renderer */
-  renderer = gtk_cell_renderer_text_new ();
-  gtk_cell_layout_pack_start (GTK_CELL_LAYOUT (combo_box), renderer, TRUE);
-  gtk_cell_layout_set_attributes (GTK_CELL_LAYOUT (combo_box), renderer,
-                                  "text", ACTION_MODEL_TEXT,
-                                  "sensitive", ACTION_MODEL_SENSITIVE,
-                                  NULL);
-
-  /* get entry */
-  model = gtk_combo_box_get_model (combo_box);
-  ret = gtk_tree_model_get_iter_first (model, &iter);
-  if (!ret)
-    return;
-
-  /* disable any actions we cannot do */
-  do
-    {
-      gtk_tree_model_get (model, &iter,
-                          ACTION_MODEL_VALUE, &value_tmp,
-                          -1);
-      switch (value_tmp) {
-      case GSD_POWER_ACTION_SUSPEND:
-        enabled = up_client_get_can_suspend (self->priv->up_client);
-        break;
-      case GSD_POWER_ACTION_HIBERNATE:
-        enabled = up_client_get_can_hibernate (self->priv->up_client);
-        break;
-      default:
-        enabled = TRUE;
-      }
-      gtk_list_store_set (GTK_LIST_STORE (model), &iter,
-                          ACTION_MODEL_SENSITIVE, enabled,
-                          -1);
-    } while (gtk_tree_model_iter_next (model, &iter));
-}
-
-static void
 set_value_for_combo (GtkComboBox *combo_box, gint value)
 {
   GtkTreeIter iter;
+  GtkTreeIter last;
   GtkTreeModel *model;
   gint value_tmp;
   gboolean ret;
@@ -918,14 +979,17 @@ set_value_for_combo (GtkComboBox *combo_box, gint value)
   do
     {
       gtk_tree_model_get (model, &iter,
-                          1, &value_tmp,
+                          ACTION_MODEL_VALUE, &value_tmp,
                           -1);
       if (value == value_tmp)
         {
           gtk_combo_box_set_active_iter (combo_box, &iter);
-          break;
+          return;
         }
+      last = iter;
     } while (gtk_tree_model_iter_next (model, &iter));
+
+  gtk_combo_box_set_active_iter (combo_box, &last);
 }
 
 static void
@@ -938,7 +1002,6 @@ set_ac_battery_ui_mode (CcPowerPanel *self)
   guint i;
   UpDevice *device;
   UpDeviceKind kind;
-  CcPowerPanelPrivate *priv = self->priv;
 
   /* 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);
@@ -950,57 +1013,875 @@ set_ac_battery_ui_mode (CcPowerPanel *self)
     }
 
   devices = up_client_get_devices (self->priv->up_client);
-  for (i=0; i<devices->len; i++)
+g_print ("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)
+      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:
-  gtk_widget_set_visible (WID (priv->builder, "label_header_battery"), has_batteries);
-  gtk_widget_set_visible (WID (priv->builder, "label_header_ac"), has_batteries);
-  gtk_widget_set_visible (WID (priv->builder, "combobox_sleep_battery"), has_batteries);
-  gtk_widget_set_visible (WID (priv->builder, "label_critical"), has_batteries);
-  gtk_widget_set_visible (WID (priv->builder, "combobox_critical"), has_batteries);
+  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)
+{
+  gchar *adapter_path;
+  GDBusConnection *bus;
+
+  g_object_get (client, "default-adapter", &adapter_path, NULL);
+
+  bus = g_bus_get_sync (G_BUS_TYPE_SYSTEM, NULL, NULL);
+  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);
+}
+
+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
-activate_link_cb (GtkLabel *label, gchar *uri, CcPowerPanel *self)
+has_wifi_devices (NMClient *client)
 {
-  CcShell *shell;
-  GError *error = NULL;
+  const GPtrArray *devices;
+  NMDevice *device;
+  gint i;
 
-  shell = cc_panel_get_shell (CC_PANEL (self));
-  if (cc_shell_set_active_panel_from_id (shell, uri, NULL, &error) == FALSE)
+  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++)
     {
-      g_warning ("Failed to activate %s panel: %s", uri, error->message);
-      g_error_free (error);
+      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;
+
   return TRUE;
+  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 void
+add_power_saving_section (CcPowerPanel *self)
+{
+  CcPowerPanelPrivate *priv = self->priv;
+  GtkWidget *vbox;
+  GtkWidget *widget, *box, *label, *scale;
+  GtkWidget *box2;
+  GtkWidget *sw;
+  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 ());
+  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);
+  label = gtk_label_new ("");
+  gtk_box_pack_start (GTK_BOX (box2), label, FALSE, TRUE, 0);
+  gtk_size_group_add_widget (priv->charge_sizegroup, label);
+
+  priv->brightness_scale = scale = gtk_scale_new_with_range (GTK_ORIENTATION_HORIZONTAL, 0, 100, 1);
+  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);
+
+  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);
+
+  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 (_("Screen _Power Saving"));
+  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);
+
+  label = gtk_label_new ("Automatically dims and blanks the screen");
+  gtk_misc_set_alignment (GTK_MISC (label), 0, 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, TRUE, TRUE, 0);
+
+  /* FIXME: implement and use a screen-power-saving setting */
+  sw = gtk_switch_new ();
+  g_settings_bind (priv->gsd_settings, "idle-dim-battery",
+                   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 (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);
+
+#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);
+
+  label = gtk_label_new ("Turns off wireless devices");
+  gtk_misc_set_alignment (GTK_MISC (label), 0, 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, 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);
+
+  label = gtk_label_new ("Turns off WWAN and WiMax devices");
+  gtk_misc_set_alignment (GTK_MISC (label), 0, 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, 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
+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 ());
+  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);
+  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);
+      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 = GTK_WIDGET (gtk_builder_get_object (priv->builder, "automatic_suspend_dialog"));
+  sw = GTK_WIDGET (gtk_builder_get_object (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 = GTK_WIDGET (gtk_builder_get_object (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 = GTK_WIDGET (gtk_builder_get_object (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 = GTK_WIDGET (gtk_builder_get_object (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 = GTK_WIDGET (gtk_builder_get_object (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 ());
+  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 ());
+  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;
-  gint        value;
-  char       *text;
+  GtkWidget  *box;
 
-  self->priv = POWER_PANEL_PRIVATE (self);
+  priv = self->priv = POWER_PANEL_PRIVATE (self);
 
-  self->priv->builder = gtk_builder_new ();
+  priv->builder = gtk_builder_new ();
 
   error = NULL;
-  gtk_builder_add_from_file (self->priv->builder,
+  gtk_builder_add_from_file (priv->builder,
                              GNOMECC_UI_DIR "/power.ui",
                              &error);
 
@@ -1011,75 +1892,53 @@ cc_power_panel_init (CcPowerPanel *self)
       return;
     }
 
-  /* add levelbar */
-  self->priv->levelbar_primary = GTK_WIDGET
-    (gtk_builder_get_object (self->priv->builder, "levelbar_primary"));
-  self->priv->cancellable = g_cancellable_new ();
+  priv->cancellable = g_cancellable_new ();
 
-  /* get initial icon state */
   g_dbus_proxy_new_for_bus (G_BUS_TYPE_SESSION,
                             G_DBUS_PROXY_FLAGS_NONE,
                             NULL,
                             "org.gnome.SettingsDaemon",
                             "/org/gnome/SettingsDaemon/Power",
-                            "org.gnome.SettingsDaemon.Power",
-                            self->priv->cancellable,
-                            got_power_proxy_cb,
+                            "org.gnome.SettingsDaemon.Power.Screen",
+                            priv->cancellable,
+                            got_screen_proxy_cb,
                             self);
 
-  /* find out if there are any battery or UPS devices attached
-   * and setup UI accordingly */
-  self->priv->up_client = up_client_new ();
-  set_ac_battery_ui_mode (self);
+  priv->up_client = up_client_new ();
+
+  priv->gsd_settings = g_settings_new ("org.gnome.settings-daemon.plugins.power");
 
-  self->priv->gsd_settings = g_settings_new ("org.gnome.settings-daemon.plugins.power");
-  g_signal_connect (self->priv->gsd_settings,
-                    "changed",
-                    G_CALLBACK (on_lock_settings_changed),
-                    self);
-
-  /* auto-sleep time */
-  value = g_settings_get_int (self->priv->gsd_settings, "sleep-inactive-ac-timeout");
-  widget = GTK_WIDGET (gtk_builder_get_object (self->priv->builder,
-                                               "combobox_sleep_ac"));
-  set_value_for_combo (GTK_COMBO_BOX (widget), value);
-  g_object_set_data (G_OBJECT(widget), "_gsettings_key", "sleep-inactive-ac-timeout");
-  g_signal_connect (widget, "changed",
-                    G_CALLBACK (combo_time_changed_cb),
-                    self);
-  value = g_settings_get_int (self->priv->gsd_settings, "sleep-inactive-battery-timeout");
-  widget = GTK_WIDGET (gtk_builder_get_object (self->priv->builder,
-                                               "combobox_sleep_battery"));
-  set_value_for_combo (GTK_COMBO_BOX (widget), value);
-  g_object_set_data (G_OBJECT(widget), "_gsettings_key", "sleep-inactive-battery-timeout");
-  g_signal_connect (widget, "changed",
-                    G_CALLBACK (combo_time_changed_cb),
-                    self);
-
-  /* actions */
-  value = g_settings_get_enum (self->priv->gsd_settings, "critical-battery-action");
-  widget = GTK_WIDGET (gtk_builder_get_object (self->priv->builder,
-                                               "combobox_critical"));
-  disable_unavailable_combo_items (self, GTK_COMBO_BOX (widget));
-  set_value_for_combo (GTK_COMBO_BOX (widget), value);
-  g_object_set_data (G_OBJECT(widget), "_gsettings_key", "critical-battery-action");
-  g_signal_connect (widget, "changed",
-                    G_CALLBACK (combo_enum_changed_cb),
-                    self);
-
-  /* set screen link */
-  widget = GTK_WIDGET (gtk_builder_get_object (self->priv->builder,
-                                               "label_screen_settings"));
-  /* TRANSLATORS: this is a link to the "Brightness and Lock" control center panel */
-  text = g_strdup_printf ("<span size=\"small\">%s</span>",
-                          _("Tip: <a href=\"screen\">screen brightness</a> affects how much power is used"));
-  gtk_label_set_markup (GTK_LABEL (widget), text);
-  g_free (text);
-
-  g_signal_connect (widget, "activate-link",
-                    G_CALLBACK (activate_link_cb),
-                    self);
-
-  widget = WID (self->priv->builder, "vbox_power");
-  gtk_widget_reparent (widget, (GtkWidget *) self);
+  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);
+
+  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_scrolled_window_add_with_viewport (GTK_SCROLLED_WINDOW (box), widget);
+  gtk_style_context_add_class (gtk_widget_get_style_context (gtk_widget_get_parent (widget)), "view");
+  gtk_style_context_add_class (gtk_widget_get_style_context (gtk_widget_get_parent (widget)), "content-view");
+  g_object_unref (widget);
 }
diff --git a/panels/power/power.ui b/panels/power/power.ui
index 3e7b269..f4f2ce8 100644
--- a/panels/power/power.ui
+++ b/panels/power/power.ui
@@ -7,19 +7,15 @@
       <column type="gchararray"/>
       <!-- column-name value -->
       <column type="gint"/>
-      <!-- column-name sensitive -->
-      <column type="gboolean"/>
     </columns>
     <data>
       <row>
         <col id="0" translatable="yes">Hibernate</col>
         <col id="1">3</col>
-        <col id="2">True</col>
       </row>
       <row>
         <col id="0" translatable="yes">Power off</col>
         <col id="1">2</col>
-        <col id="2">True</col>
       </row>
     </data>
   </object>
@@ -47,10 +43,6 @@
         <col id="0" translatable="yes">1 hour</col>
         <col id="1">3600</col>
       </row>
-      <row>
-        <col id="0" translatable="yes">Don't suspend</col>
-        <col id="1">0</col>
-      </row>
     </data>
   </object>
   <object class="GtkWindow" id="window_power">
@@ -62,299 +54,194 @@
         <property name="can_focus">False</property>
         <property name="border_width">12</property>
         <property name="spacing">3</property>
-        <child>
-          <object class="GtkGrid" id="grid_combos">
-            <property name="visible">True</property>
+      </object>
+    </child>
+  </object>
+
+  <object class="GtkDialog" id="automatic_suspend_dialog">
+    <property name="can_focus">False</property>
+    <property name="border_width">5</property>
+    <property name="title" translatable="yes">Automatic Suspend</property>
+    <property name="type_hint">dialog</property>
+    <property name="resizable">False</property>
+    <child internal-child="vbox">
+      <object class="GtkBox" id="asdf">
+        <property name="can_focus">False</property>
+        <property name="resize_mode">immediate</property>
+        <property name="orientation">vertical</property>
+        <property name="spacing">2</property>
+        <child internal-child="action_area">
+          <object class="GtkButtonBox" id="dialog-action_area1">
             <property name="can_focus">False</property>
-            <property name="margin_left">53</property>
-            <property name="margin_right">60</property>
-            <property name="margin_bottom">24</property>
-            <property name="orientation">vertical</property>
-            <property name="row_spacing">6</property>
-            <property name="column_spacing">12</property>
+            <property name="layout_style">end</property>
             <child>
-              <object class="GtkLabel" id="label_header_battery">
+              <object class="GtkButton" id="automatic_suspend_close">
+                <property name="label" translatable="yes">_Close</property>
                 <property name="visible">True</property>
-                <property name="can_focus">False</property>
-                <property name="label" translatable="yes">On battery power</property>
-                <property name="halign">center</property>
-                <attributes>
-                  <attribute name="scale" value="0.82999999999999996"/>
-                </attributes>
+                <property name="can_focus">True</property>
+                <property name="can_default">True</property>
+                <property name="has_default">True</property>
+                <property name="receives_default">True</property>
+                <property name="use_underline">True</property>
               </object>
               <packing>
-                <property name="left_attach">1</property>
-                <property name="top_attach">0</property>
+                <property name="expand">False</property>
+                <property name="fill">True</property>
+                <property name="position">1</property>
               </packing>
             </child>
+          </object>
+          <packing>
+            <property name="expand">False</property>
+            <property name="fill">True</property>
+            <property name="pack_type">end</property>
+            <property name="position">0</property>
+          </packing>
+        </child>
+        <child>
+          <object class="GtkGrid" id="grid1">
+            <property name="visible">True</property>
+            <property name="can_focus">False</property>
+            <property name="margin_left">12</property>
+            <property name="margin_right">6</property>
+            <property name="margin_top">12</property>
+            <property name="margin_bottom">12</property>
+            <property name="row_spacing">12</property>
+            <property name="column_spacing">6</property>
             <child>
-              <object class="GtkLabel" id="label_header_ac">
+              <object class="GtkSwitch" id="suspend_on_battery_switch">
                 <property name="visible">True</property>
-                <property name="can_focus">False</property>
-                <property name="label" translatable="yes">When plugged in</property>
-                <property name="halign">center</property>
-                <attributes>
-                  <attribute name="scale" value="0.82999999999999996"/>
-                </attributes>
+                <property name="can_focus">True</property>
               </object>
               <packing>
-                <property name="left_attach">2</property>
+                <property name="left_attach">0</property>
                 <property name="top_attach">0</property>
+                <property name="width">1</property>
+                <property name="height">1</property>
               </packing>
             </child>
             <child>
-              <object class="GtkLabel" id="label7">
+              <object class="GtkSwitch" id="suspend_on_ac_switch">
                 <property name="visible">True</property>
-                <property name="can_focus">False</property>
-                <property name="halign">end</property>
-                <property name="label" translatable="yes">Suspend when inactive for</property>
+                <property name="can_focus">True</property>
               </object>
               <packing>
                 <property name="left_attach">0</property>
                 <property name="top_attach">1</property>
+                <property name="width">1</property>
+                <property name="height">1</property>
               </packing>
             </child>
             <child>
-              <object class="GtkComboBoxText" id="combobox_sleep_battery">
+              <object class="GtkLabel" id="suspend_on_battery_label">
                 <property name="visible">True</property>
                 <property name="can_focus">False</property>
-                <property name="model">liststore_time</property>
-                <property name="hexpand">True</property>
-                <accessibility>
-                  <relation type="labelled-by" target="label_header_battery"/>
-                  <relation type="labelled-by" target="label7"/>
-                </accessibility>
+                <property name="xalign">0</property>
+                <property name="label" translatable="yes">When on _Battery Power</property>
+                <property name="use_underline">True</property>
+                <property name="mnemonic_widget">suspend_on_battery_switch</property>
               </object>
               <packing>
                 <property name="left_attach">1</property>
-                <property name="top_attach">1</property>
-              </packing>
-            </child>
-            <child>
-              <object class="GtkComboBoxText" id="combobox_sleep_ac">
-                <property name="width_request">150</property>
-                <property name="visible">True</property>
-                <property name="can_focus">False</property>
-                <property name="model">liststore_time</property>
-                <property name="hexpand">True</property>
-                <accessibility>
-                  <relation type="labelled-by" target="label_header_ac"/>
-                  <relation type="labelled-by" target="label7"/>
-                </accessibility>
-              </object>
-              <packing>
-                <property name="left_attach">2</property>
-                <property name="top_attach">1</property>
+                <property name="top_attach">0</property>
+                <property name="width">1</property>
+                <property name="height">1</property>
               </packing>
             </child>
             <child>
-              <object class="GtkLabel" id="label_critical">
+              <object class="GtkLabel" id="suspend_on_ac_label">
                 <property name="visible">True</property>
                 <property name="can_focus">False</property>
-                <property name="halign">end</property>
-                <property name="label" translatable="yes">When power is _critically low</property>
+                <property name="xalign">0</property>
+                <property name="label" translatable="yes">When _Plugged In</property>
                 <property name="use_underline">True</property>
-                <property name="mnemonic_widget">combobox_critical</property>
-              </object>
-              <packing>
-                <property name="left_attach">0</property>
-                <property name="top_attach">2</property>
-              </packing>
-            </child>
-            <child>
-              <object class="GtkComboBox" id="combobox_critical">
-                <property name="visible">True</property>
-                <property name="can_focus">False</property>
-                <property name="model">liststore_critical</property>
+                <property name="mnemonic_widget">suspend_on_ac_switch</property>
               </object>
               <packing>
                 <property name="left_attach">1</property>
-                <property name="top_attach">2</property>
+                <property name="top_attach">1</property>
+                <property name="width">1</property>
+                <property name="height">1</property>
               </packing>
             </child>
-          </object>
-          <packing>
-            <property name="expand">False</property>
-            <property name="fill">False</property>
-            <property name="position">0</property>
-          </packing>
-        </child>
-        <child>
-          <object class="GtkBox" id="box_primary">
-            <property name="visible">True</property>
-            <property name="can_focus">False</property>
-            <property name="margin_left">53</property>
-            <property name="margin_right">60</property>
-            <property name="orientation">vertical</property>
-            <property name="spacing">3</property>
             <child>
-              <object class="GtkBox" id="box_primary_header">
+              <object class="GtkLabel" id="suspend_on_battery_delay_label">
                 <property name="visible">True</property>
                 <property name="can_focus">False</property>
-                <property name="spacing">3</property>
-                <child>
-                  <object class="GtkImage" id="image_primary_warning">
-                    <property name="visible">True</property>
-                    <property name="can_focus">False</property>
-                    <property name="icon_name">dialog-warning-symbolic</property>
-                  </object>
-                  <packing>
-                    <property name="expand">False</property>
-                    <property name="fill">True</property>
-                    <property name="position">0</property>
-                  </packing>
-                </child>
-                <child>
-                  <object class="GtkLabel" id="label_battery_primary">
-                    <property name="visible">True</property>
-                    <property name="can_focus">False</property>
-                    <property name="xalign">0</property>
-                    <property name="label">55 minutes until fully charged</property>
-                  </object>
-                  <packing>
-                    <property name="expand">True</property>
-                    <property name="fill">True</property>
-                    <property name="position">1</property>
-                  </packing>
-                </child>
-                <child>
-                  <object class="GtkBox" id="box_battery_addon">
-                    <property name="visible">True</property>
-                    <property name="can_focus">False</property>
-                    <property name="spacing">3</property>
-                    <child>
-                      <object class="GtkImage" id="image_battery_addon">
-                        <property name="visible">True</property>
-                        <property name="can_focus">False</property>
-                        <property name="xalign">1</property>
-                        <property name="stock">gtk-info</property>
-                      </object>
-                      <packing>
-                        <property name="expand">False</property>
-                        <property name="fill">True</property>
-                        <property name="position">0</property>
-                      </packing>
-                    </child>
-                    <child>
-                      <object class="GtkLabel" id="label_battery_addon">
-                        <property name="visible">True</property>
-                        <property name="can_focus">False</property>
-                        <property name="xalign">1</property>
-                        <property name="label">Your secondary battery is empty</property>
-                      </object>
-                      <packing>
-                        <property name="expand">False</property>
-                        <property name="fill">True</property>
-                        <property name="position">1</property>
-                      </packing>
-                    </child>
-                  </object>
-                  <packing>
-                    <property name="expand">False</property>
-                    <property name="fill">False</property>
-                    <property name="position">2</property>
-                  </packing>
-                </child>
+                <property name="label" translatable="yes">Delay</property>
+                <property name="margin-left">20</property>
+                <style>
+                  <class name="dim-label"/>
+                </style>
               </object>
               <packing>
-                <property name="expand">False</property>
-                <property name="fill">True</property>
-                <property name="position">0</property>
+                <property name="left_attach">2</property>
+                <property name="top_attach">0</property>
+                <property name="width">1</property>
+                <property name="height">1</property>
               </packing>
             </child>
             <child>
-              <object class="GtkLevelBar" id="levelbar_primary">
-                <property name="can_focus">False</property>
+              <object class="GtkLabel" id="suspend_on_ac_delay_label">
                 <property name="visible">True</property>
+                <property name="can_focus">False</property>
+                <property name="label" translatable="yes">Delay</property>
+                <property name="margin-left">20</property>
+                <style>
+                  <class name="dim-label"/>
+                </style>
               </object>
               <packing>
-                <property name="expand">False</property>
-                <property name="fill">True</property>
-                <property name="position">1</property>
+                <property name="left_attach">2</property>
+                <property name="top_attach">1</property>
+                <property name="width">1</property>
+                <property name="height">1</property>
               </packing>
             </child>
-          </object>
-          <packing>
-            <property name="expand">False</property>
-            <property name="fill">False</property>
-            <property name="position">1</property>
-          </packing>
-        </child>
-        <child>
-          <object class="GtkLabel" id="label_screen_settings">
-            <property name="visible">True</property>
-            <property name="can_focus">False</property>
-            <property name="margin_left">53</property>
-            <property name="margin_right">40</property>
-            <property name="xalign">0</property>
-            <property name="yalign">0.49000000953674316</property>
-            <property name="ypad">4</property>
-            <property name="label">Tip: &lt;a href="moo"&gt;Screen Settings&lt;/a&gt; affect how much power is used</property>
-            <property name="use_markup">True</property>
-            <property name="track_visited_links">False</property>
-          </object>
-          <packing>
-            <property name="expand">False</property>
-            <property name="fill">False</property>
-            <property name="position">2</property>
-          </packing>
-        </child>
-        <child>
-          <object class="GtkBox" id="box_secondary">
-            <property name="visible">True</property>
-            <property name="can_focus">False</property>
-            <property name="margin_top">15</property>
-            <property name="orientation">vertical</property>
-            <property name="spacing">24</property>
             <child>
-              <object class="GtkSeparator" id="separator_secondary">
+              <object class="GtkComboBoxText" id="suspend_on_battery_delay_combo">
                 <property name="visible">True</property>
                 <property name="can_focus">False</property>
+                <property name="entry_text_column">0</property>
+                <property name="model">liststore_time</property>
+                <property name="margin_left">4</property>
+                <property name="margin_right">4</property>
               </object>
               <packing>
-                <property name="expand">False</property>
-                <property name="fill">True</property>
-                <property name="position">0</property>
+                <property name="left_attach">3</property>
+                <property name="top_attach">0</property>
+                <property name="width">1</property>
+                <property name="height">1</property>
               </packing>
             </child>
             <child>
-              <object class="GtkGrid" id="grid_secondary">
+              <object class="GtkComboBoxText" id="suspend_on_ac_delay_combo">
                 <property name="visible">True</property>
                 <property name="can_focus">False</property>
-                <property name="margin_left">9</property>
-                <property name="margin_right">28</property>
-                <property name="margin_bottom">15</property>
-                <property name="row_spacing">18</property>
-                <property name="column_spacing">6</property>
-                <property name="column_homogeneous">True</property>
-                <child>
-                  <placeholder/>
-                </child>
-                <child>
-                  <placeholder/>
-                </child>
+                <property name="entry_text_column">0</property>
+                <property name="model">liststore_time</property>
+                <property name="margin_left">4</property>
+                <property name="margin_right">4</property>
               </object>
               <packing>
-                <property name="expand">False</property>
-                <property name="fill">True</property>
-                <property name="position">1</property>
+                <property name="left_attach">3</property>
+                <property name="top_attach">1</property>
+                <property name="width">1</property>
+                <property name="height">1</property>
               </packing>
             </child>
           </object>
           <packing>
             <property name="expand">False</property>
-            <property name="fill">False</property>
-            <property name="position">3</property>
+            <property name="fill">True</property>
+            <property name="position">1</property>
           </packing>
         </child>
       </object>
     </child>
-  </object>
-  <object class="GtkSizeGroup" id="sizegroup_combos">
-    <widgets>
-      <widget name="combobox_critical"/>
-      <widget name="combobox_sleep_battery"/>
-      <widget name="combobox_sleep_ac"/>
-    </widgets>
+    <action-widgets>
+      <action-widget response="0">automatic_suspend_close</action-widget>
+    </action-widgets>
   </object>
 </interface>
+



[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]