Open With feature
[geeqie.git] / src / desktop-file.cc
1 /*
2  * Copyright (C) 2004 John Ellis
3  * Copyright (C) 2008 - 2016 The Geeqie Team
4  *
5  * Author: Vladimir Nadvornik
6  *
7  * This program is free software; you can redistribute it and/or modify
8  * it under the terms of the GNU General Public License as published by
9  * the Free Software Foundation; either version 2 of the License, or
10  * (at your option) any later version.
11  *
12  * This program is distributed in the hope that it will be useful,
13  * but WITHOUT ANY WARRANTY; without even the implied warranty of
14  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15  * GNU General Public License for more details.
16  *
17  * You should have received a copy of the GNU General Public License along
18  * with this program; if not, write to the Free Software Foundation, Inc.,
19  * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
20  */
21
22 #include "main.h"
23 #include "desktop-file.h"
24
25 #include "editors.h"
26 #include "layout-util.h"
27 #include "misc.h"
28 #include "pixbuf-util.h"
29 #include "ui-fileops.h"
30 #include "ui-misc.h"
31 #include "utilops.h"
32 #include "window.h"
33
34 #define CONFIG_WINDOW_DEF_WIDTH         700
35 #define CONFIG_WINDOW_DEF_HEIGHT        400
36
37
38
39 struct EditorWindow
40 {
41         GtkWidget *window;
42         GtkWidget *entry;
43         GtkWidget *save_button;
44         GtkTextBuffer *buffer;
45         gchar *desktop_name;
46         gboolean modified;
47 };
48
49 struct EditorListWindow
50 {
51         GtkWidget *window;
52         GtkWidget *view;
53         GenericDialog *gd;      /* any open confirm dialogs ? */
54         GtkWidget *delete_button;
55         GtkWidget *edit_button;
56 };
57
58 struct EditorWindowDel_Data
59 {
60         EditorListWindow *ewl;
61         gchar *path;
62 };
63
64 static EditorListWindow *editor_list_window = nullptr;
65
66 static gboolean editor_window_save(EditorWindow *ew)
67 {
68         gchar *dir;
69         gchar *path;
70         gchar *text;
71         GtkTextIter start, end;
72         GError *error = nullptr;
73         gboolean ret = TRUE;
74         const gchar *name = gq_gtk_entry_get_text(GTK_ENTRY(ew->entry));
75
76         if (!name || !name[0])
77                 {
78                 file_util_warning_dialog(_("Can't save"), _("Please specify file name."), GQ_ICON_DIALOG_ERROR, nullptr);
79                 return FALSE;
80                 }
81
82         gtk_text_buffer_get_bounds(ew->buffer, &start, &end);
83         text = gtk_text_buffer_get_text(ew->buffer, &start, &end, FALSE);
84
85         dir = g_build_filename(get_rc_dir(), "applications", NULL);
86         path = g_build_filename(dir, name, NULL);
87
88         if (!recursive_mkdir_if_not_exists(dir, 0755))
89                 {
90                 file_util_warning_dialog(_("Can't save"), _("Could not create directory"), GQ_ICON_DIALOG_ERROR, nullptr);
91                 ret = FALSE;
92                 }
93
94         if (ret && !g_file_set_contents(path, text, -1, &error))
95                 {
96                 file_util_warning_dialog(_("Can't save"), error->message, GQ_ICON_DIALOG_ERROR, nullptr);
97                 g_error_free(error);
98                 ret = FALSE;
99                 }
100
101         g_free(path);
102         g_free(dir);
103         g_free(text);
104         layout_editors_reload_start();
105         /* idle function is not needed, everything should be cached */
106         layout_editors_reload_finish();
107         return ret;
108 }
109
110 static void editor_window_close_cb(GtkWidget *, gpointer data)
111 {
112         auto ew = static_cast<EditorWindow *>(data);
113
114         g_free(ew->desktop_name);
115         gq_gtk_widget_destroy(ew->window);
116         g_free(ew);
117 }
118
119 static gint editor_window_delete_cb(GtkWidget *w, GdkEventAny *, gpointer data)
120 {
121         editor_window_close_cb(w, data);
122         return TRUE;
123 }
124
125 static void editor_window_save_cb(GtkWidget *, gpointer data)
126 {
127         auto ew = static_cast<EditorWindow *>(data);
128
129         if (ew->modified)
130                 {
131                 editor_window_save(ew);
132                 }
133
134         gtk_widget_set_sensitive(ew->save_button, FALSE);
135         gtk_text_buffer_set_modified(ew->buffer, FALSE);
136         ew->modified = FALSE;
137 }
138
139 static void editor_window_text_modified_cb(GtkWidget *, gpointer data)
140 {
141         auto ew = static_cast<EditorWindow *>(data);
142
143         if (gtk_text_buffer_get_modified(ew->buffer))
144                 {
145                 gtk_widget_set_sensitive(ew->save_button, TRUE);
146                 ew->modified = TRUE;
147                 }
148 }
149
150 static void editor_window_entry_changed_cb(GtkWidget *, gpointer data)
151 {
152         auto ew = static_cast<EditorWindow *>(data);
153         const gchar *content = gq_gtk_entry_get_text(GTK_ENTRY(ew->entry));
154         gboolean modified = ew->modified;
155
156         if (!modified)
157                 {
158                 modified = (!ew->desktop_name && *content);
159                 }
160
161         if (!modified)
162                 {
163                 modified = strcmp(ew->desktop_name, content);
164                 }
165
166         gtk_widget_set_sensitive(ew->save_button, modified);
167         ew->modified = modified;
168 }
169
170 static void editor_window_new(const gchar *src_path, const gchar *desktop_name)
171 {
172         EditorWindow *ew;
173         GtkWidget *win_vbox;
174         GtkWidget *hbox;
175         GtkWidget *button;
176         GtkWidget *ct_button;
177         GtkWidget *button_hbox;
178         GtkWidget *scrolled;
179         GtkWidget *text_view;
180         gchar *text;
181         gsize size;
182
183         ew = g_new0(EditorWindow, 1);
184
185
186         ew->window = window_new("Desktop", PIXBUF_INLINE_ICON_CONFIG, nullptr, _("Desktop file"));
187         DEBUG_NAME(ew->window);
188         gtk_window_set_type_hint(GTK_WINDOW(ew->window), GDK_WINDOW_TYPE_HINT_DIALOG);
189
190         g_signal_connect(G_OBJECT(ew->window), "delete_event",
191                          G_CALLBACK(editor_window_delete_cb), ew);
192
193         gtk_window_set_default_size(GTK_WINDOW(ew->window), CONFIG_WINDOW_DEF_WIDTH, CONFIG_WINDOW_DEF_HEIGHT);
194         gtk_window_set_resizable(GTK_WINDOW(ew->window), TRUE);
195         gtk_container_set_border_width(GTK_CONTAINER(ew->window), PREF_PAD_BORDER);
196
197         win_vbox = gtk_box_new(GTK_ORIENTATION_VERTICAL, PREF_PAD_SPACE);
198         gq_gtk_container_add(GTK_WIDGET(ew->window), win_vbox);
199         gtk_widget_show(win_vbox);
200
201         hbox = gtk_box_new(GTK_ORIENTATION_HORIZONTAL, PREF_PAD_SPACE);
202         gq_gtk_box_pack_end(GTK_BOX(win_vbox), hbox, FALSE, FALSE, 0);
203         gtk_widget_show(hbox);
204
205         ew->entry = gtk_entry_new();
206         gq_gtk_box_pack_start(GTK_BOX(hbox), ew->entry, TRUE, TRUE, 0);
207         ew->desktop_name = nullptr;
208         if (desktop_name)
209                 {
210                 gq_gtk_entry_set_text(GTK_ENTRY(ew->entry), desktop_name);
211                 ew->desktop_name = g_strdup(desktop_name);
212                 }
213         gtk_widget_show(ew->entry);
214         g_signal_connect(G_OBJECT(ew->entry), "changed", G_CALLBACK(editor_window_entry_changed_cb), ew);
215
216         button_hbox = gtk_button_box_new(GTK_ORIENTATION_HORIZONTAL);
217         gtk_button_box_set_layout(GTK_BUTTON_BOX(button_hbox), GTK_BUTTONBOX_END);
218         gtk_box_set_spacing(GTK_BOX(button_hbox), PREF_PAD_BUTTON_GAP);
219         gq_gtk_box_pack_end(GTK_BOX(hbox), button_hbox, FALSE, FALSE, 0);
220         gtk_widget_show(button_hbox);
221
222         ew->save_button = pref_button_new(nullptr, GQ_ICON_SAVE, _("Save"),
223                                  G_CALLBACK(editor_window_save_cb), ew);
224         gq_gtk_container_add(GTK_WIDGET(button_hbox), ew->save_button);
225         gtk_widget_set_can_default(ew->save_button, TRUE);
226         gtk_widget_set_sensitive(ew->save_button, FALSE);
227         gtk_widget_show(ew->save_button);
228         ct_button = ew->save_button;
229
230         button = pref_button_new(nullptr, GQ_ICON_CLOSE, _("Close"),
231                                  G_CALLBACK(editor_window_close_cb), ew);
232         gq_gtk_container_add(GTK_WIDGET(button_hbox), button);
233         gtk_widget_set_can_default(button, TRUE);
234         gtk_widget_show(button);
235
236         if (!generic_dialog_get_alternative_button_order(ew->window))
237                 {
238                 gtk_box_reorder_child(GTK_BOX(button_hbox), ct_button, -1);
239                 }
240
241
242         scrolled = gq_gtk_scrolled_window_new(nullptr, nullptr);
243         gq_gtk_scrolled_window_set_shadow_type(GTK_SCROLLED_WINDOW(scrolled), GTK_SHADOW_IN);
244         gtk_scrolled_window_set_policy(GTK_SCROLLED_WINDOW(scrolled),
245                                        GTK_POLICY_AUTOMATIC, GTK_POLICY_AUTOMATIC);
246         gq_gtk_box_pack_start(GTK_BOX(win_vbox), scrolled, TRUE, TRUE, 5);
247         gtk_widget_show(scrolled);
248
249         text_view = gtk_text_view_new();
250         gq_gtk_container_add(GTK_WIDGET(scrolled), text_view);
251         gtk_widget_show(text_view);
252
253         ew->buffer = gtk_text_view_get_buffer(GTK_TEXT_VIEW(text_view));
254         if (g_file_get_contents(src_path, &text, &size, nullptr))
255                 {
256                 gtk_text_buffer_set_text(ew->buffer, text, size);
257                 }
258         gtk_text_buffer_set_modified(ew->buffer, FALSE);
259         g_signal_connect(G_OBJECT(ew->buffer), "modified-changed",
260                          G_CALLBACK(editor_window_text_modified_cb), ew);
261
262         gtk_widget_show(ew->window);
263 }
264
265
266 static void editor_list_window_close_cb(GtkWidget *, gpointer)
267 {
268         gq_gtk_widget_destroy(editor_list_window->window);
269         g_free(editor_list_window);
270         editor_list_window = nullptr;
271 }
272
273 static gboolean editor_list_window_delete(GtkWidget *, GdkEventAny *, gpointer)
274 {
275         editor_list_window_close_cb(nullptr, nullptr);
276         return TRUE;
277 }
278
279 static void editor_list_window_delete_dlg_cancel(GenericDialog *gd, gpointer data);
280
281 static void editor_list_window_delete_dlg_cancel(GenericDialog *, gpointer data)
282 {
283         auto ewdl = static_cast<EditorWindowDel_Data *>(data);
284
285         ewdl->ewl->gd = nullptr;
286         g_free(ewdl->path);
287         g_free(ewdl);
288 }
289
290 static void editor_list_window_delete_dlg_ok_cb(GenericDialog *gd, gpointer data)
291 {
292         auto ewdl = static_cast<EditorWindowDel_Data *>(data);
293
294         if (!unlink_file(ewdl->path))
295                 {
296                 gchar *text = g_strdup_printf(_("Unable to delete file:\n%s"), ewdl->path);
297                 warning_dialog(_("File deletion failed"), text, GQ_ICON_DIALOG_WARNING, nullptr);
298                 g_free(text);
299                 }
300         else
301                 {
302                 /* refresh list */
303                 layout_editors_reload_start();
304                 /* idle function is not needed, everything should be cached */
305                 layout_editors_reload_finish();
306                 }
307
308         editor_list_window_delete_dlg_cancel(gd, data);
309 }
310
311 static void editor_list_window_delete_cb(GtkWidget *, gpointer data)
312 {
313         auto ewl = static_cast<EditorListWindow *>(data);
314         GtkTreeSelection *sel = gtk_tree_view_get_selection(GTK_TREE_VIEW(ewl->view));
315         GtkTreeIter iter;
316
317         if (gtk_tree_selection_get_selected(sel, nullptr, &iter))
318                 {
319                 GtkTreeModel *store = gtk_tree_view_get_model(GTK_TREE_VIEW(ewl->view));
320                 gchar *path;
321                 gchar *key;
322                 gchar *text;
323                 EditorWindowDel_Data *ewdl;
324
325                 gtk_tree_model_get(store, &iter,
326                                    DESKTOP_FILE_COLUMN_PATH, &path,
327                                    DESKTOP_FILE_COLUMN_KEY, &key, -1);
328
329
330                 ewdl = g_new(EditorWindowDel_Data, 1);
331                 ewdl->ewl = ewl;
332                 ewdl->path = path;
333
334                 if (ewl->gd)
335                         {
336                         GenericDialog *gd = ewl->gd;
337                         editor_list_window_delete_dlg_cancel(ewl->gd, ewl->gd->data);
338                         generic_dialog_close(gd);
339                         }
340
341                 ewl->gd = generic_dialog_new(_("Delete file"), "dlg_confirm",
342                                             nullptr, TRUE,
343                                             editor_list_window_delete_dlg_cancel, ewdl);
344
345                 generic_dialog_add_button(ewl->gd, GQ_ICON_DELETE, "Delete", editor_list_window_delete_dlg_ok_cb, TRUE);
346
347                 text = g_strdup_printf(_("About to delete the file:\n %s"), path);
348                 generic_dialog_add_message(ewl->gd, GQ_ICON_DIALOG_QUESTION,
349                                            _("Delete file"), text, TRUE);
350                 g_free(text);
351
352                 gtk_widget_show(ewl->gd->dialog);
353                 }
354 }
355
356 static void editor_list_window_edit_cb(GtkWidget *, gpointer data)
357 {
358         auto ewl = static_cast<EditorListWindow *>(data);
359         GtkTreeSelection *sel = gtk_tree_view_get_selection(GTK_TREE_VIEW(ewl->view));
360         GtkTreeIter iter;
361
362         if (gtk_tree_selection_get_selected(sel, nullptr, &iter))
363                 {
364                 GtkTreeModel *store = gtk_tree_view_get_model(GTK_TREE_VIEW(ewl->view));
365                 gchar *path;
366                 gchar *key;
367
368                 gtk_tree_model_get(store, &iter,
369                                    DESKTOP_FILE_COLUMN_PATH, &path,
370                                    DESKTOP_FILE_COLUMN_KEY, &key, -1);
371                 editor_window_new(path, key);
372                 g_free(key);
373                 g_free(path);
374                 }
375 }
376
377 static void editor_list_window_new_cb(GtkWidget *, gpointer)
378 {
379         editor_window_new(desktop_file_template, _("new.desktop"));
380 }
381
382 static void editor_list_window_help_cb(GtkWidget *, gpointer)
383 {
384         help_window_show("GuidePluginsConfig.html");
385 }
386
387 static void editor_list_window_selection_changed_cb(GtkWidget *, gpointer data)
388 {
389         auto ewl = static_cast<EditorListWindow *>(data);
390         GtkTreeSelection *sel = gtk_tree_view_get_selection(GTK_TREE_VIEW(ewl->view));
391         GtkTreeIter iter;
392
393         if (gtk_tree_selection_get_selected(sel, nullptr, &iter))
394                 {
395                 GtkTreeModel *store = gtk_tree_view_get_model(GTK_TREE_VIEW(ewl->view));
396                 gchar *path;
397
398                 gtk_tree_model_get(store, &iter,
399                                                    DESKTOP_FILE_COLUMN_PATH, &path,
400                                                    -1);
401
402                 gtk_widget_set_sensitive(ewl->delete_button, access_file(path, W_OK));
403                 gtk_widget_set_sensitive(ewl->edit_button, TRUE);
404                 g_free(path);
405                 }
406
407 }
408
409 static gint editor_list_window_sort_cb(GtkTreeModel *model, GtkTreeIter *a, GtkTreeIter *b, gpointer data)
410 {
411         gint n = GPOINTER_TO_INT(data);
412         gint ret = 0;
413         gboolean bool1, bool2;
414
415         switch (n)
416                 {
417                 case DESKTOP_FILE_COLUMN_KEY:
418                 case DESKTOP_FILE_COLUMN_NAME:
419                 case DESKTOP_FILE_COLUMN_PATH:
420                 case DESKTOP_FILE_COLUMN_HIDDEN:
421                         {
422                         gchar *s1, *s2;
423
424                         gtk_tree_model_get(model, a, n, &s1, -1);
425                         gtk_tree_model_get(model, b, n, &s2, -1);
426
427                         if (!s1 || !s2)
428                                 {
429                                 if (!s1 && !s2) break;
430                                 ret = s1 ? 1 : -1;
431                                 }
432                         else
433                                 {
434                                 ret = g_utf8_collate(s1, s2);
435                                 }
436
437                         g_free(s1);
438                         g_free(s2);
439                         }
440                         break;
441                 case DESKTOP_FILE_COLUMN_DISABLED:
442                         {
443                         gtk_tree_model_get(model, a, n, &bool1, -1);
444                         gtk_tree_model_get(model, b, n, &bool2, -1);
445
446                         if (bool1 == bool2)
447                                 {
448                                 ret = 0;
449                                 }
450                         else if (bool1 > bool2)
451                                 {
452                                 ret = -1;
453                                 }
454                         else
455                                 {
456                                 ret = 1;
457                                 }
458                         break;
459                         }
460
461                 default:
462                         g_return_val_if_reached(0);
463                 }
464
465         return ret;
466 }
467
468 static void plugin_disable_cb(GtkCellRendererToggle *, gchar *path_str, gpointer data)
469 {
470         auto ewl = static_cast<EditorListWindow *>(data);
471         GtkTreePath *tpath;
472         GtkTreeIter iter;
473         GtkTreeModel *model;
474         gboolean disabled;
475         gchar *path;
476         GList *list;
477         gchar *haystack;
478
479         tpath = gtk_tree_path_new_from_string(path_str);
480         model = gtk_tree_view_get_model(GTK_TREE_VIEW(ewl->view));
481         gtk_tree_model_get_iter(GTK_TREE_MODEL(model), &iter, tpath);
482         gtk_tree_model_get(GTK_TREE_MODEL(model), &iter, DESKTOP_FILE_COLUMN_DISABLED, &disabled, -1);
483         gtk_tree_model_get(GTK_TREE_MODEL(model), &iter, DESKTOP_FILE_COLUMN_PATH, &path, -1);
484
485         gtk_list_store_set(GTK_LIST_STORE(desktop_file_list), &iter, DESKTOP_FILE_COLUMN_DISABLED, !disabled, -1);
486
487         if (!disabled)
488                 {
489                 options->disabled_plugins = g_list_append((options->disabled_plugins), g_strdup(path));
490                 }
491         else
492                 {
493                 list = options->disabled_plugins;
494                 while (list)
495                         {
496                         haystack = static_cast<gchar *>(list->data);
497
498                         if (haystack && strcmp(haystack, path) == 0)
499                                 {
500                                 options->disabled_plugins = g_list_remove(options->disabled_plugins, haystack);
501                                 g_free(haystack);
502                                 }
503
504                         list = list->next;
505                         }
506                 }
507
508         layout_editors_reload_start();
509         layout_editors_reload_finish();
510 }
511
512 static void plugin_disable_set_func(GtkTreeViewColumn *, GtkCellRenderer *cell,
513                                                         GtkTreeModel *tree_model, GtkTreeIter *iter, gpointer)
514 {
515         gboolean disabled;
516
517         gtk_tree_model_get(tree_model, iter, DESKTOP_FILE_COLUMN_DISABLED, &disabled, -1);
518
519         if (disabled)
520                 {
521                 g_object_set(GTK_CELL_RENDERER(cell), "active", TRUE, NULL);
522                 }
523         else
524                 {
525                 g_object_set(GTK_CELL_RENDERER(cell), "active", FALSE, NULL);
526                 }
527 }
528
529 static void editor_list_window_create()
530 {
531         GtkWidget *win_vbox;
532         GtkWidget *hbox;
533         GtkWidget *button;
534         GtkWidget *scrolled;
535         GtkCellRenderer *renderer;
536         GtkTreeSelection *selection;
537         GtkTreeViewColumn *column;
538         GtkTreeModel *store;
539         GtkTreeSortable *sortable;
540         EditorListWindow *ewl;
541
542         editor_list_window = ewl = g_new0(EditorListWindow, 1);
543
544         ewl->window = window_new("editors", PIXBUF_INLINE_ICON_CONFIG, nullptr, _("Plugins"));
545         DEBUG_NAME(ewl->window);
546         gtk_window_set_type_hint(GTK_WINDOW(ewl->window), GDK_WINDOW_TYPE_HINT_DIALOG);
547         g_signal_connect(G_OBJECT(ewl->window), "delete_event",
548                          G_CALLBACK(editor_list_window_delete), NULL);
549         gtk_window_set_default_size(GTK_WINDOW(ewl->window), CONFIG_WINDOW_DEF_WIDTH, CONFIG_WINDOW_DEF_HEIGHT);
550         gtk_window_set_resizable(GTK_WINDOW(ewl->window), TRUE);
551         gtk_container_set_border_width(GTK_CONTAINER(ewl->window), PREF_PAD_BORDER);
552
553         win_vbox = gtk_box_new(GTK_ORIENTATION_VERTICAL, PREF_PAD_SPACE);
554         gq_gtk_container_add(GTK_WIDGET(ewl->window), win_vbox);
555         gtk_widget_show(win_vbox);
556
557         hbox = gtk_button_box_new(GTK_ORIENTATION_HORIZONTAL);
558         gtk_button_box_set_layout(GTK_BUTTON_BOX(hbox), GTK_BUTTONBOX_END);
559         gtk_box_set_spacing(GTK_BOX(hbox), PREF_PAD_BUTTON_GAP);
560         gq_gtk_box_pack_end(GTK_BOX(win_vbox), hbox, FALSE, FALSE, 0);
561         gtk_widget_show(hbox);
562
563         button = pref_button_new(nullptr, GQ_ICON_HELP, _("Help"),
564                                  G_CALLBACK(editor_list_window_help_cb), ewl);
565         gq_gtk_container_add(GTK_WIDGET(hbox), button);
566         gtk_widget_set_can_default(button, TRUE);
567         gtk_widget_show(button);
568
569         button = pref_button_new(nullptr, GQ_ICON_NEW, _("New"),
570                                  G_CALLBACK(editor_list_window_new_cb), ewl);
571         gq_gtk_container_add(GTK_WIDGET(hbox), button);
572         gtk_widget_set_can_default(button, TRUE);
573         gtk_widget_show(button);
574
575         button = pref_button_new(nullptr, GQ_ICON_EDIT, _("Edit"),
576                                  G_CALLBACK(editor_list_window_edit_cb), ewl);
577         gq_gtk_container_add(GTK_WIDGET(hbox), button);
578         gtk_widget_set_can_default(button, TRUE);
579         gtk_widget_set_sensitive(button, FALSE);
580         gtk_widget_show(button);
581         ewl->edit_button = button;
582
583         button = pref_button_new(nullptr, GQ_ICON_DELETE, "Delete",
584                                  G_CALLBACK(editor_list_window_delete_cb), ewl);
585         gq_gtk_container_add(GTK_WIDGET(hbox), button);
586         gtk_widget_set_can_default(button, TRUE);
587         gtk_widget_set_sensitive(button, FALSE);
588         gtk_widget_show(button);
589         ewl->delete_button = button;
590
591         button = pref_button_new(nullptr, GQ_ICON_CLOSE, _("Close"),
592                                  G_CALLBACK(editor_list_window_close_cb), ewl);
593         gq_gtk_container_add(GTK_WIDGET(hbox), button);
594         gtk_widget_set_can_default(button, TRUE);
595         gtk_widget_show(button);
596
597         scrolled = gq_gtk_scrolled_window_new(nullptr, nullptr);
598         gq_gtk_scrolled_window_set_shadow_type(GTK_SCROLLED_WINDOW(scrolled), GTK_SHADOW_IN);
599         gtk_scrolled_window_set_policy(GTK_SCROLLED_WINDOW(scrolled),
600                                        GTK_POLICY_AUTOMATIC, GTK_POLICY_AUTOMATIC);
601         gq_gtk_box_pack_start(GTK_BOX(win_vbox), scrolled, TRUE, TRUE, 5);
602         gtk_widget_show(scrolled);
603
604         ewl->view = gtk_tree_view_new_with_model(GTK_TREE_MODEL(desktop_file_list));
605         selection = gtk_tree_view_get_selection(GTK_TREE_VIEW(ewl->view));
606         gtk_tree_selection_set_mode(GTK_TREE_SELECTION(selection), GTK_SELECTION_SINGLE);
607         g_signal_connect(selection, "changed", G_CALLBACK(editor_list_window_selection_changed_cb), ewl);
608
609         gtk_tree_view_set_enable_search(GTK_TREE_VIEW(ewl->view), FALSE);
610
611         column = gtk_tree_view_column_new();
612         gtk_tree_view_column_set_title(column, _("Disabled"));
613         gtk_tree_view_column_set_resizable(column, TRUE);
614
615         renderer = gtk_cell_renderer_toggle_new();
616         g_signal_connect(G_OBJECT(renderer), "toggled",
617                          G_CALLBACK(plugin_disable_cb), ewl);
618         gtk_tree_view_column_pack_start(column, renderer, FALSE);
619         gtk_tree_view_column_set_cell_data_func(column, renderer, plugin_disable_set_func,
620                                                 nullptr, nullptr);
621         gtk_tree_view_append_column(GTK_TREE_VIEW(ewl->view), column);
622         gtk_tree_view_column_set_sort_column_id(column, DESKTOP_FILE_COLUMN_DISABLED);
623
624         column = gtk_tree_view_column_new();
625         gtk_tree_view_column_set_title(column, _("Name"));
626         gtk_tree_view_column_set_resizable(column, TRUE);
627         renderer = gtk_cell_renderer_text_new();
628         gtk_tree_view_column_pack_start(column, renderer, FALSE);
629         gtk_tree_view_column_add_attribute(column, renderer, "text", DESKTOP_FILE_COLUMN_NAME);
630         gtk_tree_view_append_column(GTK_TREE_VIEW(ewl->view), column);
631         gtk_tree_view_column_set_sort_column_id(column, DESKTOP_FILE_COLUMN_NAME);
632
633         column = gtk_tree_view_column_new();
634         gtk_tree_view_column_set_title(column, _("Hidden"));
635         gtk_tree_view_column_set_sizing(column, GTK_TREE_VIEW_COLUMN_AUTOSIZE);
636         renderer = gtk_cell_renderer_text_new();
637         gtk_tree_view_column_pack_start(column, renderer, FALSE);
638         gtk_tree_view_column_add_attribute(column, renderer, "text", DESKTOP_FILE_COLUMN_HIDDEN);
639         gtk_tree_view_append_column(GTK_TREE_VIEW(ewl->view), column);
640         gtk_tree_view_column_set_sort_column_id(column, DESKTOP_FILE_COLUMN_HIDDEN);
641         gtk_tree_view_column_set_alignment(column, 0.5);
642
643         column = gtk_tree_view_column_new();
644         gtk_tree_view_column_set_title(column, _("Desktop file"));
645         gtk_tree_view_column_set_resizable(column, TRUE);
646         renderer = gtk_cell_renderer_text_new();
647         gtk_tree_view_column_pack_start(column, renderer, FALSE);
648         gtk_tree_view_column_add_attribute(column, renderer, "text", DESKTOP_FILE_COLUMN_KEY);
649         gtk_tree_view_append_column(GTK_TREE_VIEW(ewl->view), column);
650         gtk_tree_view_column_set_sort_column_id(column, DESKTOP_FILE_COLUMN_KEY);
651
652         column = gtk_tree_view_column_new();
653         gtk_tree_view_column_set_title(column, _("Path"));
654         gtk_tree_view_column_set_resizable(column, TRUE);
655         renderer = gtk_cell_renderer_text_new();
656         gtk_tree_view_column_pack_start(column, renderer, FALSE);
657         gtk_tree_view_column_add_attribute(column, renderer, "text", DESKTOP_FILE_COLUMN_PATH);
658         gtk_tree_view_append_column(GTK_TREE_VIEW(ewl->view), column);
659         gtk_tree_view_column_set_sort_column_id(column, DESKTOP_FILE_COLUMN_PATH);
660
661         /* set up sorting */
662         store = gtk_tree_view_get_model(GTK_TREE_VIEW(ewl->view));
663         sortable = GTK_TREE_SORTABLE(store);
664         gtk_tree_sortable_set_sort_func(sortable, DESKTOP_FILE_COLUMN_KEY, editor_list_window_sort_cb,
665                                         GINT_TO_POINTER(DESKTOP_FILE_COLUMN_KEY), nullptr);
666         gtk_tree_sortable_set_sort_func(sortable, DESKTOP_FILE_COLUMN_HIDDEN, editor_list_window_sort_cb,
667                                         GINT_TO_POINTER(DESKTOP_FILE_COLUMN_HIDDEN), nullptr);
668         gtk_tree_sortable_set_sort_func(sortable, DESKTOP_FILE_COLUMN_NAME, editor_list_window_sort_cb,
669                                         GINT_TO_POINTER(DESKTOP_FILE_COLUMN_NAME), nullptr);
670         gtk_tree_sortable_set_sort_func(sortable, DESKTOP_FILE_COLUMN_PATH, editor_list_window_sort_cb,
671                                         GINT_TO_POINTER(DESKTOP_FILE_COLUMN_PATH), nullptr);
672         gtk_tree_sortable_set_sort_func(sortable, DESKTOP_FILE_COLUMN_DISABLED, editor_list_window_sort_cb,
673                                         GINT_TO_POINTER(DESKTOP_FILE_COLUMN_DISABLED), nullptr);
674
675         /* set initial sort order */
676     gtk_tree_sortable_set_sort_column_id(sortable, DESKTOP_FILE_COLUMN_NAME, GTK_SORT_ASCENDING);
677
678         gq_gtk_container_add(GTK_WIDGET(scrolled), ewl->view);
679         gtk_widget_show(ewl->view);
680
681         gtk_widget_show(ewl->window);
682 }
683
684 /*
685  *-----------------------------------------------------------------------------
686  * config window show (public)
687  *-----------------------------------------------------------------------------
688  */
689
690 void show_editor_list_window()
691 {
692         if (editor_list_window)
693                 {
694                 gtk_window_present(GTK_WINDOW(editor_list_window));
695                 return;
696                 }
697
698         editor_list_window_create();
699 }
700 /* vim: set shiftwidth=8 softtabstop=0 cindent cinoptions={1s: */