[geary/wip/17-noisy-problem-reports] Show details for status-based service problems



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 &lt;a href="https://wiki.gnome.org/Apps/Geary/Contact"&gt;mailing list&lt;/a&gt; or 
file a &lt;a href="https://wiki.gnome.org/Apps/Geary/ReportingABug"&gt;new bug report&lt;/a&gt;.</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 &lt;a href="https://wiki.gnome.org/Apps/Geary/Contact"&gt;mailing 
list&lt;/a&gt; or file a &lt;a href="https://wiki.gnome.org/Apps/Geary/ReportingABug"&gt;new bug 
report&lt;/a&gt;.</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]