bluetooth: Adapt to new designs for the bluetooth menu
This is a part of the new system status design, see https://wiki.gnome.org/GnomeShell/Design/Guidelines/SystemStatus/ for design details. https://bugzilla.gnome.org/show_bug.cgi?id=704368
This commit is contained in:
parent
87245c7b33
commit
7dc9a9bf2f
@ -13,13 +13,6 @@ const NotificationDaemon = imports.ui.notificationDaemon;
|
||||
const PanelMenu = imports.ui.panelMenu;
|
||||
const PopupMenu = imports.ui.popupMenu;
|
||||
|
||||
const ConnectionState = {
|
||||
DISCONNECTED: 0,
|
||||
CONNECTED: 1,
|
||||
DISCONNECTING: 2,
|
||||
CONNECTING: 3
|
||||
}
|
||||
|
||||
const Indicator = new Lang.Class({
|
||||
Name: 'BTIndicator',
|
||||
Extends: PanelMenu.SystemStatusButton,
|
||||
@ -27,59 +20,18 @@ const Indicator = new Lang.Class({
|
||||
_init: function() {
|
||||
this.parent('bluetooth-disabled-symbolic', _("Bluetooth"));
|
||||
|
||||
// The Bluetooth menu only appears when Bluetooth is in use,
|
||||
// so just statically build it with a "Turn Off" menu item.
|
||||
this._item = new PopupMenu.PopupSubMenuMenuItem(_("Bluetooth"), true);
|
||||
this._item.icon.icon_name = 'bluetooth-active-symbolic';
|
||||
this._item.menu.addAction(_("Turn Off"), Lang.bind(this, function() {
|
||||
this._applet.killswitch_state = GnomeBluetooth.KillswitchState.SOFT_BLOCKED;
|
||||
}));
|
||||
this._item.menu.addSettingsAction(_("Bluetooth Settings"), 'gnome-bluetooth-panel.desktop');
|
||||
|
||||
this._applet = new GnomeBluetoothApplet.Applet();
|
||||
|
||||
this._killswitch = new PopupMenu.PopupSwitchMenuItem(_("Bluetooth"), false);
|
||||
this._applet.connect('notify::killswitch-state', Lang.bind(this, this._updateKillswitch));
|
||||
this._killswitch.connect('toggled', Lang.bind(this, function() {
|
||||
let current_state = this._applet.killswitch_state;
|
||||
if (current_state != GnomeBluetooth.KillswitchState.HARD_BLOCKED &&
|
||||
current_state != GnomeBluetooth.KillswitchState.NO_ADAPTER) {
|
||||
this._applet.killswitch_state = this._killswitch.state ?
|
||||
GnomeBluetooth.KillswitchState.UNBLOCKED:
|
||||
GnomeBluetooth.KillswitchState.SOFT_BLOCKED;
|
||||
} else
|
||||
this._killswitch.setToggleState(false);
|
||||
}));
|
||||
|
||||
this._discoverable = new PopupMenu.PopupSwitchMenuItem(_("Visibility"), this._applet.discoverable);
|
||||
this._applet.connect('notify::discoverable', Lang.bind(this, function() {
|
||||
this._discoverable.setToggleState(this._applet.discoverable);
|
||||
}));
|
||||
this._discoverable.connect('toggled', Lang.bind(this, function() {
|
||||
this._applet.discoverable = this._discoverable.state;
|
||||
}));
|
||||
|
||||
this._updateKillswitch();
|
||||
this.menu.addMenuItem(this._killswitch);
|
||||
this.menu.addMenuItem(this._discoverable);
|
||||
this.menu.addMenuItem(new PopupMenu.PopupSeparatorMenuItem());
|
||||
|
||||
this._fullMenuItems = [new PopupMenu.PopupSeparatorMenuItem(),
|
||||
new PopupMenu.PopupMenuItem(_("Send Files to Device…")),
|
||||
new PopupMenu.PopupMenuItem(_("Set Up a New Device…")),
|
||||
new PopupMenu.PopupSeparatorMenuItem()];
|
||||
this._hasDevices = false;
|
||||
|
||||
this._fullMenuItems[1].connect('activate', function() {
|
||||
GLib.spawn_command_line_async('bluetooth-sendto');
|
||||
});
|
||||
this._fullMenuItems[2].connect('activate', function() {
|
||||
GLib.spawn_command_line_async('bluetooth-wizard');
|
||||
});
|
||||
|
||||
for (let i = 0; i < this._fullMenuItems.length; i++) {
|
||||
let item = this._fullMenuItems[i];
|
||||
this.menu.addMenuItem(item);
|
||||
}
|
||||
|
||||
this._deviceItemPosition = 3;
|
||||
this._deviceItems = [];
|
||||
this._applet.connect('devices-changed', Lang.bind(this, this._updateDevices));
|
||||
this._updateDevices();
|
||||
|
||||
this._applet.connect('notify::show-full-menu', Lang.bind(this, this._updateFullMenu));
|
||||
this._updateFullMenu();
|
||||
this._applet.connect('devices-changed', Lang.bind(this, this._sync));
|
||||
this._sync();
|
||||
|
||||
this._applet.connect('pincode-request', Lang.bind(this, this._pinRequest));
|
||||
this._applet.connect('confirm-request', Lang.bind(this, this._confirmRequest));
|
||||
@ -88,183 +40,18 @@ const Indicator = new Lang.Class({
|
||||
this._applet.connect('cancel-request', Lang.bind(this, this._cancelRequest));
|
||||
},
|
||||
|
||||
_updateKillswitch: function() {
|
||||
let current_state = this._applet.killswitch_state;
|
||||
let on = current_state == GnomeBluetooth.KillswitchState.UNBLOCKED;
|
||||
let has_adapter = current_state != GnomeBluetooth.KillswitchState.NO_ADAPTER;
|
||||
let can_toggle = current_state != GnomeBluetooth.KillswitchState.NO_ADAPTER &&
|
||||
current_state != GnomeBluetooth.KillswitchState.HARD_BLOCKED;
|
||||
|
||||
this._killswitch.setToggleState(on);
|
||||
if (can_toggle)
|
||||
this._killswitch.setStatus(null);
|
||||
else
|
||||
/* TRANSLATORS: this means that bluetooth was disabled by hardware rfkill */
|
||||
this._killswitch.setStatus(_("hardware disabled"));
|
||||
|
||||
this.actor.visible = has_adapter;
|
||||
|
||||
if (on) {
|
||||
this._discoverable.actor.show();
|
||||
this.setIcon('bluetooth-active-symbolic');
|
||||
} else {
|
||||
this._discoverable.actor.hide();
|
||||
this.setIcon('bluetooth-disabled-symbolic');
|
||||
}
|
||||
},
|
||||
|
||||
_updateDevices: function() {
|
||||
let devices = this._applet.get_devices();
|
||||
|
||||
let newlist = [ ];
|
||||
for (let i = 0; i < this._deviceItems.length; i++) {
|
||||
let item = this._deviceItems[i];
|
||||
let destroy = true;
|
||||
for (let j = 0; j < devices.length; j++) {
|
||||
if (item._device.device_path == devices[j].device_path) {
|
||||
this._updateDeviceItem(item, devices[j]);
|
||||
destroy = false;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (destroy)
|
||||
item.destroy();
|
||||
else
|
||||
newlist.push(item);
|
||||
}
|
||||
|
||||
this._deviceItems = newlist;
|
||||
this._hasDevices = newlist.length > 0;
|
||||
for (let i = 0; i < devices.length; i++) {
|
||||
let d = devices[i];
|
||||
if (d._item)
|
||||
continue;
|
||||
let item = this._createDeviceItem(d);
|
||||
if (item) {
|
||||
this.menu.addMenuItem(item, this._deviceItemPosition + this._deviceItems.length);
|
||||
this._deviceItems.push(item);
|
||||
this._hasDevices = true;
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
_updateDeviceItem: function(item, device) {
|
||||
if (!device.can_connect && device.capabilities == GnomeBluetoothApplet.Capabilities.NONE) {
|
||||
item.destroy();
|
||||
return;
|
||||
}
|
||||
|
||||
let prevDevice = item._device;
|
||||
let prevCapabilities = prevDevice.capabilities;
|
||||
let prevCanConnect = prevDevice.can_connect;
|
||||
|
||||
// adopt the new device object
|
||||
item._device = device;
|
||||
device._item = item;
|
||||
|
||||
// update properties
|
||||
item.label.text = device.alias;
|
||||
|
||||
if (prevCapabilities != device.capabilities ||
|
||||
prevCanConnect != device.can_connect) {
|
||||
// need to rebuild the submenu
|
||||
item.menu.removeAll();
|
||||
this._buildDeviceSubMenu(item, device);
|
||||
}
|
||||
|
||||
// update connected property
|
||||
if (device.can_connect)
|
||||
item._connectedMenuItem.setToggleState(device.connected);
|
||||
},
|
||||
|
||||
_createDeviceItem: function(device) {
|
||||
if (!device.can_connect && device.capabilities == GnomeBluetoothApplet.Capabilities.NONE)
|
||||
return null;
|
||||
let item = new PopupMenu.PopupSubMenuMenuItem(device.alias);
|
||||
|
||||
// adopt the device object, and add a back link
|
||||
item._device = device;
|
||||
device._item = item;
|
||||
|
||||
this._buildDeviceSubMenu(item, device);
|
||||
|
||||
return item;
|
||||
},
|
||||
|
||||
_buildDeviceSubMenu: function(item, device) {
|
||||
if (device.can_connect) {
|
||||
let menuitem = new PopupMenu.PopupSwitchMenuItem(_("Connection"), device.connected);
|
||||
item._connected = device.connected;
|
||||
item._connectedMenuItem = menuitem;
|
||||
menuitem.connect('toggled', Lang.bind(this, function() {
|
||||
if (item._connected > ConnectionState.CONNECTED) {
|
||||
// operation already in progress, revert
|
||||
// (should not happen anyway)
|
||||
menuitem.setToggleState(menuitem.state);
|
||||
}
|
||||
if (item._connected) {
|
||||
item._connected = ConnectionState.DISCONNECTING;
|
||||
menuitem.setStatus(_("disconnecting..."));
|
||||
this._applet.disconnect_device(item._device.device_path, function(applet, success) {
|
||||
if (success) { // apply
|
||||
item._connected = ConnectionState.DISCONNECTED;
|
||||
menuitem.setToggleState(false);
|
||||
} else { // revert
|
||||
item._connected = ConnectionState.CONNECTED;
|
||||
menuitem.setToggleState(true);
|
||||
}
|
||||
menuitem.setStatus(null);
|
||||
_sync: function() {
|
||||
let connectedDevices = this._applet.get_devices().filter(function(device) {
|
||||
return device.connected;
|
||||
});
|
||||
} else {
|
||||
item._connected = ConnectionState.CONNECTING;
|
||||
menuitem.setStatus(_("connecting..."));
|
||||
this._applet.connect_device(item._device.device_path, function(applet, success) {
|
||||
if (success) { // apply
|
||||
item._connected = ConnectionState.CONNECTED;
|
||||
menuitem.setToggleState(true);
|
||||
} else { // revert
|
||||
item._connected = ConnectionState.DISCONNECTED;
|
||||
menuitem.setToggleState(false);
|
||||
}
|
||||
menuitem.setStatus(null);
|
||||
});
|
||||
}
|
||||
}));
|
||||
let nDevices = connectedDevices.length;
|
||||
|
||||
item.menu.addMenuItem(menuitem);
|
||||
}
|
||||
let on = nDevices > 0;
|
||||
this.mainIcon.visible = on;
|
||||
this.actor.visible = on;
|
||||
|
||||
if (device.capabilities & GnomeBluetoothApplet.Capabilities.OBEX_PUSH) {
|
||||
item.menu.addAction(_("Send Files…"), Lang.bind(this, function() {
|
||||
this._applet.send_to_address(device.bdaddr, device.alias);
|
||||
}));
|
||||
}
|
||||
},
|
||||
|
||||
_updateFullMenu: function() {
|
||||
if (this._applet.show_full_menu) {
|
||||
this._showAll(this._fullMenuItems);
|
||||
if (this._hasDevices)
|
||||
this._showAll(this._deviceItems);
|
||||
} else {
|
||||
this._hideAll(this._fullMenuItems);
|
||||
this._hideAll(this._deviceItems);
|
||||
}
|
||||
},
|
||||
|
||||
_showAll: function(items) {
|
||||
for (let i = 0; i < items.length; i++)
|
||||
items[i].actor.show();
|
||||
},
|
||||
|
||||
_hideAll: function(items) {
|
||||
for (let i = 0; i < items.length; i++)
|
||||
items[i].actor.hide();
|
||||
},
|
||||
|
||||
_destroyAll: function(items) {
|
||||
for (let i = 0; i < items.length; i++)
|
||||
items[i].destroy();
|
||||
if (on)
|
||||
this._item.status.text = ngettext("%d Connected Device", "%d Connected Devices").format(nDevices);
|
||||
},
|
||||
|
||||
_ensureSource: function() {
|
||||
|
Loading…
Reference in New Issue
Block a user