added simple desktop file editor
[geeqie.git] / src / desktop_file.c
1 /*
2  * Geeqie
3  * (C) 2004 John Ellis
4  * Copyright (C) 2008 - 2009 The Geeqie Team
5  *
6  * Author: Vladimir Nadvornik
7  *
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!
11  */
12
13 #include "main.h"
14 #include "desktop_file.h"
15
16 #include "editors.h"
17 #include "filedata.h"
18 #include "misc.h"
19 #include "ui_misc.h"
20 #include "ui_fileops.h"
21 #include "ui_utildlg.h"
22 #include "pixbuf_util.h"
23 #include "window.h"
24 #include "utilops.h"
25 #include "layout_util.h"
26
27 #define CONFIG_WINDOW_DEF_WIDTH         700
28 #define CONFIG_WINDOW_DEF_HEIGHT        400
29
30
31
32 typedef struct _EditorWindow EditorWindow;
33 struct _EditorWindow
34 {
35         GtkWidget *window;
36         GtkWidget *entry;
37         GtkTextBuffer *buffer;
38 };
39
40
41 static GtkWidget *editor_list_window = NULL;
42 GtkWidget *editor_list_view = NULL;
43
44
45 static gboolean editor_window_save(EditorWindow *ew)
46 {
47         gchar *path;
48         gchar *text;
49         GtkTextIter start, end;
50         GError *error = NULL;
51         gboolean ret = TRUE;
52         const gchar *name = gtk_entry_get_text(GTK_ENTRY(ew->entry));
53         
54         if (!name || !name[0]) 
55                 {
56                 file_util_warning_dialog(_("Can't save"), _("Please specify file name."), GTK_STOCK_DIALOG_ERROR, NULL);
57                 return FALSE;
58                 }
59         
60         gtk_text_buffer_get_bounds(ew->buffer, &start, &end);
61         text = gtk_text_buffer_get_text(ew->buffer, &start, &end, FALSE);
62
63         path = g_build_filename(get_rc_dir(), "applications", name, NULL);
64
65         if (!g_file_set_contents(path, text, -1, &error)) 
66                 {
67                 file_util_warning_dialog(_("Can't save"), error->message, GTK_STOCK_DIALOG_ERROR, NULL);
68                 g_error_free(error);
69                 ret = FALSE;
70                 }
71         
72         g_free(path);
73         g_free(text);
74         layout_editors_reload_all();
75         return ret;
76 }
77
78 static void editor_window_close_cb(GtkWidget *widget, gpointer data)
79 {
80         EditorWindow *ew = data;
81         
82         gtk_widget_destroy(ew->window);
83         g_free(ew);
84 }
85
86 static gint editor_window_delete_cb(GtkWidget *w, GdkEventAny *event, gpointer data)
87 {
88         editor_window_close_cb(w, data);
89         return TRUE;
90 }
91
92 static void editor_window_apply_cb(GtkWidget *widget, gpointer data)
93 {
94         EditorWindow *ew = data;
95         editor_window_save(ew);
96 }
97 static void editor_window_ok_cb(GtkWidget *widget, gpointer data)
98 {
99         EditorWindow *ew = data;
100         if (!editor_window_save(ew)) return;
101         editor_window_close_cb(widget, ew);
102 }
103
104 static void editor_window_new(const gchar *src_path, const gchar *desktop_name)
105 {
106         EditorWindow *ew;
107         GtkWidget *win_vbox;
108         GtkWidget *hbox;
109         GtkWidget *button;
110         GtkWidget *ct_button;
111         GtkWidget *button_hbox;
112         GtkWidget *scrolled;
113         GtkWidget *text_view;
114         gchar *text;
115         gsize size;
116
117         ew = g_new0(EditorWindow, 1);
118
119
120         ew->window = window_new(GTK_WINDOW_TOPLEVEL, "Desktop", PIXBUF_INLINE_ICON_CONFIG, NULL, _("Desktop file"));
121         gtk_window_set_type_hint(GTK_WINDOW(ew->window), GDK_WINDOW_TYPE_HINT_DIALOG);
122
123         g_signal_connect(G_OBJECT(ew->window), "delete_event",
124                          G_CALLBACK(editor_window_delete_cb), ew);
125
126         gtk_window_set_default_size(GTK_WINDOW(ew->window), CONFIG_WINDOW_DEF_WIDTH, CONFIG_WINDOW_DEF_HEIGHT);
127         gtk_window_set_resizable(GTK_WINDOW(ew->window), TRUE);
128         gtk_container_set_border_width(GTK_CONTAINER(ew->window), PREF_PAD_BORDER);
129
130         win_vbox = gtk_vbox_new(FALSE, PREF_PAD_SPACE);
131         gtk_container_add(GTK_CONTAINER(ew->window), win_vbox);
132         gtk_widget_show(win_vbox);
133
134         hbox = gtk_hbox_new(FALSE, PREF_PAD_SPACE);
135         gtk_box_pack_end(GTK_BOX(win_vbox), hbox, FALSE, FALSE, 0);
136         gtk_widget_show(hbox);
137
138         ew->entry = gtk_entry_new();
139         gtk_box_pack_start(GTK_BOX(hbox), ew->entry, TRUE, TRUE, 0);
140         if (desktop_name)
141                 {
142                 gtk_entry_set_text(GTK_ENTRY(ew->entry), desktop_name);
143                 }
144         gtk_widget_show(ew->entry);
145         
146
147         button_hbox = gtk_hbutton_box_new();
148         gtk_button_box_set_layout(GTK_BUTTON_BOX(button_hbox), GTK_BUTTONBOX_END);
149         gtk_box_set_spacing(GTK_BOX(button_hbox), PREF_PAD_BUTTON_GAP);
150         gtk_box_pack_end(GTK_BOX(hbox), button_hbox, FALSE, FALSE, 0);
151         gtk_widget_show(button_hbox);
152
153         button = pref_button_new(NULL, GTK_STOCK_OK, NULL, FALSE,
154                                  G_CALLBACK(editor_window_ok_cb), ew);
155         gtk_container_add(GTK_CONTAINER(button_hbox), button);
156         GTK_WIDGET_SET_FLAGS(button, GTK_CAN_DEFAULT);
157         gtk_widget_grab_default(button);
158         gtk_widget_show(button);
159
160         ct_button = button;
161
162         button = pref_button_new(NULL, GTK_STOCK_APPLY, NULL, FALSE,
163                                  G_CALLBACK(editor_window_apply_cb), ew);
164         gtk_container_add(GTK_CONTAINER(button_hbox), button);
165         GTK_WIDGET_SET_FLAGS(button, GTK_CAN_DEFAULT);
166         gtk_widget_show(button);
167
168         button = pref_button_new(NULL, GTK_STOCK_CANCEL, NULL, FALSE,
169                                  G_CALLBACK(editor_window_close_cb), ew);
170         gtk_container_add(GTK_CONTAINER(button_hbox), button);
171         GTK_WIDGET_SET_FLAGS(button, GTK_CAN_DEFAULT);
172         gtk_widget_show(button);
173
174         if (!generic_dialog_get_alternative_button_order(ew->window))
175                 {
176                 gtk_box_reorder_child(GTK_BOX(button_hbox), ct_button, -1);
177                 }
178
179
180         scrolled = gtk_scrolled_window_new(NULL, NULL);
181         gtk_scrolled_window_set_shadow_type(GTK_SCROLLED_WINDOW(scrolled), GTK_SHADOW_IN);
182         gtk_scrolled_window_set_policy(GTK_SCROLLED_WINDOW(scrolled),
183                                        GTK_POLICY_AUTOMATIC, GTK_POLICY_AUTOMATIC);
184         gtk_box_pack_start(GTK_BOX(win_vbox), scrolled, TRUE, TRUE, 5);
185         gtk_widget_show(scrolled);
186
187         text_view = gtk_text_view_new();
188         gtk_container_add(GTK_CONTAINER(scrolled), text_view);
189         gtk_widget_show(text_view);
190
191         ew->buffer = gtk_text_view_get_buffer(GTK_TEXT_VIEW(text_view));
192         if (g_file_get_contents(src_path, &text, &size, NULL))
193                 {
194                 gtk_text_buffer_set_text(ew->buffer, text, size);
195                 }
196
197
198         gtk_widget_show(ew->window);
199 }
200
201
202 static void editor_list_window_close_cb(GtkWidget *widget, gpointer data)
203 {
204         gtk_widget_destroy(editor_list_window);
205         editor_list_window = NULL;
206         editor_list_view = NULL;
207 }
208
209 static gboolean editor_list_window_delete(GtkWidget *widget, GdkEventAny *event, gpointer data)
210 {
211         editor_list_window_close_cb(NULL, NULL);
212         return TRUE;
213 }
214
215 static void editor_list_window_edit_cb(GtkWidget *widget, gpointer data)
216 {
217         GtkTreeSelection *sel = gtk_tree_view_get_selection(GTK_TREE_VIEW(editor_list_view)); 
218         GtkTreeIter iter;
219
220         if (gtk_tree_selection_get_selected(sel, NULL, &iter)) 
221                 {
222                 GtkTreeModel *store = gtk_tree_view_get_model(GTK_TREE_VIEW(editor_list_view));
223                 gchar *path;
224                 gchar *key;
225
226                 gtk_tree_model_get(store, &iter,
227                                    DESKTOP_FILE_COLUMN_PATH, &path,
228                                    DESKTOP_FILE_COLUMN_KEY, &key, -1);
229                 editor_window_new(path, key);   
230                 g_free(key);
231                 g_free(path);
232                 }
233 }
234
235 static void editor_list_window_new_cb(GtkWidget *widget, gpointer data)
236 {
237         editor_window_new(DESKTOP_FILE_TEMPLATE, _("new.desktop"));
238 }
239
240 static void editor_list_window_create(void)
241 {
242         GtkWidget *win_vbox;
243         GtkWidget *hbox;
244         GtkWidget *button;
245         GtkWidget *scrolled;
246         GtkCellRenderer *renderer;
247         GtkTreeSelection *selection;
248         GtkTreeViewColumn *column;
249
250         editor_list_window = window_new(GTK_WINDOW_TOPLEVEL, "editors", PIXBUF_INLINE_ICON_CONFIG, NULL, _("Editors"));
251         gtk_window_set_type_hint(GTK_WINDOW(editor_list_window), GDK_WINDOW_TYPE_HINT_DIALOG);
252         g_signal_connect(G_OBJECT(editor_list_window), "delete_event",
253                          G_CALLBACK(editor_list_window_delete), NULL);
254         gtk_window_set_default_size(GTK_WINDOW(editor_list_window), CONFIG_WINDOW_DEF_WIDTH, CONFIG_WINDOW_DEF_HEIGHT);
255         gtk_window_set_resizable(GTK_WINDOW(editor_list_window), TRUE);
256         gtk_container_set_border_width(GTK_CONTAINER(editor_list_window), PREF_PAD_BORDER);
257
258         win_vbox = gtk_vbox_new(FALSE, PREF_PAD_SPACE);
259         gtk_container_add(GTK_CONTAINER(editor_list_window), win_vbox);
260         gtk_widget_show(win_vbox);
261
262         hbox = gtk_hbutton_box_new();
263         gtk_button_box_set_layout(GTK_BUTTON_BOX(hbox), GTK_BUTTONBOX_END);
264         gtk_box_set_spacing(GTK_BOX(hbox), PREF_PAD_BUTTON_GAP);
265         gtk_box_pack_end(GTK_BOX(win_vbox), hbox, FALSE, FALSE, 0);
266         gtk_widget_show(hbox);
267
268
269         button = pref_button_new(NULL, GTK_STOCK_NEW, NULL, FALSE,
270                                  G_CALLBACK(editor_list_window_new_cb), NULL);
271         gtk_container_add(GTK_CONTAINER(hbox), button);
272         GTK_WIDGET_SET_FLAGS(button, GTK_CAN_DEFAULT);
273         gtk_widget_show(button);
274
275         button = pref_button_new(NULL, GTK_STOCK_EDIT, NULL, FALSE,
276                                  G_CALLBACK(editor_list_window_edit_cb), NULL);
277         gtk_container_add(GTK_CONTAINER(hbox), button);
278         GTK_WIDGET_SET_FLAGS(button, GTK_CAN_DEFAULT);
279         gtk_widget_show(button);
280
281         button = pref_button_new(NULL, GTK_STOCK_CLOSE, NULL, FALSE,
282                                  G_CALLBACK(editor_list_window_close_cb), NULL);
283         gtk_container_add(GTK_CONTAINER(hbox), button);
284         GTK_WIDGET_SET_FLAGS(button, GTK_CAN_DEFAULT);
285         gtk_widget_show(button);
286
287         scrolled = gtk_scrolled_window_new(NULL, NULL);
288         gtk_scrolled_window_set_shadow_type(GTK_SCROLLED_WINDOW(scrolled), GTK_SHADOW_IN);
289         gtk_scrolled_window_set_policy(GTK_SCROLLED_WINDOW(scrolled),
290                                        GTK_POLICY_AUTOMATIC, GTK_POLICY_AUTOMATIC);
291         gtk_box_pack_start(GTK_BOX(win_vbox), scrolled, TRUE, TRUE, 5);
292         gtk_widget_show(scrolled);
293
294         editor_list_view = gtk_tree_view_new_with_model(GTK_TREE_MODEL(desktop_file_list));
295         selection = gtk_tree_view_get_selection(GTK_TREE_VIEW(editor_list_view));
296         gtk_tree_selection_set_mode(GTK_TREE_SELECTION(selection), GTK_SELECTION_SINGLE);
297
298         gtk_tree_view_set_enable_search(GTK_TREE_VIEW(editor_list_view), FALSE);
299
300         column = gtk_tree_view_column_new();
301         gtk_tree_view_column_set_title(column, _("Desktop file"));
302         gtk_tree_view_column_set_resizable(column, TRUE);
303         renderer = gtk_cell_renderer_text_new();
304         gtk_tree_view_column_pack_start(column, renderer, FALSE);
305         gtk_tree_view_column_add_attribute(column, renderer, "text", DESKTOP_FILE_COLUMN_KEY);
306         gtk_tree_view_append_column(GTK_TREE_VIEW(editor_list_view), column);
307
308         column = gtk_tree_view_column_new();
309         gtk_tree_view_column_set_title(column, _("Hidden"));
310         gtk_tree_view_column_set_sizing(column, GTK_TREE_VIEW_COLUMN_AUTOSIZE);
311         renderer = gtk_cell_renderer_toggle_new();
312         gtk_tree_view_column_pack_start(column, renderer, FALSE);
313         gtk_tree_view_column_add_attribute(column, renderer, "active", DESKTOP_FILE_COLUMN_HIDDEN);
314         gtk_tree_view_append_column(GTK_TREE_VIEW(editor_list_view), column);
315
316         column = gtk_tree_view_column_new();
317         gtk_tree_view_column_set_title(column, _("Name"));
318         gtk_tree_view_column_set_resizable(column, TRUE);
319         renderer = gtk_cell_renderer_text_new();
320         gtk_tree_view_column_pack_start(column, renderer, FALSE);
321         gtk_tree_view_column_add_attribute(column, renderer, "text", DESKTOP_FILE_COLUMN_NAME);
322         gtk_tree_view_append_column(GTK_TREE_VIEW(editor_list_view), column);
323
324         column = gtk_tree_view_column_new();
325         gtk_tree_view_column_set_title(column, _("Path"));
326         gtk_tree_view_column_set_resizable(column, TRUE);
327         renderer = gtk_cell_renderer_text_new();
328         gtk_tree_view_column_pack_start(column, renderer, FALSE);
329         gtk_tree_view_column_add_attribute(column, renderer, "text", DESKTOP_FILE_COLUMN_PATH);
330         gtk_tree_view_append_column(GTK_TREE_VIEW(editor_list_view), column);
331
332         gtk_container_add(GTK_CONTAINER(scrolled), editor_list_view);
333         gtk_widget_show(editor_list_view);
334
335         gtk_widget_show(editor_list_window);
336 }
337
338 /*
339  *-----------------------------------------------------------------------------
340  * config window show (public)
341  *-----------------------------------------------------------------------------
342  */
343
344 void show_editor_list_window(void)
345 {
346         if (editor_list_window)
347                 {
348                 gtk_window_present(GTK_WINDOW(editor_list_window));
349                 return;
350                 }
351
352         editor_list_window_create();
353 }