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>
31 #include <goffice/goffice.h>
33 #define RECENT_KEY "recent-dialog"
39 /* ------------------------------------------------------------------------- */
42 cb_selected (GtkTreeModel
*model
,
43 G_GNUC_UNUSED GtkTreePath
*path
,
49 gtk_tree_model_get (model
, iter
, RECENT_COL_INFO
, &info
, -1);
50 uri
= g_strdup (gtk_recent_info_get_uri (info
));
51 gtk_recent_info_unref (info
);
53 gui_file_read (wbcg
, uri
, NULL
, NULL
);
59 cb_response (GtkWidget
*dialog
,
63 GtkBuilder
*gui
= g_object_get_data (G_OBJECT (dialog
), "gui");
64 GtkTreeView
*tv
= GTK_TREE_VIEW (gtk_builder_get_object (gui
, "docs_treeview"));
65 GtkTreeSelection
*tsel
= gtk_tree_view_get_selection (tv
);
67 switch (response_id
) {
69 gtk_tree_selection_selected_foreach (tsel
, (GtkTreeSelectionForeachFunc
) cb_selected
, wbcg
);
70 gtk_widget_destroy (dialog
);
74 gtk_widget_destroy (dialog
);
79 cb_destroy (GtkDialog
*dialog
)
81 /* Trigger tear-down. */
82 g_object_set_data (G_OBJECT (dialog
), "gui", NULL
);
87 cb_key_press (GtkWidget
*widget
, GdkEventKey
*event
)
89 GtkTreeView
*tree_view
= (GtkTreeView
*) widget
;
91 switch (event
->keyval
) {
92 case GDK_KEY_KP_Delete
:
93 case GDK_KEY_Delete
: {
94 GtkTreeSelection
*tsel
= gtk_tree_view_get_selection (tree_view
);
98 if (gtk_tree_selection_get_selected (tsel
, &model
, &iter
)) {
101 GtkRecentManager
*manager
= gtk_recent_manager_get_default ();
103 gtk_tree_model_get (model
, &iter
, RECENT_COL_INFO
, &info
, -1);
104 uri
= gtk_recent_info_get_uri (info
);
106 gtk_recent_manager_remove_item (manager
, uri
, NULL
);
107 gtk_list_store_remove (GTK_LIST_STORE (model
), &iter
);
108 gtk_recent_info_unref (info
);
121 cb_button_press (GtkWidget
*w
, GdkEventButton
*ev
, WBCGtk
*wbcg
)
123 if (ev
->type
== GDK_2BUTTON_PRESS
&& ev
->button
== 1) {
124 GtkWidget
*dlg
= gtk_widget_get_toplevel (w
);
125 if (GTK_IS_DIALOG (dlg
)) {
126 cb_response (dlg
, GTK_RESPONSE_OK
, wbcg
);
134 url_renderer_func (GtkTreeViewColumn
*tree_column
,
135 GtkCellRenderer
*cell
,
140 GtkRecentInfo
*ri
= NULL
;
142 char *markup
, *shortname
, *filename
, *longname
;
144 gtk_tree_model_get (model
, iter
, RECENT_COL_INFO
, &ri
, -1);
146 uri
= gtk_recent_info_get_uri (ri
);
147 filename
= go_filename_from_uri (uri
);
149 shortname
= g_filename_display_basename (filename
);
151 shortname
= g_filename_display_basename (uri
);
155 longname
= g_strdup (filename
);
157 char *duri
= g_uri_unescape_string (uri
, NULL
);
159 ? g_filename_display_name (duri
)
164 markup
= g_markup_printf_escaped (_("<b>%s</b>\n"
165 "<small>Location: %s</small>"),
168 g_object_set (cell
, "markup", markup
, NULL
);
173 gtk_recent_info_unref (ri
);
177 age_renderer_func (GtkTreeViewColumn
*tree_column
,
178 GtkCellRenderer
*cell
,
183 GtkRecentInfo
*ri
= NULL
;
184 GDateTime
*now
= user_data
;
185 GDateTime
*last_used
;
188 const char *date_format
;
191 gtk_tree_model_get (model
, iter
, RECENT_COL_INFO
, &ri
, -1);
192 last_used
= g_date_time_new_from_unix_local (gtk_recent_info_get_modified (ri
));
193 gtk_recent_info_unref (ri
);
195 age
= g_date_time_difference (now
, last_used
);
196 if (age
< G_TIME_SPAN_DAY
&&
197 g_date_time_get_day_of_month (now
) == g_date_time_get_day_of_month (last_used
)) {
198 if (go_locale_24h ())
200 * xgettext: This is a time format for
201 * g_date_time_format used in locales that use a
202 * 24 hour clock. You probably do not need to change
203 * this. The default will show things like "09:50"
206 date_format
= _("%H:%M");
209 * xgettext: This is a time format for
210 * g_date_time_format used in locales that use
211 * a 12 hour clock. You probably do not need
212 * to change this. The default will show
213 * things like " 9:50 am" and " 9:50 pm".
215 date_format
= _("%l:%M %P");
220 p
= text
= g_date_time_format (last_used
, date_format
);
221 while (g_ascii_isspace (*p
))
223 g_object_set (cell
, "text", p
, "xalign", 0.5, NULL
);
226 g_date_time_unref (last_used
);
230 by_age_uri (gconstpointer a_
, gconstpointer b_
)
232 GtkRecentInfo
*a
= (gpointer
)a_
;
233 GtkRecentInfo
*b
= (gpointer
)b_
;
236 res
= gtk_recent_info_get_modified (b
) - gtk_recent_info_get_modified (a
);
239 res
= strcmp (gtk_recent_info_get_uri (a
), gtk_recent_info_get_uri (b
));
245 populate_recent_model (GtkBuilder
*gui
)
247 GtkListStore
*list
= GTK_LIST_STORE (gtk_builder_get_object (gui
, "recent_model"));
248 gboolean existing_only
= gtk_toggle_button_get_active
249 (GTK_TOGGLE_BUTTON (gtk_builder_get_object (gui
, "existing_only_button")));
250 gboolean gnumeric_only
= gtk_toggle_button_get_active
251 (GTK_TOGGLE_BUTTON (gtk_builder_get_object (gui
, "gnumeric_only_button")));
252 GtkRecentManager
*manager
= gtk_recent_manager_get_default ();
255 gtk_list_store_clear (list
);
257 docs
= gtk_recent_manager_get_items (manager
);
258 docs
= g_list_sort (docs
, by_age_uri
);
259 for (l
= docs
; l
; l
= l
->next
) {
260 GtkRecentInfo
*ri
= l
->data
;
264 gboolean exists
= gtk_recent_info_is_local (ri
)
265 ? gtk_recent_info_exists (ri
)
266 : TRUE
; /* Just assume so */
272 if (!gtk_recent_info_has_application (ri
, g_get_application_name ()))
276 gtk_list_store_append (list
, &iter
);
277 gtk_list_store_set (list
, &iter
, RECENT_COL_INFO
, ri
, -1);
279 g_list_free_full (docs
, (GDestroyNotify
)gtk_recent_info_unref
);
284 dialog_recent_used (WBCGtk
*wbcg
)
289 /* Only pop up one copy per workbook */
290 if (gnm_dialog_raise_if_exists (wbcg
, RECENT_KEY
))
293 gui
= gnm_gtk_builder_load ("res:ui/recent.ui", NULL
, GO_CMD_CONTEXT (wbcg
));
297 dialog
= GTK_DIALOG (go_gtk_builder_get_widget (gui
, "recent_dialog"));
299 g_signal_connect (G_OBJECT (dialog
), "response",
300 G_CALLBACK (cb_response
), wbcg
);
305 int width
, height
, vsep
;
308 GtkTreeSelection
*tsel
;
310 w
= GTK_WIDGET (wbcg_toplevel (wbcg
));
311 layout
= gtk_widget_create_pango_layout (w
, "Mg19");
313 w
= go_gtk_builder_get_widget (gui
, "docs_treeview");
314 gtk_widget_style_get (w
, "vertical_separator", &vsep
, NULL
);
315 g_signal_connect (w
, "key-press-event",
316 G_CALLBACK (cb_key_press
),
318 g_signal_connect (w
, "button-press-event",
319 G_CALLBACK (cb_button_press
),
322 pango_layout_get_pixel_size (layout
, &width
, &height
);
323 gtk_widget_set_size_request (go_gtk_builder_get_widget (gui
, "docs_scrolledwindow"),
325 (2 * height
+ vsep
) * (5 + 1));
326 g_object_unref (layout
);
327 tv
= GTK_TREE_VIEW (gtk_builder_get_object (gui
, "docs_treeview"));
328 tsel
= gtk_tree_view_get_selection (tv
);
329 gtk_tree_selection_set_mode (tsel
, GTK_SELECTION_MULTIPLE
);
332 g_signal_connect_swapped (gtk_builder_get_object (gui
, "existing_only_button"),
333 "toggled", G_CALLBACK (populate_recent_model
), gui
);
334 g_signal_connect_swapped (gtk_builder_get_object (gui
, "gnumeric_only_button"),
335 "toggled", G_CALLBACK (populate_recent_model
), gui
);
337 populate_recent_model (gui
);
339 gtk_tree_view_column_set_cell_data_func
340 (GTK_TREE_VIEW_COLUMN (gtk_builder_get_object (gui
, "url_column")),
341 GTK_CELL_RENDERER (gtk_builder_get_object (gui
, "url_renderer")),
346 gtk_tree_view_column_set_cell_data_func
347 (GTK_TREE_VIEW_COLUMN (gtk_builder_get_object (gui
, "age_column")),
348 GTK_CELL_RENDERER (gtk_builder_get_object (gui
, "age_renderer")),
350 g_date_time_new_now_local (),
351 (GDestroyNotify
)g_date_time_unref
);
353 /* ---------------------------------------- */
355 g_object_set_data_full (G_OBJECT (dialog
), "gui", gui
, g_object_unref
);
356 g_signal_connect (dialog
, "destroy", G_CALLBACK (cb_destroy
), NULL
);
357 go_gtk_nonmodal_dialog (wbcg_toplevel (wbcg
), GTK_WINDOW (dialog
));
358 gtk_widget_show_all (GTK_WIDGET (dialog
));
361 /* ------------------------------------------------------------------------- */