[gnumeric] GUI: Rewrite file history dialog.



commit cd0e67d8bfe15e44ee54a8a34c4336e4ed54effc
Author: Morten Welinder <terra gnome org>
Date:   Wed Feb 27 22:35:48 2013 -0500

    GUI: Rewrite file history dialog.

 NEWS                        |    1 +
 src/dialogs/ChangeLog       |    4 +
 src/dialogs/Makefile.am     |    1 +
 src/dialogs/dialog-recent.c |  210 +++++++++++++++++++++++++++++++++++++------
 src/dialogs/recent.ui       |  162 +++++++++++++++++++++++++++++++++
 5 files changed, 350 insertions(+), 28 deletions(-)
---
diff --git a/NEWS b/NEWS
index 8c3427f..e9938a7 100644
--- a/NEWS
+++ b/NEWS
@@ -36,6 +36,7 @@ Morten:
        * Introspection fixes.
        * Fix ssconvert crash.  [#694741]
        * Unconditionally enable solver.
+       * Rewrite the file history dialog.
 
 --------------------------------------------------------------------------
 Gnumeric 1.12.0
diff --git a/src/dialogs/ChangeLog b/src/dialogs/ChangeLog
index aaee1b7..a8b6289 100644
--- a/src/dialogs/ChangeLog
+++ b/src/dialogs/ChangeLog
@@ -1,3 +1,7 @@
+2013-02-28  Morten Welinder  <terra gnome org>
+
+       * dialog-recent.c (dialog_recent_used): Rewrite.
+
 2013-02-28  Jean Brefort  <jean brefort normalesup org>
 
        * chi-squared.ui: fixed layout.
diff --git a/src/dialogs/Makefile.am b/src/dialogs/Makefile.am
index 121c004..99d17d3 100644
--- a/src/dialogs/Makefile.am
+++ b/src/dialogs/Makefile.am
@@ -151,6 +151,7 @@ embedded_uis =                      \
        random-generation-cor.ui        \
        random-generation.ui            \
        rank.ui                         \
+       recent.ui                       \
        regression.ui                   \
        row-height.ui                   \
        sampling.ui                     \
diff --git a/src/dialogs/dialog-recent.c b/src/dialogs/dialog-recent.c
index e0a9f8b..ce69ad9 100644
--- a/src/dialogs/dialog-recent.c
+++ b/src/dialogs/dialog-recent.c
@@ -26,10 +26,17 @@
 #include "dialogs.h"
 #include <wbc-gtk.h>
 #include <gui-file.h>
+#include <gui-util.h>
 #include <gtk/gtk.h>
 #include <string.h>
 #include <goffice/goffice.h>
 
+#define RECENT_KEY "recent-dialog"
+
+enum {
+       RECENT_COL_INFO
+};
+
 /* ------------------------------------------------------------------------- */
 
 static void
@@ -37,23 +44,27 @@ cb_response (GtkWidget *dialog,
             gint response_id,
             WBCGtk *wbcg)
 {
+       GtkBuilder *gui = g_object_get_data (G_OBJECT (dialog), "gui");
+       GtkTreeView *tv = GTK_TREE_VIEW (gtk_builder_get_object (gui, "docs_treeview"));
+       GtkTreeSelection *tsel = gtk_tree_view_get_selection (tv);
+
        switch (response_id) {
-       case GTK_RESPONSE_HELP:
-               return;
+       case GTK_RESPONSE_OK: {
+               GtkTreeModel *model;
+               GtkTreeIter iter;
+               const char *uri = NULL;
+
+               if (gtk_tree_selection_get_selected (tsel, &model, &iter)) {
+                       GtkRecentInfo *info;
+                       gtk_tree_model_get (model, &iter, RECENT_COL_INFO, &info, -1);
+                       uri = gtk_recent_info_get_uri (info);
+                       gtk_recent_info_unref (info);
+               }
 
-       case GTK_RESPONSE_ACCEPT: {
-               GtkRecentInfo *info =
-                       gtk_recent_chooser_get_current_item (GTK_RECENT_CHOOSER (dialog));
-               const char *uri = info ? gtk_recent_info_get_uri (info) : NULL;
                if (uri)
                        gui_file_read (wbcg, uri, NULL, NULL);
 
-               /*
-                * This causes crashes with gtk+ 2.10.6, at least.
-                */
-#if 0
                gtk_widget_destroy (dialog);
-#endif
                break;
        }
 
@@ -62,33 +73,176 @@ cb_response (GtkWidget *dialog,
        }
 }
 
+static void
+url_renderer_func (GtkTreeViewColumn *tree_column,
+                  GtkCellRenderer   *cell,
+                  GtkTreeModel      *model,
+                  GtkTreeIter       *iter,
+                  gpointer           user_data)
+{
+       GtkRecentInfo *ri = NULL;
+       const char *uri;
+       char *markup, *shortname, *filename, *longname, *duri;
+
+       gtk_tree_model_get (model, iter, RECENT_COL_INFO, &ri, -1);
+
+       uri = gtk_recent_info_get_uri (ri);
+       filename = go_filename_from_uri (uri);
+       if (filename) {
+               shortname = g_filename_display_basename (filename);
+       } else {
+               shortname = g_filename_display_basename (uri);
+       }
+
+       duri = g_uri_unescape_string (uri, NULL);
+       longname = duri
+               ? g_filename_display_name (duri)
+               : g_strdup (uri);
+
+       markup = g_markup_printf_escaped (_("<b>%s</b>\n"
+                                           "<small>Location: %s</small>"),
+                                         shortname,
+                                         longname);
+       g_object_set (cell, "markup", markup, NULL);
+       g_free (markup);
+       g_free (shortname);
+       g_free (longname);
+       g_free (duri);
+       g_free (filename);
+       gtk_recent_info_unref (ri);
+}
+
+static void
+age_renderer_func (GtkTreeViewColumn *tree_column,
+                  GtkCellRenderer   *cell,
+                  GtkTreeModel      *model,
+                  GtkTreeIter       *iter,
+                  gpointer           user_data)
+{
+       GtkRecentInfo *ri = NULL;
+
+       gtk_tree_model_get (model, iter, RECENT_COL_INFO, &ri, -1);
+
+       g_object_set (cell, "text", "TBD", NULL);
+
+       gtk_recent_info_unref (ri);
+}
+
+static gint
+by_age_uri (gconstpointer a_, gconstpointer b_)
+{
+       GtkRecentInfo *a = (gpointer)a_;
+       GtkRecentInfo *b = (gpointer)b_;
+       int res;
+
+       res = gtk_recent_info_get_modified (b) - gtk_recent_info_get_modified (a);
+       if (res) return res;
+
+       res = strcmp (gtk_recent_info_get_uri (a), gtk_recent_info_get_uri (b));
+       return res;
+}
+
+
+static void
+populate_recent_model (GtkBuilder *gui)
+{
+       GtkListStore *list = GTK_LIST_STORE (gtk_builder_get_object (gui, "recent_model"));
+       gboolean existing_only = gtk_toggle_button_get_active
+               (GTK_TOGGLE_BUTTON (gtk_builder_get_object (gui, "existing_only_button")));
+       gboolean gnumeric_only = gtk_toggle_button_get_active
+               (GTK_TOGGLE_BUTTON (gtk_builder_get_object (gui, "gnumeric_only_button")));
+       GtkRecentManager *manager = gtk_recent_manager_get_default ();
+       GList *docs, *l;
+
+       gtk_list_store_clear (list);
+
+       docs = gtk_recent_manager_get_items (manager);
+       docs = g_list_sort (docs, by_age_uri);
+       for (l = docs; l; l = l->next) {
+               GtkRecentInfo *ri = l->data;
+               GtkTreeIter iter;
+
+               if (existing_only) {
+                       gboolean exists = gtk_recent_info_is_local (ri)
+                               ? gtk_recent_info_exists (ri)
+                               : TRUE;  /* Just assume so */
+                       if (!exists)
+                               continue;
+               }
+
+               if (gnumeric_only) {
+                       if (!gtk_recent_info_has_application (ri, g_get_application_name ()))
+                               continue;
+               }
+
+               gtk_list_store_append (list, &iter);
+               gtk_list_store_set (list, &iter, RECENT_COL_INFO, ri, -1);
+       }
+       g_list_free_full (docs, (GDestroyNotify)gtk_recent_info_unref);
+}
+
+
 void
 dialog_recent_used (WBCGtk *wbcg)
 {
-       GtkRecentFilter *filter;
-       GtkWidget *dialog = gtk_recent_chooser_dialog_new
-               (_("Recently Used Files"),
-                wbcg_toplevel (wbcg),
-                GTK_STOCK_CANCEL, GTK_RESPONSE_CANCEL,
-                GTK_STOCK_OPEN, GTK_RESPONSE_ACCEPT,
-                NULL);
+       GtkBuilder *gui;
+       GtkDialog *dialog;
 
-       gtk_recent_chooser_set_sort_type (GTK_RECENT_CHOOSER (dialog), GTK_RECENT_SORT_MRU);
+       /* Only pop up one copy per workbook */
+       if (gnumeric_dialog_raise_if_exists (wbcg, RECENT_KEY))
+               return;
+
+       gui = gnm_gtk_builder_load ("recent.ui", NULL, GO_CMD_CONTEXT (wbcg));
+        if (gui == NULL)
+                return;
 
-       filter = gtk_recent_filter_new ();
-       gtk_recent_filter_set_name (filter, _("All files"));
-       gtk_recent_filter_add_pattern (filter, "*");
-       gtk_recent_chooser_add_filter (GTK_RECENT_CHOOSER (dialog), filter);
+       dialog = GTK_DIALOG (go_gtk_builder_get_widget (gui, "recent_dialog"));
 
-       filter = gtk_recent_filter_new ();
-       gtk_recent_filter_set_name (filter, _("All files used by Gnumeric"));
-       gtk_recent_filter_add_application (filter, g_get_application_name ());
-       gtk_recent_chooser_add_filter (GTK_RECENT_CHOOSER (dialog), filter);
-       gtk_recent_chooser_set_filter (GTK_RECENT_CHOOSER (dialog), filter);
+       gtk_tree_view_column_set_cell_data_func
+               (GTK_TREE_VIEW_COLUMN (gtk_builder_get_object (gui, "url_column")),
+                GTK_CELL_RENDERER (gtk_builder_get_object (gui, "url_renderer")),
+                url_renderer_func,
+                NULL,
+                NULL);
+
+       gtk_tree_view_column_set_cell_data_func
+               (GTK_TREE_VIEW_COLUMN (gtk_builder_get_object (gui, "age_column")),
+                GTK_CELL_RENDERER (gtk_builder_get_object (gui, "age_renderer")),
+                age_renderer_func,
+                NULL,
+                NULL);
 
        g_signal_connect (G_OBJECT (dialog), "response",
                          G_CALLBACK (cb_response), wbcg);
 
+
+       {
+               GtkWidget *w = GTK_WIDGET (wbcg_toplevel (wbcg));
+               int width, height, vsep;
+               PangoLayout *layout =
+                       gtk_widget_create_pango_layout (w, "Mg19");
+
+               gtk_widget_style_get (go_gtk_builder_get_widget (gui, "docs_treeview"),
+                                     "vertical_separator", &vsep,
+                                     NULL);
+
+               pango_layout_get_pixel_size (layout, &width, &height);
+               gtk_widget_set_size_request (go_gtk_builder_get_widget (gui, "docs_scrolledwindow"),
+                                            width * 60 / 4,
+                                            (2 * height + vsep) * (4 + 1));
+               g_object_unref (layout);
+       }
+
+       g_signal_connect_swapped (gtk_builder_get_object (gui, "existing_only_button"),
+                                 "toggled", G_CALLBACK (populate_recent_model), gui);
+       g_signal_connect_swapped (gtk_builder_get_object (gui, "gnumeric_only_button"),
+                                 "toggled", G_CALLBACK (populate_recent_model), gui);
+
+       populate_recent_model (gui);
+
+       /* ---------------------------------------- */
+
+       g_object_set_data_full (G_OBJECT (dialog), "gui", gui, g_object_unref);
        go_gtk_nonmodal_dialog (wbcg_toplevel (wbcg), GTK_WINDOW (dialog));
        gtk_widget_show_all (GTK_WIDGET (dialog));
 }
diff --git a/src/dialogs/recent.ui b/src/dialogs/recent.ui
new file mode 100644
index 0000000..3e62a6c
--- /dev/null
+++ b/src/dialogs/recent.ui
@@ -0,0 +1,162 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<interface>
+  <!-- interface-requires gtk+ 3.0 -->
+  <object class="GtkListStore" id="recent_model">
+    <columns>
+      <!-- column-name RECENT_COL_INFO -->
+      <column type="GtkRecentInfo"/>
+    </columns>
+  </object>
+  <object class="GtkDialog" id="recent_dialog">
+    <property name="can_focus">False</property>
+    <property name="border_width">5</property>
+    <property name="title" translatable="yes">Recently Used Documents</property>
+    <property name="type_hint">dialog</property>
+    <child internal-child="vbox">
+      <object class="GtkBox" id="recent_dialog_vbox">
+        <property name="can_focus">False</property>
+        <property name="orientation">vertical</property>
+        <property name="spacing">2</property>
+        <child>
+          <object class="GtkScrolledWindow" id="docs_scrolledwindow">
+            <property name="visible">True</property>
+            <property name="can_focus">True</property>
+            <property name="hscrollbar_policy">never</property>
+            <property name="shadow_type">in</property>
+            <child>
+              <object class="GtkTreeView" id="docs_treeview">
+                <property name="visible">True</property>
+                <property name="can_focus">True</property>
+                <property name="model">recent_model</property>
+                <property name="enable_search">False</property>
+                <child internal-child="selection">
+                  <object class="GtkTreeSelection" id="treeview-selection1"/>
+                </child>
+                <child>
+                  <object class="GtkTreeViewColumn" id="url_column">
+                    <property name="title" translatable="yes">Document</property>
+                    <property name="expand">True</property>
+                    <child>
+                      <object class="GtkCellRendererText" id="url_renderer"/>
+                    </child>
+                  </object>
+                </child>
+                <child>
+                  <object class="GtkTreeViewColumn" id="age_column">
+                    <property name="sizing">autosize</property>
+                    <property name="title" translatable="yes">Age</property>
+                    <child>
+                      <object class="GtkCellRendererText" id="age_renderer"/>
+                    </child>
+                  </object>
+                </child>
+              </object>
+            </child>
+          </object>
+          <packing>
+            <property name="expand">True</property>
+            <property name="fill">True</property>
+            <property name="position">0</property>
+          </packing>
+        </child>
+        <child internal-child="action_area">
+          <object class="GtkButtonBox" id="dialog-action_area1">
+            <property name="can_focus">False</property>
+            <property name="layout_style">end</property>
+            <child>
+              <object class="GtkButton" id="cancel_button">
+                <property name="label">gtk-cancel</property>
+                <property name="visible">True</property>
+                <property name="can_focus">True</property>
+                <property name="receives_default">True</property>
+                <property name="tooltip_text" translatable="yes">Discard changes in all files</property>
+                <property name="use_underline">True</property>
+                <property name="use_stock">True</property>
+                <property name="xalign">0.47999998927116394</property>
+              </object>
+              <packing>
+                <property name="expand">False</property>
+                <property name="fill">True</property>
+                <property name="position">0</property>
+              </packing>
+            </child>
+            <child>
+              <object class="GtkButton" id="open_button">
+                <property name="label">gtk-open</property>
+                <property name="visible">True</property>
+                <property name="can_focus">True</property>
+                <property name="can_default">True</property>
+                <property name="receives_default">True</property>
+                <property name="has_tooltip">True</property>
+                <property name="tooltip_text" translatable="yes">Save document</property>
+                <property name="use_underline">True</property>
+                <property name="use_stock">True</property>
+                <property name="yalign">0.44999998807907104</property>
+              </object>
+              <packing>
+                <property name="expand">False</property>
+                <property name="fill">True</property>
+                <property name="position">1</property>
+              </packing>
+            </child>
+          </object>
+          <packing>
+            <property name="expand">False</property>
+            <property name="fill">True</property>
+            <property name="pack_type">end</property>
+            <property name="position">1</property>
+          </packing>
+        </child>
+        <child>
+          <object class="GtkBox" id="box1">
+            <property name="visible">True</property>
+            <property name="can_focus">False</property>
+            <property name="orientation">vertical</property>
+            <child>
+              <object class="GtkCheckButton" id="existing_only_button">
+                <property name="label" translatable="yes">Existing only</property>
+                <property name="visible">True</property>
+                <property name="can_focus">True</property>
+                <property name="receives_default">False</property>
+                <property name="relief">none</property>
+                <property name="xalign">0</property>
+                <property name="active">True</property>
+                <property name="draw_indicator">True</property>
+              </object>
+              <packing>
+                <property name="expand">False</property>
+                <property name="fill">True</property>
+                <property name="position">0</property>
+              </packing>
+            </child>
+            <child>
+              <object class="GtkCheckButton" id="gnumeric_only_button">
+                <property name="label" translatable="yes">Gnumeric files only</property>
+                <property name="visible">True</property>
+                <property name="can_focus">True</property>
+                <property name="receives_default">False</property>
+                <property name="xalign">0</property>
+                <property name="active">True</property>
+                <property name="draw_indicator">True</property>
+              </object>
+              <packing>
+                <property name="expand">False</property>
+                <property name="fill">True</property>
+                <property name="position">1</property>
+              </packing>
+            </child>
+          </object>
+          <packing>
+            <property name="expand">False</property>
+            <property name="fill">True</property>
+            <property name="position">2</property>
+          </packing>
+        </child>
+      </object>
+    </child>
+    <action-widgets>
+      <action-widget response="-6">cancel_button</action-widget>
+      <action-widget response="-5">open_button</action-widget>
+    </action-widgets>
+  </object>
+</interface>


[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]