[gnome-shell/wip/aggregate-menu: 50/74] network: Rework the VPN rewrite to work for NMDeviceModem as well



commit da10ceb3a4e1e331a6ea00d8f9553f5e35049c4f
Author: Jasper St. Pierre <jstpierre mecheye net>
Date:   Tue Jun 11 20:13:37 2013 -0400

    network: Rework the VPN rewrite to work for NMDeviceModem as well
    
    Use the same infrastructure for other devices. For now, this removes
    almost all the functionality of the Wireless connection menu. We'll
    add it back in a later commit.

 data/theme/gnome-shell.css |    4 -
 js/ui/status/network.js    |  987 ++++++++------------------------------------
 2 files changed, 183 insertions(+), 808 deletions(-)
---
diff --git a/data/theme/gnome-shell.css b/data/theme/gnome-shell.css
index fb453c0..3f89878 100644
--- a/data/theme/gnome-shell.css
+++ b/data/theme/gnome-shell.css
@@ -262,10 +262,6 @@ StScrollBar StButton#vhandle:active {
     background-size: contain;
 }
 
-.nm-menu-item-icons {
-    spacing: .5em;
-}
-
 /* Buttons */
 
 .candidate-page-button,
diff --git a/js/ui/status/network.js b/js/ui/status/network.js
index fa775e2..788b54d 100644
--- a/js/ui/status/network.js
+++ b/js/ui/status/network.js
@@ -51,7 +51,6 @@ function ssidCompare(one, two) {
     return true;
 }
 
-// shared between NMNetworkMenuItem and NMDeviceWWAN
 function signalToIcon(value) {
     if (value > 80)
         return 'excellent';
@@ -71,63 +70,82 @@ function ssidToLabel(ssid) {
     return label;
 }
 
-const NMNetworkMenuItem = new Lang.Class({
-    Name: 'NMNetworkMenuItem',
-    Extends: PopupMenu.PopupBaseMenuItem,
+const NMConnectionItem = new Lang.Class({
+    Name: 'NMConnectionItem',
 
-    _init: function(bestAP) {
-        this.parent();
+    _init: function(client, connection) {
+        this._client = client;
+        this._connection = connection;
+        this._activeConnection = null;
+        this._activeConnectionChangedId = 0;
 
-        this.bestAP = bestAP;
+        this.menuItem = new PopupMenu.PopupSwitchMenuItem(connection.get_id(), false);
+        this.menuItem.connect('toggled', Lang.bind(this, this._toggle));
 
-        let ssid = this.bestAP.get_ssid();
-        let title = ssidToLabel(ssid);
+        this._sync();
+    },
 
-        this._label = new St.Label({ text: title });
-        this.actor.label_actor = this._label;
-        this.addActor(this._label);
-        this._icons = new St.BoxLayout({ style_class: 'nm-menu-item-icons' });
-        this.addActor(this._icons, { align: St.Align.END });
+    destroy: function() {
+        this.menuItem.destroy();
+    },
 
-        this._signalIcon = new St.Icon({ icon_name: this._getIcon(),
-                                         style_class: 'popup-menu-icon' });
-        this._icons.add_actor(this._signalIcon);
+    isActive: function() {
+        if (this._activeConnection == null)
+            return false;
 
-        this._secureIcon = new St.Icon({ style_class: 'popup-menu-icon' });
-        if (this.bestAP._secType != NMAccessPointSecurity.NONE)
-            this._secureIcon.icon_name = 'network-wireless-encrypted-symbolic';
-        this._icons.add_actor(this._secureIcon);
+        return this._activeConnection.state == NetworkManager.ActiveConnectionState.ACTIVATED;
     },
 
-    updateBestAP: function(ap) {
-        this.bestAP = ap;
-        this._signalIcon.icon_name = this._getIcon();
+    _sync: function() {
+        this.menuItem.setToggleState(this._getIsActive());
+        this.menuItem.setStatus(this._getStatus());
+        this.emit('icon-changed');
     },
 
-    _getIcon: function() {
-        if (this.bestAP.mode == NM80211Mode.ADHOC)
-            return 'network-workgroup-symbolic';
+    _toggle: function() {
+        if (this._activeConnection == null)
+            this._client.activate_connection(this._connection, null, null, null);
         else
-            return 'network-wireless-signal-' + signalToIcon(this.bestAP.strength) + '-symbolic';
-    }
-});
+            this._client.deactivate_connection(this._activeConnection);
+
+        this._sync();
+    },
+
+    _getStatus: function() {
+        return null;
+    },
+
+    _connectionStateChanged: function(ac, newstate, reason) {
+        this._sync();
+    },
+
+    setActiveConnection: function(activeConnection) {
+        if (this._activeConnectionChangedId > 0) {
+            this._activeConnection.disconnect(this._activeConnectionChangedId);
+            this._activeConnectionChangedId = 0;
+        }
+
+        this._activeConnection = activeConnection;
 
+        if (this._activeConnection)
+            this._activeConnectionChangedId = this._activeConnection.connect('state-changed',
+                                                                             Lang.bind(this, 
this._connectionStateChanged));
 
-const NMDevice = new Lang.Class({
-    Name: 'NMDevice',
+        this._sync();
+    },
+});
+Signals.addSignalMethods(NMConnectionItem.prototype);
+
+const NMConnectionSection = new Lang.Class({
+    Name: 'NMConnectionSection',
     Abstract: true,
 
-    _init: function(client, device, settings) {
+    _init: function(client) {
         this._client = client;
-        this._setDevice(device);
 
+        this._connectionItems = new Hash.Map();
         this._connections = [];
-
-        let connections = settings.list_connections();
-        connections.forEach(Lang.bind(this, this.checkConnection));
-
-        this._activeConnection = null;
-        this._activeConnectionItem = null;
+        this.section = new PopupMenu.PopupMenuSection();
 
         this.statusItem = new PopupMenu.PopupSwitchMenuItem('', this.connected);
         this._statusChanged = this.statusItem.connect('toggled', Lang.bind(this, function(item, state) {
@@ -142,122 +160,147 @@ const NMDevice = new Lang.Class({
         }));
 
         this._updateStatusItem();
-        this.section = new PopupMenu.PopupMenuSection();
+    },
+
+    destroy: function() {
+        this.statusItem.destroy();
+        this.section.destroy();
+    },
+
+    _hasConnection: function(connection) {
+        return this._connectionItems.has(connection.get_uuid());
+    },
+
+    _connectionValid: function(connection) {
+        return true;
+    },
+
+    _connectionSortFunction: function(one, two) {
+        if (one._timestamp == two._timestamp)
+            return GLib.utf8_collate(one.get_id(), two.get_id());
+
+        return two._timestamp - one._timestamp;
+    },
 
-        this._deferredWorkId = Main.initializeDeferredWork(this.section.actor, Lang.bind(this, 
this._createSection));
+    _makeConnectionItem: function(connection) {
+        return new NMConnectionItem(this._client, connection);
     },
 
     checkConnection: function(connection) {
-        let pos = this._findConnection(connection.get_uuid());
-        let exists = pos != -1;
-        let valid = this.connectionValid(connection);
-        let similar = false;
-        if (exists) {
-            let existing = this._connections[pos];
-
-            // Check if connection changed name or id
-            similar = existing.name == connection.get_id() &&
-                existing.timestamp == connection._timestamp;
-        }
+        if (!this._connectionValid(connection))
+            return;
 
-        if (exists && valid && similar) {
-            // Nothing to do
+        if (this._hasConnection(connection))
             return;
-        }
 
-        if (exists)
-            this.removeConnection(connection);
-        if (valid)
-            this.addConnection(connection);
+        this._addConnection(connection);
     },
 
-    addConnection: function(connection) {
-        // record the connection
-        let obj = {
-            connection: connection,
-            name: connection.get_id(),
-            uuid: connection.get_uuid(),
-            timestamp: connection._timestamp,
-            item: null,
-        };
-        Util.insertSorted(this._connections, obj, this._connectionSortFunction);
+    _addConnection: function(connection) {
+        let item = this._makeConnectionItem(connection);
+        if (!item)
+            return;
 
-        this._queueCreateSection();
+        item.connect('icon-changed', Lang.bind(this, function() {
+            this.emit('icon-changed');
+        }));
+        item.connect('activation-failed', Lang.bind(this, function(item, reason) {
+            this.emit('activation-failed', reason);
+        }));
+
+        let pos = Util.insertSorted(this._connections, connection, this._connectionSortFunction);
+        this.section.addMenuItem(item.menuItem, pos);
+        this._connectionItems.set(connection.get_uuid(), item);
     },
 
     removeConnection: function(connection) {
-        let pos = this._findConnection(connection.get_uuid());
-        if (pos == -1) {
-            // this connection was never added, nothing to do here
-            return;
-        }
+        this._connectionItems.get(connection.get_uuid()).destroy();
+        this._connectionItems.delete(connection.get_uuid());
 
-        let obj = this._connections[pos];
-        if (obj.item)
-            obj.item.destroy();
+        let pos = this._connections.indexOf(connection);
         this._connections.splice(pos, 1);
+    },
 
-        if (this._connections.length <= 1) {
-            // We need to show the automatic connection again
-            // (or in the case of NMDeviceWired, we want to hide
-            // the only explicit connection)
-            this._queueCreateSection();
+    getIndicatorIcon: function() {
+        let items = this._connectionItems.values();
+        for (let i = 0; i < items.length; i++) {
+            let item = items[i];
+            let icon = item.getIndicatorIcon();
+            if (icon)
+                return icon;
         }
+        return '';
     },
+});
+Signals.addSignalMethods(NMConnectionSection.prototype);
 
-    _findConnection: function(uuid) {
-        for (let i = 0; i < this._connections.length; i++) {
-            let obj = this._connections[i];
-            if (obj.uuid == uuid)
-                return i;
+const NMDeviceModem = new Lang.Class({
+    Name: 'NMDeviceModem',
+    Extends: NMConnectionSection,
+    category: NMConnectionCategory.WWAN,
+
+    _init: function(client, device, settings) {
+        this._client = client;
+        this._device = device;
+
+        this._mobileDevice = null;
+
+        let capabilities = device.current_capabilities;
+        if (device.udi.indexOf('/org/freedesktop/ModemManager1/Modem') == 0)
+            this._mobileDevice = new ModemManager.BroadbandModem(device.udi, capabilities);
+        else if (capabilities & NetworkManager.DeviceModemCapabilities.GSM_UMTS)
+            this._mobileDevice = new ModemManager.ModemGsm(device.udi);
+        else if (capabilities & NetworkManager.DeviceModemCapabilities.CDMA_EVDO)
+            this._mobileDevice = new ModemManager.ModemCdma(device.udi);
+        else if (capabilities & NetworkManager.DeviceModemCapabilities.LTE)
+            this._mobileDevice = new ModemManager.ModemGsm(device.udi);
+
+        if (this._mobileDevice) {
+            this._operatorNameId = this._mobileDevice.connect('notify::operator-name', Lang.bind(this, 
function() {
+                if (this._operatorItem) {
+                    let name = this._mobileDevice.operator_name;
+                    if (name) {
+                        this._operatorItem.label.text = name;
+                        this._operatorItem.actor.show();
+                    } else
+                        this._operatorItem.actor.hide();
+                }
+            }));
+            this._signalQualityId = this._mobileDevice.connect('notify::signal-quality', Lang.bind(this, 
function() {
+                this.emit('icon-changed');
+            }));
         }
-        return -1;
-    },
 
-    _connectionSortFunction: function(one, two) {
-        if (one.timestamp == two.timestamp)
-            return GLib.utf8_collate(one.name, two.name);
+        this._stateChangedId = this._device.connect('state-changed', Lang.bind(this, 
this._deviceStateChanged));
+        this._activeConnectionChangedId = this._device.connect('notify::active-connection', Lang.bind(this, 
this._activeConnectionChanged));
 
-        return two.timestamp - one.timestamp;
+        let connnections = settings.list_connections();
+        connections.forEach(Lang.bind(this, this.checkConnection));
     },
 
     destroy: function() {
-        this._setDevice(null);
-
-        if (this._deferredWorkId) {
-            // Just clear out, the actual removal is handled when the
-            // actor is destroyed
-            this._deferredWorkId = 0;
+        if (this._operatorNameId) {
+            this._mobileDevice.disconnect(this._operatorNameId);
+            this._operatorNameId = 0;
+        }
+        if (this._signalQualityId) {
+            this._mobileDevice.disconnect(this._signalQualityId);
+            this._signalQualityId = 0;
+        }
+        if (this._stateChangedId) {
+            GObject.Object.prototype.disconnect.call(this._device, this._stateChangedId);
+            this._stateChangedId = 0;
+        }
+        if (this._activeConnectionChangedId) {
+            GObject.Object.prototype.disconnect.call(this._device, this._activeConnectionChangedId);
+            this._stateChangedId = 0;
         }
 
-        this._clearSection();
-        if (this.statusItem)
-            this.statusItem.destroy();
-        this.section.destroy();
+        this.parent();
     },
 
-    _setDevice: function(device) {
-        if (device) {
-            this._device = device;
-            this._device._delegate = this;
-            this._stateChangedId = this._device.connect('state-changed', Lang.bind(this, 
this._deviceStateChanged));
-            this._activeConnectionChangedId = this._device.connect('notify::active-connection', 
Lang.bind(this, this._activeConnectionChanged));
-        } else if (this._device) {
-            this._device._delegate = null;
-
-            if (this._stateChangedId) {
-                // Need to go through GObject.Object.prototype because
-                // nm_device_disconnect conflicts with g_signal_disconnect
-                GObject.Object.prototype.disconnect.call(this._device, this._stateChangedId);
-                this._stateChangedId = 0;
-            }
-            if (this._activeConnectionChangedId) {
-                GObject.Object.prototype.disconnect.call(this._device, this._activeConnectionChangedId);
-                this._stateChangedId = 0;
-            }
-
-            this._device = null;
-        }
+    _connectionValid: function(connection) {
+        return this._device.connection_valid(connection);
     },
 
     deactivate: function() {
@@ -289,10 +332,6 @@ const NMDevice = new Lang.Class({
         return true;
     },
 
-    get connected() {
-        return this._device && this._device.state == NetworkManager.DeviceState.ACTIVATED;
-    },
-
     _activeConnectionChanged: function() {
         let activeConnection = this._device.active_connection;
 
@@ -300,22 +339,10 @@ const NMDevice = new Lang.Class({
             // nothing to do
             return;
 
-        // remove any UI
-        if (this._activeConnectionItem) {
-            this._activeConnectionItem.destroy();
-            this._activeConnectionItem = null;
-        }
-
         this._activeConnection = activeConnection;
-
-        this._queueCreateSection();
     },
 
-    connectionValid: function(connection) {
-        return this._device.connection_valid(connection);
-    },
-
-    getStatusLabel: function() {
+    _getStatus: function() {
         if (!this._device)
             return null;
 
@@ -363,73 +390,6 @@ const NMDevice = new Lang.Class({
             this.statusItem.label.text = this._device._description;
     },
 
-    _queueCreateSection: function() {
-        if (this._deferredWorkId) {
-            this._clearSection();
-            Main.queueDeferredWork(this._deferredWorkId);
-        }
-    },
-
-    _clearSection: function() {
-        // Clear everything
-        this.section.removeAll();
-        this._activeConnectionItem = null;
-        for (let i = 0; i < this._connections.length; i++) {
-            this._connections[i].item = null;
-        }
-    },
-
-    _shouldShowConnectionList: function() {
-        return (this._device.state >= NetworkManager.DeviceState.DISCONNECTED);
-    },
-
-    _createSection: function() {
-        if (!this._shouldShowConnectionList())
-            return;
-
-        if (this._activeConnection) {
-            this._createActiveConnectionItem();
-            this.section.addMenuItem(this._activeConnectionItem);
-        }
-        if (this._connections.length > 0) {
-            let activeOffset = this._activeConnectionItem ? 1 : 0;
-
-            for(let j = 0; j < this._connections.length; ++j) {
-                let obj = this._connections[j];
-                if (this._activeConnection &&
-                    obj.connection == this._activeConnection._connection)
-                    continue;
-                obj.item = this._createConnectionItem(obj);
-
-                this.section.addMenuItem(obj.item);
-            }
-        }
-    },
-
-    _createConnectionItem: function(obj) {
-        let connection = obj.connection;
-        let item = new PopupMenu.PopupMenuItem(obj.name);
-
-        item.connect('activate', Lang.bind(this, function() {
-            this._client.activate_connection(connection, this._device, null, null);
-        }));
-        return item;
-    },
-
-    _createActiveConnectionItem: function() {
-        let title;
-        let active = this._activeConnection._connection;
-        if (active) {
-            title = active.get_id();
-        } else {
-            /* TRANSLATORS: this is the indication that a connection for another logged in user is active,
-               and we cannot access its settings (including the name) */
-            title = _("Connected (private)");
-        }
-        this._activeConnectionItem = new PopupMenu.PopupMenuItem(title, { reactive: false });
-        this._activeConnectionItem.setOrnament(PopupMenu.Ornament.DOT);
-    },
-
     _deviceStateChanged: function(device, newstate, oldstate, reason) {
         if (newstate == oldstate) {
             log('device emitted state-changed without actually changing state');
@@ -445,8 +405,6 @@ const NMDevice = new Lang.Class({
         }
 
         this._updateStatusItem();
-
-        this._queueCreateSection();
     },
 
     _updateStatusItem: function() {
@@ -456,76 +414,21 @@ const NMDevice = new Lang.Class({
 
     _substateChanged: function() {
         this.statusItem.setStatus(this.getStatusLabel());
-    }
-});
-Signals.addSignalMethods(NMDevice.prototype);
-
-const NMDeviceModem = new Lang.Class({
-    Name: 'NMDeviceModem',
-    Extends: NMDevice,
-    category: NMConnectionCategory.WWAN,
-
-    _init: function(client, device, settings) {
-        device._description = _("Mobile broadband");
-        this.mobileDevice = null;
-
-        this._capabilities = device.current_capabilities;
-        // Support new ModemManager1 devices
-        if (device.udi.indexOf('/org/freedesktop/ModemManager1/Modem') == 0) {
-            this.mobileDevice = new ModemManager.BroadbandModem(device.udi, device.current_capabilities);
-        } else if (this._capabilities & NetworkManager.DeviceModemCapabilities.GSM_UMTS) {
-            this.mobileDevice = new ModemManager.ModemGsm(device.udi);
-        } else if (this._capabilities & NetworkManager.DeviceModemCapabilities.CDMA_EVDO) {
-            this.mobileDevice = new ModemManager.ModemCdma(device.udi);
-        } else if (this._capabilities & NetworkManager.DeviceModemCapabilities.LTE) {
-            this.mobileDevice = new ModemManager.ModemGsm(device.udi);
-        }
-
-        if (this.mobileDevice) {
-            this._operatorNameId = this.mobileDevice.connect('notify::operator-name', Lang.bind(this, 
function() {
-                if (this._operatorItem) {
-                    let name = this.mobileDevice.operator_name;
-                    if (name) {
-                        this._operatorItem.label.text = name;
-                        this._operatorItem.actor.show();
-                    } else
-                        this._operatorItem.actor.hide();
-                }
-            }));
-            this._signalQualityId = this.mobileDevice.connect('notify::signal-quality', Lang.bind(this, 
function() {
-                this.emit('icon-changed');
-            }));
-        }
-
-        this.parent(client, device, settings);
-    },
-
-    destroy: function() {
-        if (this._operatorNameId) {
-            this.mobileDevice.disconnect(this._operatorNameId);
-            this._operatorNameId = 0;
-        }
-        if (this._signalQualityId) {
-            this.mobileDevice.disconnect(this._signalQualityId);
-            this._signalQualityId = 0;
-        }
-
-        this.parent();
     },
 
     _getSignalIcon: function() {
-        return 'network-cellular-signal-' + signalToIcon(this.mobileDevice.signal_quality) + '-symbolic';
+        return 'network-cellular-signal-' + signalToIcon(this._mobileDevice.signal_quality) + '-symbolic';
     },
 
     _createSection: function() {
         if (!this._shouldShowConnectionList())
             return;
 
-        if (this.mobileDevice) {
+        if (this._mobileDevice) {
             // If operator_name is null, just pass the empty string, as the item is hidden anyway
-            this._operatorItem = new PopupMenu.PopupMenuItem(this.mobileDevice.operator_name || '',
+            this._operatorItem = new PopupMenu.PopupMenuItem(this._mobileDevice.operator_name || '',
                                                              { style_class: 'popup-status-menu-item' });
-            if (!this.mobileDevice.operator_name)
+            if (!this._mobileDevice.operator_name)
                 this._operatorItem.actor.hide();
             this.section.addMenuItem(this._operatorItem);
         }
@@ -551,7 +454,7 @@ const NMDeviceModem = new Lang.Class({
         if (this._device.active_connection.state == NetworkManager.ActiveConnectionState.ACTIVATING)
             return 'network-cellular-acquiring-symbolic';
 
-        if (!this.mobileDevice) {
+        if (!this._mobileDevice) {
             // this can happen for bluetooth in PAN mode
             return 'network-cellular-connected-symbolic';
         }
@@ -560,483 +463,9 @@ const NMDeviceModem = new Lang.Class({
     }
 });
 
-const NMDeviceWireless = new Lang.Class({
-    Name: 'NMDeviceWireless',
-    Extends: NMDevice,
-
-    _init: function(client, device, settings) {
-        this.category = NMConnectionCategory.WIRELESS;
-
-        this._networks = [ ];
-
-        this.parent(client, device, settings);
-
-        let accessPoints = device.get_access_points() || [ ];
-        accessPoints.forEach(Lang.bind(this, function(ap) {
-            this._accessPointAdded(this._device, ap);
-        }));
-
-        this._activeApChanged();
-        this._networks.sort(this._networkSortFunction);
-
-        this._apChangedId = device.connect('notify::active-access-point', Lang.bind(this, 
this._activeApChanged));
-        this._apAddedId = device.connect('access-point-added', Lang.bind(this, this._accessPointAdded));
-        this._apRemovedId = device.connect('access-point-removed', Lang.bind(this, 
this._accessPointRemoved));
-    },
-
-    destroy: function() {
-        if (this._apChangedId) {
-            // see above for this HACK
-            GObject.Object.prototype.disconnect.call(this._device, this._apChangedId);
-            this._apChangedId = 0;
-        }
-
-        if (this._apAddedId) {
-            GObject.Object.prototype.disconnect.call(this._device, this._apAddedId);
-            this._apAddedId = 0;
-        }
-
-        if (this._apRemovedId) {
-            GObject.Object.prototype.disconnect.call(this._device, this._apRemovedId);
-            this._apRemovedId = 0;
-        }
-
-        this.parent();
-    },
-
-    activate: function() {
-        if (this._activeConnection)
-            // nothing to do
-            return true;
-
-        // All possible policy we can have here is just broken
-        // NM autoconnects when wifi devices are enabled, and if it
-        // didn't, there is a good reason
-        // User, pick a connection from the list, thank you
-        return false;
-    },
-
-    _notifySsidCb: function(accessPoint) {
-        if (accessPoint.get_ssid() != null) {
-            accessPoint.disconnect(accessPoint._notifySsidId);
-            accessPoint._notifySsidId = 0;
-            this._accessPointAdded(this._device, accessPoint);
-        }
-    },
-
-    _activeApChanged: function() {
-        this._activeNetwork = null;
-
-        let activeAp = this._device.active_access_point;
-
-        if (activeAp) {
-            let res = this._findExistingNetwork(activeAp);
-
-            if (res != null)
-                this._activeNetwork = this._networks[res.network];
-        }
-
-        // we don't refresh the view here, _activeConnectionChanged will
-    },
-
-    _getApSecurityType: function(accessPoint) {
-        if (accessPoint._secType)
-            return accessPoint._secType;
-
-        let flags = accessPoint.flags;
-        let wpa_flags = accessPoint.wpa_flags;
-        let rsn_flags = accessPoint.rsn_flags;
-        let type;
-        if (rsn_flags != NM80211ApSecurityFlags.NONE) {
-            /* RSN check first so that WPA+WPA2 APs are treated as RSN/WPA2 */
-            if (rsn_flags & NM80211ApSecurityFlags.KEY_MGMT_802_1X)
-               type = NMAccessPointSecurity.WPA2_ENT;
-           else if (rsn_flags & NM80211ApSecurityFlags.KEY_MGMT_PSK)
-               type = NMAccessPointSecurity.WPA2_PSK;
-        } else if (wpa_flags != NM80211ApSecurityFlags.NONE) {
-            if (wpa_flags & NM80211ApSecurityFlags.KEY_MGMT_802_1X)
-                type = NMAccessPointSecurity.WPA_ENT;
-            else if (wpa_flags & NM80211ApSecurityFlags.KEY_MGMT_PSK)
-               type = NMAccessPointSecurity.WPA_PSK;
-        } else {
-            if (flags & NM80211ApFlags.PRIVACY)
-                type = NMAccessPointSecurity.WEP;
-            else
-                type = NMAccessPointSecurity.NONE;
-        }
-
-        // cache the found value to avoid checking flags all the time
-        accessPoint._secType = type;
-        return type;
-    },
-
-    _networkSortFunction: function(one, two) {
-        let oneHasConnection = one.connections.length != 0;
-        let twoHasConnection = two.connections.length != 0;
-
-        // place known connections first
-        // (-1 = good order, 1 = wrong order)
-        if (oneHasConnection && !twoHasConnection)
-            return -1;
-        else if (!oneHasConnection && twoHasConnection)
-            return 1;
-
-        let oneStrength = one.accessPoints[0].strength;
-        let twoStrength = two.accessPoints[0].strength;
-
-        // place stronger connections first
-        if (oneStrength != twoStrength)
-            return oneStrength < twoStrength ? 1 : -1;
-
-        let oneHasSecurity = one.security != NMAccessPointSecurity.NONE;
-        let twoHasSecurity = two.security != NMAccessPointSecurity.NONE;
-
-        // place secure connections first
-        // (we treat WEP/WPA/WPA2 the same as there is no way to
-        // take them apart from the UI)
-        if (oneHasSecurity && !twoHasSecurity)
-            return -1;
-        else if (!oneHasSecurity && twoHasSecurity)
-            return 1;
-
-        // sort alphabetically
-        return GLib.utf8_collate(one.ssidText, two.ssidText);
-    },
-
-    _networkCompare: function(network, accessPoint) {
-        if (!ssidCompare(network.ssid, accessPoint.get_ssid()))
-            return false;
-        if (network.mode != accessPoint.mode)
-            return false;
-        if (network.security != this._getApSecurityType(accessPoint))
-            return false;
-
-        return true;
-    },
-
-    _findExistingNetwork: function(accessPoint) {
-        for (let i = 0; i < this._networks.length; i++) {
-            let network = this._networks[i];
-            for (let j = 0; j < network.accessPoints.length; j++) {
-                if (network.accessPoints[j] == accessPoint)
-                    return { network: i, ap: j };
-            }
-        }
-
-        return null;
-    },
-
-    _findNetwork: function(accessPoint) {
-        if (accessPoint.get_ssid() == null)
-            return -1;
-
-        for (let i = 0; i < this._networks.length; i++) {
-            if (this._networkCompare(this._networks[i], accessPoint))
-                return i;
-        }
-        return -1;
-    },
-
-    _onApStrengthChanged: function(ap) {
-        let res = this._findExistingNetwork(ap);
-        if (res == null) {
-            // Uhm... stale signal?
-            return;
-        }
-
-        let network = this._networks[res.network];
-        network.accessPoints.splice(res.ap, 1);
-        Util.insertSorted(network.accessPoints, ap, function(one, two) {
-            return two.strength - one.strength;
-        });
-
-        this._networks.splice(res.network, 1);
-        let newPos = Util.insertSorted(this._networks, network, Lang.bind(this, this._networkSortFunction));
-
-        if (newPos != res.network)
-            this._queueCreateSection();
-    },
-
-    _accessPointAdded: function(device, accessPoint) {
-        if (accessPoint.get_ssid() == null) {
-            // This access point is not visible yet
-            // Wait for it to get a ssid
-            accessPoint._notifySsidId = accessPoint.connect('notify::ssid', Lang.bind(this, 
this._notifySsidCb));
-            return;
-        }
-
-        let pos = this._findNetwork(accessPoint);
-        let network;
-        let needsupdate = false;
-
-        if (pos != -1) {
-            network = this._networks[pos];
-            if (network.accessPoints.indexOf(accessPoint) != -1) {
-                log('Access point was already seen, not adding again');
-                return;
-            }
-
-            Util.insertSorted(network.accessPoints, accessPoint, function(one, two) {
-                return two.strength - one.strength;
-            });
-            if (network.item)
-                network.item.updateBestAP(network.accessPoints[0]);
-        } else {
-            network = { ssid: accessPoint.get_ssid(),
-                        mode: accessPoint.mode,
-                        security: this._getApSecurityType(accessPoint),
-                        connections: [ ],
-                        item: null,
-                        accessPoints: [ accessPoint ]
-                      };
-            network.ssidText = ssidToLabel(network.ssid);
-        }
-        accessPoint._updateId = accessPoint.connect('notify::strength', Lang.bind(this, 
this._onApStrengthChanged));
-
-        // check if this enables new connections for this group
-        for (let i = 0; i < this._connections.length; i++) {
-            let connection = this._connections[i].connection;
-            if (accessPoint.connection_valid(connection) &&
-                network.connections.indexOf(connection) == -1) {
-                network.connections.push(connection);
-            }
-        }
-
-        if (pos != -1)
-            this._networks.splice(pos, 1);
-        let newPos = Util.insertSorted(this._networks, network, this._networkSortFunction);
-
-        // Queue an update of the UI if we changed the order
-        if (newPos != pos)
-            this._queueCreateSection();
-    },
-
-    _accessPointRemoved: function(device, accessPoint) {
-        if (accessPoint._updateId) {
-            accessPoint.disconnect(accessPoint._updateId);
-            accessPoint._updateId = 0;
-        }
-
-        let res = this._findExistingNetwork(accessPoint);
-
-        if (res == null) {
-            log('Removing an access point that was never added');
-            return;
-        }
-
-        let network = this._networks[res.network];
-        network.accessPoints.splice(res.ap, 1);
-
-        if (network.accessPoints.length == 0) {
-            if (this._activeNetwork == network)
-                this._activeNetwork = null;
-
-            if (network.item)
-                network.item.destroy();
-
-            this._networks.splice(res.network, 1);
-        } else {
-            let okPrev = true, okNext = true;
-
-            if (res.network > 0)
-                okPrev = this._networkSortFunction(this._networks[res.network - 1], network) >= 0;
-            if (res.network < this._networks.length-1)
-                okNext = this._networkSortFunction(this._networks[res.network + 1], network) <= 0;
-
-            if (!okPrev || !okNext)
-                this._queueCreateSection();
-            else if (network.item)
-                network.item.updateBestAP(network.accessPoints[0]);
-        }
-    },
-
-    _clearSection: function() {
-        this.parent();
-        for (let i = 0; i < this._networks.length; i++)
-            this._networks[i].item = null;
-    },
-
-    removeConnection: function(connection) {
-        let pos = this._findConnection(connection.get_uuid());
-        if (pos == -1) {
-            // removing connection that was never added
-            return;
-        }
-
-        let obj = this._connections[pos];
-        this._connections.splice(pos, 1);
-
-        let forceupdate = false;
-        for (let i = 0; i < this._networks.length; i++) {
-            let network = this._networks[i];
-            let connections = network.connections;
-            for (let k = 0; k < connections.length; k++) {
-                if (connections[k].get_uuid() == connection.get_uuid()) {
-                    // remove the connection from the access point group
-                    connections.splice(k, 1);
-                    forceupdate = forceupdate || connections.length == 0;
-
-                    if (forceupdate)
-                        break;
-
-                    if (network.item) {
-                        network.item.destroy();
-                        network.item = null;
-                    }
-                    break;
-                }
-            }
-        }
-
-        if (forceupdate) {
-            this._networks.sort(this._networkSortFunction);
-            this._queueCreateSection();
-        }
-    },
-
-    addConnection: function(connection) {
-        // record the connection
-        let obj = {
-            connection: connection,
-            name: connection.get_id(),
-            uuid: connection.get_uuid(),
-        };
-        this._connections.push(obj);
-
-        // find an appropriate access point
-        let forceupdate = false;
-        for (let i = 0; i < this._networks.length; i++) {
-            let network = this._networks[i];
-
-            // Check if connection is valid for any of these access points
-            for (let k = 0; k < network.accessPoints.length; k++) {
-                let ap = network.accessPoints[k];
-                if (ap.connection_valid(connection)) {
-                    network.connections.push(connection);
-                    // this potentially changes the sorting order
-                    forceupdate = true;
-                    break;
-                }
-            }
-        }
-
-        if (forceupdate) {
-            this._networks.sort(this._networkSortFunction);
-            this._queueCreateSection();
-        }
-    },
-
-    _createActiveConnectionItem: function() {
-        let title;
-        if (this._activeConnection && this._activeConnection._connection)
-            title = this._activeConnection._connection.get_id();
-        else
-            title = _("Connected (private)");
-
-        this._activeConnectionItem = new NMNetworkMenuItem(this._device.active_access_point);
-        this._activeConnectionItem.setSensitive(false);
-        this._activeConnectionItem.setOrnament(PopupMenu.Ornament.DOT);
-    },
-
-    _createNetworkItem: function(network, position) {
-        if(!network.accessPoints || network.accessPoints.length == 0) {
-            // this should not happen, but I have no idea why it happens
-            return;
-        }
-
-        network.item = new NMNetworkMenuItem(network.accessPoints[0]);
-        if(network.connections.length > 0) {
-            let connection = network.connections[0];
-            network.item._connection = connection;
-            network.item.connect('activate', Lang.bind(this, function() {
-                let accessPoints = network.accessPoints;
-                for (let i = 0; i < accessPoints.length; i++) {
-                    if (accessPoints[i].connection_valid(connection)) {
-                        this._client.activate_connection(connection, this._device, 
accessPoints[i].dbus_path, null);
-                        break;
-                    }
-                }
-            }));
-        } else {
-            network.item.connect('activate', Lang.bind(this, function() {
-                let accessPoints = network.accessPoints;
-                if (   (accessPoints[0]._secType == NMAccessPointSecurity.WPA2_ENT)
-                    || (accessPoints[0]._secType == NMAccessPointSecurity.WPA_ENT)) {
-                    // 802.1x-enabled APs require further configuration, so they're
-                    // handled in gnome-control-center
-                    Util.spawn(['gnome-control-center', 'network', 'connect-8021x-wifi',
-                                this._device.get_path(), accessPoints[0].dbus_path]);
-                } else {
-                    let connection = new NetworkManager.Connection();
-                    this._client.add_and_activate_connection(connection, this._device, 
accessPoints[0].dbus_path, null)
-                }
-            }));
-        }
-        network.item._network = network;
-
-        this.section.addMenuItem(network.item, position);
-    },
-
-    _createSection: function() {
-        if (!this._shouldShowConnectionList())
-            return;
-
-        if (this._activeNetwork) {
-            this._createActiveConnectionItem();
-            this.section.addMenuItem(this._activeConnectionItem);
-        }
-
-        let activeOffset = this._activeConnectionItem ? 1 : 0;
-
-        for(let j = 0; j < this._networks.length; j++) {
-            let network = this._networks[j];
-            if (network == this._activeNetwork) {
-                activeOffset--;
-                continue;
-            }
-
-            this._createNetworkItem(network, j + activeOffset);
-        }
-    },
-
-    _strengthChanged: function() {
-        this.emit('icon-changed');
-    },
-
-    getIndicatorIcon: function() {
-        if (this._device.active_connection.state == NetworkManager.ActiveConnectionState.ACTIVATING)
-            return 'network-wireless-acquiring-symbolic';
-
-        let ap = this._device.active_access_point;
-        if (!ap) {
-            if (this._device.mode != NM80211Mode.ADHOC)
-                log('An active wireless connection, in infrastructure mode, involves no access point?');
-
-            return 'network-wireless-connected-symbolic';
-        }
-
-        return 'network-wireless-signal-' + signalToIcon(ap.strength) + '-symbolic';
-    },
-});
-
 const NMVPNConnectionItem = new Lang.Class({
     Name: 'NMVPNConnectionItem',
-
-    _init: function(client, connection) {
-        this._client = client;
-        this.connection = connection;
-        this._activeConnection = null;
-        this._activeConnectionChangedId = 0;
-
-        this.menuItem = new PopupMenu.PopupSwitchMenuItem(connection.get_id(), false);
-        this.menuItem.connect('toggled', Lang.bind(this, this._toggle));
-
-        this._sync();
-    },
-
-    destroy: function() {
-        this.menuItem.destroy();
-    },
+    Extends: NMConnectionItem,
 
     isActive: function() {
         if (this._activeConnection == null)
@@ -1067,21 +496,6 @@ const NMVPNConnectionItem = new Lang.Class({
         }
     },
 
-    _toggle: function() {
-        if (this._activeConnection == null)
-            this._client.activate_connection(this.connection, null, null, null);
-        else
-            this._client.deactivate_connection(this._activeConnection);
-
-        this._sync();
-    },
-
-    _sync: function() {
-        this.menuItem.setToggleState(this.isActive());
-        this.menuItem.setStatus(this._getStatus());
-        this.emit('icon-changed');
-    },
-
     _connectionStateChanged: function(ac, newstate, reason) {
         if (newstate == NetworkManager.VPNConnectionState.FAILED &&
             reason != NetworkManager.VPNConnectionStateReason.NO_SECRETS) {
@@ -1091,7 +505,7 @@ const NMVPNConnectionItem = new Lang.Class({
             this.emit('activation-failed', reason);
         }
 
-        this._sync();
+        this.parent();
     },
 
     setActiveConnection: function(activeConnection) {
@@ -1120,41 +534,12 @@ const NMVPNConnectionItem = new Lang.Class({
         }
     },
 });
-Signals.addSignalMethods(NMVPNConnectionItem.prototype);
 
 const NMVPNSection = new Lang.Class({
     Name: 'NMVPNSection',
+    Extends: NMConnectionSection,
     category: NMConnectionCategory.VPN,
 
-    _init: function(client) {
-        this._client = client;
-        this._connectionItems = new Hash.Map();
-
-        this.section = new PopupMenu.PopupMenuSection();
-    },
-
-    checkConnection: function(connection) {
-        if (this._connectionItems.has(connection.get_uuid()))
-            return;
-
-        let item = new NMVPNConnectionItem(this._client, connection);
-
-        item.connect('icon-changed', Lang.bind(this, function() {
-            this.emit('icon-changed');
-        }));
-        item.connect('activation-failed', Lang.bind(this, function(item, reason) {
-            this.emit('activation-failed', reason);
-        }));
-
-        this.section.addMenuItem(item.menuItem);
-        this._connectionItems.set(connection.get_uuid(), item);
-    },
-
-    removeConnection: function(connection) {
-        this._connectionItems.get(connection.get_uuid()).destroy();
-        this._connectionItems.delete(connection.get_uuid());
-    },
-
     addActiveConnection: function(activeConnection) {
         let item = this._connectionItems.get(activeConnection._connection.get_uuid());
         item.setActiveConnection(activeConnection);
@@ -1165,15 +550,8 @@ const NMVPNSection = new Lang.Class({
         item.setActiveConnection(null);
     },
 
-    getIndicatorIcon: function() {
-        let items = this._connectionItems.values();
-        for (let i = 0; i < items.length; i++) {
-            let item = items[i];
-            let icon = item.getIndicatorIcon();
-            if (icon)
-                return icon;
-        }
-        return '';
+    _makeConnectionItem: function(connection) {
+        return new NMVPNConnectionItem(this._client, connection);
     },
 });
 Signals.addSignalMethods(NMVPNSection.prototype);
@@ -1190,7 +568,7 @@ const NMApplet = new Lang.Class({
 
         // Device types
         this._dtypes = { };
-        this._dtypes[NetworkManager.DeviceType.WIFI] = NMDeviceWireless;
+        // this._dtypes[NetworkManager.DeviceType.WIFI] = NMDeviceWireless;
         this._dtypes[NetworkManager.DeviceType.MODEM] = NMDeviceModem;
         this._dtypes[NetworkManager.DeviceType.BT] = NMDeviceModem;
         // TODO: WiMax support
@@ -1331,6 +709,7 @@ const NMApplet = new Lang.Class({
         let wrapperClass = this._dtypes[device.get_device_type()];
         if (wrapperClass) {
             let wrapper = new wrapperClass(this._client, device, this._settings);
+            device._delegate = wrapper;
             this._addDeviceWrapper(wrapper);
 
             this._nmDevices.push(device);



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