[gnome-control-center] power: Refactor battery row code into a `CcBatteryRow` type



commit f297f544f185b426ec545d2a101f11bd8395db39
Author: Ian Douglas Scott <idscott system76 com>
Date:   Tue Sep 22 11:19:43 2020 -0700

    power: Refactor battery row code into a `CcBatteryRow` type
    
    `set_primary()` and `add_primary()` had a lot of redundant code. This
    unifies them, and moves them to a custom widget called `CcBatteryRow`.
    This also decreases the somewhat excessive size of `cc-power-panel.c`,
    and makes it easier to see the layout of widgets, now that it's
    specified in xml.
    
    Before this, `warning-battery-offset` was set to `0.03` for a "primary"
    battery, and `0.05` otherwise. I expect this is a bug, so I've changed
    both to `0.03`.
    
    No other style or behavior change is intended.

 panels/power/cc-battery-row.c    | 279 ++++++++++++++++++++++++++++++++++
 panels/power/cc-battery-row.h    |  46 ++++++
 panels/power/cc-battery-row.ui   |  98 ++++++++++++
 panels/power/cc-power-panel.c    | 314 ++-------------------------------------
 panels/power/meson.build         |   6 +-
 panels/power/power.gresource.xml |   1 +
 po/POTFILES.in                   |   1 +
 7 files changed, 442 insertions(+), 303 deletions(-)
---
diff --git a/panels/power/cc-battery-row.c b/panels/power/cc-battery-row.c
new file mode 100644
index 000000000..1ecf61f62
--- /dev/null
+++ b/panels/power/cc-battery-row.c
@@ -0,0 +1,279 @@
+/* cc-brightness-scale.c
+ *
+ * Copyright (C) 2010 Red Hat, Inc
+ * Copyright (C) 2008 William Jon McCann <jmccann redhat com>
+ * Copyright (C) 2010,2015 Richard Hughes <richard hughsie com>
+ * Copyright (C) 2020 System76, Inc.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, see <http://www.gnu.org/licenses/>.
+ *
+ * SPDX-License-Identifier: GPL-2.0-or-later
+ */
+
+#include <glib/gi18n.h>
+
+#include "cc-battery-row.h"
+
+struct _CcBatteryRow {
+  GtkListBoxRow parent_instance;
+
+  GtkBox       *battery_box;
+  GtkLabel     *details_label;
+  GtkImage     *icon;
+  GtkLevelBar  *levelbar;
+  GtkLabel     *name_label;
+  GtkLabel     *percentage_label;
+  GtkBox       *primary_bottom_box;
+  GtkLabel     *primary_percentage_label;
+};
+
+G_DEFINE_TYPE (CcBatteryRow, cc_battery_row, GTK_TYPE_LIST_BOX_ROW)
+
+static void
+cc_battery_row_class_init (CcBatteryRowClass *klass)
+{
+  GtkWidgetClass *widget_class = GTK_WIDGET_CLASS (klass);
+
+  gtk_widget_class_set_template_from_resource (widget_class, 
"/org/gnome/control-center/power/cc-battery-row.ui");
+
+  gtk_widget_class_bind_template_child (widget_class, CcBatteryRow, battery_box);
+  gtk_widget_class_bind_template_child (widget_class, CcBatteryRow, details_label);
+  gtk_widget_class_bind_template_child (widget_class, CcBatteryRow, icon);
+  gtk_widget_class_bind_template_child (widget_class, CcBatteryRow, levelbar);
+  gtk_widget_class_bind_template_child (widget_class, CcBatteryRow, name_label);
+  gtk_widget_class_bind_template_child (widget_class, CcBatteryRow, percentage_label);
+  gtk_widget_class_bind_template_child (widget_class, CcBatteryRow, primary_bottom_box);
+  gtk_widget_class_bind_template_child (widget_class, CcBatteryRow, primary_percentage_label);
+}
+
+static void
+cc_battery_row_init (CcBatteryRow *self)
+{
+  gtk_widget_init_template (GTK_WIDGET (self));
+}
+
+static gchar *
+get_timestring (guint64 time_secs)
+{
+  gchar* timestring = NULL;
+  gint  hours;
+  gint  minutes;
+
+  /* Add 0.5 to do rounding */
+  minutes = (int) ( ( time_secs / 60.0 ) + 0.5 );
+
+  if (minutes == 0)
+    return g_strdup (_("Unknown time"));
+
+  if (minutes < 60)
+    return timestring = g_strdup_printf (ngettext ("%i minute",
+                                         "%i minutes",
+                                         minutes), minutes);
+
+  hours = minutes / 60;
+  minutes = minutes % 60;
+
+  if (minutes == 0)
+    return timestring = g_strdup_printf (ngettext (
+                                         "%i hour",
+                                         "%i hours",
+                                         hours), hours);
+
+  /* TRANSLATOR: "%i %s %i %s" are "%i hours %i minutes"
+   * Swap order with "%2$s %2$i %1$s %1$i if needed */
+  return timestring = g_strdup_printf (_("%i %s %i %s"),
+                                       hours, ngettext ("hour", "hours", hours),
+                                       minutes, ngettext ("minute", "minutes", minutes));
+}
+
+static gchar *
+get_details_string (gdouble percentage, UpDeviceState state, guint64 time)
+{
+  g_autofree gchar *details = NULL;
+
+  if (time > 0)
+    {
+      g_autofree gchar *time_string = NULL;
+
+      time_string = get_timestring (time);
+      switch (state)
+        {
+          case UP_DEVICE_STATE_CHARGING:
+            /* TRANSLATORS: %1 is a time string, e.g. "1 hour 5 minutes" */
+            details = g_strdup_printf (_("%s until fully charged"), time_string);
+            break;
+          case UP_DEVICE_STATE_DISCHARGING:
+          case UP_DEVICE_STATE_PENDING_DISCHARGE:
+            if (percentage < 20)
+              {
+                /* TRANSLATORS: %1 is a time string, e.g. "1 hour 5 minutes" */
+                details = g_strdup_printf (_("Caution: %s remaining"), time_string);
+              }
+            else
+              {
+                /* TRANSLATORS: %1 is a time string, e.g. "1 hour 5 minutes" */
+                details = g_strdup_printf (_("%s remaining"), time_string);
+              }
+            break;
+          case UP_DEVICE_STATE_FULLY_CHARGED:
+            /* TRANSLATORS: primary battery */
+            details = g_strdup (_("Fully charged"));
+            break;
+          case UP_DEVICE_STATE_PENDING_CHARGE:
+            /* TRANSLATORS: primary battery */
+            details = g_strdup (_("Not charging"));
+            break;
+          case UP_DEVICE_STATE_EMPTY:
+            /* TRANSLATORS: primary battery */
+            details = g_strdup (_("Empty"));
+            break;
+          default:
+            details = g_strdup_printf ("error: %s", up_device_state_to_string (state));
+            break;
+        }
+    }
+  else
+    {
+      switch (state)
+        {
+          case UP_DEVICE_STATE_CHARGING:
+            /* TRANSLATORS: primary battery */
+            details = g_strdup (_("Charging"));
+            break;
+          case UP_DEVICE_STATE_DISCHARGING:
+          case UP_DEVICE_STATE_PENDING_DISCHARGE:
+            /* TRANSLATORS: primary battery */
+            details = g_strdup (_("Discharging"));
+            break;
+          case UP_DEVICE_STATE_FULLY_CHARGED:
+            /* TRANSLATORS: primary battery */
+            details = g_strdup (_("Fully charged"));
+            break;
+          case UP_DEVICE_STATE_PENDING_CHARGE:
+            /* TRANSLATORS: primary battery */
+            details = g_strdup (_("Not charging"));
+            break;
+          case UP_DEVICE_STATE_EMPTY:
+            /* TRANSLATORS: primary battery */
+            details = g_strdup (_("Empty"));
+            break;
+          default:
+            details = g_strdup_printf ("error: %s",
+                                       up_device_state_to_string (state));
+            break;
+        }
+    }
+
+  return g_steal_pointer (&details);
+}
+
+CcBatteryRow*
+cc_battery_row_new (UpDevice *device,
+                    gboolean  primary)
+{
+  g_autofree gchar *details = NULL;
+  gdouble percentage;
+  UpDeviceKind kind;
+  UpDeviceState state;
+  g_autofree gchar *s = NULL;
+  g_autofree gchar *icon_name = NULL;
+  const gchar *name;
+  CcBatteryRow *self;
+  guint64 time_empty, time_full, time;
+  gdouble energy_full, energy_rate;
+
+  self = g_object_new (CC_TYPE_BATTERY_ROW, NULL);
+
+  g_object_get (device,
+                "kind", &kind,
+                "state", &state,
+                "percentage", &percentage,
+                "icon-name", &icon_name,
+                "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;
+
+  /* Name label */
+  if (g_object_get_data (G_OBJECT (device), "is-main-battery") != NULL)
+    name = C_("Battery name", "Main");
+  else
+    name = C_("Battery name", "Extra");
+  gtk_label_set_text (self->name_label, name);
+
+  /* Icon */
+  if (icon_name != NULL && *icon_name != '\0')
+    gtk_image_set_from_icon_name (self->icon, icon_name, GTK_ICON_SIZE_BUTTON);
+
+  /* Percentage label */
+  s = g_strdup_printf ("%d%%", (int)percentage);
+  gtk_label_set_text (self->percentage_label, s);
+  gtk_label_set_text (self->primary_percentage_label, s);
+
+  /* Level bar */
+  gtk_level_bar_set_value (self->levelbar, percentage / 100.0);
+
+  /* Details label (primary only) */
+  details = get_details_string (percentage, state, time);
+  gtk_label_set_text (self->details_label, details);
+
+  /* Handle "primary" row differently */
+  gtk_widget_set_visible (GTK_WIDGET (self->battery_box), !primary);
+  gtk_widget_set_visible (GTK_WIDGET (self->percentage_label), !primary);
+  gtk_widget_set_visible (GTK_WIDGET (self->primary_bottom_box), primary);
+  atk_object_add_relationship (gtk_widget_get_accessible (GTK_WIDGET (self->levelbar)),
+                               ATK_RELATION_LABELLED_BY,
+                               gtk_widget_get_accessible (GTK_WIDGET (primary ? 
self->primary_percentage_label
+                                                                              : self->percentage_label)));
+  g_object_set_data (G_OBJECT (self), "primary", GINT_TO_POINTER (primary));
+
+  g_object_set_data (G_OBJECT (self), "kind", GINT_TO_POINTER (kind));
+
+  return self;
+}
+
+
+
+void
+cc_battery_row_set_level_sizegroup (CcBatteryRow *self,
+                                    GtkSizeGroup *sizegroup)
+{
+  gtk_size_group_add_widget (sizegroup, GTK_WIDGET (self->levelbar));
+}
+
+void
+cc_battery_row_set_row_sizegroup (CcBatteryRow *self,
+                                  GtkSizeGroup *sizegroup)
+{
+  gtk_size_group_add_widget (sizegroup, GTK_WIDGET (self));
+}
+
+void
+cc_battery_row_set_charge_sizegroup (CcBatteryRow *self,
+                                     GtkSizeGroup *sizegroup)
+{
+  gtk_size_group_add_widget (sizegroup, GTK_WIDGET (self->percentage_label));
+}
+
+void
+cc_battery_row_set_battery_sizegroup (CcBatteryRow *self,
+                                      GtkSizeGroup *sizegroup)
+{
+  gtk_size_group_add_widget (sizegroup, GTK_WIDGET (self->battery_box));
+}
\ No newline at end of file
diff --git a/panels/power/cc-battery-row.h b/panels/power/cc-battery-row.h
new file mode 100644
index 000000000..a4c27b629
--- /dev/null
+++ b/panels/power/cc-battery-row.h
@@ -0,0 +1,46 @@
+/* cc-brightness-scale.h
+ *
+ * Copyright (C) 2020 System76, Inc.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, see <http://www.gnu.org/licenses/>.
+ *
+ * SPDX-License-Identifier: GPL-2.0-or-later
+ */
+
+#pragma once
+
+#include <gtk/gtk.h>
+#include <libupower-glib/upower.h>
+
+G_BEGIN_DECLS
+
+#define CC_TYPE_BATTERY_ROW (cc_battery_row_get_type())
+G_DECLARE_FINAL_TYPE (CcBatteryRow, cc_battery_row, CC, BATTERY_ROW, GtkListBoxRow)
+
+CcBatteryRow* cc_battery_row_new                    (UpDevice *device,
+                                                     gboolean  primary);
+
+void          cc_battery_row_set_level_sizegroup     (CcBatteryRow *self,
+                                                      GtkSizeGroup *sizegroup);
+
+void          cc_battery_row_set_row_sizegroup       (CcBatteryRow *self,
+                                                      GtkSizeGroup *sizegroup);
+
+void          cc_battery_row_set_charge_sizegroup    (CcBatteryRow *self,
+                                                      GtkSizeGroup *sizegroup);
+
+void          cc_battery_row_set_battery_sizegroup   (CcBatteryRow *self,
+                                                      GtkSizeGroup *sizegroup);
+
+G_END_DECLS
\ No newline at end of file
diff --git a/panels/power/cc-battery-row.ui b/panels/power/cc-battery-row.ui
new file mode 100644
index 000000000..932e5d39f
--- /dev/null
+++ b/panels/power/cc-battery-row.ui
@@ -0,0 +1,98 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<interface>
+  <!-- interface-requires gtk+ 3.0 -->
+  <template class="CcBatteryRow" parent="GtkListBoxRow">
+    <property name="visible">True</property>
+    <property name="selectable">False</property>
+    <property name="activatable">False</property>
+    <child>
+      <object class="GtkBox">
+        <property name="visible">True</property>
+        <property name="orientation">vertical</property>
+        <property name="valign">center</property>
+        <property name="margin-start">12</property>
+        <property name="margin-end">12</property>
+        <property name="margin-top">16</property>
+        <property name="margin-bottom">14</property>
+        <property name="spacing">10</property>
+        <child>
+          <object class="GtkBox">
+            <property name="visible">True</property>
+            <property name="orientation">horizontal</property>
+            <property name="spacing">12</property>
+            <child>
+              <object class="GtkBox" id="battery_box">
+                <property name="visible">True</property>
+                <property name="orientation">horizontal</property>
+                <property name="spacing">12</property>
+                <child>
+                  <object class="GtkLabel" id="name_label">
+                    <property name="visible">True</property>
+                  </object>
+                </child>
+                <child>
+                  <object class="GtkImage" id="icon">
+                    <property name="visible">True</property>
+                    <property name="halign">end</property>
+                    <property name="valign">center</property>
+                    <style>
+                      <class name="dim-label"/>
+                    </style>
+                  </object>
+                  <packing>
+                    <property name="pack-type">end</property>
+                  </packing>
+                </child>
+              </object>
+            </child>
+            <child>
+              <object class="GtkLabel" id="percentage_label">
+                <property name="visible">True</property>
+                    <property name="halign">end</property>
+                    <style>
+                      <class name="dim-label"/>
+                    </style>
+              </object>
+            </child>
+            <child>
+              <object class="GtkLevelBar" id="levelbar">
+                <property name="visible">True</property>
+                <property name="hexpand">True</property>
+                <property name="halign">fill</property>
+                <property name="valign">center</property>
+                <offsets>
+                  <offset name="warning-battery-offset" value="0.03"/>
+                  <offset name="low-battery-offset" value="0.1"/>
+                  <offset name="high-battery-offset" value="1.0"/>
+                </offsets>
+              </object>
+              <packing>
+                <property name="expand">True</property>
+              </packing>
+            </child>
+          </object>
+        </child>
+        <child>
+          <object class="GtkBox" id="primary_bottom_box">
+            <property name="visible">True</property>
+            <property name="orientation">horizontal</property>
+            <child>
+              <object class="GtkLabel" id="details_label">
+                <property name="visible">True</property>
+              </object>
+            </child>
+            <child>
+              <object class="GtkLabel" id="primary_percentage_label">
+                <property name="visible">True</property>
+              </object>
+              <packing>
+                <property name="pack-type">end</property>
+              </packing>
+            </child>
+          </object>
+        </child>
+      </object>
+    </child>
+  </template>
+</interface>
+
diff --git a/panels/power/cc-power-panel.c b/panels/power/cc-power-panel.c
index ec4d2e842..6398f455e 100644
--- a/panels/power/cc-power-panel.c
+++ b/panels/power/cc-power-panel.c
@@ -31,6 +31,7 @@
 
 #include "shell/cc-object-storage.h"
 #include "list-box-helper.h"
+#include "cc-battery-row.h"
 #include "cc-brightness-scale.h"
 #include "cc-power-panel.h"
 #include "cc-power-resources.h"
@@ -316,131 +317,6 @@ get_chassis_type (GCancellable *cancellable)
   return g_variant_dup_string (inner, NULL);
 }
 
-static gchar *
-get_timestring (guint64 time_secs)
-{
-  gchar* timestring = NULL;
-  gint  hours;
-  gint  minutes;
-
-  /* Add 0.5 to do rounding */
-  minutes = (int) ( ( time_secs / 60.0 ) + 0.5 );
-
-  if (minutes == 0)
-    {
-      timestring = g_strdup (_("Unknown time"));
-      return timestring;
-    }
-
-  if (minutes < 60)
-    {
-      timestring = g_strdup_printf (ngettext ("%i minute",
-                                    "%i minutes",
-                                    minutes), minutes);
-      return timestring;
-    }
-
-  hours = minutes / 60;
-  minutes = minutes % 60;
-
-  if (minutes == 0)
-    {
-      timestring = g_strdup_printf (ngettext (
-                                    "%i hour",
-                                    "%i hours",
-                                    hours), hours);
-      return timestring;
-    }
-
-  /* TRANSLATOR: "%i %s %i %s" are "%i hours %i minutes"
-   * Swap order with "%2$s %2$i %1$s %1$i if needed */
-  timestring = g_strdup_printf (_("%i %s %i %s"),
-                                hours, ngettext ("hour", "hours", hours),
-                                minutes, ngettext ("minute", "minutes", minutes));
-  return timestring;
-}
-
-static gchar *
-get_details_string (gdouble percentage, UpDeviceState state, guint64 time)
-{
-  gchar *details;
-
-  if (time > 0)
-    {
-      g_autofree gchar *time_string = NULL;
-
-      time_string = get_timestring (time);
-      switch (state)
-        {
-          case UP_DEVICE_STATE_CHARGING:
-            /* TRANSLATORS: %1 is a time string, e.g. "1 hour 5 minutes" */
-            details = g_strdup_printf (_("%s until fully charged"), time_string);
-            break;
-          case UP_DEVICE_STATE_DISCHARGING:
-          case UP_DEVICE_STATE_PENDING_DISCHARGE:
-            if (percentage < 20)
-              {
-                /* TRANSLATORS: %1 is a time string, e.g. "1 hour 5 minutes" */
-                details = g_strdup_printf (_("Caution: %s remaining"), time_string);
-              }
-            else
-              {
-                /* TRANSLATORS: %1 is a time string, e.g. "1 hour 5 minutes" */
-                details = g_strdup_printf (_("%s remaining"), time_string);
-              }
-            break;
-          case UP_DEVICE_STATE_FULLY_CHARGED:
-            /* TRANSLATORS: primary battery */
-            details = g_strdup (_("Fully charged"));
-            break;
-          case UP_DEVICE_STATE_PENDING_CHARGE:
-            /* TRANSLATORS: primary battery */
-            details = g_strdup (_("Not charging"));
-            break;
-          case UP_DEVICE_STATE_EMPTY:
-            /* TRANSLATORS: primary battery */
-            details = g_strdup (_("Empty"));
-            break;
-          default:
-            details = g_strdup_printf ("error: %s", up_device_state_to_string (state));
-            break;
-        }
-    }
-  else
-    {
-      switch (state)
-        {
-          case UP_DEVICE_STATE_CHARGING:
-            /* TRANSLATORS: primary battery */
-            details = g_strdup (_("Charging"));
-            break;
-          case UP_DEVICE_STATE_DISCHARGING:
-          case UP_DEVICE_STATE_PENDING_DISCHARGE:
-            /* TRANSLATORS: primary battery */
-            details = g_strdup (_("Discharging"));
-            break;
-          case UP_DEVICE_STATE_FULLY_CHARGED:
-            /* TRANSLATORS: primary battery */
-            details = g_strdup (_("Fully charged"));
-            break;
-          case UP_DEVICE_STATE_PENDING_CHARGE:
-            /* TRANSLATORS: primary battery */
-            details = g_strdup (_("Not charging"));
-            break;
-          case UP_DEVICE_STATE_EMPTY:
-            /* TRANSLATORS: primary battery */
-            details = g_strdup (_("Empty"));
-            break;
-          default:
-            details = g_strdup_printf ("error: %s",
-                                       up_device_state_to_string (state));
-            break;
-        }
-    }
-
-  return details;
-}
-
 static void
 load_custom_css (CcPowerPanel *self)
 {
@@ -455,181 +331,15 @@ load_custom_css (CcPowerPanel *self)
 }
 
 static void
-set_primary (CcPowerPanel *panel, UpDevice *device)
+add_battery (CcPowerPanel *panel, UpDevice *device, gboolean primary)
 {
-  g_autofree gchar *details = NULL;
-  gdouble percentage;
-  guint64 time_empty, time_full, time;
-  UpDeviceState state;
-  GtkWidget *box, *box2, *label;
-  GtkWidget *levelbar, *row;
-  g_autofree gchar *s = NULL;
-  gdouble energy_full, energy_rate;
-
-  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;
-
-  /* Sometimes the reported state is fully charged but battery is at 99%,
-     refusing to reach 100%. In these cases, just assume 100%. */
-  if (state == UP_DEVICE_STATE_FULLY_CHARGED && (100.0 - percentage <= 1.0))
-    percentage = 100.0;
-
-  details = get_details_string (percentage, state, time);
-
-  row = no_prelight_row_new ();
-  gtk_widget_show (row);
-  box = gtk_box_new (GTK_ORIENTATION_VERTICAL, 10);
-  gtk_widget_show (box);
-  gtk_container_add (GTK_CONTAINER (row), box);
-
-  gtk_widget_set_margin_start (box, 12);
-  gtk_widget_set_margin_end (box, 12);
-  gtk_widget_set_margin_top (box, 16);
-  gtk_widget_set_margin_bottom (box, 14);
-
-  levelbar = gtk_level_bar_new ();
-  gtk_widget_show (levelbar);
-  gtk_level_bar_set_value (GTK_LEVEL_BAR (levelbar), percentage / 100.0);
-  gtk_level_bar_add_offset_value (GTK_LEVEL_BAR (levelbar), "warning-battery-offset", 0.03);
-  gtk_level_bar_add_offset_value (GTK_LEVEL_BAR (levelbar), "low-battery-offset", 0.1);
-  gtk_level_bar_add_offset_value (GTK_LEVEL_BAR (levelbar), "high-battery-offset", 1.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, 12);
-  gtk_widget_show (box2);
-  gtk_box_pack_start (GTK_BOX (box), box2, FALSE, TRUE, 0);
-
-  label = gtk_label_new (details);
-  gtk_widget_show (label);
-  gtk_widget_set_halign (label, GTK_ALIGN_START);
-  gtk_label_set_ellipsize (GTK_LABEL (label), PANGO_ELLIPSIZE_END);
-  gtk_label_set_xalign (GTK_LABEL (label), 0.0);
-  gtk_box_pack_start (GTK_BOX (box2), label, TRUE, TRUE, 0);
-
-  s = g_strdup_printf ("%d%%", (int)(percentage + 0.5));
-  label = gtk_label_new (s);
-  gtk_widget_show (label);
-  gtk_widget_set_halign (label, GTK_ALIGN_END);
-  gtk_style_context_add_class (gtk_widget_get_style_context (label), GTK_STYLE_CLASS_DIM_LABEL);
-  gtk_box_pack_start (GTK_BOX (box2), label, FALSE, TRUE, 0);
-
-  atk_object_add_relationship (gtk_widget_get_accessible (levelbar),
-                               ATK_RELATION_LABELLED_BY,
-                               gtk_widget_get_accessible (label));
-
-  gtk_container_add (GTK_CONTAINER (panel->battery_list), row);
-  gtk_size_group_add_widget (panel->battery_row_sizegroup, row);
-
-  g_object_set_data (G_OBJECT (row), "primary", GINT_TO_POINTER (TRUE));
-
-  gtk_widget_set_visible (panel->battery_section, TRUE);
-}
-
-static void
-add_battery (CcPowerPanel *panel, UpDevice *device)
-{
-  gdouble percentage;
-  UpDeviceKind kind;
-  UpDeviceState state;
-  GtkWidget *row;
-  GtkWidget *box;
-  GtkWidget *box2;
-  GtkWidget *label;
-  GtkWidget *title;
-  GtkWidget *levelbar;
-  GtkWidget *widget;
-  g_autofree gchar *s = NULL;
-  g_autofree gchar *icon_name = NULL;
-  const gchar *name;
-
-  g_object_get (device,
-                "kind", &kind,
-                "state", &state,
-                "percentage", &percentage,
-                "icon-name", &icon_name,
-                NULL);
-
-  if (g_object_get_data (G_OBJECT (device), "is-main-battery") != NULL)
-    name = C_("Battery name", "Main");
-  else
-    name = C_("Battery name", "Extra");
-
-  row = no_prelight_row_new ();
-  gtk_widget_show (row);
-  box = row_box_new ();
-  gtk_box_set_spacing (GTK_BOX (box), 10);
-  gtk_container_add (GTK_CONTAINER (row), box);
-
-  gtk_widget_set_margin_start (box, 12);
-  gtk_widget_set_margin_end (box, 12);
-  gtk_widget_set_margin_top (box, 16);
-  gtk_widget_set_margin_bottom (box, 14);
-
-  box2 = gtk_box_new (GTK_ORIENTATION_HORIZONTAL, 12);
-  gtk_widget_show (box2);
-  title = row_title_new (name, NULL, NULL);
-  gtk_size_group_add_widget (panel->battery_sizegroup, box2);
-  gtk_box_pack_start (GTK_BOX (box2), title, FALSE, TRUE, 0);
-  gtk_box_pack_start (GTK_BOX (box), box2, FALSE, TRUE, 0);
-
-#if 1
-  if (icon_name != NULL && *icon_name != '\0')
-    {
-      widget = gtk_image_new_from_icon_name (icon_name, GTK_ICON_SIZE_BUTTON);
-      gtk_widget_show (widget);
-      gtk_style_context_add_class (gtk_widget_get_style_context (widget), GTK_STYLE_CLASS_DIM_LABEL);
-      gtk_widget_set_halign (widget, GTK_ALIGN_END);
-      gtk_widget_set_valign (widget, GTK_ALIGN_CENTER);
-      gtk_box_pack_start (GTK_BOX (box2), widget, TRUE, TRUE, 0);
-    }
-#endif
-
-  box2 = gtk_box_new (GTK_ORIENTATION_HORIZONTAL, 12);
-  gtk_widget_show (box2);
-
-  s = g_strdup_printf ("%d%%", (int)percentage);
-  label = gtk_label_new (s);
-  gtk_widget_show (label);
-  gtk_widget_set_halign (label, GTK_ALIGN_END);
-  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 (panel->charge_sizegroup, label);
-
-  levelbar = gtk_level_bar_new ();
-  gtk_widget_show (levelbar);
-  gtk_level_bar_set_value (GTK_LEVEL_BAR (levelbar), percentage / 100.0);
-  gtk_level_bar_add_offset_value (GTK_LEVEL_BAR (levelbar), "warning-battery-offset", 0.05);
-  gtk_level_bar_add_offset_value (GTK_LEVEL_BAR (levelbar), "low-battery-offset", 0.1);
-  gtk_level_bar_add_offset_value (GTK_LEVEL_BAR (levelbar), "high-battery-offset", 1.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 (panel->level_sizegroup, levelbar);
-  gtk_box_pack_start (GTK_BOX (box), box2, TRUE, TRUE, 0);
-
-  atk_object_add_relationship (gtk_widget_get_accessible (levelbar),
-                               ATK_RELATION_LABELLED_BY,
-                               gtk_widget_get_accessible (label));
-
-
-  g_object_set_data (G_OBJECT (row), "kind", GINT_TO_POINTER (kind));
-  gtk_container_add (GTK_CONTAINER (panel->battery_list), row);
-  gtk_size_group_add_widget (panel->battery_row_sizegroup, row);
+  CcBatteryRow *row = cc_battery_row_new (device, primary);
+  cc_battery_row_set_level_sizegroup (row, panel->level_sizegroup);
+  cc_battery_row_set_row_sizegroup (row, panel->battery_row_sizegroup);
+  cc_battery_row_set_charge_sizegroup (row, panel->charge_sizegroup);
+  cc_battery_row_set_battery_sizegroup (row, panel->battery_sizegroup);
 
+  gtk_container_add (GTK_CONTAINER (panel->battery_list), GTK_WIDGET (row));
   gtk_widget_set_visible (panel->battery_section, TRUE);
 }
 
@@ -963,7 +673,7 @@ up_client_changed (CcPowerPanel *self)
   gtk_label_set_label (GTK_LABEL (self->battery_heading), s);
 
   if (!on_ups && n_batteries > 1)
-    set_primary (self, composite);
+    add_battery (self, composite, TRUE);
 
   for (i = 0; self->devices != NULL && i < self->devices->len; i++)
     {
@@ -979,15 +689,15 @@ up_client_changed (CcPowerPanel *self)
         }
       else if (kind == UP_DEVICE_KIND_UPS && on_ups)
         {
-          set_primary (self, device);
+          add_battery (self, device, TRUE);
         }
       else if (kind == UP_DEVICE_KIND_BATTERY && is_power_supply && !on_ups && n_batteries == 1)
         {
-          set_primary (self, device);
+          add_battery (self, device, TRUE);
         }
       else if (kind == UP_DEVICE_KIND_BATTERY && is_power_supply)
         {
-          add_battery (self, device);
+          add_battery (self, device, FALSE);
         }
       else
         {
diff --git a/panels/power/meson.build b/panels/power/meson.build
index 1700c91e8..45ff95d3d 100644
--- a/panels/power/meson.build
+++ b/panels/power/meson.build
@@ -18,6 +18,7 @@ i18n.merge_file(
 )
 
 sources = files(
+  'cc-battery-row.c',
   'cc-brightness-scale.c',
   'cc-power-panel.c'
 )
@@ -26,7 +27,10 @@ sources += gnome.mkenums_simple(
   'cc-brightness-scale-types',
   sources: ['cc-brightness-scale.h'])
 
-resource_data = files('cc-power-panel.ui')
+resource_data = files(
+  'cc-battery-row.ui',
+  'cc-power-panel.ui'
+)
 
 sources += gnome.compile_resources(
   'cc-' + cappletname + '-resources',
diff --git a/panels/power/power.gresource.xml b/panels/power/power.gresource.xml
index f0bcb1a62..3b0fed18c 100644
--- a/panels/power/power.gresource.xml
+++ b/panels/power/power.gresource.xml
@@ -1,6 +1,7 @@
 <?xml version="1.0" encoding="UTF-8"?>
 <gresources>
   <gresource prefix="/org/gnome/control-center/power">
+    <file preprocess="xml-stripblanks">cc-battery-row.ui</file>
     <file preprocess="xml-stripblanks">cc-power-panel.ui</file>
     <file>battery-levels.css</file>
   </gresource>
diff --git a/po/POTFILES.in b/po/POTFILES.in
index 8873e50bf..bfe941869 100644
--- a/po/POTFILES.in
+++ b/po/POTFILES.in
@@ -149,6 +149,7 @@ panels/notifications/gnome-notifications-panel.desktop.in.in
 panels/online-accounts/cc-online-accounts-panel.c
 panels/online-accounts/gnome-online-accounts-panel.desktop.in.in
 panels/online-accounts/online-accounts.ui
+panels/power/cc-battery-row.c
 panels/power/cc-power-panel.c
 panels/power/cc-power-panel.ui
 panels/power/gnome-power-panel.desktop.in.in


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