[gnome-shell] status/power: Port to quick settings



commit 80d1f68c77bb10673868ce8b149094a0da480ac5
Author: Florian Müllner <fmuellner gnome org>
Date:   Sat Jul 30 16:52:39 2022 +0200

    status/power: Port to quick settings
    
    The power indicator should not be a regular quick toggle, but
    instead be part of a "system area" row at the top of the menu.
    
    But as in the end it is still a simple button, we can do the
    port to quick settings now, and move it later when the system
    row is implemented.
    
    Part-of: <https://gitlab.gnome.org/GNOME/gnome-shell/-/merge_requests/2392>

 js/ui/panel.js        |   7 +-
 js/ui/status/power.js | 183 ++++++++++++++++++++++++--------------------------
 2 files changed, 90 insertions(+), 100 deletions(-)
---
diff --git a/js/ui/panel.js b/js/ui/panel.js
index 614f71606b..0b0c50153c 100644
--- a/js/ui/panel.js
+++ b/js/ui/panel.js
@@ -378,7 +378,6 @@ class AggregateMenu extends PanelMenu.Button {
         else
             this._network = null;
 
-        this._power = new imports.ui.status.power.Indicator();
         this._powerProfiles = new imports.ui.status.powerProfiles.Indicator();
         this._volume = new imports.ui.status.volume.Indicator();
         this._brightness = new imports.ui.status.brightness.Indicator();
@@ -387,7 +386,6 @@ class AggregateMenu extends PanelMenu.Button {
         if (this._network)
             this._indicators.add_child(this._network);
         this._indicators.add_child(this._volume);
-        this._indicators.add_child(this._power);
         this._indicators.add_child(this._powerProfiles);
 
         this.menu.addMenuItem(this._volume.menu);
@@ -396,12 +394,10 @@ class AggregateMenu extends PanelMenu.Button {
         if (this._network)
             this.menu.addMenuItem(this._network.menu);
 
-        this.menu.addMenuItem(this._power.menu);
         this.menu.addMenuItem(this._powerProfiles.menu);
         this.menu.addMenuItem(new PopupMenu.PopupSeparatorMenuItem());
         this.menu.addMenuItem(this._system.menu);
 
-        menuLayout.addSizeChild(this._power.menu.actor);
         menuLayout.addSizeChild(this._powerProfiles.menu.actor);
         menuLayout.addSizeChild(this._system.menu.actor);
     }
@@ -430,6 +426,7 @@ class QuickSettings extends PanelMenu.Button {
         this._nightLight = new imports.ui.status.nightLight.Indicator();
         this._rfkill = new imports.ui.status.rfkill.Indicator();
         this._unsafeMode = new UnsafeModeIndicator();
+        this._power = new imports.ui.status.power.Indicator();
 
         this._indicators.add_child(this._remoteAccess);
         this._indicators.add_child(this._thunderbolt);
@@ -439,6 +436,7 @@ class QuickSettings extends PanelMenu.Button {
             this._indicators.add_child(this._bluetooth);
         this._indicators.add_child(this._rfkill);
         this._indicators.add_child(this._unsafeMode);
+        this._indicators.add_child(this._power);
 
         this._addItems(this._remoteAccess.quickSettingsItems);
         this._addItems(this._thunderbolt.quickSettingsItems);
@@ -448,6 +446,7 @@ class QuickSettings extends PanelMenu.Button {
         this._addItems(this._nightLight.quickSettingsItems);
         this._addItems(this._rfkill.quickSettingsItems);
         this._addItems(this._unsafeMode.quickSettingsItems);
+        this._addItems(this._power.quickSettingsItems);
     }
 
     _addItems(items, colSpan = 1) {
diff --git a/js/ui/status/power.js b/js/ui/status/power.js
index 5d23006f59..de363d0ce0 100644
--- a/js/ui/status/power.js
+++ b/js/ui/status/power.js
@@ -1,13 +1,12 @@
 // -*- mode: js; js-indent-level: 4; indent-tabs-mode: nil -*-
 /* exported Indicator */
 
-const { Clutter, Gio, GObject, St, UPowerGlib: UPower } = imports.gi;
+const {Atk, Clutter, Gio, GObject, Shell, St, UPowerGlib: UPower} = imports.gi;
 
 const Main = imports.ui.main;
-const PanelMenu = imports.ui.panelMenu;
-const PopupMenu = imports.ui.popupMenu;
+const {QuickToggle, SystemIndicator} = imports.ui.quickSettings;
 
-const { loadInterfaceXML } = imports.misc.fileUtils;
+const {loadInterfaceXML} = imports.misc.fileUtils;
 
 const BUS_NAME = 'org.freedesktop.UPower';
 const OBJECT_PATH = '/org/freedesktop/UPower/devices/DisplayDevice';
@@ -15,106 +14,54 @@ const OBJECT_PATH = '/org/freedesktop/UPower/devices/DisplayDevice';
 const DisplayDeviceInterface = loadInterfaceXML('org.freedesktop.UPower.Device');
 const PowerManagerProxy = Gio.DBusProxy.makeProxyWrapper(DisplayDeviceInterface);
 
-const SHOW_BATTERY_PERCENTAGE       = 'show-battery-percentage';
+const SHOW_BATTERY_PERCENTAGE = 'show-battery-percentage';
 
-var Indicator = GObject.registerClass(
-class Indicator extends PanelMenu.SystemIndicator {
+const PowerToggle = GObject.registerClass({
+    Properties: {
+        'fallback-icon-name': GObject.ParamSpec.string('fallback-icon-name', '', '',
+            GObject.ParamFlags.READWRITE,
+            ''),
+    },
+}, class PowerToggle extends QuickToggle {
     _init() {
-        super._init();
-
-        this._desktopSettings = new Gio.Settings({
-            schema_id: 'org.gnome.desktop.interface',
+        super._init({
+            accessible_role: Atk.Role.PUSH_BUTTON,
         });
-        this._desktopSettings.connect(
-            `changed::${SHOW_BATTERY_PERCENTAGE}`, this._sync.bind(this));
-
-        this._indicator = this._addIndicator();
-        this._percentageLabel = new St.Label({
-            y_expand: true,
-            y_align: Clutter.ActorAlign.CENTER,
-        });
-        this.add_child(this._percentageLabel);
-        this.add_style_class_name('power-status');
 
         this._proxy = new PowerManagerProxy(Gio.DBus.system, BUS_NAME, OBJECT_PATH,
             (proxy, error) => {
-                if (error) {
-                    log(error.message);
-                } else {
-                    this._proxy.connect('g-properties-changed',
-                        this._sync.bind(this));
-                }
+                if (error)
+                    console.error(error.message);
+                else
+                    this._proxy.connect('g-properties-changed', () => this._sync());
                 this._sync();
             });
 
-        this._item = new PopupMenu.PopupSubMenuMenuItem('', true);
-        this._item.menu.addSettingsAction(_('Power Settings'),
-            'gnome-power-panel.desktop');
-        this.menu.addMenuItem(this._item);
+        this.bind_property('fallback-icon-name',
+            this._icon, 'fallback-icon-name',
+            GObject.BindingFlags.SYNC_CREATE);
+
+        this.connect('clicked', () => {
+            const app = Shell.AppSystem.get_default().lookup_app('gnome-power-panel.desktop');
+            Main.overview.hide();
+            Main.panel.closeQuickSettings();
+            app.activate();
+        });
 
-        Main.sessionMode.connect('updated', this._sessionUpdated.bind(this));
+        Main.sessionMode.connect('updated', () => this._sessionUpdated());
         this._sessionUpdated();
+        this._sync();
     }
 
     _sessionUpdated() {
-        let sensitive = !Main.sessionMode.isLocked && !Main.sessionMode.isGreeter;
-        this.menu.setSensitive(sensitive);
-    }
-
-    _getStatus() {
-        let seconds = 0;
-
-        if (this._proxy.State === UPower.DeviceState.FULLY_CHARGED)
-            return _('Fully Charged');
-        else if (this._proxy.State === UPower.DeviceState.CHARGING)
-            seconds = this._proxy.TimeToFull;
-        else if (this._proxy.State === UPower.DeviceState.DISCHARGING)
-            seconds = this._proxy.TimeToEmpty;
-        else if (this._proxy.State === UPower.DeviceState.PENDING_CHARGE)
-            return _('Not Charging');
-        // state is PENDING_DISCHARGE
-        else
-            return _('Estimating…');
-
-        let time = Math.round(seconds / 60);
-        if (time === 0) {
-            // 0 is reported when UPower does not have enough data
-            // to estimate battery life
-            return _('Estimating…');
-        }
-
-        let minutes = time % 60;
-        let hours = Math.floor(time / 60);
-
-        if (this._proxy.State === UPower.DeviceState.DISCHARGING) {
-            // Translators: this is <hours>:<minutes> Remaining (<percentage>)
-            return _('%d\u2236%02d Remaining (%d\u2009%%)').format(
-                hours, minutes, this._proxy.Percentage);
-        }
-
-        if (this._proxy.State === UPower.DeviceState.CHARGING) {
-            // Translators: this is <hours>:<minutes> Until Full (<percentage>)
-            return _('%d\u2236%02d Until Full (%d\u2009%%)').format(
-                hours, minutes, this._proxy.Percentage);
-        }
-
-        return null;
+        this.reactive = Main.sessionMode.allowSettings;
     }
 
     _sync() {
         // Do we have batteries or a UPS?
-        let visible = this._proxy.IsPresent;
-        if (visible) {
-            this._item.show();
-            this._percentageLabel.visible =
-                this._desktopSettings.get_boolean(SHOW_BATTERY_PERCENTAGE);
-        } else {
-            // If there's no battery, then we use the power icon.
-            this._item.hide();
-            this._indicator.icon_name = 'system-shutdown-symbolic';
-            this._percentageLabel.hide();
+        this.visible = this._proxy.IsPresent;
+        if (!this.visible)
             return;
-        }
 
         // The icons
         let chargingState = this._proxy.State === UPower.DeviceState.CHARGING
@@ -129,23 +76,67 @@ class Indicator extends PanelMenu.SystemIndicator {
 
         // Make sure we fall back to fallback-icon-name and not GThemedIcon's
         // default fallbacks
-        let gicon = new Gio.ThemedIcon({
+        const gicon = new Gio.ThemedIcon({
             name: icon,
             use_default_fallbacks: false,
         });
 
-        this._indicator.gicon = gicon;
-        this._item.icon.gicon = gicon;
+        this.set({
+            label: _('%d\u2009%%').format(this._proxy.Percentage),
+            fallback_icon_name: this._proxy.IconName,
+            gicon,
+        });
+    }
+});
+
+var Indicator = GObject.registerClass(
+class Indicator extends SystemIndicator {
+    _init() {
+        super._init();
+
+        this._desktopSettings = new Gio.Settings({
+            schema_id: 'org.gnome.desktop.interface',
+        });
+        this._desktopSettings.connect(
+            `changed::${SHOW_BATTERY_PERCENTAGE}`, () => this._sync());
+
+        this._indicator = this._addIndicator();
+        this._percentageLabel = new St.Label({
+            y_expand: true,
+            y_align: Clutter.ActorAlign.CENTER,
+        });
+        this.add_child(this._percentageLabel);
+        this.add_style_class_name('power-status');
+
+        this._powerToggle = new PowerToggle();
 
-        let fallbackIcon = this._proxy.IconName;
-        this._indicator.fallback_icon_name = fallbackIcon;
-        this._item.icon.fallback_icon_name = fallbackIcon;
+        this._powerToggle.bind_property('label',
+            this._percentageLabel, 'text',
+            GObject.BindingFlags.SYNC_CREATE);
 
-        // The icon label
-        const label = _('%d\u2009%%').format(this._proxy.Percentage);
-        this._percentageLabel.text = label;
+        this._powerToggle.connectObject(
+            'notify::visible', () => this._sync(),
+            'notify::gicon', () => this._sync(),
+            'notify::fallback-icon-name', () => this._sync(),
+            this);
 
-        // The status label
-        this._item.label.text = this._getStatus();
+        this.quickSettingsItems.push(this._powerToggle);
+
+        this._sync();
+    }
+
+    _sync() {
+        if (this._powerToggle.visible) {
+            this._indicator.set({
+                gicon: this._powerToggle.gicon,
+                fallback_icon_name: this._powerToggle.fallback_icon_name,
+            });
+            this._percentageLabel.visible =
+                this._desktopSettings.get_boolean(SHOW_BATTERY_PERCENTAGE);
+        } else {
+            // If there's no battery, then we use the power icon.
+            this._indicator.icon_name = 'system-shutdown-symbolic';
+            this._percentageLabel.hide();
+        }
     }
 });


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