4 * Copyright (C) 2008 - 2009 The Geeqie Team
6 * Author: Vladimir Nadvornik
8 * This software is released under the GNU General Public License (GNU GPL).
9 * Please read the included file COPYING for more information.
10 * This software comes with no warranty of any kind, use at your own risk!
14 #include "desktop_file.h"
20 #include "ui_fileops.h"
21 #include "ui_utildlg.h"
22 #include "pixbuf_util.h"
25 #include "layout_util.h"
27 #define CONFIG_WINDOW_DEF_WIDTH 700
28 #define CONFIG_WINDOW_DEF_HEIGHT 400
32 typedef struct _EditorWindow EditorWindow;
37 GtkWidget *save_button;
38 GtkTextBuffer *buffer;
43 typedef struct _EditorListWindow EditorListWindow;
44 struct _EditorListWindow
48 GenericDialog *gd; /* any open confirm dialogs ? */
51 typedef struct _EditorWindowDel_Data EditorWindowDel_Data;
52 struct _EditorWindowDel_Data
54 EditorListWindow *ewl;
58 static EditorListWindow *editor_list_window = NULL;
60 static gboolean editor_window_save(EditorWindow *ew)
65 GtkTextIter start, end;
68 const gchar *name = gtk_entry_get_text(GTK_ENTRY(ew->entry));
70 if (!name || !name[0])
72 file_util_warning_dialog(_("Can't save"), _("Please specify file name."), GTK_STOCK_DIALOG_ERROR, NULL);
76 gtk_text_buffer_get_bounds(ew->buffer, &start, &end);
77 text = gtk_text_buffer_get_text(ew->buffer, &start, &end, FALSE);
79 dir = g_build_filename(get_rc_dir(), "applications", NULL);
80 path = g_build_filename(dir, name, NULL);
82 if (!recursive_mkdir_if_not_exists(dir, 0755))
84 file_util_warning_dialog(_("Can't save"), _("Could not create directory"), GTK_STOCK_DIALOG_ERROR, NULL);
88 if (ret && !g_file_set_contents(path, text, -1, &error))
90 file_util_warning_dialog(_("Can't save"), error->message, GTK_STOCK_DIALOG_ERROR, NULL);
98 layout_editors_reload_start();
99 /* idle function is not needed, everything should be cached */
100 layout_editors_reload_finish();
104 static void editor_window_close_cb(GtkWidget *widget, gpointer data)
106 EditorWindow *ew = data;
108 g_free(ew->desktop_name);
109 gtk_widget_destroy(ew->window);
113 static gint editor_window_delete_cb(GtkWidget *w, GdkEventAny *event, gpointer data)
115 editor_window_close_cb(w, data);
119 static void editor_window_save_cb(GtkWidget *widget, gpointer data)
121 EditorWindow *ew = data;
125 editor_window_save(ew);
128 gtk_widget_set_sensitive(ew->save_button, FALSE);
129 ew->modified = FALSE;
132 static void editor_window_text_modified_cb(GtkWidget *widget, gpointer data)
134 EditorWindow *ew = data;
136 if (gtk_text_buffer_get_modified(ew->buffer))
138 gtk_widget_set_sensitive(ew->save_button, TRUE);
143 static void editor_window_entry_changed_cb(GtkWidget *widget, gpointer data)
145 EditorWindow *ew = data;
146 const gchar *content = gtk_entry_get_text(GTK_ENTRY(ew->entry));
147 gboolean modified = ew->modified;
151 modified = (!ew->desktop_name && *content);
156 modified = strcmp(ew->desktop_name, content);
159 gtk_widget_set_sensitive(ew->save_button, modified);
160 ew->modified = modified;
163 static void editor_window_new(const gchar *src_path, const gchar *desktop_name)
169 GtkWidget *ct_button;
170 GtkWidget *button_hbox;
172 GtkWidget *text_view;
176 ew = g_new0(EditorWindow, 1);
179 ew->window = window_new(GTK_WINDOW_TOPLEVEL, "Desktop", PIXBUF_INLINE_ICON_CONFIG, NULL, _("Desktop file"));
180 gtk_window_set_type_hint(GTK_WINDOW(ew->window), GDK_WINDOW_TYPE_HINT_DIALOG);
182 g_signal_connect(G_OBJECT(ew->window), "delete_event",
183 G_CALLBACK(editor_window_delete_cb), ew);
185 gtk_window_set_default_size(GTK_WINDOW(ew->window), CONFIG_WINDOW_DEF_WIDTH, CONFIG_WINDOW_DEF_HEIGHT);
186 gtk_window_set_resizable(GTK_WINDOW(ew->window), TRUE);
187 gtk_container_set_border_width(GTK_CONTAINER(ew->window), PREF_PAD_BORDER);
189 win_vbox = gtk_vbox_new(FALSE, PREF_PAD_SPACE);
190 gtk_container_add(GTK_CONTAINER(ew->window), win_vbox);
191 gtk_widget_show(win_vbox);
193 hbox = gtk_hbox_new(FALSE, PREF_PAD_SPACE);
194 gtk_box_pack_end(GTK_BOX(win_vbox), hbox, FALSE, FALSE, 0);
195 gtk_widget_show(hbox);
197 ew->entry = gtk_entry_new();
198 gtk_box_pack_start(GTK_BOX(hbox), ew->entry, TRUE, TRUE, 0);
199 ew->desktop_name = NULL;
202 gtk_entry_set_text(GTK_ENTRY(ew->entry), desktop_name);
203 ew->desktop_name = g_strdup(desktop_name);
205 gtk_widget_show(ew->entry);
206 g_signal_connect(G_OBJECT(ew->entry), "changed", G_CALLBACK(editor_window_entry_changed_cb), ew);
208 button_hbox = gtk_hbutton_box_new();
209 gtk_button_box_set_layout(GTK_BUTTON_BOX(button_hbox), GTK_BUTTONBOX_END);
210 gtk_box_set_spacing(GTK_BOX(button_hbox), PREF_PAD_BUTTON_GAP);
211 gtk_box_pack_end(GTK_BOX(hbox), button_hbox, FALSE, FALSE, 0);
212 gtk_widget_show(button_hbox);
214 ew->save_button = pref_button_new(NULL, GTK_STOCK_SAVE, NULL, FALSE,
215 G_CALLBACK(editor_window_save_cb), ew);
216 gtk_container_add(GTK_CONTAINER(button_hbox), ew->save_button);
217 GTK_WIDGET_SET_FLAGS(ew->save_button, GTK_CAN_DEFAULT);
218 gtk_widget_set_sensitive(ew->save_button, FALSE);
219 gtk_widget_show(ew->save_button);
220 ct_button = ew->save_button;
222 button = pref_button_new(NULL, GTK_STOCK_CLOSE, NULL, FALSE,
223 G_CALLBACK(editor_window_close_cb), ew);
224 gtk_container_add(GTK_CONTAINER(button_hbox), button);
225 GTK_WIDGET_SET_FLAGS(button, GTK_CAN_DEFAULT);
226 gtk_widget_show(button);
228 if (!generic_dialog_get_alternative_button_order(ew->window))
230 gtk_box_reorder_child(GTK_BOX(button_hbox), ct_button, -1);
234 scrolled = gtk_scrolled_window_new(NULL, NULL);
235 gtk_scrolled_window_set_shadow_type(GTK_SCROLLED_WINDOW(scrolled), GTK_SHADOW_IN);
236 gtk_scrolled_window_set_policy(GTK_SCROLLED_WINDOW(scrolled),
237 GTK_POLICY_AUTOMATIC, GTK_POLICY_AUTOMATIC);
238 gtk_box_pack_start(GTK_BOX(win_vbox), scrolled, TRUE, TRUE, 5);
239 gtk_widget_show(scrolled);
241 text_view = gtk_text_view_new();
242 gtk_container_add(GTK_CONTAINER(scrolled), text_view);
243 gtk_widget_show(text_view);
245 ew->buffer = gtk_text_view_get_buffer(GTK_TEXT_VIEW(text_view));
246 if (g_file_get_contents(src_path, &text, &size, NULL))
248 gtk_text_buffer_set_text(ew->buffer, text, size);
250 gtk_text_buffer_set_modified(ew->buffer, FALSE);
251 g_signal_connect(G_OBJECT(ew->buffer), "modified-changed",
252 G_CALLBACK(editor_window_text_modified_cb), ew);
254 gtk_widget_show(ew->window);
258 static void editor_list_window_close_cb(GtkWidget *widget, gpointer data)
260 gtk_widget_destroy(editor_list_window->window);
261 g_free(editor_list_window);
262 editor_list_window = NULL;
265 static gboolean editor_list_window_delete(GtkWidget *widget, GdkEventAny *event, gpointer data)
267 editor_list_window_close_cb(NULL, NULL);
271 static void editor_list_window_delete_dlg_cancel(GenericDialog *gd, gpointer data);
273 static void editor_list_window_delete_dlg_cancel(GenericDialog *gd, gpointer data)
275 EditorWindowDel_Data *ewdl = data;
277 ewdl->ewl->gd = NULL;
282 static void editor_list_window_delete_dlg_ok_cb(GenericDialog *gd, gpointer data)
284 EditorWindowDel_Data *ewdl = data;
286 if (!unlink_file(ewdl->path))
288 gchar *text = g_strdup_printf(_("Unable to delete file:\n%s"), ewdl->path);
289 warning_dialog(_("File deletion failed"), text, GTK_STOCK_DIALOG_WARNING, NULL);
295 layout_editors_reload_start();
296 /* idle function is not needed, everything should be cached */
297 layout_editors_reload_finish();
300 editor_list_window_delete_dlg_cancel(gd, data);
303 static void editor_list_window_delete_cb(GtkWidget *widget, gpointer data)
305 EditorListWindow *ewl = data;
306 GtkTreeSelection *sel = gtk_tree_view_get_selection(GTK_TREE_VIEW(ewl->view));
309 if (gtk_tree_selection_get_selected(sel, NULL, &iter))
311 GtkTreeModel *store = gtk_tree_view_get_model(GTK_TREE_VIEW(ewl->view));
315 EditorWindowDel_Data *ewdl;
317 gtk_tree_model_get(store, &iter,
318 DESKTOP_FILE_COLUMN_PATH, &path,
319 DESKTOP_FILE_COLUMN_KEY, &key, -1);
322 ewdl = g_new(EditorWindowDel_Data, 1);
328 GenericDialog *gd = ewl->gd;
329 editor_list_window_delete_dlg_cancel(ewl->gd, ewl->gd->data);
330 generic_dialog_close(gd);
333 ewl->gd = generic_dialog_new(_("Delete file"), "dlg_confirm",
335 editor_list_window_delete_dlg_cancel, ewdl);
337 generic_dialog_add_button(ewl->gd, GTK_STOCK_DELETE, NULL, editor_list_window_delete_dlg_ok_cb, TRUE);
339 text = g_strdup_printf(_("About to delete the file:\n %s"), path);
340 generic_dialog_add_message(ewl->gd, GTK_STOCK_DIALOG_QUESTION,
341 _("Delete file"), text);
344 gtk_widget_show(ewl->gd->dialog);
348 static void editor_list_window_edit_cb(GtkWidget *widget, gpointer data)
350 EditorListWindow *ewl = data;
351 GtkTreeSelection *sel = gtk_tree_view_get_selection(GTK_TREE_VIEW(ewl->view));
354 if (gtk_tree_selection_get_selected(sel, NULL, &iter))
356 GtkTreeModel *store = gtk_tree_view_get_model(GTK_TREE_VIEW(ewl->view));
360 gtk_tree_model_get(store, &iter,
361 DESKTOP_FILE_COLUMN_PATH, &path,
362 DESKTOP_FILE_COLUMN_KEY, &key, -1);
363 editor_window_new(path, key);
369 static void editor_list_window_new_cb(GtkWidget *widget, gpointer data)
371 editor_window_new(DESKTOP_FILE_TEMPLATE, _("new.desktop"));
375 static gint editor_list_window_sort_cb(GtkTreeModel *model, GtkTreeIter *a, GtkTreeIter *b, gpointer data)
377 gint n = GPOINTER_TO_INT(data);
382 case DESKTOP_FILE_COLUMN_KEY:
383 case DESKTOP_FILE_COLUMN_NAME:
384 case DESKTOP_FILE_COLUMN_PATH:
388 gtk_tree_model_get(model, a, n, &s1, -1);
389 gtk_tree_model_get(model, b, n, &s2, -1);
393 if (!s1 && !s2) break;
398 ret = g_utf8_collate(s1, s2);
406 case DESKTOP_FILE_COLUMN_HIDDEN:
410 gtk_tree_model_get(model, a, n, &v1, -1);
411 gtk_tree_model_get(model, b, n, &v2, -1);
423 g_return_val_if_reached(0);
429 static void editor_list_window_create(void)
435 GtkCellRenderer *renderer;
436 GtkTreeSelection *selection;
437 GtkTreeViewColumn *column;
439 GtkTreeSortable *sortable;
440 EditorListWindow *ewl;
442 editor_list_window = ewl = g_new0(EditorListWindow, 1);
444 ewl->window = window_new(GTK_WINDOW_TOPLEVEL, "editors", PIXBUF_INLINE_ICON_CONFIG, NULL, _("Editors"));
445 gtk_window_set_type_hint(GTK_WINDOW(ewl->window), GDK_WINDOW_TYPE_HINT_DIALOG);
446 g_signal_connect(G_OBJECT(ewl->window), "delete_event",
447 G_CALLBACK(editor_list_window_delete), NULL);
448 gtk_window_set_default_size(GTK_WINDOW(ewl->window), CONFIG_WINDOW_DEF_WIDTH, CONFIG_WINDOW_DEF_HEIGHT);
449 gtk_window_set_resizable(GTK_WINDOW(ewl->window), TRUE);
450 gtk_container_set_border_width(GTK_CONTAINER(ewl->window), PREF_PAD_BORDER);
452 win_vbox = gtk_vbox_new(FALSE, PREF_PAD_SPACE);
453 gtk_container_add(GTK_CONTAINER(ewl->window), win_vbox);
454 gtk_widget_show(win_vbox);
456 hbox = gtk_hbutton_box_new();
457 gtk_button_box_set_layout(GTK_BUTTON_BOX(hbox), GTK_BUTTONBOX_END);
458 gtk_box_set_spacing(GTK_BOX(hbox), PREF_PAD_BUTTON_GAP);
459 gtk_box_pack_end(GTK_BOX(win_vbox), hbox, FALSE, FALSE, 0);
460 gtk_widget_show(hbox);
463 button = pref_button_new(NULL, GTK_STOCK_NEW, NULL, FALSE,
464 G_CALLBACK(editor_list_window_new_cb), ewl);
465 gtk_container_add(GTK_CONTAINER(hbox), button);
466 GTK_WIDGET_SET_FLAGS(button, GTK_CAN_DEFAULT);
467 gtk_widget_show(button);
469 button = pref_button_new(NULL, GTK_STOCK_EDIT, NULL, FALSE,
470 G_CALLBACK(editor_list_window_edit_cb), ewl);
471 gtk_container_add(GTK_CONTAINER(hbox), button);
472 GTK_WIDGET_SET_FLAGS(button, GTK_CAN_DEFAULT);
473 gtk_widget_show(button);
475 button = pref_button_new(NULL, GTK_STOCK_DELETE, NULL, FALSE,
476 G_CALLBACK(editor_list_window_delete_cb), ewl);
477 gtk_container_add(GTK_CONTAINER(hbox), button);
478 GTK_WIDGET_SET_FLAGS(button, GTK_CAN_DEFAULT);
479 gtk_widget_show(button);
481 button = pref_button_new(NULL, GTK_STOCK_CLOSE, NULL, FALSE,
482 G_CALLBACK(editor_list_window_close_cb), ewl);
483 gtk_container_add(GTK_CONTAINER(hbox), button);
484 GTK_WIDGET_SET_FLAGS(button, GTK_CAN_DEFAULT);
485 gtk_widget_show(button);
487 scrolled = gtk_scrolled_window_new(NULL, NULL);
488 gtk_scrolled_window_set_shadow_type(GTK_SCROLLED_WINDOW(scrolled), GTK_SHADOW_IN);
489 gtk_scrolled_window_set_policy(GTK_SCROLLED_WINDOW(scrolled),
490 GTK_POLICY_AUTOMATIC, GTK_POLICY_AUTOMATIC);
491 gtk_box_pack_start(GTK_BOX(win_vbox), scrolled, TRUE, TRUE, 5);
492 gtk_widget_show(scrolled);
494 ewl->view = gtk_tree_view_new_with_model(GTK_TREE_MODEL(desktop_file_list));
495 selection = gtk_tree_view_get_selection(GTK_TREE_VIEW(ewl->view));
496 gtk_tree_selection_set_mode(GTK_TREE_SELECTION(selection), GTK_SELECTION_SINGLE);
498 gtk_tree_view_set_enable_search(GTK_TREE_VIEW(ewl->view), FALSE);
500 column = gtk_tree_view_column_new();
501 gtk_tree_view_column_set_title(column, _("Name"));
502 gtk_tree_view_column_set_resizable(column, TRUE);
503 renderer = gtk_cell_renderer_text_new();
504 gtk_tree_view_column_pack_start(column, renderer, FALSE);
505 gtk_tree_view_column_add_attribute(column, renderer, "text", DESKTOP_FILE_COLUMN_NAME);
506 gtk_tree_view_append_column(GTK_TREE_VIEW(ewl->view), column);
507 gtk_tree_view_column_set_sort_column_id(column, DESKTOP_FILE_COLUMN_NAME);
509 column = gtk_tree_view_column_new();
510 gtk_tree_view_column_set_title(column, _("Hidden"));
511 gtk_tree_view_column_set_sizing(column, GTK_TREE_VIEW_COLUMN_AUTOSIZE);
512 renderer = gtk_cell_renderer_toggle_new();
513 g_object_set(G_OBJECT(renderer),
514 "activatable", FALSE, // not clickable for now
515 "xalign", 0.5, // centered
517 gtk_tree_view_column_pack_start(column, renderer, TRUE); // TRUE needed for centering
518 gtk_tree_view_column_add_attribute(column, renderer, "active", DESKTOP_FILE_COLUMN_HIDDEN);
519 gtk_tree_view_append_column(GTK_TREE_VIEW(ewl->view), column);
520 gtk_tree_view_column_set_sort_column_id(column, DESKTOP_FILE_COLUMN_HIDDEN);
521 gtk_tree_view_column_set_alignment(column, 0.5);
523 column = gtk_tree_view_column_new();
524 gtk_tree_view_column_set_title(column, _("Desktop file"));
525 gtk_tree_view_column_set_resizable(column, TRUE);
526 renderer = gtk_cell_renderer_text_new();
527 gtk_tree_view_column_pack_start(column, renderer, FALSE);
528 gtk_tree_view_column_add_attribute(column, renderer, "text", DESKTOP_FILE_COLUMN_KEY);
529 gtk_tree_view_append_column(GTK_TREE_VIEW(ewl->view), column);
530 gtk_tree_view_column_set_sort_column_id(column, DESKTOP_FILE_COLUMN_KEY);
532 column = gtk_tree_view_column_new();
533 gtk_tree_view_column_set_title(column, _("Path"));
534 gtk_tree_view_column_set_resizable(column, TRUE);
535 renderer = gtk_cell_renderer_text_new();
536 gtk_tree_view_column_pack_start(column, renderer, FALSE);
537 gtk_tree_view_column_add_attribute(column, renderer, "text", DESKTOP_FILE_COLUMN_PATH);
538 gtk_tree_view_append_column(GTK_TREE_VIEW(ewl->view), column);
539 gtk_tree_view_column_set_sort_column_id(column, DESKTOP_FILE_COLUMN_PATH);
542 store = gtk_tree_view_get_model(GTK_TREE_VIEW(ewl->view));
543 sortable = GTK_TREE_SORTABLE(store);
544 gtk_tree_sortable_set_sort_func(sortable, DESKTOP_FILE_COLUMN_KEY, editor_list_window_sort_cb,
545 GINT_TO_POINTER(DESKTOP_FILE_COLUMN_KEY), NULL);
546 gtk_tree_sortable_set_sort_func(sortable, DESKTOP_FILE_COLUMN_HIDDEN, editor_list_window_sort_cb,
547 GINT_TO_POINTER(DESKTOP_FILE_COLUMN_HIDDEN), NULL);
548 gtk_tree_sortable_set_sort_func(sortable, DESKTOP_FILE_COLUMN_NAME, editor_list_window_sort_cb,
549 GINT_TO_POINTER(DESKTOP_FILE_COLUMN_NAME), NULL);
550 gtk_tree_sortable_set_sort_func(sortable, DESKTOP_FILE_COLUMN_PATH, editor_list_window_sort_cb,
551 GINT_TO_POINTER(DESKTOP_FILE_COLUMN_PATH), NULL);
553 /* set initial sort order */
554 //gtk_tree_sortable_set_sort_column_id(sortable, DESKTOP_FILE_COLUMN_KEY, GTK_SORT_ASCENDING);
556 gtk_container_add(GTK_CONTAINER(scrolled), ewl->view);
557 gtk_widget_show(ewl->view);
559 gtk_widget_show(ewl->window);
563 *-----------------------------------------------------------------------------
564 * config window show (public)
565 *-----------------------------------------------------------------------------
568 void show_editor_list_window(void)
570 if (editor_list_window)
572 gtk_window_present(GTK_WINDOW(editor_list_window));
576 editor_list_window_create();
578 /* vim: set shiftwidth=8 softtabstop=0 cindent cinoptions={1s: */