[geary/mjog/logging-improvements: 15/23] Components.InspectorLogView: Add sidebar listing accounts & log domains



commit 4b097b45426039a6431e536673fd6f59d33515d9
Author: Michael Gratton <mike vee net>
Date:   Thu Apr 16 13:05:07 2020 +1000

    Components.InspectorLogView: Add sidebar listing accounts & log domains
    
    Adds a sidebar that displays accounts and logging domains, grouped into
    accounts, internal domains, and external domains.

 .../components/components-inspector-log-view.vala  | 99 ++++++++++++++++++++++
 ui/components-inspector-log-view.ui                | 95 +++++++++++++++------
 ui/geary.css                                       | 10 +++
 3 files changed, 178 insertions(+), 26 deletions(-)
---
diff --git a/src/client/components/components-inspector-log-view.vala 
b/src/client/components/components-inspector-log-view.vala
index f3c401ad..351d457e 100644
--- a/src/client/components/components-inspector-log-view.vala
+++ b/src/client/components/components-inspector-log-view.vala
@@ -15,6 +15,37 @@ public class Components.InspectorLogView : Gtk.Grid {
     private const int COL_MESSAGE = 0;
 
 
+    private class SidebarRow : Gtk.ListBoxRow {
+
+        public enum RowType { ACCOUNT, INTERNAL_DOMAIN, EXTERNAL_DOMAIN }
+
+
+        public RowType row_type { get; private set; }
+        public string id  { get; private set; }
+
+        internal Gtk.CheckButton enabled = new Gtk.CheckButton();
+
+
+        public SidebarRow(RowType type, string label, string id) {
+            this.row_type  = type;
+            this.id = id;
+
+            var label_widget = new Gtk.Label(label);
+            label_widget.hexpand = true;
+            label_widget.xalign = 0.0f;
+
+            var grid = new Gtk.Grid();
+            grid.orientation = HORIZONTAL;
+            grid.add(label_widget);
+            grid.add(this.enabled);
+            add(grid);
+
+            show_all();
+        }
+
+    }
+
+
     /** Determines if the log record search user interface is shown. */
     public bool search_mode_enabled {
         get { return this.search_bar.search_mode_enabled; }
@@ -27,6 +58,9 @@ public class Components.InspectorLogView : Gtk.Grid {
     [GtkChild]
     private Gtk.SearchEntry search_entry { get; private set; }
 
+    [GtkChild]
+    private Gtk.ListBox sidebar;
+
     [GtkChild]
     private Gtk.ScrolledWindow logs_scroller;
 
@@ -49,6 +83,10 @@ public class Components.InspectorLogView : Gtk.Grid {
 
     private bool autoscroll = true;
 
+    private Gee.Set<string> seen_accounts = new Gee.HashSet<string>();
+
+    private Gee.Set<string> seen_domains = new Gee.HashSet<string>();
+
     private Geary.AccountInformation? account_filter = null;
 
     private bool listener_installed = false;
@@ -68,6 +106,7 @@ public class Components.InspectorLogView : Gtk.Grid {
         );
 
         this.search_bar.connect_entry(this.search_entry);
+        this.sidebar.set_header_func(this.sidebar_header_update);
         this.account_filter = filter_by;
     }
 
@@ -210,8 +249,56 @@ public class Components.InspectorLogView : Gtk.Grid {
         }
     }
 
+    private void add_account(Geary.AccountInformation account) {
+        if (this.seen_accounts.add(account.id)) {
+            var row = new SidebarRow(ACCOUNT, account.display_name, account.id);
+            for (int i = 0;; i++) {
+                var existing = this.sidebar.get_row_at_index(i) as SidebarRow;
+                if (existing == null ||
+                    existing.row_type != ACCOUNT ||
+                    existing.id.collate(row.id) > 0) {
+                    this.sidebar.insert(row, i);
+                    break;
+                }
+            }
+        }
+    }
+
+    private void add_domain(string? domain) {
+        var safe_domain = domain ?? "(none)";
+        if (this.seen_domains.add(domain)) {
+            var type = (
+                safe_domain.down().has_prefix(Geary.Logging.DOMAIN.down())
+                ? SidebarRow.RowType.INTERNAL_DOMAIN
+                : SidebarRow.RowType.EXTERNAL_DOMAIN
+            );
+            var row = new SidebarRow(type, safe_domain, safe_domain);
+            int i = 0;
+            for (;; i++) {
+                var existing = this.sidebar.get_row_at_index(i) as SidebarRow;
+                if (existing == null ||
+                    existing.row_type == type) {
+                    break;
+                }
+            }
+            for (;; i++) {
+                var existing = this.sidebar.get_row_at_index(i) as SidebarRow;
+                if (existing == null ||
+                    existing.row_type != type ||
+                    existing.id.collate(row.id) > 0) {
+                    this.sidebar.insert(row, i);
+                    break;
+                }
+            }
+        }
+    }
+
     private inline bool should_append(Geary.Logging.Record record) {
         record.fill_well_known_sources();
+        if (record.account != null) {
+            add_account(record.account.information);
+        }
+        add_domain(record.domain);
         return (
             record.account == null ||
             this.account_filter == null ||
@@ -239,6 +326,18 @@ public class Components.InspectorLogView : Gtk.Grid {
         }
     }
 
+    private void sidebar_header_update(Gtk.ListBoxRow current_row,
+                                       Gtk.ListBoxRow? previous_row) {
+        Gtk.Widget? header = null;
+        var current = current_row as SidebarRow;
+        var previous = previous_row as SidebarRow;
+        if (current != null &&
+            (previous == null || current.row_type != previous.row_type)) {
+            header = new Gtk.Separator(HORIZONTAL);
+        }
+        current_row.set_header(header);
+    }
+
     [GtkCallback]
     private void on_logs_size_allocate() {
         if (this.autoscroll) {
diff --git a/ui/components-inspector-log-view.ui b/ui/components-inspector-log-view.ui
index e72c39b0..d2dd568e 100644
--- a/ui/components-inspector-log-view.ui
+++ b/ui/components-inspector-log-view.ui
@@ -1,5 +1,5 @@
 <?xml version="1.0" encoding="UTF-8"?>
-<!-- Generated with glade 3.22.1 -->
+<!-- Generated with glade 3.22.2 -->
 <interface>
   <requires lib="gtk+" version="3.20"/>
   <requires lib="libhandy" version="0.0"/>
@@ -33,45 +33,85 @@
             <signal name="search-changed" handler="on_logs_search_changed" swapped="no"/>
           </object>
         </child>
-              </object>
-              <packing>
-                <property name="left_attach">0</property>
-                <property name="top_attach">0</property>
-              </packing>
+      </object>
+      <packing>
+        <property name="left_attach">0</property>
+        <property name="top_attach">0</property>
+      </packing>
     </child>
     <child>
-      <object class="GtkScrolledWindow" id="logs_scroller">
+      <object class="GtkGrid">
         <property name="visible">True</property>
-        <property name="can_focus">True</property>
-        <property name="vexpand">True</property>
-        <property name="shadow_type">in</property>
+        <property name="can_focus">False</property>
         <child>
-          <object class="GtkTreeView" id="logs_view">
+          <object class="GtkScrolledWindow">
             <property name="visible">True</property>
             <property name="can_focus">True</property>
-            <property name="model">logs_store</property>
-            <property name="headers_visible">False</property>
-            <property name="enable_search">False</property>
-            <property name="show_expanders">False</property>
-            <signal name="size-allocate" handler="on_logs_size_allocate" swapped="no"/>
-            <child internal-child="selection">
-              <object class="GtkTreeSelection">
-                <property name="mode">multiple</property>
-                <signal name="changed" handler="on_logs_selection_changed" swapped="no"/>
+            <property name="hscrollbar_policy">never</property>
+            <property name="shadow_type">in</property>
+            <child>
+              <object class="GtkViewport">
+                <property name="visible">True</property>
+                <property name="can_focus">False</property>
+                <child>
+                  <object class="GtkListBox" id="sidebar">
+                    <property name="visible">True</property>
+                    <property name="can_focus">False</property>
+                    <property name="hexpand">False</property>
+                    <property name="selection_mode">none</property>
+                    <style>
+                      <class name="sidebar"/>
+                    </style>
+                  </object>
+                </child>
               </object>
             </child>
+          </object>
+          <packing>
+            <property name="left_attach">0</property>
+            <property name="top_attach">0</property>
+          </packing>
+        </child>
+        <child>
+          <object class="GtkScrolledWindow" id="logs_scroller">
+            <property name="visible">True</property>
+            <property name="can_focus">True</property>
+            <property name="hexpand">True</property>
+            <property name="vexpand">True</property>
+            <property name="shadow_type">in</property>
             <child>
-              <object class="GtkTreeViewColumn" id="log_column">
-                <property name="title">column</property>
+              <object class="GtkTreeView" id="logs_view">
+                <property name="visible">True</property>
+                <property name="can_focus">True</property>
+                <property name="model">logs_store</property>
+                <property name="headers_visible">False</property>
+                <property name="enable_search">False</property>
+                <property name="show_expanders">False</property>
+                <signal name="size-allocate" handler="on_logs_size_allocate" swapped="no"/>
+                <child internal-child="selection">
+                  <object class="GtkTreeSelection">
+                    <property name="mode">multiple</property>
+                    <signal name="changed" handler="on_logs_selection_changed" swapped="no"/>
+                  </object>
+                </child>
                 <child>
-                  <object class="GtkCellRendererText" id="log_renderer"/>
-                  <attributes>
-                    <attribute name="text">0</attribute>
-                  </attributes>
+                  <object class="GtkTreeViewColumn" id="log_column">
+                    <property name="title">column</property>
+                    <child>
+                      <object class="GtkCellRendererText" id="log_renderer"/>
+                      <attributes>
+                        <attribute name="text">0</attribute>
+                      </attributes>
+                    </child>
+                  </object>
                 </child>
               </object>
             </child>
           </object>
+          <packing>
+            <property name="left_attach">1</property>
+            <property name="top_attach">0</property>
+          </packing>
         </child>
       </object>
       <packing>
@@ -79,5 +119,8 @@
         <property name="top_attach">1</property>
       </packing>
     </child>
+    <style>
+      <class name="geary-inspector-log-viewer"/>
+    </style>
   </template>
 </interface>
diff --git a/ui/geary.css b/ui/geary.css
index de4a51e6..355882e6 100644
--- a/ui/geary.css
+++ b/ui/geary.css
@@ -327,3 +327,13 @@ treeview.sidebar:drop(active).into {
   border-top-style: solid;
   border-bottom-style: solid;
 }
+
+/* Inspector */
+
+.geary-inspector-log-viewer .sidebar row > grid {
+  padding: 0 6px;
+}
+
+.geary-inspector-log-viewer .sidebar row > grid * {
+  margin: 4px;
+}


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