[geary/wip/713006-better-error-reporting: 1/6] Add initial support for using Gtk.InfoBars to display errors.
- From: Michael Gratton <mjog src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [geary/wip/713006-better-error-reporting: 1/6] Add initial support for using Gtk.InfoBars to display errors.
- Date: Sun, 12 Nov 2017 11:23:36 +0000 (UTC)
commit 80680f280ea122cfd1c4f569d107c497c392e41e
Author: Michael James Gratton <mike vee net>
Date: Wed Nov 8 18:13:51 2017 +1100
Add initial support for using Gtk.InfoBars to display errors.
* src/client/components/main-window-info-bar.vala (MainWindowInfoBar):
New class and UI file for displaying an info bar in the main window, as
well as providing a way to show technical informartion if needed.
* src/client/components/main-window.vala (MainWindow): Add a Gtk.Frame
and container to hold inforbar instances. Show it when showing an
infobar, and hide it when there are none. Add show_infobar() method to
provide a cromulent way of adding info bars.
* src/client/application/geary-controller.vala (BaseObject): Rather than
bailing out on an account when an error occurs, display an info bar
instead.
* ui/geary.css: Style the info bar frame to only show a border between
main content and the info bars.
po/POTFILES.in | 2 +
src/CMakeLists.txt | 1 +
src/client/application/geary-controller.vala | 72 +++++---
src/client/components/main-window-info-bar.vala | 245 +++++++++++++++++++++++
src/client/components/main-window.vala | 21 ++
ui/CMakeLists.txt | 1 +
ui/geary.css | 10 +
ui/main-window-info-bar.ui | 142 +++++++++++++
ui/main-window.ui | 114 ++++++++---
9 files changed, 552 insertions(+), 56 deletions(-)
---
diff --git a/po/POTFILES.in b/po/POTFILES.in
index 1f25f47..1969cba 100644
--- a/po/POTFILES.in
+++ b/po/POTFILES.in
@@ -31,6 +31,7 @@ src/client/components/folder-popover.vala
src/client/components/icon-factory.vala
src/client/components/main-toolbar.vala
src/client/components/main-window.vala
+src/client/components/main-window-info-bar.vala
src/client/components/monitored-progress-bar.vala
src/client/components/monitored-spinner.vala
src/client/components/search-bar.vala
@@ -411,6 +412,7 @@ ui/login.glade
ui/main-toolbar.ui
ui/main-toolbar-menus.ui
ui/main-window.ui
+ui/main-window-info-bar.ui
ui/password-dialog.glade
ui/preferences-dialog.ui
ui/remove_confirm.glade
diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt
index 218f525..efe2403 100644
--- a/src/CMakeLists.txt
+++ b/src/CMakeLists.txt
@@ -342,6 +342,7 @@ client/components/folder-popover.vala
client/components/icon-factory.vala
client/components/main-toolbar.vala
client/components/main-window.vala
+client/components/main-window-info-bar.vala
client/components/monitored-progress-bar.vala
client/components/monitored-spinner.vala
client/components/search-bar.vala
diff --git a/src/client/application/geary-controller.vala b/src/client/application/geary-controller.vala
index 451218f..910af28 100644
--- a/src/client/application/geary-controller.vala
+++ b/src/client/application/geary-controller.vala
@@ -872,44 +872,66 @@ public class GearyController : Geary.BaseObject {
debug("Error updating stored passwords: %s", e.message);
}
}
-
+
private void on_report_problem(Geary.Account account, Geary.Account.Problem problem, Error? err) {
debug("Reported problem: %s Error: %s", problem.to_string(), err != null ? err.message : "(N/A)");
-
+
switch (problem) {
- case Geary.Account.Problem.DATABASE_FAILURE:
- case Geary.Account.Problem.HOST_UNREACHABLE:
- case Geary.Account.Problem.NETWORK_UNAVAILABLE:
- // TODO
+ case Geary.Account.Problem.CONNECTION_FAILURE:
+ ErrorDialog dialog = new ErrorDialog(
+ main_window,
+ _("Error connecting to the server"),
+ _("Geary encountered an error while connecting to the server. Please try again in a few
moments.")
+ );
+ dialog.run();
break;
-
- case Geary.Account.Problem.RECV_EMAIL_LOGIN_FAILED:
- case Geary.Account.Problem.SEND_EMAIL_LOGIN_FAILED:
- // At this point, we've prompted them for the password and
- // they've hit cancel, so there's not much for us to do here.
- close_account(account);
+
+ case Geary.Account.Problem.DATABASE_FAILURE:
+ case Geary.Account.Problem.HOST_UNREACHABLE:
+ case Geary.Account.Problem.NETWORK_UNAVAILABLE:
+ case Geary.Account.Problem.RECV_EMAIL_LOGIN_FAILED:
+ case Geary.Account.Problem.SEND_EMAIL_ERROR:
+ case Geary.Account.Problem.SEND_EMAIL_LOGIN_FAILED:
+ MainWindowInfoBar info_bar = new MainWindowInfoBar.for_problem(
+ problem, account, err
+ );
+ info_bar.retry.connect(on_retry_problem);
+ this.main_window.show_infobar(info_bar);
+ break;
+
+ case Geary.Account.Problem.SEND_EMAIL_DELIVERY_FAILURE:
+ handle_outbox_failure(StatusBar.Message.OUTBOX_SEND_FAILURE);
break;
- case Geary.Account.Problem.SEND_EMAIL_DELIVERY_FAILURE:
- handle_outbox_failure(StatusBar.Message.OUTBOX_SEND_FAILURE);
+ case Geary.Account.Problem.SEND_EMAIL_SAVE_FAILED:
+ handle_outbox_failure(StatusBar.Message.OUTBOX_SAVE_SENT_MAIL_FAILED);
break;
- case Geary.Account.Problem.SEND_EMAIL_SAVE_FAILED:
- handle_outbox_failure(StatusBar.Message.OUTBOX_SAVE_SENT_MAIL_FAILED);
+ default:
+ assert_not_reached();
+ }
+ }
+
+ private void on_retry_problem(MainWindowInfoBar info_bar) {
+ switch (info_bar.problem) {
+ case Geary.Account.Problem.RECV_EMAIL_LOGIN_FAILED:
break;
- case Geary.Account.Problem.CONNECTION_FAILURE:
- ErrorDialog dialog = new ErrorDialog(main_window,
- _("Error connecting to the server"),
- _("Geary encountered an error while connecting to the server. Please try again in a few
moments."));
- dialog.run();
+ case Geary.Account.Problem.SEND_EMAIL_ERROR:
break;
- default:
- assert_not_reached();
+ case Geary.Account.Problem.SEND_EMAIL_LOGIN_FAILED:
+ break;
+
+ default:
+ debug("Un-handled problem retry for %s: %s".printf(
+ info_bar.account.information.id,
+ info_bar.problem.to_string()
+ ));
+ break;
}
}
-
+
private void handle_outbox_failure(StatusBar.Message message) {
bool activate_message = false;
try {
@@ -2817,5 +2839,5 @@ public class GearyController : Geary.BaseObject {
});
}
}
-}
+}
diff --git a/src/client/components/main-window-info-bar.vala b/src/client/components/main-window-info-bar.vala
new file mode 100644
index 0000000..a5a6691
--- /dev/null
+++ b/src/client/components/main-window-info-bar.vala
@@ -0,0 +1,245 @@
+/*
+ * Copyright 2017 Michael Gratton <mike vee net>
+ *
+ * This software is licensed under the GNU Lesser General Public License
+ * (version 2.1 or later). See the COPYING file in this distribution.
+ */
+
+/**
+ * Displays application-wide or important account-related messages.
+ */
+[GtkTemplate (ui = "/org/gnome/Geary/main-window-info-bar.ui")]
+public class MainWindowInfoBar : Gtk.InfoBar {
+
+
+ private enum ResponseType { COPY, DETAILS, RETRY; }
+
+
+ /** If reporting a problem returns, the specific problem else null. */
+ public Geary.Account.Problem? problem { get; private set; default = null; }
+
+ /** If reporting a problem for an account, returns the account else null. */
+ public Geary.Account? account { get; private set; default = null; }
+
+ /** If reporting a problem, returns the error thrown, if any. */
+ public Error error { get; private set; default = null; }
+
+
+ /** Emitted when the user clicks the Retry button, if any. */
+ public signal void retry();
+
+
+ [GtkChild]
+ private Gtk.Label title;
+
+ [GtkChild]
+ private Gtk.Label description;
+
+ [GtkChild]
+ private Gtk.Grid problem_details;
+
+ [GtkChild]
+ private Gtk.TextView detail_text;
+
+
+ public MainWindowInfoBar.for_problem(Geary.Account.Problem problem,
+ Geary.Account account,
+ GLib.Error? error) {
+ string name = account.information.display_name;
+ Gtk.MessageType type = Gtk.MessageType.WARNING;
+ string title = "";
+ string descr = "";
+ string? retry = null;
+ bool show_close = false;
+ switch (problem) {
+ case Geary.Account.Problem.DATABASE_FAILURE:
+ type = Gtk.MessageType.ERROR;
+ title = _("A database problem has occurred");
+ descr = _("Messages for %s must be downloaded again.").printf(name);
+ show_close = true;
+ break;
+
+ case Geary.Account.Problem.HOST_UNREACHABLE:
+ // XXX should really be displaying the server name here
+ title = _("Could not contact server");
+ descr = _("Please check %s server names are correct and are working.").printf(name);
+ show_close = true;
+ break;
+
+ case Geary.Account.Problem.NETWORK_UNAVAILABLE:
+ title = _("Not connected to the Internet");
+ descr = _("Please check your connection to the Internet.");
+ show_close = true;
+ break;
+
+ case Geary.Account.Problem.RECV_EMAIL_LOGIN_FAILED:
+ title = _("Incoming mail password required");
+ descr = _("Messages cannot be received for %s without the correct password.").printf(name);
+ retry = _("Retry receiving email, you will be prompted for a password");
+ break;
+
+ case Geary.Account.Problem.SEND_EMAIL_ERROR:
+ type = Gtk.MessageType.ERROR;
+ title = _("A problem occurred sending mail");
+ descr = _("A message was unable to be sent for %s, try again in a moment").printf(name);
+ retry = _("Retry sending queued messages");
+ break;
+
+ case Geary.Account.Problem.SEND_EMAIL_LOGIN_FAILED:
+ title = _("Outgoing mail password required");
+ descr = _("Messages cannot be sent for %s without the correct password.").printf(name);
+ retry = _("Retry sending queued messages, you will be prompted for a password");
+ break;
+
+ default:
+ debug("Un-handled problem type for %s: %s".printf(
+ account.information.id, problem.to_string()
+ ));
+ break;
+ }
+
+ this(type, title, descr, show_close);
+ this.problem = problem;
+ this.account = account;
+ this.error = error;
+
+ if (this.error != null) {
+ Gtk.Button details = add_button(_("_Details"), ResponseType.DETAILS);
+ details.tooltip_text = _("View technical details about the error");
+ }
+
+ if (retry != null) {
+ Gtk.Button retry_btn = add_button(_("_Retry"), ResponseType.RETRY);
+ retry_btn.tooltip_text = retry;
+ }
+ }
+
+ protected MainWindowInfoBar(Gtk.MessageType type,
+ string title,
+ string description,
+ bool show_close) {
+ this.message_type = type;
+ this.title.label = title;
+ this.description.label = description;
+ this.show_close_button = show_close;
+ }
+
+ private string format_details() {
+ string type = "";
+ if (this.error != null) {
+ const string QUARK_SUFFIX = "-quark";
+ string ugly_domain = this.error.domain.to_string();
+ if (ugly_domain.has_suffix(QUARK_SUFFIX)) {
+ ugly_domain = ugly_domain.substring(
+ 0, ugly_domain.length - QUARK_SUFFIX.length
+ );
+ }
+ StringBuilder nice_domain = new StringBuilder();
+ foreach (string part in ugly_domain.split("_")) {
+ nice_domain.append(part.up(1));
+ nice_domain.append(part.substring(1));
+ }
+
+ type = "%s %i".printf(nice_domain.str, this.error.code);
+ }
+
+ return """Geary version: %s
+GTK+ version: %u.%u.%u
+Desktop: %s
+Error type: %s
+Message: %s
+""".printf(
+ GearyApplication.VERSION,
+ Gtk.get_major_version(), Gtk.get_minor_version(), Gtk.get_micro_version(),
+ Environment.get_variable("XDG_CURRENT_DESKTOP") ?? "Unknown",
+ type,
+ (this.error != null) ? error.message : ""
+ );
+ }
+
+ private void show_details() {
+ this.detail_text.buffer.text = format_details();
+
+ // Would love to construct the dialog in Builder, but we to
+ // construct the dialog manually since we can't adjust the
+ // Headerbar setting afterwards. If the user re-clicks on the
+ // Details button to re-show it, a whole bunch of GTK
+ // criticals are spewed and the dialog appears b0rked, so just
+ // do it from scratch ever time anyway.
+ bool use_header = Gtk.Settings.get_default().gtk_dialogs_use_header;
+ Gtk.DialogFlags flags = Gtk.DialogFlags.MODAL;
+ if (use_header) {
+ flags |= Gtk.DialogFlags.USE_HEADER_BAR;
+ }
+ Gtk.Dialog dialog = new Gtk.Dialog.with_buttons(
+ _("Details"), // same as the button
+ get_toplevel() as Gtk.Window,
+ flags
+ );
+ dialog.set_default_size(600, -1);
+ dialog.get_content_area().add(this.problem_details);
+
+ Gtk.HeaderBar? header_bar = dialog.get_header_bar() as Gtk.HeaderBar;
+ use_header = (header_bar != null);
+ if (use_header) {
+ header_bar.show_close_button = true;
+ } else {
+ dialog.add_button(_("_Close"), Gtk.ResponseType.CLOSE);
+ }
+
+ Gtk.Widget copy = dialog.add_button(
+ _("Copy to Clipboard"), ResponseType.COPY
+ );
+ copy.tooltip_text =
+ _("Copy technical details to clipboard for pasting into an email or bug report");
+
+
+ dialog.set_default_response(ResponseType.COPY);
+ dialog.response.connect(on_details_response);
+ dialog.show();
+ copy.grab_focus();
+ }
+
+ private void copy_details() {
+ get_clipboard(Gdk.SELECTION_CLIPBOARD).set_text(format_details(), -1);
+ }
+
+ [GtkCallback]
+ private void on_info_bar_response(int response) {
+ switch(response) {
+ case ResponseType.DETAILS:
+ show_details();
+ break;
+
+ case ResponseType.RETRY:
+ retry();
+ this.hide();
+ break;
+
+ default:
+ this.hide();
+ break;
+ }
+ }
+
+ [GtkCallback]
+ private void on_hide() {
+ this.parent.remove(this);
+ }
+
+ private void on_details_response(Gtk.Dialog dialog, int response) {
+ switch(response) {
+ case ResponseType.COPY:
+ copy_details();
+ break;
+
+ default:
+ // fml
+ dialog.get_content_area().remove(this.problem_details);
+ dialog.hide();
+ break;
+ }
+ }
+
+
+}
diff --git a/src/client/components/main-window.vala b/src/client/components/main-window.vala
index 13fedf7..4161fa3 100644
--- a/src/client/components/main-window.vala
+++ b/src/client/components/main-window.vala
@@ -50,6 +50,12 @@ public class MainWindow : Gtk.ApplicationWindow {
[GtkChild]
private Gtk.ScrolledWindow conversation_list_scrolled;
+ // This is a frame so users can use F6/Shift-F6 to get to it
+ [GtkChild]
+ private Gtk.Frame info_bar_frame;
+
+ [GtkChild]
+ private Gtk.Grid info_bar_container;
/** Fired when the shift key is pressed or released. */
public signal void on_shift_key(bool pressed);
@@ -72,6 +78,11 @@ public class MainWindow : Gtk.ApplicationWindow {
on_change_orientation();
}
+ public void show_infobar(MainWindowInfoBar info_bar) {
+ this.info_bar_container.add(info_bar);
+ this.info_bar_frame.show();
+ }
+
private void load_config(Configuration config) {
// This code both loads AND saves the pane positions with live updating. This is more
// resilient against crashes because the value in dconf changes *immediately*, and
@@ -422,4 +433,14 @@ public class MainWindow : Gtk.ApplicationWindow {
}
return Gdk.EVENT_STOP;
}
+
+ [GtkCallback]
+ private void on_info_bar_container_remove() {
+ // Ensure the info bar frame is hidden when the last info bar
+ // is removed from the container.
+ if (this.info_bar_container.get_children().length() == 0) {
+ this.info_bar_frame.hide();
+ }
+ }
+
}
diff --git a/ui/CMakeLists.txt b/ui/CMakeLists.txt
index 05a74e7..4513df6 100644
--- a/ui/CMakeLists.txt
+++ b/ui/CMakeLists.txt
@@ -30,6 +30,7 @@ set(RESOURCE_LIST
STRIPBLANKS "main-toolbar.ui"
STRIPBLANKS "main-toolbar-menus.ui"
STRIPBLANKS "main-window.ui"
+ STRIPBLANKS "main-window-info-bar.ui"
STRIPBLANKS "password-dialog.glade"
STRIPBLANKS "preferences-dialog.ui"
STRIPBLANKS "remove_confirm.glade"
diff --git a/ui/geary.css b/ui/geary.css
index cfeb72d..d92ca39 100644
--- a/ui/geary.css
+++ b/ui/geary.css
@@ -6,6 +6,8 @@
* (version 2.1 or later). See the COPYING file in this distribution.
*/
+/* MainWindow */
+
.geary-folder-frame > border {
border-left-width: 0;
border-top-width: 0;
@@ -39,6 +41,14 @@
border-top-left-radius: 0px;
}
+/* MainWindowInfoBarSet */
+
+.geary-info-bar-frame > border {
+ border-top-width: 0;
+ border-left-width: 0;
+ border-right-width: 0;
+}
+
/* FolderPopover */
row.geary-folder-popover-list-row {
diff --git a/ui/main-window-info-bar.ui b/ui/main-window-info-bar.ui
new file mode 100644
index 0000000..465f441
--- /dev/null
+++ b/ui/main-window-info-bar.ui
@@ -0,0 +1,142 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!-- Generated with glade 3.20.0 -->
+<interface>
+ <requires lib="gtk+" version="3.20"/>
+ <template class="MainWindowInfoBar" parent="GtkInfoBar">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="hexpand">True</property>
+ <signal name="hide" handler="on_hide" after="yes" swapped="no"/>
+ <signal name="response" handler="on_info_bar_response" swapped="no"/>
+ <child internal-child="action_area">
+ <object class="GtkButtonBox">
+ <property name="can_focus">False</property>
+ <property name="spacing">6</property>
+ <property name="layout_style">end</property>
+ <child>
+ <placeholder/>
+ </child>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="fill">False</property>
+ <property name="position">0</property>
+ </packing>
+ </child>
+ <child internal-child="content_area">
+ <object class="GtkBox">
+ <property name="can_focus">False</property>
+ <property name="spacing">16</property>
+ <child>
+ <object class="GtkGrid">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <child>
+ <object class="GtkLabel" id="title">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="halign">start</property>
+ <property name="label">Title</property>
+ <attributes>
+ <attribute name="weight" value="bold"/>
+ </attributes>
+ </object>
+ <packing>
+ <property name="left_attach">0</property>
+ <property name="top_attach">0</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkLabel" id="description">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="halign">start</property>
+ <property name="label">Description.</property>
+ <property name="ellipsize">end</property>
+ </object>
+ <packing>
+ <property name="left_attach">0</property>
+ <property name="top_attach">1</property>
+ </packing>
+ </child>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="fill">True</property>
+ <property name="position">0</property>
+ </packing>
+ </child>
+ <style>
+ <class name="sigh"/>
+ </style>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="fill">False</property>
+ <property name="position">0</property>
+ </packing>
+ </child>
+ </template>
+ <object class="GtkGrid" id="problem_details">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="margin_left">18</property>
+ <property name="margin_right">18</property>
+ <property name="margin_top">18</property>
+ <property name="margin_bottom">18</property>
+ <property name="row_spacing">6</property>
+ <property name="column_spacing">12</property>
+ <child>
+ <object class="GtkLabel">
+ <property name="visible">True</property>
+ <property name="can_focus">True</property>
+ <property name="halign">start</property>
+ <property name="valign">baseline</property>
+ <property name="margin_bottom">12</property>
+ <property name="hexpand">True</property>
+ <property name="label" translatable="yes">If the problem is serious or persists, please copy and
send these details to the <a href="https://wiki.gnome.org/Apps/Geary/Contact">mailing list</a> or
lodge a <a href="https://wiki.gnome.org/Apps/Geary/ReportingABug">bug report</a>.</property>
+ <property name="use_markup">True</property>
+ <property name="wrap">True</property>
+ <property name="xalign">0</property>
+ </object>
+ <packing>
+ <property name="left_attach">0</property>
+ <property name="top_attach">0</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkLabel">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="halign">start</property>
+ <property name="valign">baseline</property>
+ <property name="label" translatable="yes">Details:</property>
+ <property name="track_visited_links">False</property>
+ </object>
+ <packing>
+ <property name="left_attach">0</property>
+ <property name="top_attach">1</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkTextView" id="detail_text">
+ <property name="visible">True</property>
+ <property name="can_focus">True</property>
+ <property name="hexpand">True</property>
+ <property name="vexpand">True</property>
+ <property name="editable">False</property>
+ <property name="wrap_mode">word</property>
+ <property name="left_margin">6</property>
+ <property name="right_margin">6</property>
+ <property name="top_margin">6</property>
+ <property name="bottom_margin">6</property>
+ <property name="cursor_visible">False</property>
+ <property name="monospace">True</property>
+ </object>
+ <packing>
+ <property name="left_attach">0</property>
+ <property name="top_attach">2</property>
+ </packing>
+ </child>
+ </object>
+</interface>
diff --git a/ui/main-window.ui b/ui/main-window.ui
index 1ed5894..e09e308 100644
--- a/ui/main-window.ui
+++ b/ui/main-window.ui
@@ -1,69 +1,60 @@
<?xml version="1.0" encoding="UTF-8"?>
+<!-- Generated with glade 3.20.0 -->
<interface>
- <requires lib="gtk+" version="3.14"/>
+ <requires lib="gtk+" version="3.20"/>
<template class="MainWindow" parent="GtkApplicationWindow">
- <property name="visible">False</property>
- <property name="show_menubar">False</property>
<property name="name">GearyMainWindow</property>
+ <property name="can_focus">False</property>
<property name="events">GDK_KEY_PRESS_MASK | GDK_KEY_RELEASE_MASK | GDK_FOCUS_CHANGE_MASK |
GDK_STRUCTURE_MASK</property>
- <signal name="delete_event" handler="on_delete_event"/>
- <signal name="key_release_event" handler="on_key_release_event"/>
- <signal name="focus_in_event" handler="on_focus_event"/>
+ <property name="show_menubar">False</property>
+ <signal name="delete-event" handler="on_delete_event" swapped="no"/>
+ <signal name="focus-in-event" handler="on_focus_event" swapped="no"/>
+ <signal name="key-release-event" handler="on_key_release_event" swapped="no"/>
<child>
<object class="GtkBox" id="main_layout">
<property name="visible">True</property>
<property name="can_focus">False</property>
<property name="orientation">vertical</property>
- <property name="spacing">0</property>
<child>
<object class="GtkPaned" id="conversations_paned">
<property name="visible">True</property>
<property name="can_focus">False</property>
- <property name="orientation">horizontal</property>
<child>
<object class="GtkBox" id="search_bar_box">
<property name="visible">True</property>
<property name="can_focus">False</property>
<property name="orientation">vertical</property>
- <property name="spacing">0</property>
- <style>
- <class name="sidebar"/>
- </style>
<child>
<object class="GtkPaned" id="folder_paned">
<property name="visible">True</property>
<property name="can_focus">False</property>
- <property name="orientation">horizontal</property>
- <style>
- <class name="geary-sidebar-pane-separator"/>
- </style>
<child>
<object class="GtkBox" id="folder_box">
<property name="visible">True</property>
<property name="can_focus">False</property>
<property name="orientation">vertical</property>
- <property name="spacing">0</property>
<child>
<object class="GtkFrame" id="folder_frame">
<property name="visible">True</property>
<property name="can_focus">False</property>
+ <property name="label_xalign">0</property>
<property name="shadow_type">in</property>
- <style>
- <class name="geary-folder-frame"/>
- </style>
<child>
<object class="GtkScrolledWindow" id="folder_list_scrolled">
+ <property name="width_request">100</property>
<property name="visible">True</property>
<property name="can_focus">False</property>
- <property name="width_request">100</property>
<property name="hscrollbar_policy">never</property>
- <property name="vscrollbar_policy">automatic</property>
</object>
</child>
+ <style>
+ <class name="geary-folder-frame"/>
+ </style>
</object>
<packing>
<property name="expand">True</property>
<property name="fill">True</property>
+ <property name="position">0</property>
</packing>
</child>
</object>
@@ -77,28 +68,27 @@
<property name="visible">True</property>
<property name="can_focus">False</property>
<property name="orientation">vertical</property>
- <property name="spacing">0</property>
<child>
<object class="GtkFrame" id="conversation_frame">
<property name="visible">True</property>
<property name="can_focus">False</property>
+ <property name="label_xalign">0</property>
<property name="shadow_type">in</property>
- <style>
- <class name="geary-conversation-frame"/>
- </style>
<child>
<object class="GtkScrolledWindow" id="conversation_list_scrolled">
+ <property name="width_request">250</property>
<property name="visible">True</property>
<property name="can_focus">False</property>
- <property name="width_request">250</property>
- <property name="hscrollbar_policy">automatic</property>
- <property name="vscrollbar_policy">automatic</property>
</object>
</child>
+ <style>
+ <class name="geary-conversation-frame"/>
+ </style>
</object>
<packing>
<property name="expand">True</property>
<property name="fill">True</property>
+ <property name="position">0</property>
</packing>
</child>
</object>
@@ -107,13 +97,20 @@
<property name="shrink">False</property>
</packing>
</child>
+ <style>
+ <class name="geary-sidebar-pane-separator"/>
+ </style>
</object>
<packing>
- <property name="pack_type">end</property>
<property name="expand">True</property>
<property name="fill">True</property>
+ <property name="pack_type">end</property>
+ <property name="position">0</property>
</packing>
</child>
+ <style>
+ <class name="sidebar"/>
+ </style>
</object>
<packing>
<property name="resize">False</property>
@@ -122,9 +119,64 @@
</child>
</object>
<packing>
- <property name="pack_type">end</property>
<property name="expand">True</property>
<property name="fill">True</property>
+ <property name="pack_type">end</property>
+ <property name="position">0</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkFrame" id="info_bar_frame">
+ <property name="can_focus">False</property>
+ <property name="no_show_all">True</property>
+ <property name="label_xalign">0</property>
+ <property name="shadow_type">in</property>
+ <child>
+ <object class="GtkGrid" id="info_bar_container">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="orientation">vertical</property>
+ <signal name="remove" handler="on_info_bar_container_remove" swapped="no"/>
+ <child>
+ <placeholder/>
+ </child>
+ <child>
+ <placeholder/>
+ </child>
+ <child>
+ <placeholder/>
+ </child>
+ <child>
+ <placeholder/>
+ </child>
+ <child>
+ <placeholder/>
+ </child>
+ <child>
+ <placeholder/>
+ </child>
+ <child>
+ <placeholder/>
+ </child>
+ <child>
+ <placeholder/>
+ </child>
+ <child>
+ <placeholder/>
+ </child>
+ </object>
+ </child>
+ <child type="label_item">
+ <placeholder/>
+ </child>
+ <style>
+ <class name="geary-info-bar-frame"/>
+ </style>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="fill">True</property>
+ <property name="position">1</property>
</packing>
</child>
</object>
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]