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.
This commit is contained in:
Michael Gratton 2020-04-16 13:05:07 +10:00
parent d5e94a257d
commit 4b097b4542
3 changed files with 180 additions and 28 deletions

View file

@ -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) {

View file

@ -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"/>
</object>
</child>
<property name="hscrollbar_policy">never</property>
<property name="shadow_type">in</property>
<child>
<object class="GtkTreeViewColumn" id="log_column">
<property name="title">column</property>
<object class="GtkViewport">
<property name="visible">True</property>
<property name="can_focus">False</property>
<child>
<object class="GtkCellRendererText" id="log_renderer"/>
<attributes>
<attribute name="text">0</attribute>
</attributes>
<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="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="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>

View file

@ -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;
}