[geary/wip/17-noisy-problem-reports] Show details for status-based service problems
- From: Michael Gratton <mjog src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [geary/wip/17-noisy-problem-reports] Show details for status-based service problems
- Date: Mon, 7 Jan 2019 12:16:56 +0000 (UTC)
commit 574651eb9dd3d57f834ae1eee352e168c7510668
Author: Michael Gratton <mike vee net>
Date: Mon Jan 7 23:13:30 2019 +1100
Show details for status-based service problems
This breaks out the problem details dialog out into a seperate class so
it can be used for both problem reports and status problems. Pass in any
service errors to the main window when updating account status, show a
Details button on the service status info bar and show the details
dialog when clicked.
po/POTFILES.in | 2 +
src/client/application/geary-controller.vala | 16 ++-
src/client/components/main-window-info-bar.vala | 127 +------------------
src/client/components/main-window.vala | 41 +++++-
.../dialogs/dialogs-problem-details-dialog.vala | 104 ++++++++++++++++
src/client/meson.build | 1 +
ui/main-window-info-bar.ui | 75 +----------
ui/main-window.ui | 23 +++-
ui/org.gnome.Geary.gresource.xml | 1 +
ui/problem-details-dialog.ui | 138 +++++++++++++++++++++
10 files changed, 324 insertions(+), 204 deletions(-)
---
diff --git a/po/POTFILES.in b/po/POTFILES.in
index 8e1e600a..7a7364d1 100644
--- a/po/POTFILES.in
+++ b/po/POTFILES.in
@@ -62,6 +62,7 @@ src/client/conversation-viewer/conversation-web-view.vala
src/client/dialogs/alert-dialog.vala
src/client/dialogs/attachment-dialog.vala
src/client/dialogs/certificate-warning-dialog.vala
+src/client/dialogs/dialogs-problem-details-dialog.vala
src/client/dialogs/password-dialog.vala
src/client/dialogs/preferences-dialog.vala
src/client/dialogs/upgrade-dialog.vala
@@ -428,4 +429,5 @@ ui/main-window.ui
ui/main-window-info-bar.ui
ui/password-dialog.glade
ui/preferences-dialog.ui
+ui/problem-details-dialog.vala
ui/upgrade_dialog.glade
diff --git a/src/client/application/geary-controller.vala b/src/client/application/geary-controller.vala
index 516854ed..986fd008 100644
--- a/src/client/application/geary-controller.vala
+++ b/src/client/application/geary-controller.vala
@@ -891,7 +891,8 @@ public class GearyController : Geary.BaseObject {
private void report_problem(Geary.ProblemReport report) {
debug("Problem reported: %s", report.to_string());
- if (!(report.error is IOError.CANCELLED)) {
+ if (report.error == null ||
+ !(report.error.thrown is IOError.CANCELLED)) {
MainWindowInfoBar info_bar = new MainWindowInfoBar.for_problem(report);
info_bar.retry.connect(on_retry_problem);
this.main_window.show_infobar(info_bar);
@@ -900,16 +901,23 @@ public class GearyController : Geary.BaseObject {
private void update_account_status() {
Geary.Account.Status effective_status = 0;
- bool auth_error = false;
+ bool has_auth_error = false;
+ Geary.Account? service_problem_source = null;
foreach (AccountContext context in this.accounts.values) {
effective_status |= context.get_effective_status();
- auth_error |= context.authentication_failed;
+ if (effective_status.has_service_problem() &&
+ service_problem_source == null) {
+ service_problem_source = context.account;
+ }
+ has_auth_error |= context.authentication_failed;
}
foreach (Gtk.Window window in this.application.get_windows()) {
MainWindow? main = window as MainWindow;
if (main != null) {
- main.update_account_status(effective_status, auth_error);
+ main.update_account_status(
+ effective_status, has_auth_error, service_problem_source
+ );
}
}
}
diff --git a/src/client/components/main-window-info-bar.vala b/src/client/components/main-window-info-bar.vala
index 7c489064..183c0988 100644
--- a/src/client/components/main-window-info-bar.vala
+++ b/src/client/components/main-window-info-bar.vala
@@ -12,7 +12,7 @@
public class MainWindowInfoBar : Gtk.InfoBar {
- private enum ResponseType { COPY, DETAILS, RETRY; }
+ private enum ResponseType { DETAILS, RETRY; }
/** If reporting a problem, returns the problem report else null. */
public Geary.ProblemReport? report { get; private set; default = null; }
@@ -27,12 +27,6 @@ public class MainWindowInfoBar : Gtk.InfoBar {
[GtkChild]
private Gtk.Label description;
- [GtkChild]
- private Gtk.Grid problem_details;
-
- [GtkChild]
- private Gtk.TextView detail_text;
-
public MainWindowInfoBar.for_problem(Geary.ProblemReport report) {
Gtk.MessageType type = Gtk.MessageType.WARNING;
@@ -182,107 +176,13 @@ public class MainWindowInfoBar : Gtk.InfoBar {
this.show_close_button = show_close;
}
- private string format_details() {
- Geary.ServiceProblemReport? service_report = this.report as Geary.ServiceProblemReport;
- Geary.AccountProblemReport? account_report = this.report as Geary.AccountProblemReport;
-
- StringBuilder details = new StringBuilder();
- details.append_printf(
- "Geary version: %s\n",
- GearyApplication.VERSION
- );
- details.append_printf(
- "GTK version: %u.%u.%u\n",
- Gtk.get_major_version(), Gtk.get_minor_version(), Gtk.get_micro_version()
- );
- details.append_printf(
- "Desktop: %s\n",
- Environment.get_variable("XDG_CURRENT_DESKTOP") ?? "Unknown"
- );
- details.append_printf(
- "Problem type: %s\n",
- this.report.problem_type.to_string()
- );
- if (account_report != null) {
- details.append_printf(
- "Account type: %s\n",
- account_report.account.service_provider.to_string()
- );
- }
- if (service_report != null) {
- details.append_printf(
- "Service type: %s\n",
- service_report.service.protocol.to_string()
- );
- details.append_printf(
- "Service host: %s\n",
- service_report.service.host
- );
- }
- if (this.report.error == null) {
- details.append("No error reported");
- } else {
- details.append_printf(
- "Error type: %s\n", this.report.error.format_error_type()
- );
- details.append_printf(
- "Message: %s\n", this.report.error.thrown.message
- );
- details.append("Back trace:\n");
- foreach (Geary.ErrorContext.StackFrame frame in
- this.report.error.backtrace) {
- details.append_printf(" - %s\n", frame.to_string());
- }
- }
- return details.str;
- }
-
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,
- null
+ Dialogs.ProblemDetailsDialog dialog =
+ new Dialogs.ProblemDetailsDialog.for_problem_report(
+ get_toplevel() as Gtk.Window, this.report
);
- 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);
+ dialog.run();
+ dialog.destroy();
}
[GtkCallback]
@@ -308,19 +208,4 @@ public class MainWindowInfoBar : Gtk.InfoBar {
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 9d7e3307..cd39e6aa 100644
--- a/src/client/components/main-window.vala
+++ b/src/client/components/main-window.vala
@@ -33,6 +33,7 @@ public class MainWindow : Gtk.ApplicationWindow, Geary.BaseInterface {
public ConversationViewer conversation_viewer { get; private set; default = new ConversationViewer(); }
public StatusBar status_bar { get; private set; default = new StatusBar(); }
private MonitoredSpinner spinner = new MonitoredSpinner();
+
[GtkChild]
private Gtk.Box main_layout;
[GtkChild]
@@ -65,12 +66,16 @@ public class MainWindow : Gtk.ApplicationWindow, Geary.BaseInterface {
[GtkChild]
private Gtk.InfoBar service_problem_infobar;
+ [GtkChild]
+ private Gtk.Button service_problem_details;
+
[GtkChild]
private Gtk.InfoBar cert_problem_infobar;
[GtkChild]
private Gtk.InfoBar auth_problem_infobar;
+ private Geary.Account? service_problem_account = null;
/** Fired when the user requests an account status be retried. */
public signal void retry_service_problem(Geary.ClientService.Status problem);
@@ -105,7 +110,8 @@ public class MainWindow : Gtk.ApplicationWindow, Geary.BaseInterface {
/** Updates the window's account status info bars. */
public void update_account_status(Geary.Account.Status status,
- bool auth_error) {
+ bool has_auth_error,
+ Geary.Account? service_problem) {
// Only ever show one at a time. Offline is primary since
// nothing else can happen when offline. Service problems are
// secondary since auth and cert problems can't be resolved
@@ -120,12 +126,15 @@ public class MainWindow : Gtk.ApplicationWindow, Geary.BaseInterface {
show_offline = true;
} else if (status.has_service_problem()) {
show_service = true;
- } else if (auth_error) {
+ } else if (has_auth_error) {
show_auth = true;
}
+ this.service_problem_account = service_problem;
+
this.offline_infobar.set_visible(show_offline);
this.service_problem_infobar.set_visible(show_service);
+ this.service_problem_details.set_visible(get_problem_service() != null);
this.cert_problem_infobar.hide();
this.auth_problem_infobar.set_visible(show_auth);
update_infobar_frame();
@@ -512,6 +521,18 @@ public class MainWindow : Gtk.ApplicationWindow, Geary.BaseInterface {
}
}
+ private Geary.ClientService? get_problem_service() {
+ Geary.ClientService? service = null;
+ if (this.service_problem_account != null) {
+ if (this.service_problem_account.incoming.last_error != null) {
+ service = this.service_problem_account.incoming;
+ } else if (this.service_problem_account.outgoing.last_error != null) {
+ service = this.service_problem_account.outgoing;
+ }
+ }
+ return service;
+ }
+
[GtkCallback]
private bool on_focus_event() {
on_shift_key(false);
@@ -543,6 +564,22 @@ public class MainWindow : Gtk.ApplicationWindow, Geary.BaseInterface {
retry_service_problem(Geary.ClientService.Status.CONNECTION_FAILED);
}
+ [GtkCallback]
+ private void on_service_problem_details() {
+ Geary.ClientService? service = get_problem_service();
+ if (service != null) {
+ Dialogs.ProblemDetailsDialog dialog =
+ new Dialogs.ProblemDetailsDialog(
+ this,
+ service.last_error,
+ this.service_problem_account.information,
+ service.configuration
+ );
+ dialog.run();
+ dialog.destroy();
+ }
+ }
+
[GtkCallback]
private void on_cert_problem_retry() {
this.cert_problem_infobar.hide();
diff --git a/src/client/dialogs/dialogs-problem-details-dialog.vala
b/src/client/dialogs/dialogs-problem-details-dialog.vala
new file mode 100644
index 00000000..c6608e53
--- /dev/null
+++ b/src/client/dialogs/dialogs-problem-details-dialog.vala
@@ -0,0 +1,104 @@
+/*
+ * Copyright 2019 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 technical details when a problem has been reported.
+ */
+[GtkTemplate (ui = "/org/gnome/Geary/problem-details-dialog.ui")]
+public class Dialogs.ProblemDetailsDialog : Gtk.Dialog {
+
+
+ private Geary.ErrorContext error;
+ private Geary.AccountInformation? account;
+ private Geary.ServiceInformation? service;
+
+ [GtkChild]
+ private Gtk.TextView detail_text;
+
+
+ public ProblemDetailsDialog(Gtk.Window parent,
+ Geary.ErrorContext error,
+ Geary.AccountInformation? account,
+ Geary.ServiceInformation? service) {
+ Object(use_header_bar: 1);
+ set_default_size(600, -1);
+
+ this.error = error;
+ this.account = account;
+ this.service = service;
+
+ this.detail_text.buffer.text = format_details();
+ }
+
+ public ProblemDetailsDialog.for_problem_report(Gtk.Window parent,
+ Geary.ProblemReport report) {
+ Geary.ServiceProblemReport? service_report =
+ report as Geary.ServiceProblemReport;
+ Geary.AccountProblemReport? account_report =
+ report as Geary.AccountProblemReport;
+ this(
+ parent,
+ report.error,
+ account_report != null ? account_report.account : null,
+ service_report != null ? service_report.service : null
+ );
+ }
+
+ private string format_details() {
+ StringBuilder details = new StringBuilder();
+ details.append_printf(
+ "Geary version: %s\n",
+ GearyApplication.VERSION
+ );
+ details.append_printf(
+ "GTK version: %u.%u.%u\n",
+ Gtk.get_major_version(), Gtk.get_minor_version(), Gtk.get_micro_version()
+ );
+ details.append_printf(
+ "Desktop: %s\n",
+ Environment.get_variable("XDG_CURRENT_DESKTOP") ?? "Unknown"
+ );
+ if (this.account != null) {
+ details.append_printf(
+ "Account type: %s\n",
+ this.account.service_provider.to_string()
+ );
+ }
+ if (this.service != null) {
+ details.append_printf(
+ "Service type: %s\n",
+ this.service.protocol.to_string()
+ );
+ details.append_printf(
+ "Service host: %s\n",
+ this.service.host
+ );
+ }
+ if (this.error == null) {
+ details.append("No error reported");
+ } else {
+ details.append_printf(
+ "Error type: %s\n", this.error.format_error_type()
+ );
+ details.append_printf(
+ "Message: %s\n", this.error.thrown.message
+ );
+ details.append("Back trace:\n");
+ foreach (Geary.ErrorContext.StackFrame frame in
+ this.error.backtrace) {
+ details.append_printf(" - %s\n", frame.to_string());
+ }
+ }
+ return details.str;
+ }
+
+ [GtkCallback]
+ private void on_copy_clicked() {
+ get_clipboard(Gdk.SELECTION_CLIPBOARD).set_text(format_details(), -1);
+ }
+
+}
diff --git a/src/client/meson.build b/src/client/meson.build
index 6cb48042..0afae2c1 100644
--- a/src/client/meson.build
+++ b/src/client/meson.build
@@ -62,6 +62,7 @@ geary_client_vala_sources = files(
'dialogs/alert-dialog.vala',
'dialogs/attachment-dialog.vala',
'dialogs/certificate-warning-dialog.vala',
+ 'dialogs/dialogs-problem-details-dialog.vala',
'dialogs/password-dialog.vala',
'dialogs/preferences-dialog.vala',
'dialogs/upgrade-dialog.vala',
diff --git a/ui/main-window-info-bar.ui b/ui/main-window-info-bar.ui
index 68179278..f649291d 100644
--- a/ui/main-window-info-bar.ui
+++ b/ui/main-window-info-bar.ui
@@ -1,5 +1,5 @@
<?xml version="1.0" encoding="UTF-8"?>
-<!-- Generated with glade 3.20.0 -->
+<!-- Generated with glade 3.22.1 -->
<interface>
<requires lib="gtk+" version="3.20"/>
<template class="MainWindowInfoBar" parent="GtkInfoBar">
@@ -77,77 +77,4 @@
</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
file a <a href="https://wiki.gnome.org/Apps/Geary/ReportingABug">new 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="GtkScrolledWindow">
- <property name="width_request">600</property>
- <property name="height_request">200</property>
- <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="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>
- </child>
- </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 e3c88a7e..b0e26849 100644
--- a/ui/main-window.ui
+++ b/ui/main-window.ui
@@ -242,18 +242,33 @@ You will not be able to send or receive email until it is re-connected.</propert
<property name="can_focus">False</property>
<property name="spacing">6</property>
<property name="layout_style">end</property>
+ <child>
+ <object class="GtkButton" id="service_problem_details">
+ <property name="label" translatable="yes" comments="Button label for
displaying technical details about an account problem">Details</property>
+ <property name="can_focus">True</property>
+ <property name="receives_default">True</property>
+ <property name="tooltip_text" translatable="yes" comments="Button tooltip
for displaying technical details about an account problem">View technical details about the error</property>
+ <signal name="clicked" handler="on_service_problem_details" swapped="no"/>
+ </object>
+ <packing>
+ <property name="expand">True</property>
+ <property name="fill">True</property>
+ <property name="position">0</property>
+ </packing>
+ </child>
<child>
<object class="GtkButton">
<property name="label" translatable="yes" comments="Button label for
retrying an account problem">Retry</property>
<property name="visible">True</property>
<property name="can_focus">True</property>
<property name="receives_default">True</property>
+ <property name="tooltip_text" translatable="yes" comments="Button tooltip
for retrying an account problem">Retry connecting now</property>
<signal name="clicked" handler="on_service_problem_retry" swapped="no"/>
</object>
<packing>
<property name="expand">True</property>
<property name="fill">True</property>
- <property name="position">0</property>
+ <property name="position">1</property>
</packing>
</child>
</object>
@@ -340,10 +355,11 @@ Please check your Internet connection, the server configuration and try again.</
<property name="layout_style">end</property>
<child>
<object class="GtkButton">
- <property name="label" translatable="yes" comments="Button label for
retrying an account problem">Retry</property>
+ <property name="label" translatable="yes" comments="Button label for
retrying TLS cert validation">Check</property>
<property name="visible">True</property>
<property name="can_focus">True</property>
<property name="receives_default">True</property>
+ <property name="tooltip_text" translatable="yes" comments="Button tooltip
for retrying TLS cert validation">Check the security details for the connection</property>
<signal name="clicked" handler="on_cert_problem_retry" swapped="no"/>
</object>
<packing>
@@ -436,10 +452,11 @@ Please check the server configuration and try again.</property>
<property name="layout_style">end</property>
<child>
<object class="GtkButton">
- <property name="label" translatable="yes" comments="Button label for
retrying an account problem">Retry</property>
+ <property name="label" translatable="yes" comments="Button label for
retrying when a login error has occurred">Login</property>
<property name="visible">True</property>
<property name="can_focus">True</property>
<property name="receives_default">True</property>
+ <property name="tooltip_text" translatable="yes" comments="Button tooltip
for retrying when a login error has occurred">Retry login, you will be prompted for you password</property>
<signal name="clicked" handler="on_auth_problem_retry" swapped="no"/>
</object>
<packing>
diff --git a/ui/org.gnome.Geary.gresource.xml b/ui/org.gnome.Geary.gresource.xml
index 8f43542f..38fce5d8 100644
--- a/ui/org.gnome.Geary.gresource.xml
+++ b/ui/org.gnome.Geary.gresource.xml
@@ -35,6 +35,7 @@
<file compressed="true" preprocess="xml-stripblanks">main-window-info-bar.ui</file>
<file compressed="true" preprocess="xml-stripblanks">password-dialog.glade</file>
<file compressed="true" preprocess="xml-stripblanks">preferences-dialog.ui</file>
+ <file compressed="true" preprocess="xml-stripblanks">problem-details-dialog.ui</file>
<file compressed="true" preprocess="xml-stripblanks">upgrade_dialog.glade</file>
<file compressed="true">geary.css</file>
</gresource>
diff --git a/ui/problem-details-dialog.ui b/ui/problem-details-dialog.ui
new file mode 100644
index 00000000..0e7d2b88
--- /dev/null
+++ b/ui/problem-details-dialog.ui
@@ -0,0 +1,138 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!-- Generated with glade 3.22.1 -->
+<interface>
+ <requires lib="gtk+" version="3.20"/>
+ <template class="DialogsProblemDetailsDialog" parent="GtkDialog">
+ <property name="can_focus">False</property>
+ <property name="modal">True</property>
+ <property name="type_hint">dialog</property>
+ <child type="titlebar">
+ <object class="GtkHeaderBar">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="title" translatable="yes" comments="Dialog title for displaying technical details of
a problem. Same as the button that invokes it.">Details</property>
+ <property name="show_close_button">True</property>
+ <child>
+ <object class="GtkButton">
+ <property name="label" translatable="yes" comments="Button label for copying technical
information to the clipboard">Copy to Clipboard</property>
+ <property name="visible">True</property>
+ <property name="can_focus">True</property>
+ <property name="receives_default">True</property>
+ <property name="tooltip_text" translatable="yes" comments="Button tooltip for copying technical
information to the clipboard">Copy technical details to clipboard for pasting into an email or bug
report</property>
+ <signal name="clicked" handler="on_copy_clicked" swapped="no"/>
+ <style>
+ <class name="suggested-action"/>
+ </style>
+ </object>
+ <packing>
+ <property name="pack_type">end</property>
+ </packing>
+ </child>
+ </object>
+ </child>
+ <child internal-child="vbox">
+ <object class="GtkBox">
+ <property name="can_focus">False</property>
+ <property name="orientation">vertical</property>
+ <property name="spacing">2</property>
+ <child internal-child="action_area">
+ <object class="GtkButtonBox">
+ <property name="can_focus">False</property>
+ <property name="layout_style">end</property>
+ <child>
+ <placeholder/>
+ </child>
+ <child>
+ <placeholder/>
+ </child>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="fill">False</property>
+ <property name="position">0</property>
+ </packing>
+ </child>
+ <child>
+ <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 file a <a href="https://wiki.gnome.org/Apps/Geary/ReportingABug">new 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="GtkScrolledWindow">
+ <property name="width_request">600</property>
+ <property name="height_request">200</property>
+ <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="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>
+ </child>
+ </object>
+ <packing>
+ <property name="left_attach">0</property>
+ <property name="top_attach">2</property>
+ </packing>
+ </child>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="fill">True</property>
+ <property name="position">1</property>
+ </packing>
+ </child>
+ </object>
+ </child>
+ </template>
+</interface>
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]