[gnome-shell] Status area: introduce battery & power indicator



commit 8b3f05b6e3993aa51a230fd546de17062e7b07ee
Author: Giovanni Campagna <gcampagna src gnome org>
Date:   Mon Nov 15 22:45:17 2010 +0100

    Status area: introduce battery & power indicator
    
    Add an indicator for battery charge and power indication in the
    system status area, using the newly exported DBus API from
    gnome-power-manager.
    
    https://bugzilla.gnome.org/show_bug.cgi?id=622451

 data/theme/gnome-shell.css             |    4 +
 js/Makefile.am                         |    1 +
 js/ui/panel.js                         |    1 +
 js/ui/status/power.js                  |  230 ++++++++++++++++++++++++++++++++
 tools/build/gnome-shell-build-setup.sh |    5 +-
 tools/build/gnome-shell.modules        |   58 ++++++++-
 6 files changed, 294 insertions(+), 5 deletions(-)
---
diff --git a/data/theme/gnome-shell.css b/data/theme/gnome-shell.css
index 4307494..82b8440 100644
--- a/data/theme/gnome-shell.css
+++ b/data/theme/gnome-shell.css
@@ -156,6 +156,10 @@ StTooltip StLabel {
     -slider-handle-radius: 0.5em;
 }
 
+.popup-device-menu-item {
+    spacing: .5em;
+}
+
 .popup-menu-icon {
     icon-size: 1em;
 }
diff --git a/js/Makefile.am b/js/Makefile.am
index eca1726..b7632b4 100644
--- a/js/Makefile.am
+++ b/js/Makefile.am
@@ -43,6 +43,7 @@ nobase_dist_js_DATA = 	\
 	ui/statusIconDispatcher.js	\
 	ui/statusMenu.js	\
 	ui/status/accessibility.js	\
+	ui/status/power.js	\
 	ui/status/volume.js	\
 	ui/telepathyClient.js	\
 	ui/tweener.js		\
diff --git a/js/ui/panel.js b/js/ui/panel.js
index 2866995..690d992 100644
--- a/js/ui/panel.js
+++ b/js/ui/panel.js
@@ -33,6 +33,7 @@ const STANDARD_TRAY_ICON_ORDER = ['a11y', 'display', 'keyboard', 'volume', 'blue
 const STANDARD_TRAY_ICON_SHELL_IMPLEMENTATION = {
     'a11y': imports.ui.status.accessibility.ATIndicator,
     'volume': imports.ui.status.volume.Indicator,
+    'battery': imports.ui.status.power.Indicator
 };
 
 const CLOCK_FORMAT_KEY        = 'format';
diff --git a/js/ui/status/power.js b/js/ui/status/power.js
new file mode 100644
index 0000000..2e02853
--- /dev/null
+++ b/js/ui/status/power.js
@@ -0,0 +1,230 @@
+/* -*- mode: js2; js2-basic-offset: 4; indent-tabs-mode: nil -*- */
+
+const Gio = imports.gi.Gio;
+const GLib = imports.gi.GLib;
+const DBus = imports.dbus;
+const Lang = imports.lang;
+const Mainloop = imports.mainloop;
+const Shell = imports.gi.Shell;
+const St = imports.gi.St;
+
+const PanelMenu = imports.ui.panelMenu;
+const PopupMenu = imports.ui.popupMenu;
+
+const Gettext = imports.gettext.domain('gnome-shell');
+const _ = Gettext.gettext;
+
+const BUS_NAME = 'org.gnome.PowerManager';
+const OBJECT_PATH = '/org/gnome/PowerManager';
+
+const UPDeviceType = {
+    UNKNOWN: 0,
+    AC_POWER: 1,
+    BATTERY: 2,
+    UPS: 3,
+    MONITOR: 4,
+    MOUSE: 5,
+    KEYBOARD: 6,
+    PDA: 7,
+    PHONE: 8
+};
+
+const UPDeviceState = {
+    UNKNOWN: 0,
+    CHARGING: 1,
+    DISCHARGING: 2,
+    EMPTY: 3,
+    FULLY_CHARGED: 4,
+    PENDING_CHARGE: 5,
+    PENDING_DISCHARGE: 6
+};
+
+const PowerManagerInterface = {
+    name: 'org.gnome.PowerManager',
+    methods: [
+        { name: 'GetDevices', inSignature: '', outSignature: 'a(susbut)' },
+        { name: 'GetPrimaryDevice', inSignature: '', outSignature: '(susbut)' },
+        ],
+    signals: [
+        { name: 'Changed', outSignature: '' },
+        ],
+    properties: [
+        { name: 'Icon', signature: 's', access: 'read' },
+        { name: 'Tooltip', signature: 's', access: 'read' },
+        ]
+};
+let PowerManagerProxy = DBus.makeProxyClass(PowerManagerInterface);
+
+function Indicator() {
+    this._init.apply(this, arguments);
+}
+
+Indicator.prototype = {
+    __proto__: PanelMenu.SystemStatusButton.prototype,
+
+    _init: function() {
+        PanelMenu.SystemStatusButton.prototype._init.call(this, 'battery-missing');
+        this._proxy = new PowerManagerProxy(DBus.session, BUS_NAME, OBJECT_PATH);
+
+        this._deviceItems = [ ];
+        this._hasPrimary = false;
+        this._primaryDeviceId = null;
+        this._batteryItem = new PopupMenu.PopupMenuItem('');
+        this.menu.addMenuItem(this._batteryItem);
+        this._deviceSep = new PopupMenu.PopupSeparatorMenuItem();
+        this.menu.addMenuItem(this._deviceSep);
+        this._otherDevicePosition = 2;
+        this.menu.addMenuItem(new PopupMenu.PopupSeparatorMenuItem());
+        this.menu.addAction(_("What's using power..."),function() {
+            GLib.spawn_command_line_async('gnome-power-statistics --device wakeups');
+        });
+        this.menu.addAction(_("Power Settings"),function() {
+            GLib.spawn_command_line_async('gnome-control-center power');
+        });
+
+        this._proxy.connect('Changed', Lang.bind(this, this._devicesChanged));
+        this._devicesChanged();
+    },
+
+    _readPrimaryDevice: function() {
+        this._proxy.GetPrimaryDeviceRemote(Lang.bind(this, function(device, error) {
+            if (error) {
+                this._checkError(error);
+                this._hasPrimary = false;
+                this._primaryDeviceId = null;
+                this._batteryItem.actor.hide();
+                this._deviceSep.actor.hide();
+                return;
+            }
+            let [device_id, device_type, summary, percentage, state, time] = device;
+            if (device_type == UPDeviceType.BATTERY) {
+                this._hasPrimary = true;
+                this._batteryItem.label.text = summary;
+                this._batteryItem.actor.show();
+                if (this._deviceItems.length > 0)
+                    this._deviceSep.actor.show();
+            } else {
+                this._hasPrimary = false;
+                this._batteryItem.actor.hide();
+                this._deviceSep.actor.hide();
+            }
+
+            this._primaryDeviceId = device_id;
+        }));
+    },
+
+    _readOtherDevices: function() {
+        this._proxy.GetDevicesRemote(Lang.bind(this, function(devices, error) {
+            this._deviceItems.forEach(function(i) { i.destroy(); });
+            this._deviceItems = [];
+
+            if (error) {
+                this._checkError(error);
+                this._deviceSep.actor.hide();
+                return;
+            }
+
+            let position = 0;
+            for (let i = 0; i < devices.length; i++) {
+                let [device_id, device_type] = devices[i];
+                if (device_type == UPDeviceType.AC_POWER || device_id == this._primaryDeviceId)
+                    continue;
+
+                let item = new DeviceItem (devices[i]);
+                item.connect('activate', function() {
+                    let p = new Shell.Process({ args: ['gnome-power-statistics', '--device', device_id] });
+                    p.run();
+                });
+                this._deviceItems.push(item);
+                this.menu.addMenuItem(item, this._otherDevicePosition + position);
+                position++;
+            }
+
+            if (this._hasPrimary && position > 0)
+                this._deviceSep.actor.show();
+            else
+                this._deviceSep.actor.hide();
+        }));
+    },
+
+    _devicesChanged: function() {
+        this._proxy.GetRemote('Icon', Lang.bind(this, function(icon, error) {
+            if (icon) {
+                let gicon = Shell.util_icon_from_string (icon);
+                this.setGIcon(gicon);
+                this.actor.show();
+            } else {
+                this._checkError(error);
+                this.menu.close();
+                this.actor.hide();
+            }
+        }));
+        this._proxy.GetRemote('Tooltip', Lang.bind(this, function(tooltip) {
+            this.setTooltip(tooltip);
+        }));
+        this._readPrimaryDevice();
+        this._readOtherDevices();
+    },
+
+    _checkError: function(error) {
+        if (!this._restarted && error && error.message.match(/org\.freedesktop\.DBus\.Error\.(UnknownMethod|InvalidArgs)/)) {
+            GLib.spawn_command_line_sync('pkill -f "^gnome-power-manager$"');
+            GLib.spawn_command_line_async('gnome-power-manager');
+            this._restarted = true;
+        }
+    }
+};
+
+function DeviceItem() {
+    this._init.apply(this, arguments);
+}
+
+DeviceItem.prototype = {
+    __proto__: PopupMenu.PopupBaseMenuItem.prototype,
+
+    _init: function(device) {
+        PopupMenu.PopupBaseMenuItem.prototype._init.call(this);
+
+        let [device_id, device_type, summary, percentage, state, time] = device;
+
+        this._box = new St.BoxLayout({ style_class: 'popup-device-menu-item' });
+        this._label = new St.Label({ text: summary });
+
+        let icon;
+        switch (state) {
+        case UPDeviceState.FULLY_CHARGED:
+            icon = 'battery-full-charged';
+            break;
+        case UPDeviceState.UNKNOWN:
+            icon = 'battery-missing';
+            break;
+        default:
+            icon = this._percentageToIcon(percentage) + (state == UPDeviceState.CHARGING ? '-charging' : '');
+        }
+
+        this._icon = new St.Icon({ icon_name: icon,
+                                   icon_type: St.IconType.SYMBOLIC,
+                                   style_class: 'popup-menu-icon' });
+
+        this._box.add_actor(this._icon);
+        this._box.add_actor(this._label);
+        this.addActor(this._box);
+
+        let percentBin = new St.Bin({ x_align: St.Align.END });
+        let percentLabel = new St.Label({ text: '%d%%'.format(percentage) });
+        percentBin.child = percentLabel;
+        this.addActor(percentBin);
+    },
+
+    _percentageToIcon: function(p) {
+        if (p > 60)
+            return 'battery-full';
+        if (p > 30)
+            return 'battery-good';
+        if (p > 10)
+            return 'battery-low';
+        if (p > 0)
+            return 'battery-caution';
+        return 'battery-empty';
+    }
+}
diff --git a/tools/build/gnome-shell-build-setup.sh b/tools/build/gnome-shell-build-setup.sh
index 3ffa1ae..b5d8564 100755
--- a/tools/build/gnome-shell-build-setup.sh
+++ b/tools/build/gnome-shell-build-setup.sh
@@ -61,7 +61,7 @@ fi
 # libjasper, libjpeg, libpng, libpulse, libtiff, libwnck,
 # libxklavier, libxml2, ORBit2, pam, python, readline,
 # spidermonkey ({mozilla,firefox,xulrunner}-js), startup-notification
-# xdamage, icon-naming-utils, libtool-ltdl, libvorbis
+# xdamage, icon-naming-utils, upower, libtool-ltdl, libvorbis
 #
 # Non-devel packages needed by gnome-shell and its deps:
 # glxinfo, gstreamer-plugins-base, gstreamer-plugins-good,
@@ -117,7 +117,8 @@ if test "x$system" = xFedora ; then
     libXdamage-devel libcroco-devel libxml2-devel gstreamer-devel
     gstreamer-plugins-base gstreamer-plugins-good glx-utils expat-devel
     startup-notification-devel xorg-x11-server-Xephyr gnome-terminal zenity
-    icon-naming-utils libtool-ltdl-devel libvorbis-devel libxklavier-devel
+    icon-naming-utils upower-devel libtool-ltdl-devel libvorbis-devel
+    libxklavier-devel
     "
 
   if expr $version \>= 14 > /dev/null ; then
diff --git a/tools/build/gnome-shell.modules b/tools/build/gnome-shell.modules
index 5010771..044c997 100644
--- a/tools/build/gnome-shell.modules
+++ b/tools/build/gnome-shell.modules
@@ -191,6 +191,59 @@
     </dependencies>
   </autotools>
 
+  <autotools id="gnome-keyring">
+    <branch repo="git.gnome.org" module="gnome-keyring"/>
+    <dependencies>
+       <dep package="glib"/>
+    </dependencies>
+  </autotools>
+
+  <autotools id="libnotify">
+    <branch repo="git.gnome.org" module="libnotify"/>
+    <dependencies>
+      <dep package="gtk3"/>
+    </dependencies>
+  </autotools>
+
+  <autotools id="libgnomekbd">
+    <branch repo="git.gnome.org" module="libgnomekbd"/>
+    <dependencies>
+      <dep package="gtk3"/>
+    </dependencies>
+  </autotools>
+
+  <autotools id="gnome-settings-daemon">
+    <branch repo="git.gnome.org" module="gnome-settings-daemon"/>
+    <dependencies>
+      <dep package="libnotify"/>
+      <dep package="gnome-desktop-3"/>
+    </dependencies>
+  </autotools>
+
+  <autotools id="gnome-control-center">
+    <branch repo="git.gnome.org" module="gnome-control-center"/>
+    <dependencies>
+      <dep package="gtk3"/>
+      <dep package="libcanberra"/>
+      <dep package="gnome-desktop-3"/>
+      <dep package="gnome-settings-daemon"/>
+    </dependencies>
+  </autotools>
+
+  <autotools id="gnome-power-manager">
+    <branch repo="git.gnome.org" module="gnome-power-manager" />
+    <dependencies>
+        <dep package="gtk3"/>
+        <dep package="glib"/>
+        <dep package="gconf"/>
+        <dep package="cairo"/>
+        <dep package="libnotify"/>
+        <dep package="gnome-keyring"/>
+        <dep package="libcanberra"/>
+	<dep package="gnome-control-center"/>
+    </dependencies>
+  </autotools>
+
   <autotools id="gnome-shell">
     <branch repo="git.gnome.org" module="gnome-shell"/>
     <dependencies>
@@ -214,9 +267,7 @@
        change their ~/.jhbuildrc -->
   <metamodule id="gnome-shell-using-gir-repository">
     <dependencies>
-      <dep package="librsvg"/>
-      <dep package="gnome-themes-standard"/>
-      <dep package="gnome-shell"/>
+      <dep package="gnome-shell-full"/>
     </dependencies>
   </metamodule>
 
@@ -225,6 +276,7 @@
       <dep package="librsvg"/>
       <dep package="gnome-themes-standard"/>
       <dep package="gnome-shell"/>
+      <dep package="gnome-power-manager"/>
     </dependencies>
   </metamodule>
 



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