[polari/wip/fmuellner/connection-list: 5/8] connections: Add ConnectionsList



commit d552bbe05755ad114b13fefeafd330f7069f4de8
Author: Florian Müllner <fmuellner gnome org>
Date:   Fri Feb 5 06:03:50 2016 +0100

    connections: Add ConnectionsList
    
    This is a widget that displays predefined networks as a scrollable
    list and creates a new account with default parameters when an entry
    is activated.

 src/connections.js     |  135 ++++++++++++++++++++++++++++++++++++++++++++++++
 src/networksManager.js |   36 +++++++++++++
 2 files changed, 171 insertions(+), 0 deletions(-)
---
diff --git a/src/connections.js b/src/connections.js
index f047c88..cee4f04 100644
--- a/src/connections.js
+++ b/src/connections.js
@@ -3,7 +3,9 @@ const GObject = imports.gi.GObject;
 const Gtk = imports.gi.Gtk;
 const Tp = imports.gi.TelepathyGLib;
 
+const AccountsMonitor = imports.accountsMonitor;
 const Lang = imports.lang;
+const NetworksManager = imports.networksManager;
 const Signals = imports.signals;
 
 const ErrorHint = {
@@ -12,6 +14,139 @@ const ErrorHint = {
     NICK: 2
 };
 
+const ConnectionRow = new Lang.Class({
+    Name: 'ConnectionRow',
+    Extends: Gtk.ListBoxRow,
+
+    _init: function(params) {
+        if (!params || !params.id)
+            throw new Error('No id in parameters');
+
+        this._id = params.id;
+        delete params.id;
+
+        this.parent(params);
+
+        this.bind_property('sensitive', this, 'activatable',
+                           GObject.BindingFlags.SYNC_CREATE);
+
+        let box = new Gtk.Box({ spacing: 12, margin: 12 });
+        this.add(box);
+
+        let name = NetworksManager.getDefault().getNetworkName(this._id);
+        box.add(new Gtk.Label({ label: name, halign: Gtk.Align.START }));
+
+        let insensitiveDesc = new Gtk.Label({ label: _("Already added"),
+                                              hexpand: true,
+                                              halign: Gtk.Align.END });
+        box.add(insensitiveDesc);
+
+        this.show_all();
+
+        this.bind_property('sensitive', insensitiveDesc, 'visible',
+                           GObject.BindingFlags.SYNC_CREATE |
+                           GObject.BindingFlags.INVERT_BOOLEAN);
+    },
+
+    get id() {
+        return this._id;
+    }
+});
+
+const ConnectionsList = new Lang.Class({
+    Name: 'ConnectionsList',
+    Extends: Gtk.ScrolledWindow,
+    Signals: { 'account-created': { param_types: [Tp.Account.$gtype] },
+               'account-selected': {}},
+
+    _init: function(params) {
+        this.parent(params);
+
+        this.hscrollbar_policy = Gtk.PolicyType.NEVER;
+
+        this._list = new Gtk.ListBox({ visible: true });
+        this._list.connect('row-activated',
+                           Lang.bind(this, this._onRowActivated));
+        this.add(this._list);
+
+        this._rows = new Map();
+
+        this._list.set_header_func(Lang.bind(this, this._updateHeader));
+
+        this._accountsMonitor = AccountsMonitor.getDefault();
+        this._accountsMonitor.connect('account-added', Lang.bind(this,
+            function(mon, account) {
+                this._setAccountRowSensitive(account, false);
+            }));
+        this._accountsMonitor.connect('account-removed', Lang.bind(this,
+            function(mon, account) {
+                this._setAccountRowSensitive(account, true);
+            }));
+
+        this._networksManager = NetworksManager.getDefault();
+        this._networksManager.connect('changed',
+                                      Lang.bind(this, this._networksChanged));
+        this._networksChanged();
+    },
+
+    _updateHeader: function(row, before) {
+        if (!before)
+            row.set_header(null);
+        else if (!row.get_header())
+            row.set_header(new Gtk.Separator());
+    },
+
+    _networksChanged: function() {
+        this._list.foreach(function(w) { w.destroy(); });
+
+        let accounts = this._accountsMonitor.dupAccounts();
+        let usedNetworks = accounts.filter(Lang.bind(this, function(a) {
+            return this._networksManager.getAccountIsPredefined(a);
+        })).map(function(a) {
+            return a.service;
+        });
+
+        this._networksManager.networks.forEach(Lang.bind(this,
+            function(network) {
+                let sensitive = usedNetworks.indexOf(network.id) < 0;
+                this._rows.set(network.id,
+                               new ConnectionRow({ id: network.id,
+                                                   sensitive: sensitive }));
+                this._list.add(this._rows.get(network.id));
+            }));
+    },
+
+    _onRowActivated: function(list, row) {
+        let name = this._networksManager.getNetworkName(row.id);
+        let req = new Tp.AccountRequest({ account_manager: Tp.AccountManager.dup(),
+                                          connection_manager: 'idle',
+                                          protocol: 'irc',
+                                          display_name: name });
+        req.set_service(row.id);
+        req.set_enabled(true);
+
+        let details = this._networksManager.getNetworkDetails(row.id);
+
+        for (let prop in details)
+            req.set_parameter(prop, details[prop]);
+
+        req.create_account_async(Lang.bind(this,
+            function(r, res) {
+                let account = req.create_account_finish(res);
+                if (account) // TODO: Handle errors
+                    this.emit('account-created', account);
+            }));
+        this.emit('account-selected');
+    },
+
+    _setAccountRowSensitive: function(account, sensitive) {
+        if (!this._networksManager.getAccountIsPredefined(account))
+            return;
+
+        this._rows.get(account.service).sensitive = sensitive;
+    }
+});
+
 const ConnectionDetails = new Lang.Class({
     Name: 'ConnectionDetails',
     Extends: Gtk.Grid,
diff --git a/src/networksManager.js b/src/networksManager.js
index 74015b7..c099a24 100644
--- a/src/networksManager.js
+++ b/src/networksManager.js
@@ -17,6 +17,7 @@ const NetworksManager = new Lang.Class({
 
     _init: function() {
         this._networks = [];
+        this._networksById = new Map();
 
         let uri = 'resource:///org/gnome/Polari/data/networks.json';
         let file = Gio.File.new_for_uri(uri);
@@ -41,11 +42,46 @@ const NetworksManager = new Lang.Class({
         }
 
         this._networks = networks;
+        this._networks.forEach(Lang.bind(this,
+            function(network) {
+                this._networksById.set(network.id, network);
+            }));
         this.emit('changed');
     },
 
+    _lookupNetwork: function(id) {
+        let network = this._networksById.get(id);
+        if (!network)
+            throw new Error('Invalid network ID');
+        return network;
+    },
+
     get networks() {
         return this._networks;
+    },
+
+    getAccountIsPredefined: function(account) {
+        return account && this._networksById.get(account.service) != null;
+    },
+
+    getNetworkName: function(id) {
+        return this._lookupNetwork(id).name;
+    },
+
+    getNetworkDetails: function(id) {
+        let network = this._lookupNetwork(id);
+        if (!network.servers || !network.servers.length)
+            throw new Error('No servers for network ' + id);
+
+        let sslServers = network.servers.filter(function(s) { return s.ssl; });
+        let server = sslServers.length > 0 ? sslServers[0]
+                                           : network.servers[0];
+        return {
+            'account': new GLib.Variant('s', GLib.get_user_name()),
+            'server': new GLib.Variant('s', server.address),
+            'port': new GLib.Variant('u', server.port),
+            'use-ssl': new GLib.Variant('b', server.ssl),
+        };
     }
 });
 Signals.addSignalMethods(NetworksManager.prototype);


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