c4c5c4fd5c
Remove the `this.actor = ...` and `this.actor._delegate = this` patterns in most of classes, by inheriting all the actor container classes. Uses interfaces when needed for making sure that multiple classes will implement some required methods or to avoid redefining the same code multiple times. https://gitlab.gnome.org/GNOME/gnome-shell/merge_requests/559
146 lines
5.7 KiB
JavaScript
146 lines
5.7 KiB
JavaScript
// -*- mode: js; js-indent-level: 4; indent-tabs-mode: nil -*-
|
|
/* exported Indicator */
|
|
|
|
const { Clutter, Gio, GObject, St, UPowerGlib: UPower } = imports.gi;
|
|
|
|
const Main = imports.ui.main;
|
|
const PanelMenu = imports.ui.panelMenu;
|
|
const PopupMenu = imports.ui.popupMenu;
|
|
|
|
const { loadInterfaceXML } = imports.misc.fileUtils;
|
|
|
|
const BUS_NAME = 'org.freedesktop.UPower';
|
|
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';
|
|
|
|
var Indicator = GObject.registerClass({
|
|
GTypeName: 'Power_Indicator'
|
|
}, class Indicator extends PanelMenu.SystemIndicator {
|
|
_init() {
|
|
super._init();
|
|
|
|
this._desktopSettings = new Gio.Settings({ schema_id: 'org.gnome.desktop.interface' });
|
|
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(this._percentageLabel, { expand: true, y_fill: true });
|
|
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);
|
|
return;
|
|
}
|
|
this._proxy.connect('g-properties-changed',
|
|
this._sync.bind(this));
|
|
this._sync();
|
|
});
|
|
|
|
this._item = new PopupMenu.PopupSubMenuMenuItem("", true);
|
|
this._item.menu.addSettingsAction(_("Power Settings"), 'gnome-power-panel.desktop');
|
|
this.menu.addMenuItem(this._item);
|
|
|
|
Main.sessionMode.connect('updated', this._sessionUpdated.bind(this));
|
|
this._sessionUpdated();
|
|
}
|
|
|
|
_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;
|
|
}
|
|
|
|
_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();
|
|
return;
|
|
}
|
|
|
|
// The icons
|
|
let chargingState = this._proxy.State == UPower.DeviceState.CHARGING
|
|
? '-charging' : '';
|
|
let fillLevel = 10 * Math.floor(this._proxy.Percentage / 10);
|
|
let icon = this._proxy.State == UPower.DeviceState.FULLY_CHARGED
|
|
? 'battery-level-100-charged-symbolic'
|
|
: `battery-level-${fillLevel}${chargingState}-symbolic`;
|
|
|
|
// Make sure we fall back to fallback-icon-name and not GThemedIcon's
|
|
// default fallbacks
|
|
let gicon = new Gio.ThemedIcon({
|
|
name: icon,
|
|
use_default_fallbacks: false
|
|
});
|
|
|
|
this._indicator.gicon = gicon;
|
|
this._item.icon.gicon = gicon;
|
|
|
|
let fallbackIcon = this._proxy.IconName;
|
|
this._indicator.fallback_icon_name = fallbackIcon;
|
|
this._item.icon.fallback_icon_name = fallbackIcon;
|
|
|
|
// The icon label
|
|
let label;
|
|
if (this._proxy.State == UPower.DeviceState.FULLY_CHARGED)
|
|
label = _("%d\u2009%%").format(100);
|
|
else
|
|
label = _("%d\u2009%%").format(this._proxy.Percentage);
|
|
this._percentageLabel.clutter_text.set_markup('<span size="smaller">' + label + '</span>');
|
|
|
|
// The status label
|
|
this._item.label.text = this._getStatus();
|
|
}
|
|
});
|