[polari] Implement connections list



commit 4d4992e9b44cb6d51bd68ab269de19108660b52a
Author: Florian Müllner <florian muellner gmail com>
Date:   Sun Jul 21 13:08:42 2013 +0200

    Implement connections list

 data/polari.gresource.xml                   |    2 +
 data/resources/connection-details-dialog.ui |  234 ++++++++++++++++++++++
 data/resources/connection-list-dialog.ui    |  217 +++++++++++++++++++++
 data/resources/join-room-dialog.ui          |    4 +-
 po/POTFILES.in                              |    2 +
 src/Makefile.am                             |    1 +
 src/application.js                          |    7 +
 src/connections.js                          |  278 +++++++++++++++++++++++++++
 8 files changed, 743 insertions(+), 2 deletions(-)
---
diff --git a/data/polari.gresource.xml b/data/polari.gresource.xml
index 8fd5640..7ecc781 100644
--- a/data/polari.gresource.xml
+++ b/data/polari.gresource.xml
@@ -2,6 +2,8 @@
 <gresources>
   <gresource prefix="/org/gnome/polari">
     <file alias="app-menu.ui" preprocess="xml-stripblanks">resources/app-menu.ui</file>
+    <file alias="connection-details-dialog.ui" 
preprocess="xml-stripblanks">resources/connection-details-dialog.ui</file>
+    <file alias="connection-list-dialog.ui" 
preprocess="xml-stripblanks">resources/connection-list-dialog.ui</file>
     <file alias="join-room-dialog.ui" preprocess="xml-stripblanks">resources/join-room-dialog.ui</file>
     <file alias="main-window.ui" preprocess="xml-stripblanks">resources/main-window.ui</file>
     <file alias="application.css">resources/application.css</file>
diff --git a/data/resources/connection-details-dialog.ui b/data/resources/connection-details-dialog.ui
new file mode 100644
index 0000000..c7bf329
--- /dev/null
+++ b/data/resources/connection-details-dialog.ui
@@ -0,0 +1,234 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<interface>
+  <!-- interface-requires gtk+ 3.10 -->
+  <object class="GtkDialog" id="connection_details_dialog">
+    <property name="can_focus">False</property>
+    <property name="title" translatable="yes">New Connection</property>
+    <property name="modal">True</property>
+    <property name="destroy_with_parent">True</property>
+    <property name="type_hint">dialog</property>
+    <child internal-child="vbox">
+      <object class="GtkBox" id="dialog-vbox1">
+        <property name="can_focus">False</property>
+        <property name="orientation">vertical</property>
+        <property name="spacing">2</property>
+        <child internal-child="action_area">
+          <object class="GtkButtonBox" id="dialog-action_area1">
+            <property name="can_focus">False</property>
+            <property name="layout_style">end</property>
+            <child>
+              <object class="GtkButton" id="cancel_button">
+                <property name="label" translatable="yes">_Cancel</property>
+                <property name="visible">True</property>
+                <property name="can_focus">True</property>
+                <property name="receives_default">True</property>
+                <property name="use_underline">True</property>
+              </object>
+              <packing>
+                <property name="expand">False</property>
+                <property name="fill">True</property>
+                <property name="position">0</property>
+              </packing>
+            </child>
+            <child>
+              <object class="GtkButton" id="confirm_button">
+                <property name="label" translatable="yes">Cr_eate</property>
+                <property name="visible">True</property>
+                <property name="can_focus">True</property>
+                <property name="can_default">True</property>
+                <property name="has_default">True</property>
+                <property name="receives_default">True</property>
+                <property name="use_underline">True</property>
+              </object>
+              <packing>
+                <property name="expand">False</property>
+                <property name="fill">True</property>
+                <property name="position">1</property>
+              </packing>
+            </child>
+          </object>
+          <packing>
+            <property name="expand">False</property>
+            <property name="fill">True</property>
+            <property name="pack_type">end</property>
+            <property name="position">0</property>
+          </packing>
+        </child>
+        <child>
+          <object class="GtkGrid" id="grid1">
+            <property name="visible">True</property>
+            <property name="can_focus">False</property>
+            <property name="halign">center</property>
+            <property name="margin_left">96</property>
+            <property name="margin_right">96</property>
+            <property name="margin_top">12</property>
+            <property name="margin_bottom">48</property>
+            <property name="row_spacing">12</property>
+            <property name="column_spacing">12</property>
+            <child>
+              <object class="GtkLabel" id="label1">
+                <property name="visible">True</property>
+                <property name="can_focus">False</property>
+                <property name="label" translatable="yes">Server</property>
+                <attributes>
+                  <attribute name="weight" value="bold"/>
+                </attributes>
+              </object>
+              <packing>
+                <property name="left_attach">0</property>
+                <property name="top_attach">0</property>
+                <property name="width">2</property>
+                <property name="height">1</property>
+              </packing>
+            </child>
+            <child>
+              <object class="GtkLabel" id="server_label">
+                <property name="visible">True</property>
+                <property name="can_focus">False</property>
+                <property name="halign">end</property>
+                <property name="label" translatable="yes">_Address</property>
+                <property name="use_underline">True</property>
+                <property name="mnemonic_widget">server_entry</property>
+              </object>
+              <packing>
+                <property name="left_attach">0</property>
+                <property name="top_attach">1</property>
+                <property name="width">1</property>
+                <property name="height">1</property>
+              </packing>
+            </child>
+            <child>
+              <object class="GtkLabel" id="description_label">
+                <property name="visible">True</property>
+                <property name="can_focus">False</property>
+                <property name="halign">end</property>
+                <property name="label" translatable="yes">_Description</property>
+                <property name="use_underline">True</property>
+                <property name="mnemonic_widget">description_entry</property>
+              </object>
+              <packing>
+                <property name="left_attach">0</property>
+                <property name="top_attach">2</property>
+                <property name="width">1</property>
+                <property name="height">1</property>
+              </packing>
+            </child>
+            <child>
+              <object class="GtkLabel" id="label2">
+                <property name="visible">True</property>
+                <property name="can_focus">False</property>
+                <property name="margin_top">24</property>
+                <property name="label" translatable="yes">Identity</property>
+                <attributes>
+                  <attribute name="weight" value="bold"/>
+                </attributes>
+              </object>
+              <packing>
+                <property name="left_attach">0</property>
+                <property name="top_attach">3</property>
+                <property name="width">2</property>
+                <property name="height">1</property>
+              </packing>
+            </child>
+            <child>
+              <object class="GtkLabel" id="nickname_label">
+                <property name="visible">True</property>
+                <property name="can_focus">False</property>
+                <property name="halign">end</property>
+                <property name="label" translatable="yes">_Nickname</property>
+                <property name="use_underline">True</property>
+                <property name="mnemonic_widget">nickname_entry</property>
+              </object>
+              <packing>
+                <property name="left_attach">0</property>
+                <property name="top_attach">4</property>
+                <property name="width">1</property>
+                <property name="height">1</property>
+              </packing>
+            </child>
+            <child>
+              <object class="GtkLabel" id="realname_label">
+                <property name="visible">True</property>
+                <property name="can_focus">False</property>
+                <property name="halign">end</property>
+                <property name="label" translatable="yes">_Real Name</property>
+                <property name="use_underline">True</property>
+                <property name="mnemonic_widget">realname_entry</property>
+              </object>
+              <packing>
+                <property name="left_attach">0</property>
+                <property name="top_attach">5</property>
+                <property name="width">1</property>
+                <property name="height">1</property>
+              </packing>
+            </child>
+            <child>
+              <object class="GtkEntry" id="realname_entry">
+                <property name="visible">True</property>
+                <property name="can_focus">True</property>
+                <property name="activates_default">True</property>
+                <property name="placeholder_text" translatable="yes">optional</property>
+              </object>
+              <packing>
+                <property name="left_attach">1</property>
+                <property name="top_attach">5</property>
+                <property name="width">1</property>
+                <property name="height">1</property>
+              </packing>
+            </child>
+            <child>
+              <object class="GtkEntry" id="nickname_entry">
+                <property name="visible">True</property>
+                <property name="can_focus">True</property>
+                <property name="can_default">True</property>
+                <property name="activates_default">True</property>
+              </object>
+              <packing>
+                <property name="left_attach">1</property>
+                <property name="top_attach">4</property>
+                <property name="width">1</property>
+                <property name="height">1</property>
+              </packing>
+            </child>
+            <child>
+              <object class="GtkEntry" id="description_entry">
+                <property name="visible">True</property>
+                <property name="can_focus">True</property>
+                <property name="activates_default">True</property>
+                <property name="placeholder_text" translatable="yes">optional</property>
+              </object>
+              <packing>
+                <property name="left_attach">1</property>
+                <property name="top_attach">2</property>
+                <property name="width">1</property>
+                <property name="height">1</property>
+              </packing>
+            </child>
+            <child>
+              <object class="GtkEntry" id="server_entry">
+                <property name="visible">True</property>
+                <property name="can_focus">True</property>
+                <property name="activates_default">True</property>
+              </object>
+              <packing>
+                <property name="left_attach">1</property>
+                <property name="top_attach">1</property>
+                <property name="width">1</property>
+                <property name="height">1</property>
+              </packing>
+            </child>
+          </object>
+          <packing>
+            <property name="expand">False</property>
+            <property name="fill">True</property>
+            <property name="position">1</property>
+          </packing>
+        </child>
+      </object>
+    </child>
+    <action-widgets>
+      <action-widget response="-6">cancel_button</action-widget>
+      <action-widget response="-5">confirm_button</action-widget>
+    </action-widgets>
+  </object>
+</interface>
diff --git a/data/resources/connection-list-dialog.ui b/data/resources/connection-list-dialog.ui
new file mode 100644
index 0000000..65845ab
--- /dev/null
+++ b/data/resources/connection-list-dialog.ui
@@ -0,0 +1,217 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<interface>
+  <!-- interface-requires gtk+ 3.10 -->
+  <object class="GtkDialog" id="connection_list_dialog">
+    <property name="can_focus">False</property>
+    <property name="title" translatable="yes">Connections</property>
+    <property name="modal">True</property>
+    <property name="default_width">320</property>
+    <property name="default_height">260</property>
+    <property name="destroy_with_parent">True</property>
+    <property name="type_hint">dialog</property>
+    <child internal-child="vbox">
+      <object class="GtkBox" id="dialog-vbox1">
+        <property name="can_focus">False</property>
+        <property name="orientation">vertical</property>
+        <property name="spacing">2</property>
+        <child internal-child="action_area">
+          <object class="GtkButtonBox" id="dialog-action_area1">
+            <property name="can_focus">False</property>
+            <property name="layout_style">end</property>
+            <child>
+              <object class="GtkButton" id="button3">
+                <property name="label" translatable="yes">_Close</property>
+                <property name="visible">True</property>
+                <property name="can_focus">True</property>
+                <property name="receives_default">True</property>
+                <property name="use_underline">True</property>
+              </object>
+              <packing>
+                <property name="expand">False</property>
+                <property name="fill">True</property>
+                <property name="position">1</property>
+              </packing>
+            </child>
+          </object>
+          <packing>
+            <property name="expand">False</property>
+            <property name="fill">True</property>
+            <property name="pack_type">end</property>
+            <property name="position">0</property>
+          </packing>
+        </child>
+        <child>
+          <object class="GtkBox" id="box1">
+            <property name="visible">True</property>
+            <property name="can_focus">False</property>
+            <property name="margin_left">6</property>
+            <property name="margin_right">6</property>
+            <property name="orientation">vertical</property>
+            <child>
+              <object class="GtkScrolledWindow" id="scrolledwindow1">
+                <property name="visible">True</property>
+                <property name="can_focus">True</property>
+                <property name="hexpand">True</property>
+                <property name="vexpand">True</property>
+                <property name="hscrollbar_policy">never</property>
+                <property name="shadow_type">in</property>
+                <child>
+                  <object class="GtkListBox" id="accounts_list">
+                    <property name="visible">True</property>
+                    <property name="can_focus">True</property>
+                    <property name="selection_mode">single</property>
+                    <child>
+                      <placeholder/>
+                    </child>
+                  </object>
+                </child>
+              </object>
+              <packing>
+                <property name="expand">False</property>
+                <property name="fill">True</property>
+                <property name="position">0</property>
+              </packing>
+            </child>
+            <child>
+              <object class="GtkToolbar" id="toolbar1">
+                <property name="visible">True</property>
+                <property name="can_focus">False</property>
+                <style>
+                  <class name="inline-toolbar"/>
+                </style>
+                <child>
+                  <object class="GtkToolItem" id="toolbutton1">
+                    <property name="visible">True</property>
+                    <property name="can_focus">False</property>
+                    <child>
+                      <object class="GtkBox" id="box2">
+                        <property name="visible">True</property>
+                        <property name="can_focus">False</property>
+                        <child>
+                          <object class="GtkButton" id="add_button">
+                            <property name="visible">True</property>
+                            <property name="can_focus">True</property>
+                            <property name="receives_default">True</property>
+                            <child internal-child="accessible">
+                              <object class="AtkObject" id="add_button-atkobject">
+                                <property name="AtkObject::accessible-name" translatable="yes">Add</property>
+                              </object>
+                            </child>
+                            <child>
+                              <object class="GtkImage" id="image1">
+                                <property name="visible">True</property>
+                                <property name="can_focus">False</property>
+                                <property name="icon_name">list-add-symbolic</property>
+                                <property name="icon_size">1</property>
+                              </object>
+                            </child>
+                          </object>
+                          <packing>
+                            <property name="expand">False</property>
+                            <property name="fill">True</property>
+                            <property name="position">0</property>
+                          </packing>
+                        </child>
+                        <child>
+                          <object class="GtkButton" id="remove_button">
+                            <property name="visible">True</property>
+                            <property name="can_focus">True</property>
+                            <property name="receives_default">True</property>
+                            <child internal-child="accessible">
+                              <object class="AtkObject" id="remove_button-atkobject">
+                                <property name="AtkObject::accessible-name" 
translatable="yes">Remove</property>
+                              </object>
+                            </child>
+                            <child>
+                              <object class="GtkImage" id="image2">
+                                <property name="visible">True</property>
+                                <property name="can_focus">False</property>
+                                <property name="icon_name">list-remove-symbolic</property>
+                                <property name="icon_size">1</property>
+                              </object>
+                            </child>
+                          </object>
+                          <packing>
+                            <property name="expand">False</property>
+                            <property name="fill">True</property>
+                            <property name="position">1</property>
+                          </packing>
+                        </child>
+                      </object>
+                    </child>
+                  </object>
+                  <packing>
+                    <property name="expand">False</property>
+                    <property name="homogeneous">True</property>
+                  </packing>
+                </child>
+                <child>
+                  <object class="GtkSeparatorToolItem" id="toolbutton2">
+                    <property name="visible">True</property>
+                    <property name="can_focus">False</property>
+                    <property name="draw">False</property>
+                  </object>
+                  <packing>
+                    <property name="expand">True</property>
+                    <property name="homogeneous">True</property>
+                  </packing>
+                </child>
+                <child>
+                  <object class="GtkToolItem" id="toolbutton3">
+                    <property name="visible">True</property>
+                    <property name="can_focus">False</property>
+                    <child>
+                      <object class="GtkBox" id="box3">
+                        <property name="visible">True</property>
+                        <property name="can_focus">False</property>
+                        <property name="orientation">vertical</property>
+                        <child>
+                          <object class="GtkButton" id="edit_button">
+                            <property name="visible">True</property>
+                            <property name="can_focus">True</property>
+                            <property name="receives_default">True</property>
+                            <property name="halign">end</property>
+                            <child>
+                              <object class="GtkImage" id="image3">
+                                <property name="visible">True</property>
+                                <property name="can_focus">False</property>
+                                <property name="icon_name">preferences-system-symbolic</property>
+                                <property name="icon_size">1</property>
+                              </object>
+                            </child>
+                          </object>
+                          <packing>
+                            <property name="expand">False</property>
+                            <property name="fill">True</property>
+                            <property name="position">0</property>
+                          </packing>
+                        </child>
+                      </object>
+                    </child>
+                  </object>
+                  <packing>
+                    <property name="expand">False</property>
+                    <property name="homogeneous">True</property>
+                  </packing>
+                </child>
+              </object>
+              <packing>
+                <property name="expand">False</property>
+                <property name="fill">True</property>
+                <property name="position">1</property>
+              </packing>
+            </child>
+          </object>
+          <packing>
+            <property name="expand">False</property>
+            <property name="fill">True</property>
+            <property name="position">1</property>
+          </packing>
+        </child>
+      </object>
+    </child>
+    <action-widgets>
+      <action-widget response="-7">button3</action-widget>
+    </action-widgets>
+  </object>
+</interface>
diff --git a/data/resources/join-room-dialog.ui b/data/resources/join-room-dialog.ui
index 9e7e4ce..46356fd 100644
--- a/data/resources/join-room-dialog.ui
+++ b/data/resources/join-room-dialog.ui
@@ -19,11 +19,11 @@
             <property name="layout_style">end</property>
             <child>
               <object class="GtkButton" id="cancel_button">
-                <property name="label">gtk-cancel</property>
+                <property name="label" translatable="yes">_Cancel</property>
                 <property name="visible">True</property>
                 <property name="can_focus">True</property>
                 <property name="receives_default">True</property>
-                <property name="use_stock">True</property>
+                <property name="use_underline">True</property>
               </object>
               <packing>
                 <property name="expand">False</property>
diff --git a/po/POTFILES.in b/po/POTFILES.in
index 6ce2f0c..1d7e731 100644
--- a/po/POTFILES.in
+++ b/po/POTFILES.in
@@ -1,5 +1,7 @@
 data/polari.desktop.in
 [type: gettext/glade]data/resources/app-menu.ui
+[type: gettext/glade]data/resources/connection-details-dialog.ui
+[type: gettext/glade]data/resources/connection-list-dialog.ui
 [type: gettext/glade]data/resources/join-room-dialog.ui
 [type: gettext/glade]data/resources/main-window.ui
 src/application.js
diff --git a/src/Makefile.am b/src/Makefile.am
index 376f833..69fb719 100644
--- a/src/Makefile.am
+++ b/src/Makefile.am
@@ -30,6 +30,7 @@ dist_js_DATA = \
        application.js \
        chatroomManager.js \
        chatView.js \
+       connections.js \
        main.js \
        mainWindow.js \
        roomList.js \
diff --git a/src/application.js b/src/application.js
index 89f456c..f48fc8e 100644
--- a/src/application.js
+++ b/src/application.js
@@ -3,6 +3,7 @@ const GLib = imports.gi.GLib;
 const Gtk = imports.gi.Gtk;
 
 const Config = imports.config;
+const Connections = imports.connections;
 const Format = imports.format;
 const Lang = imports.lang;
 const MainWindow = imports.mainWindow;
@@ -68,6 +69,12 @@ const Application = new Lang.Class({
     },
 
     _listConnections: function() {
+        let dialog = new Connections.ConnectionsDialog();
+        dialog.widget.show();
+        dialog.widget.connect('response',
+            function(widget) {
+                widget.destroy();
+            });
     },
 
     _showPreferences: function() {
diff --git a/src/connections.js b/src/connections.js
new file mode 100644
index 0000000..bbbb05d
--- /dev/null
+++ b/src/connections.js
@@ -0,0 +1,278 @@
+const Gio = imports.gi.Gio;
+const GLib = imports.gi.GLib;
+const GObject = imports.gi.GObject;
+const Gtk = imports.gi.Gtk;
+const Tp = imports.gi.TelepathyGLib;
+
+const Lang = imports.lang;
+
+const ConnectionsDialog = new Lang.Class({
+    Name: 'ConnectionsDialog',
+
+    _init: function() {
+        this._createWindow();
+        this._prepareAccountManager();
+    },
+
+    _createWindow: function() {
+        let app = Gio.Application.get_default();
+
+        let builder = new Gtk.Builder();
+        builder.add_from_resource('/org/gnome/polari/connection-list-dialog.ui');
+
+        this.widget = builder.get_object('connection_list_dialog');
+        this.widget.transient_for = app.get_active_window();
+
+        this._listBox = builder.get_object('accounts_list');
+        this._stack = builder.get_object('stack');
+
+        let addButton = builder.get_object('add_button');
+        addButton.connect('clicked', Lang.bind(this, this._addConnection));
+
+        let remButton = builder.get_object('remove_button');
+        remButton.connect('clicked', Lang.bind(this, this._removeConnection));
+        remButton.sensitive = false;
+
+        let editButton = builder.get_object('edit_button');
+        editButton.connect('clicked', Lang.bind(this, this._editConnection));
+        editButton.sensitive = false;
+
+        this._listBox.connect('row-selected',
+            function(w, row) {
+                remButton.sensitive = row != null;
+                editButton.sensitive = row != null;
+            });
+        this.widget.connect('destroy', Lang.bind(this, this._onDestroy));
+    },
+
+    _prepareAccountManager: function() {
+        this._accountMgr = Tp.AccountManager.dup();
+
+        this._accountValidityChangedId =
+            this._accountMgr.connect('account-validity-changed', Lang.bind(this,
+                function(am, account, valid) {
+                    if (valid)
+                        this._addAccount(account);
+                    else
+                        this._removeAccount(account);
+                }));
+        this._accountRemovedId =
+            this._accountMgr.connect('account-removed', Lang.bind(this,
+                function(am, account) {
+                    this._removeAccount(account);
+                }));
+
+        this._accountMgr.prepare_async(null, Lang.bind(this,
+            function(am) {
+                am.dup_valid_accounts().filter(
+                    function(a) {
+                        return a.protocol_name == 'irc';
+                }).forEach(Lang.bind(this, this._addAccount));
+            }));
+    },
+
+    _addAccount: function(account) {
+        let row = new Gtk.ListBoxRow();
+        row._account = account;
+
+        let box = new Gtk.Box({ orientation: Gtk.Orientation.HORIZONTAL,
+                                spacing: 6, margin: 6 });
+        row.add(box);
+
+        let label = new Gtk.Label({ hexpand: true, halign: Gtk.Align.START });
+        box.add(label);
+
+        let sw = new Gtk.Switch();
+        box.add(sw);
+
+        this._listBox.add(row);
+        row.show_all();
+
+        account.bind_property('display-name', label, 'label',
+                              GObject.BindingFlags.SYNC_CREATE);
+        account.bind_property('enabled', sw, 'active',
+                              GObject.BindingFlags.SYNC_CREATE);
+
+        sw.connect('notify::active',
+            function() {
+                account.set_enabled_async(sw.active, null);
+            });
+    },
+
+    _removeAccount: function(account) {
+        let rows = this._listBox.get_children();
+        for (let i = 0; i < rows.length; i++)
+            if (rows[i]._account == account) {
+                rows[i].destroy();
+                return;
+            }
+    },
+
+    _addConnection: function() {
+        this._showConnectionDetailsDialog(null,
+                                          Lang.bind(this,
+                                                    this._createAccount));
+    },
+
+    _removeConnection: function() {
+        let row = this._listBox.get_selected_row();
+        row._account.remove_async(Lang.bind(this,
+            function(a, res) {
+                a.remove_finish(res); // TODO: Check for errors
+            }));
+    },
+
+    _editConnection: function() {
+        let account = this._listBox.get_selected_row()._account;
+        this._showConnectionDetailsDialog(account,
+                                          Lang.bind(this,
+                                                    this._updateAccount,
+                                                    account));
+    },
+
+    _createAccount: function(params) {
+        let req = new Tp.AccountRequest({ account_manager: this._accountMgr,
+                                          connection_manager: 'idle',
+                                          protocol: 'irc',
+                                          display_name: params.name });
+
+        let [details,] = this._detailsFromParams(params, {});
+
+        for (let prop in details)
+            req.set_parameter(prop, details[prop]);
+
+        req.create_account_async(Lang.bind(this,
+            function(r, res) {
+                req.create_account_finish(res); // TODO: Check for errors
+            }));
+    },
+
+    _updateAccount: function(params, account) {
+        let oldDetails = account.dup_parameters_vardict().deep_unpack();
+        let [details, removed] = this._detailsFromParams(params, oldDetails);
+        let vardict = GLib.Variant.new('a{sv}', details);
+
+        account.update_parameters_vardict_async(vardict, removed,
+            Lang.bind(this, function(a, res) {
+                a.update_parameters_vardict_finish(res); // TODO: Check for errors
+            }));
+
+        account.set_display_name_async(params.name, Lang.bind(this,
+            function(a, res) {
+                a.set_display_name_finish(res); // TODO: Check for errors
+            }));
+    },
+
+    _detailsFromParams: function(params, oldDetails) {
+        let details = { account: GLib.Variant.new('s', params.account),
+                        server:  GLib.Variant.new('s', params.server) };
+
+        if (params.port)
+            details.port = GLib.Variant.new('u', params.port);
+        if (params.fullname)
+            details.fullname = GLib.Variant.new('s', params.fullname);
+
+        let removed = Object.keys(oldDetails).filter(
+                function(p) {
+                    return !details.hasOwnProperty(p);
+                });
+
+        return [details, removed];
+    },
+
+    _showConnectionDetailsDialog: function(account, callback) {
+        let dialog = new ConnectionDetailsDialog(account);
+        dialog.widget.transient_for = this.widget;
+        dialog.widget.show();
+        dialog.widget.connect('response',
+            function(w, response) {
+                if (response == Gtk.ResponseType.OK)
+                    callback(dialog.getParams());
+                dialog.widget.destroy();
+            });
+    },
+
+    _onDestroy: function() {
+        this._accountMgr.disconnect(this._accountValidityChangedId);
+        this._accountMgr.disconnect(this._accountRemovedId);
+    }
+});
+
+const ConnectionDetailsDialog = new Lang.Class({
+    Name: 'ConnectionDetailsDialog',
+
+    _init: function(account) {
+        this._createWindow();
+
+        if (account) {
+            this.widget.title = 'Edit Connection';
+            this._confirmButton.label = 'Apply';
+
+            this._populateFromAccount(account);
+        }
+    },
+
+    getParams: function() {
+        let serverRegEx = /(.*?)(?::(\d{1,5}))?$/;
+        let [, server, port] = this._serverEntry.text.match(serverRegEx);
+
+        let params = {
+            name: this._descEntry.text.length ? this._descEntry.text : server,
+            server: server,
+            account: this._nickEntry.text
+        };
+
+        if (port)
+            params.port = port;
+        if (this._realnameEntry.text)
+            params.fullname = this._realnameEntry.text;
+
+        return params;
+    },
+
+    _createWindow: function() {
+        let builder = new Gtk.Builder();
+        builder.add_from_resource('/org/gnome/polari/connection-details-dialog.ui');
+
+        this.widget = builder.get_object('connection_details_dialog');
+
+        this._serverEntry = builder.get_object('server_entry');
+        this._descEntry = builder.get_object('description_entry');
+        this._nickEntry = builder.get_object('nickname_entry');
+        this._realnameEntry = builder.get_object('realname_entry');
+        this._confirmButton = builder.get_object('confirm_button');
+
+        this._serverEntry.connect('changed',
+                                  Lang.bind(this, this._updateSensitivity));
+        this._nickEntry.connect('changed',
+                                Lang.bind(this, this._updateSensitivity));
+        this._updateSensitivity();
+    },
+
+    _updateSensitivity: function() {
+        let sensitive = this._serverEntry.get_text_length() > 0 &&
+                        this._nickEntry.get_text_length() > 0;
+        this._confirmButton.sensitive = sensitive;
+    },
+
+    _populateFromAccount: function(account) {
+        let params = account.dup_parameters_vardict().deep_unpack();
+        for (let p in params)
+            params[p] = params[p].deep_unpack();
+
+        let server = params.server || '';
+        let port = params.port || 6667;
+        let nick = params.account || '';
+        let realname = params.fullname || '';
+
+        if (port != 6667)
+            server += ':%d'.format(port);
+
+        this._serverEntry.text = server;
+        this._nickEntry.text = nick;
+        this._realnameEntry.text = realname;
+
+        if (server != account.display_name)
+            this._descEntry.text = account.display_name;
+    }
+});


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