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.
This commit is contained in:
parent
304fa9dcc2
commit
80680f280e
9 changed files with 560 additions and 64 deletions
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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
|
||||
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.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.SEND_EMAIL_DELIVERY_FAILURE:
|
||||
handle_outbox_failure(StatusBar.Message.OUTBOX_SEND_FAILURE);
|
||||
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_SAVE_FAILED:
|
||||
handle_outbox_failure(StatusBar.Message.OUTBOX_SAVE_SENT_MAIL_FAILED);
|
||||
case Geary.Account.Problem.SEND_EMAIL_DELIVERY_FAILURE:
|
||||
handle_outbox_failure(StatusBar.Message.OUTBOX_SEND_FAILURE);
|
||||
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_SAVE_FAILED:
|
||||
handle_outbox_failure(StatusBar.Message.OUTBOX_SAVE_SENT_MAIL_FAILED);
|
||||
break;
|
||||
|
||||
default:
|
||||
assert_not_reached();
|
||||
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.SEND_EMAIL_ERROR:
|
||||
break;
|
||||
|
||||
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 {
|
|||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
|||
245
src/client/components/main-window-info-bar.vala
Normal file
245
src/client/components/main-window-info-bar.vala
Normal file
|
|
@ -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;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
|
@ -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();
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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"
|
||||
|
|
|
|||
10
ui/geary.css
10
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 {
|
||||
|
|
|
|||
142
ui/main-window-info-bar.ui
Normal file
142
ui/main-window-info-bar.ui
Normal file
|
|
@ -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>
|
||||
|
|
@ -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>
|
||||
<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="hscrollbar_policy">never</property>
|
||||
</object>
|
||||
</child>
|
||||
<style>
|
||||
<class name="geary-folder-frame"/>
|
||||
</style>
|
||||
<child>
|
||||
<object class="GtkScrolledWindow" id="folder_list_scrolled">
|
||||
<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>
|
||||
</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>
|
||||
<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>
|
||||
</object>
|
||||
</child>
|
||||
<style>
|
||||
<class name="geary-conversation-frame"/>
|
||||
</style>
|
||||
<child>
|
||||
<object class="GtkScrolledWindow" id="conversation_list_scrolled">
|
||||
<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>
|
||||
</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>
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue