[polari/wip/fmuellner/connection-list: 7/8] joinDialog: Allow filtering predefined connections



commit 649ab9e12720f4f45d45fcfc8d3bea276f7ad056
Author: Florian Müllner <fmuellner gnome org>
Date:   Fri Feb 5 06:33:05 2016 +0100

    joinDialog: Allow filtering predefined connections
    
    The list of connections is quite extensive, which makes it hard to
    navigate. Address this by adding a filter entry which follows the
    preferred search pattern: The searched text is split into words and
    only items that match all terms are displayed, which allows to
    quickly narrow down the number of items.
    
    https://bugzilla.gnome.org/show_bug.cgi?id=761859

 data/resources/application.css     |    5 +++++
 data/resources/join-room-dialog.ui |   31 +++++++++++++++++++++++++++++--
 src/connections.js                 |   20 ++++++++++++++++++++
 src/joinDialog.js                  |   18 ++++++++++++++++++
 src/networksManager.js             |    9 +++++++++
 5 files changed, 81 insertions(+), 2 deletions(-)
---
diff --git a/data/resources/application.css b/data/resources/application.css
index 059bf0a..ee2ac92 100644
--- a/data/resources/application.css
+++ b/data/resources/application.css
@@ -151,3 +151,8 @@
     color: @theme_fg_color;
     font-size: smaller;
 }
+
+.polari-listbox-filterbar {
+    border: solid @borders;
+    border-width: 0 0 1px;
+}
diff --git a/data/resources/join-room-dialog.ui b/data/resources/join-room-dialog.ui
index 3be1286..0251cea 100644
--- a/data/resources/join-room-dialog.ui
+++ b/data/resources/join-room-dialog.ui
@@ -177,9 +177,36 @@
                     <property name="vexpand">True</property>
                     <property name="transition-type">crossfade</property>
                     <child>
-                      <object class="Gjs_ConnectionsList" id="connectionsList">
+                      <object class="GtkBox">
                         <property name="visible">True</property>
-                        <property name="shadow-type">in</property>
+                        <property name="orientation">vertical</property>
+                        <style>
+                          <class name="linked"/>
+                          <class name="frame"/>
+                        </style>
+                        <child>
+                          <object class="GtkBox">
+                            <property name="visible">True</property>
+                            <style>
+                              <class name="polari-listbox-filterbar"/>
+                            </style>
+                            <child>
+                              <object class="GtkSearchEntry" id="filterEntry">
+                                <property name="visible">True</property>
+                                <property name="hexpand">True</property>
+                                <property name="margin">60</property>
+                                <property name="margin-top">6</property>
+                                <property name="margin-bottom">6</property>
+                              </object>
+                            </child>
+                          </object>
+                        </child>
+                        <child>
+                          <object class="Gjs_ConnectionsList" id="connectionsList">
+                            <property name="visible">True</property>
+                            <property name="vexpand">True</property>
+                          </object>
+                        </child>
                       </object>
                       <packing>
                         <property name="name">predefined</property>
diff --git a/src/connections.js b/src/connections.js
index cee4f04..ff532f6 100644
--- a/src/connections.js
+++ b/src/connections.js
@@ -71,6 +71,8 @@ const ConnectionsList = new Lang.Class({
 
         this._rows = new Map();
 
+        this._filterTerms = [];
+        this._list.set_filter_func(Lang.bind(this, this._filterRows));
         this._list.set_header_func(Lang.bind(this, this._updateHeader));
 
         this._accountsMonitor = AccountsMonitor.getDefault();
@@ -89,6 +91,24 @@ const ConnectionsList = new Lang.Class({
         this._networksChanged();
     },
 
+    setFilter: function(filter) {
+        this._filterTerms = filter.trim().toLowerCase().replace(/\s+/g, ' ').split(' ');
+        this._list.invalidate_filter();
+    },
+
+    activateFirst: function() {
+        let row = this._list.get_row_at_y(0);
+        if (row)
+            row.activate();
+    },
+
+    _filterRows: function(row) {
+        let matchTerms = this._networksManager.getNetworkMatchTerms(row.id);
+        return this._filterTerms.every(function(term) {
+            return matchTerms.some(function(s) { return s.indexOf(term) != -1; });
+        });
+    },
+
     _updateHeader: function(row, before) {
         if (!before)
             row.set_header(null);
diff --git a/src/joinDialog.js b/src/joinDialog.js
index 8d45096..3b395f0 100644
--- a/src/joinDialog.js
+++ b/src/joinDialog.js
@@ -28,6 +28,7 @@ const JoinDialog = new Lang.Class({
                        'nameEntry',
                        'nameCompletion',
                        'connectionStack',
+                       'filterEntry',
                        'connectionsList',
                        'details',
                        'addButton',
@@ -141,6 +142,23 @@ const JoinDialog = new Lang.Class({
                     this._details.reset();
                 }
             }));
+
+        this._filterEntry.connect('search-changed', Lang.bind(this,
+            function() {
+                this._connectionsList.setFilter(this._filterEntry.text);
+            }));
+        this._filterEntry.connect('stop-search', Lang.bind(this,
+            function() {
+                if (this._filterEntry.text.length > 0)
+                    this._filterEntry.text = '';
+                else
+                    this.response(Gtk.ResponseType.CANCEL);
+            }));
+        this._filterEntry.connect('activate', Lang.bind(this,
+            function() {
+                if (this._filterEntry.text.length > 0)
+                    this._connectionsList.activateFirst();
+            }));
     },
 
     _onAccountChanged: function() {
diff --git a/src/networksManager.js b/src/networksManager.js
index c099a24..65f472e 100644
--- a/src/networksManager.js
+++ b/src/networksManager.js
@@ -82,6 +82,15 @@ const NetworksManager = new Lang.Class({
             'port': new GLib.Variant('u', server.port),
             'use-ssl': new GLib.Variant('b', server.ssl),
         };
+    },
+
+    getNetworkMatchTerms: function(id) {
+        let network = this._lookupNetwork(id);
+        let servers = network.servers.map(function(s) {
+            return s.address.toLowerCase();
+        });
+        return [network.name.toLowerCase(),
+                network.id.toLowerCase()].concat(servers);
     }
 });
 Signals.addSignalMethods(NetworksManager.prototype);


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