3 * Dialog for selecting from recently used files.
6 * Morten Welinder (terra@gnome.org)
8 * This program is free software; you can redistribute it and/or modify
9 * it under the terms of the GNU General Public License as published by
10 * the Free Software Foundation; either version 2 of the License, or
11 * (at your option) any later version.
13 * This program is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 * GNU General Public License for more details.
18 * You should have received a copy of the GNU General Public License
19 * along with this program; if not, see <https://www.gnu.org/licenses/>.
22 #include <gnumeric-config.h>
23 #include <glib/gi18n-lib.h>
25 #include <dialogs/dialogs.h>
30 #include <goffice/goffice.h>
32 #define RECENT_KEY "recent-dialog"
38 /* ------------------------------------------------------------------------- */
41 cb_selected (GtkTreeModel
*model
,
42 G_GNUC_UNUSED GtkTreePath
*path
,
48 gtk_tree_model_get (model
, iter
, RECENT_COL_INFO
, &info
, -1);
49 uri
= g_strdup (gtk_recent_info_get_uri (info
));
50 gtk_recent_info_unref (info
);
52 gui_file_read (wbcg
, uri
, NULL
, NULL
);
58 cb_response (GtkWidget
*dialog
,
62 GtkBuilder
*gui
= g_object_get_data (G_OBJECT (dialog
), "gui");
63 GtkTreeView
*tv
= GTK_TREE_VIEW (gtk_builder_get_object (gui
, "docs_treeview"));
64 GtkTreeSelection
*tsel
= gtk_tree_view_get_selection (tv
);
66 switch (response_id
) {
68 gtk_tree_selection_selected_foreach (tsel
, (GtkTreeSelectionForeachFunc
) cb_selected
, wbcg
);
69 gtk_widget_destroy (dialog
);
73 gtk_widget_destroy (dialog
);
78 cb_destroy (GtkDialog
*dialog
)
80 /* Trigger tear-down. */
81 g_object_set_data (G_OBJECT (dialog
), "gui", NULL
);
86 cb_key_press (GtkWidget
*widget
, GdkEventKey
*event
)
88 GtkTreeView
*tree_view
= (GtkTreeView
*) widget
;
90 switch (event
->keyval
) {
91 case GDK_KEY_KP_Delete
:
92 case GDK_KEY_Delete
: {
93 GtkTreeSelection
*tsel
= gtk_tree_view_get_selection (tree_view
);
97 if (gtk_tree_selection_get_selected (tsel
, &model
, &iter
)) {
100 GtkRecentManager
*manager
= gtk_recent_manager_get_default ();
102 gtk_tree_model_get (model
, &iter
, RECENT_COL_INFO
, &info
, -1);
103 uri
= gtk_recent_info_get_uri (info
);
105 gtk_recent_manager_remove_item (manager
, uri
, NULL
);
106 gtk_list_store_remove (GTK_LIST_STORE (model
), &iter
);
107 gtk_recent_info_unref (info
);
120 cb_button_press (GtkWidget
*w
, GdkEventButton
*ev
, WBCGtk
*wbcg
)
122 if (ev
->type
== GDK_2BUTTON_PRESS
&& ev
->button
== 1) {
123 GtkWidget
*dlg
= gtk_widget_get_toplevel (w
);
124 if (GTK_IS_DIALOG (dlg
)) {
125 cb_response (dlg
, GTK_RESPONSE_OK
, wbcg
);
133 url_renderer_func (GtkTreeViewColumn
*tree_column
,
134 GtkCellRenderer
*cell
,
139 GtkRecentInfo
*ri
= NULL
;
141 char *markup
, *shortname
, *filename
, *longname
;
143 gtk_tree_model_get (model
, iter
, RECENT_COL_INFO
, &ri
, -1);
145 uri
= gtk_recent_info_get_uri (ri
);
146 filename
= go_filename_from_uri (uri
);
148 shortname
= g_filename_display_basename (filename
);
150 shortname
= g_filename_display_basename (uri
);
154 longname
= g_strdup (filename
);
156 char *duri
= g_uri_unescape_string (uri
, NULL
);
158 ? g_filename_display_name (duri
)
163 markup
= g_markup_printf_escaped (_("<b>%s</b>\n"
164 "<small>Location: %s</small>"),
167 g_object_set (cell
, "markup", markup
, NULL
);
172 gtk_recent_info_unref (ri
);
176 age_renderer_func (GtkTreeViewColumn
*tree_column
,
177 GtkCellRenderer
*cell
,
182 GtkRecentInfo
*ri
= NULL
;
183 GDateTime
*now
= user_data
;
184 GDateTime
*last_used
;
187 const char *date_format
;
190 gtk_tree_model_get (model
, iter
, RECENT_COL_INFO
, &ri
, -1);
191 last_used
= g_date_time_new_from_unix_local (gtk_recent_info_get_modified (ri
));
192 gtk_recent_info_unref (ri
);
194 age
= g_date_time_difference (now
, last_used
);
195 if (age
< G_TIME_SPAN_DAY
&&
196 g_date_time_get_day_of_month (now
) == g_date_time_get_day_of_month (last_used
)) {
197 if (go_locale_24h ())
199 * xgettext: This is a time format for
200 * g_date_time_format used in locales that use a
201 * 24 hour clock. You probably do not need to change
202 * this. The default will show things like "09:50"
205 date_format
= _("%H:%M");
208 * xgettext: This is a time format for
209 * g_date_time_format used in locales that use
210 * a 12 hour clock. You probably do not need
211 * to change this. The default will show
212 * things like " 9:50 am" and " 9:50 pm".
214 date_format
= _("%l:%M %P");
219 p
= text
= g_date_time_format (last_used
, date_format
);
220 while (g_ascii_isspace (*p
))
222 g_object_set (cell
, "text", p
, "xalign", 0.5, NULL
);
225 g_date_time_unref (last_used
);
229 by_age_uri (gconstpointer a_
, gconstpointer b_
)
231 GtkRecentInfo
*a
= (gpointer
)a_
;
232 GtkRecentInfo
*b
= (gpointer
)b_
;
235 res
= gtk_recent_info_get_modified (b
) - gtk_recent_info_get_modified (a
);
238 res
= strcmp (gtk_recent_info_get_uri (a
), gtk_recent_info_get_uri (b
));
244 populate_recent_model (GtkBuilder
*gui
)
246 GtkListStore
*list
= GTK_LIST_STORE (gtk_builder_get_object (gui
, "recent_model"));
247 gboolean existing_only
= gtk_toggle_button_get_active
248 (GTK_TOGGLE_BUTTON (gtk_builder_get_object (gui
, "existing_only_button")));
249 gboolean gnumeric_only
= gtk_toggle_button_get_active
250 (GTK_TOGGLE_BUTTON (gtk_builder_get_object (gui
, "gnumeric_only_button")));
251 GtkRecentManager
*manager
= gtk_recent_manager_get_default ();
254 gtk_list_store_clear (list
);
256 docs
= gtk_recent_manager_get_items (manager
);
257 docs
= g_list_sort (docs
, by_age_uri
);
258 for (l
= docs
; l
; l
= l
->next
) {
259 GtkRecentInfo
*ri
= l
->data
;
263 gboolean exists
= gtk_recent_info_is_local (ri
)
264 ? gtk_recent_info_exists (ri
)
265 : TRUE
; /* Just assume so */
271 if (!gtk_recent_info_has_application (ri
, g_get_application_name ()))
275 gtk_list_store_append (list
, &iter
);
276 gtk_list_store_set (list
, &iter
, RECENT_COL_INFO
, ri
, -1);
278 g_list_free_full (docs
, (GDestroyNotify
)gtk_recent_info_unref
);
283 dialog_recent_used (WBCGtk
*wbcg
)
288 /* Only pop up one copy per workbook */
289 if (gnm_dialog_raise_if_exists (wbcg
, RECENT_KEY
))
292 gui
= gnm_gtk_builder_load ("res:ui/recent.ui", NULL
, GO_CMD_CONTEXT (wbcg
));
296 dialog
= GTK_DIALOG (go_gtk_builder_get_widget (gui
, "recent_dialog"));
298 g_signal_connect (G_OBJECT (dialog
), "response",
299 G_CALLBACK (cb_response
), wbcg
);
304 int width
, height
, vsep
;
307 GtkTreeSelection
*tsel
;
309 w
= GTK_WIDGET (wbcg_toplevel (wbcg
));
310 layout
= gtk_widget_create_pango_layout (w
, "Mg19");
312 w
= go_gtk_builder_get_widget (gui
, "docs_treeview");
313 gtk_widget_style_get (w
, "vertical_separator", &vsep
, NULL
);
314 g_signal_connect (w
, "key-press-event",
315 G_CALLBACK (cb_key_press
),
317 g_signal_connect (w
, "button-press-event",
318 G_CALLBACK (cb_button_press
),
321 pango_layout_get_pixel_size (layout
, &width
, &height
);
322 gtk_widget_set_size_request (go_gtk_builder_get_widget (gui
, "docs_scrolledwindow"),
324 (2 * height
+ vsep
) * (5 + 1));
325 g_object_unref (layout
);
326 tv
= GTK_TREE_VIEW (gtk_builder_get_object (gui
, "docs_treeview"));
327 tsel
= gtk_tree_view_get_selection (tv
);
328 gtk_tree_selection_set_mode (tsel
, GTK_SELECTION_MULTIPLE
);
331 g_signal_connect_swapped (gtk_builder_get_object (gui
, "existing_only_button"),
332 "toggled", G_CALLBACK (populate_recent_model
), gui
);
333 g_signal_connect_swapped (gtk_builder_get_object (gui
, "gnumeric_only_button"),
334 "toggled", G_CALLBACK (populate_recent_model
), gui
);
336 populate_recent_model (gui
);
338 gtk_tree_view_column_set_cell_data_func
339 (GTK_TREE_VIEW_COLUMN (gtk_builder_get_object (gui
, "url_column")),
340 GTK_CELL_RENDERER (gtk_builder_get_object (gui
, "url_renderer")),
345 gtk_tree_view_column_set_cell_data_func
346 (GTK_TREE_VIEW_COLUMN (gtk_builder_get_object (gui
, "age_column")),
347 GTK_CELL_RENDERER (gtk_builder_get_object (gui
, "age_renderer")),
349 g_date_time_new_now_local (),
350 (GDestroyNotify
)g_date_time_unref
);
352 /* ---------------------------------------- */
354 g_object_set_data_full (G_OBJECT (dialog
), "gui", gui
, g_object_unref
);
355 g_signal_connect (dialog
, "destroy", G_CALLBACK (cb_destroy
), NULL
);
356 go_gtk_nonmodal_dialog (wbcg_toplevel (wbcg
), GTK_WINDOW (dialog
));
357 gtk_widget_show_all (GTK_WIDGET (dialog
));
360 /* ------------------------------------------------------------------------- */