13bf64a53d
All the system status menus in the panel offer a menu item to jump to a relevant part of the control-center. This means each status icon has the same, or nearly the same bit of code to: - Add a new "action" menu item and listen for its activation. - Hide the overview if it's showing when the menu item is activated - Find the relevant control-center panel from its desktop file - Launch the control-center to the relevant panel This commit consolidates all those details in a new method, addSettingsAction. This refactoring reduces code duplication and slight inconsistencies in the code resulting from that duplication. It will also make it easier in subsequent commits to hide settings menu items when the shell is used in the login screen. https://bugzilla.gnome.org/show_bug.cgi?id=657082
227 lines
7.5 KiB
JavaScript
227 lines
7.5 KiB
JavaScript
/* -*- mode: js2; js2-basic-offset: 4; indent-tabs-mode: nil -*- */
|
|
|
|
const Gio = imports.gi.Gio;
|
|
const DBus = imports.dbus;
|
|
const Lang = imports.lang;
|
|
const Mainloop = imports.mainloop;
|
|
const Shell = imports.gi.Shell;
|
|
const St = imports.gi.St;
|
|
|
|
const Main = imports.ui.main;
|
|
const PanelMenu = imports.ui.panelMenu;
|
|
const PopupMenu = imports.ui.popupMenu;
|
|
const Util = imports.misc.util;
|
|
|
|
const BUS_NAME = 'org.gnome.SettingsDaemon';
|
|
const OBJECT_PATH = '/org/gnome/SettingsDaemon/Power';
|
|
|
|
const UPDeviceType = {
|
|
UNKNOWN: 0,
|
|
AC_POWER: 1,
|
|
BATTERY: 2,
|
|
UPS: 3,
|
|
MONITOR: 4,
|
|
MOUSE: 5,
|
|
KEYBOARD: 6,
|
|
PDA: 7,
|
|
PHONE: 8,
|
|
MEDIA_PLAYER: 9,
|
|
TABLET: 10,
|
|
COMPUTER: 11
|
|
};
|
|
|
|
const UPDeviceState = {
|
|
UNKNOWN: 0,
|
|
CHARGING: 1,
|
|
DISCHARGING: 2,
|
|
EMPTY: 3,
|
|
FULLY_CHARGED: 4,
|
|
PENDING_CHARGE: 5,
|
|
PENDING_DISCHARGE: 6
|
|
};
|
|
|
|
const PowerManagerInterface = {
|
|
name: 'org.gnome.SettingsDaemon.Power',
|
|
methods: [
|
|
{ name: 'GetDevices', inSignature: '', outSignature: 'a(susbut)' },
|
|
{ name: 'GetPrimaryDevice', inSignature: '', outSignature: '(susbut)' },
|
|
],
|
|
signals: [
|
|
{ name: 'Changed', inSignature: '' },
|
|
],
|
|
properties: [
|
|
{ name: 'Icon', 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('', { reactive: false });
|
|
this._primaryPercentage = new St.Label();
|
|
this._batteryItem.addActor(this._primaryPercentage, { align: St.Align.END });
|
|
this.menu.addMenuItem(this._batteryItem);
|
|
|
|
this.menu.addMenuItem(new PopupMenu.PopupSeparatorMenuItem());
|
|
this._otherDevicePosition = 2;
|
|
|
|
this.menu.addMenuItem(new PopupMenu.PopupSeparatorMenuItem());
|
|
this.menu.addSettingsAction(_("Power Settings"), 'gnome-power-panel.desktop');
|
|
|
|
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._hasPrimary = false;
|
|
this._primaryDeviceId = null;
|
|
this._batteryItem.actor.hide();
|
|
return;
|
|
}
|
|
let [device_id, device_type, icon, percentage, state, seconds] = device;
|
|
if (device_type == UPDeviceType.BATTERY) {
|
|
this._hasPrimary = true;
|
|
let time = Math.round(seconds / 60);
|
|
if (time == 0) {
|
|
// 0 is reported when UPower does not have enough data
|
|
// to estimate battery life
|
|
this._batteryItem.label.text = _("Estimating...");
|
|
} else {
|
|
let minutes = time % 60;
|
|
let hours = Math.floor(time / 60);
|
|
let timestring;
|
|
if (time > 60) {
|
|
if (minutes == 0) {
|
|
timestring = ngettext("%d hour remaining", "%d hours remaining", hours).format(hours);
|
|
} else {
|
|
/* TRANSLATORS: this is a time string, as in "%d hours %d minutes remaining" */
|
|
let template = _("%d %s %d %s remaining");
|
|
|
|
timestring = template.format (hours, ngettext("hour", "hours", hours), minutes, ngettext("minute", "minutes", minutes));
|
|
}
|
|
} else
|
|
timestring = ngettext("%d minute remaining", "%d minutes remaining", minutes).format(minutes);
|
|
this._batteryItem.label.text = timestring;
|
|
}
|
|
this._primaryPercentage.text = Math.round(percentage) + '%';
|
|
this._batteryItem.actor.show();
|
|
} else {
|
|
this._hasPrimary = false;
|
|
this._batteryItem.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) {
|
|
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]);
|
|
this._deviceItems.push(item);
|
|
this.menu.addMenuItem(item, this._otherDevicePosition + position);
|
|
position++;
|
|
}
|
|
}));
|
|
},
|
|
|
|
_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.menu.close();
|
|
this.actor.hide();
|
|
}
|
|
}));
|
|
this._readPrimaryDevice();
|
|
this._readOtherDevices();
|
|
}
|
|
};
|
|
|
|
function DeviceItem() {
|
|
this._init.apply(this, arguments);
|
|
}
|
|
|
|
DeviceItem.prototype = {
|
|
__proto__: PopupMenu.PopupBaseMenuItem.prototype,
|
|
|
|
_init: function(device) {
|
|
PopupMenu.PopupBaseMenuItem.prototype._init.call(this, { reactive: false });
|
|
|
|
let [device_id, device_type, icon, percentage, state, time] = device;
|
|
|
|
this._box = new St.BoxLayout({ style_class: 'popup-device-menu-item' });
|
|
this._label = new St.Label({ text: this._deviceTypeToString(device_type) });
|
|
|
|
this._icon = new St.Icon({ gicon: Shell.util_icon_from_string(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 percentLabel = new St.Label({ text: '%d%%'.format(Math.round(percentage)) });
|
|
this.addActor(percentLabel, { align: St.Align.END });
|
|
},
|
|
|
|
_deviceTypeToString: function(type) {
|
|
switch (type) {
|
|
case UPDeviceType.AC_POWER:
|
|
return _("AC adapter");
|
|
case UPDeviceType.BATTERY:
|
|
return _("Laptop battery");
|
|
case UPDeviceType.UPS:
|
|
return _("UPS");
|
|
case UPDeviceType.MONITOR:
|
|
return _("Monitor");
|
|
case UPDeviceType.MOUSE:
|
|
return _("Mouse");
|
|
case UPDeviceType.KEYBOARD:
|
|
return _("Keyboard");
|
|
case UPDeviceType.PDA:
|
|
return _("PDA");
|
|
case UPDeviceType.PHONE:
|
|
return _("Cell phone");
|
|
case UPDeviceType.MEDIA_PLAYER:
|
|
return _("Media player");
|
|
case UPDeviceType.TABLET:
|
|
return _("Tablet");
|
|
case UPDeviceType.COMPUTER:
|
|
return _("Computer");
|
|
default:
|
|
return _("Unknown");
|
|
}
|
|
}
|
|
}
|