349021f24745c86e07aab004634f256e5a50510d
[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 "ui-misc.h"
27 #include "ui-fileops.h"
28 #include "pixbuf-util.h"
29 #include "window.h"
30 #include "utilops.h"
31 #include "layout-util.h"
32
33 #define CONFIG_WINDOW_DEF_WIDTH         700
34 #define CONFIG_WINDOW_DEF_HEIGHT        400
35
36
37
38 struct EditorWindow
39 {
40         GtkWidget *window;
41         GtkWidget *entry;
42         GtkWidget *save_button;
43         GtkTextBuffer *buffer;
44         gchar *desktop_name;
45         gboolean modified;
46 };
47
48 struct EditorListWindow
49 {
50         GtkWidget *window;
51         GtkWidget *view;
52         GenericDialog *gd;      /* any open confirm dialogs ? */
53         GtkWidget *delete_button;
54         GtkWidget *edit_button;
55 };
56
57 struct EditorWindowDel_Data
58 {
59         EditorListWindow *ewl;
60         gchar *path;
61 };
62
63 static EditorListWindow *editor_list_window = nullptr;
64
65 static gboolean editor_window_save(EditorWindow *ew)
66 {
67         gchar *dir;
68         gchar *path;
69         gchar *text;
70         GtkTextIter start, end;
71         GError *error = nullptr;
72         gboolean ret = TRUE;
73         const gchar *name = gtk_entry_get_text(GTK_ENTRY(ew->entry));
74
75         if (!name || !name[0])
76                 {
77                 file_util_warning_dialog(_("Can't save"), _("Please specify file name."), GTK_STOCK_DIALOG_ERROR, nullptr);
78                 return FALSE;
79                 }
80
81         gtk_text_buffer_get_bounds(ew->buffer, &start, &end);
82         text = gtk_text_buffer_get_text(ew->buffer, &start, &end, FALSE);
83
84         dir = g_build_filename(get_rc_dir(), "applications", NULL);
85         path = g_build_filename(dir, name, NULL);
86
87         if (!recursive_mkdir_if_not_exists(dir, 0755))
88                 {
89                 file_util_warning_dialog(_("Can't save"), _("Could not create directory"), GTK_STOCK_DIALOG_ERROR, nullptr);
90                 ret = FALSE;
91                 }
92
93         if (ret && !g_file_set_contents(path, text, -1, &error))
94                 {
95                 file_util_warning_dialog(_("Can't save"), error->message, GTK_STOCK_DIALOG_ERROR, nullptr);
96                 g_error_free(error);
97                 ret = FALSE;
98                 }
99
100         g_free(path);
101         g_free(dir);
102         g_free(text);
103         layout_editors_reload_start();
104         /* idle function is not needed, everything should be cached */
105         layout_editors_reload_finish();
106         return ret;
107 }
108
109 static void editor_window_close_cb(GtkWidget *UNUSED(widget), gpointer data)
110 {
111         auto ew = static_cast<EditorWindow *>(data);
112
113         g_free(ew->desktop_name);
114         gtk_widget_destroy(ew->window);
115         g_free(ew);
116 }
117
118 static gint editor_window_delete_cb(GtkWidget *w, GdkEventAny *UNUSED(event), gpointer data)
119 {
120         editor_window_close_cb(w, data);
121         return TRUE;
122 }
123
124 static void editor_window_save_cb(GtkWidget *UNUSED(widget), gpointer data)
125 {
126         auto ew = static_cast<EditorWindow *>(data);
127
128         if (ew->modified)
129                 {
130                 editor_window_save(ew);
131                 }
132
133         gtk_widget_set_sensitive(ew->save_button, FALSE);
134         gtk_text_buffer_set_modified(ew->buffer, FALSE);
135         ew->modified = FALSE;
136 }
137
138 static void editor_window_text_modified_cb(GtkWidget *UNUSED(widget), gpointer data)
139 {
140         auto ew = static_cast<EditorWindow *>(data);
141
142         if (gtk_text_buffer_get_modified(ew->buffer))
143                 {
144                 gtk_widget_set_sensitive(ew->save_button, TRUE);
145                 ew->modified = TRUE;
146                 }
147 }
148
149 static void editor_window_entry_changed_cb(GtkWidget *UNUSED(widget), gpointer data)
150 {
151         auto ew = static_cast<EditorWindow *>(data);
152         const gchar *content = gtk_entry_get_text(GTK_ENTRY(ew->entry));
153         gboolean modified = ew->modified;
154
155         if (!modified)
156                 {
157                 modified = (!ew->desktop_name && *content);
158                 }
159
160         if (!modified)
161                 {
162                 modified = strcmp(ew->desktop_name, content);
163                 }
164
165         gtk_widget_set_sensitive(ew->save_button, modified);
166         ew->modified = modified;
167 }
168
169 static void editor_window_new(const gchar *src_path, const gchar *desktop_name)
170 {
171         EditorWindow *ew;
172         GtkWidget *win_vbox;
173         GtkWidget *hbox;
174         GtkWidget *button;
175         GtkWidget *ct_button;
176         GtkWidget *button_hbox;
177         GtkWidget *scrolled;
178         GtkWidget *text_view;
179         gchar *text;
180         gsize size;
181
182         ew = g_new0(EditorWindow, 1);
183
184
185         ew->window = window_new(GTK_WINDOW_TOPLEVEL, "Desktop", PIXBUF_INLINE_ICON_CONFIG, nullptr, _("Desktop file"));
186         DEBUG_NAME(ew->window);
187         gtk_window_set_type_hint(GTK_WINDOW(ew->window), GDK_WINDOW_TYPE_HINT_DIALOG);
188
189         g_signal_connect(G_OBJECT(ew->window), "delete_event",
190                          G_CALLBACK(editor_window_delete_cb), ew);
191
192         gtk_window_set_default_size(GTK_WINDOW(ew->window), CONFIG_WINDOW_DEF_WIDTH, CONFIG_WINDOW_DEF_HEIGHT);
193         gtk_window_set_resizable(GTK_WINDOW(ew->window), TRUE);
194         gtk_container_set_border_width(GTK_CONTAINER(ew->window), PREF_PAD_BORDER);
195
196         win_vbox = gtk_box_new(GTK_ORIENTATION_VERTICAL, PREF_PAD_SPACE);
197         gtk_container_add(GTK_CONTAINER(ew->window), win_vbox);
198         gtk_widget_show(win_vbox);
199
200         hbox = gtk_box_new(GTK_ORIENTATION_HORIZONTAL, PREF_PAD_SPACE);
201         gtk_box_pack_end(GTK_BOX(win_vbox), hbox, FALSE, FALSE, 0);
202         gtk_widget_show(hbox);
203
204         ew->entry = gtk_entry_new();
205         gtk_box_pack_start(GTK_BOX(hbox), ew->entry, TRUE, TRUE, 0);
206         ew->desktop_name = nullptr;
207         if (desktop_name)
208                 {
209                 gtk_entry_set_text(GTK_ENTRY(ew->entry), desktop_name);
210                 ew->desktop_name = g_strdup(desktop_name);
211                 }
212         gtk_widget_show(ew->entry);
213         g_signal_connect(G_OBJECT(ew->entry), "changed", G_CALLBACK(editor_window_entry_changed_cb), ew);
214
215         button_hbox = gtk_hbutton_box_new();
216         gtk_button_box_set_layout(GTK_BUTTON_BOX(button_hbox), GTK_BUTTONBOX_END);
217         gtk_box_set_spacing(GTK_BOX(button_hbox), PREF_PAD_BUTTON_GAP);
218         gtk_box_pack_end(GTK_BOX(hbox), button_hbox, FALSE, FALSE, 0);
219         gtk_widget_show(button_hbox);
220
221         ew->save_button = pref_button_new(nullptr, GTK_STOCK_SAVE, nullptr, FALSE,
222                                  G_CALLBACK(editor_window_save_cb), ew);
223         gtk_container_add(GTK_CONTAINER(button_hbox), ew->save_button);
224         gtk_widget_set_can_default(ew->save_button, TRUE);
225         gtk_widget_set_sensitive(ew->save_button, FALSE);
226         gtk_widget_show(ew->save_button);
227         ct_button = ew->save_button;
228
229         button = pref_button_new(nullptr, GTK_STOCK_CLOSE, nullptr, FALSE,
230                                  G_CALLBACK(editor_window_close_cb), ew);
231         gtk_container_add(GTK_CONTAINER(button_hbox), button);
232         gtk_widget_set_can_default(button, TRUE);
233         gtk_widget_show(button);
234
235         if (!generic_dialog_get_alternative_button_order(ew->window))
236                 {
237                 gtk_box_reorder_child(GTK_BOX(button_hbox), ct_button, -1);
238                 }
239
240
241         scrolled = gtk_scrolled_window_new(nullptr, nullptr);
242         gtk_scrolled_window_set_shadow_type(GTK_SCROLLED_WINDOW(scrolled), GTK_SHADOW_IN);
243         gtk_scrolled_window_set_policy(GTK_SCROLLED_WINDOW(scrolled),
244                                        GTK_POLICY_AUTOMATIC, GTK_POLICY_AUTOMATIC);
245         gtk_box_pack_start(GTK_BOX(win_vbox), scrolled, TRUE, TRUE, 5);
246         gtk_widget_show(scrolled);
247
248         text_view = gtk_text_view_new();
249         gtk_container_add(GTK_CONTAINER(scrolled), text_view);
250         gtk_widget_show(text_view);
251
252         ew->buffer = gtk_text_view_get_buffer(GTK_TEXT_VIEW(text_view));
253         if (g_file_get_contents(src_path, &text, &size, nullptr))
254                 {
255                 gtk_text_buffer_set_text(ew->buffer, text, size);
256                 }
257         gtk_text_buffer_set_modified(ew->buffer, FALSE);
258         g_signal_connect(G_OBJECT(ew->buffer), "modified-changed",
259                          G_CALLBACK(editor_window_text_modified_cb), ew);
260
261         gtk_widget_show(ew->window);
262 }
263
264
265 static void editor_list_window_close_cb(GtkWidget *UNUSED(widget), gpointer UNUSED(data))
266 {
267         gtk_widget_destroy(editor_list_window->window);
268         g_free(editor_list_window);
269         editor_list_window = nullptr;
270 }
271
272 static gboolean editor_list_window_delete(GtkWidget *UNUSED(widget), GdkEventAny *UNUSED(event), gpointer UNUSED(data))
273 {
274         editor_list_window_close_cb(nullptr, nullptr);
275         return TRUE;
276 }
277
278 static void editor_list_window_delete_dlg_cancel(GenericDialog *gd, gpointer data);
279
280 static void editor_list_window_delete_dlg_cancel(GenericDialog *UNUSED(gd), gpointer data)
281 {
282         auto ewdl = static_cast<EditorWindowDel_Data *>(data);
283
284         ewdl->ewl->gd = nullptr;
285         g_free(ewdl->path);
286         g_free(ewdl);
287 }
288
289 static void editor_list_window_delete_dlg_ok_cb(GenericDialog *gd, gpointer data)
290 {
291         auto ewdl = static_cast<EditorWindowDel_Data *>(data);
292
293         if (!unlink_file(ewdl->path))
294                 {
295                 gchar *text = g_strdup_printf(_("Unable to delete file:\n%s"), ewdl->path);
296                 warning_dialog(_("File deletion failed"), text, GTK_STOCK_DIALOG_WARNING, nullptr);
297                 g_free(text);
298                 }
299         else
300                 {
301                 /* refresh list */
302                 layout_editors_reload_start();
303                 /* idle function is not needed, everything should be cached */
304                 layout_editors_reload_finish();
305                 }
306
307         editor_list_window_delete_dlg_cancel(gd, data);
308 }
309
310 static void editor_list_window_delete_cb(GtkWidget *UNUSED(widget), gpointer data)
311 {
312         auto ewl = static_cast<EditorListWindow *>(data);
313         GtkTreeSelection *sel = gtk_tree_view_get_selection(GTK_TREE_VIEW(ewl->view));
314         GtkTreeIter iter;
315
316         if (gtk_tree_selection_get_selected(sel, nullptr, &iter))
317                 {
318                 GtkTreeModel *store = gtk_tree_view_get_model(GTK_TREE_VIEW(ewl->view));
319                 gchar *path;
320                 gchar *key;
321                 gchar *text;
322                 EditorWindowDel_Data *ewdl;
323
324                 gtk_tree_model_get(store, &iter,
325                                    DESKTOP_FILE_COLUMN_PATH, &path,
326                                    DESKTOP_FILE_COLUMN_KEY, &key, -1);
327
328
329                 ewdl = g_new(EditorWindowDel_Data, 1);
330                 ewdl->ewl = ewl;
331                 ewdl->path = path;
332
333                 if (ewl->gd)
334                         {
335                         GenericDialog *gd = ewl->gd;
336                         editor_list_window_delete_dlg_cancel(ewl->gd, ewl->gd->data);
337                         generic_dialog_close(gd);
338                         }
339
340                 ewl->gd = generic_dialog_new(_("Delete file"), "dlg_confirm",
341                                             nullptr, TRUE,
342                                             editor_list_window_delete_dlg_cancel, ewdl);
343
344                 generic_dialog_add_button(ewl->gd, GTK_STOCK_DELETE, nullptr, editor_list_window_delete_dlg_ok_cb, TRUE);
345
346                 text = g_strdup_printf(_("About to delete the file:\n %s"), path);
347                 generic_dialog_add_message(ewl->gd, GTK_STOCK_DIALOG_QUESTION,
348                                            _("Delete file"), text, TRUE);
349                 g_free(text);
350
351                 gtk_widget_show(ewl->gd->dialog);
352                 }
353 }
354
355 static void editor_list_window_edit_cb(GtkWidget *UNUSED(widget), gpointer data)
356 {
357         auto ewl = static_cast<EditorListWindow *>(data);
358         GtkTreeSelection *sel = gtk_tree_view_get_selection(GTK_TREE_VIEW(ewl->view));
359         GtkTreeIter iter;
360
361         if (gtk_tree_selection_get_selected(sel, nullptr, &iter))
362                 {
363                 GtkTreeModel *store = gtk_tree_view_get_model(GTK_TREE_VIEW(ewl->view));
364                 gchar *path;
365                 gchar *key;
366
367                 gtk_tree_model_get(store, &iter,
368                                    DESKTOP_FILE_COLUMN_PATH, &path,
369                                    DESKTOP_FILE_COLUMN_KEY, &key, -1);
370                 editor_window_new(path, key);
371                 g_free(key);
372                 g_free(path);
373                 }
374 }
375
376 static void editor_list_window_new_cb(GtkWidget *UNUSED(widget), gpointer UNUSED(data))
377 {
378         editor_window_new(desktop_file_template, _("new.desktop"));
379 }
380
381 static void editor_list_window_help_cb(GtkWidget *UNUSED(widget), gpointer UNUSED(data))
382 {
383         help_window_show("GuidePluginsConfig.html");
384 }
385
386 static void editor_list_window_selection_changed_cb(GtkWidget *UNUSED(widget), gpointer data)
387 {
388         auto ewl = static_cast<EditorListWindow *>(data);
389         GtkTreeSelection *sel = gtk_tree_view_get_selection(GTK_TREE_VIEW(ewl->view));
390         GtkTreeIter iter;
391
392         if (gtk_tree_selection_get_selected(sel, nullptr, &iter))
393                 {
394                 GtkTreeModel *store = gtk_tree_view_get_model(GTK_TREE_VIEW(ewl->view));
395                 gchar *path;
396
397                 gtk_tree_model_get(store, &iter,
398                                                    DESKTOP_FILE_COLUMN_PATH, &path,
399                                                    -1);
400
401                 gtk_widget_set_sensitive(ewl->delete_button, access_file(path, W_OK));
402                 gtk_widget_set_sensitive(ewl->edit_button, TRUE);
403                 g_free(path);
404                 }
405
406 }
407
408 static gint editor_list_window_sort_cb(GtkTreeModel *model, GtkTreeIter *a, GtkTreeIter *b, gpointer data)
409 {
410         gint n = GPOINTER_TO_INT(data);
411         gint ret = 0;
412         gboolean bool1, bool2;
413
414         switch (n)
415                 {
416                 case DESKTOP_FILE_COLUMN_KEY:
417                 case DESKTOP_FILE_COLUMN_NAME:
418                 case DESKTOP_FILE_COLUMN_PATH:
419                 case DESKTOP_FILE_COLUMN_HIDDEN:
420                         {
421                         gchar *s1, *s2;
422
423                         gtk_tree_model_get(model, a, n, &s1, -1);
424                         gtk_tree_model_get(model, b, n, &s2, -1);
425
426                         if (!s1 || !s2)
427                                 {
428                                 if (!s1 && !s2) break;
429                                 ret = s1 ? 1 : -1;
430                                 }
431                         else
432                                 {
433                                 ret = g_utf8_collate(s1, s2);
434                                 }
435
436                         g_free(s1);
437                         g_free(s2);
438                         }
439                         break;
440                 case DESKTOP_FILE_COLUMN_DISABLED:
441                         {
442                         gtk_tree_model_get(model, a, n, &bool1, -1);
443                         gtk_tree_model_get(model, b, n, &bool2, -1);
444
445                         if (bool1 == bool2)
446                                 {
447                                 ret = 0;
448                                 }
449                         else if (bool1 > bool2)
450                                 {
451                                 ret = -1;
452                                 }
453                         else
454                                 {
455                                 ret = 1;
456                                 }
457                         break;
458                         }
459
460                 default:
461                         g_return_val_if_reached(0);
462                 }
463
464         return ret;
465 }
466
467 static void plugin_disable_cb(GtkCellRendererToggle *UNUSED(renderer), gchar *path_str, gpointer data)
468 {
469         auto ewl = static_cast<EditorListWindow *>(data);
470         GtkTreePath *tpath;
471         GtkTreeIter iter;
472         GtkTreeModel *model;
473         gboolean disabled;
474         gchar *path;
475         GList *list;
476         gchar *haystack;
477
478         tpath = gtk_tree_path_new_from_string(path_str);
479         model = gtk_tree_view_get_model(GTK_TREE_VIEW(ewl->view));
480         gtk_tree_model_get_iter(GTK_TREE_MODEL(model), &iter, tpath);
481         gtk_tree_model_get(GTK_TREE_MODEL(model), &iter, DESKTOP_FILE_COLUMN_DISABLED, &disabled, -1);
482         gtk_tree_model_get(GTK_TREE_MODEL(model), &iter, DESKTOP_FILE_COLUMN_PATH, &path, -1);
483
484         gtk_list_store_set(GTK_LIST_STORE(desktop_file_list), &iter, DESKTOP_FILE_COLUMN_DISABLED, !disabled, -1);
485
486         if (!disabled)
487                 {
488                 options->disabled_plugins = g_list_append((options->disabled_plugins), g_strdup(path));
489                 }
490         else
491                 {
492                 list = options->disabled_plugins;
493                 while (list)
494                         {
495                         haystack = static_cast<gchar *>(list->data);
496
497                         if (haystack && strcmp(haystack, path) == 0)
498                                 {
499                                 options->disabled_plugins = g_list_remove(options->disabled_plugins, haystack);
500                                 g_free(haystack);
501                                 }
502
503                         list = list->next;
504                         }
505                 }
506
507         layout_editors_reload_start();
508         layout_editors_reload_finish();
509 }
510
511 static void plugin_disable_set_func(GtkTreeViewColumn *UNUSED(tree_column), GtkCellRenderer *cell,
512                                                         GtkTreeModel *tree_model, GtkTreeIter *iter, gpointer UNUSED(data))
513 {
514         gboolean disabled;
515
516         gtk_tree_model_get(tree_model, iter, DESKTOP_FILE_COLUMN_DISABLED, &disabled, -1);
517
518         if (disabled)
519                 {
520                 g_object_set(GTK_CELL_RENDERER(cell), "active", TRUE, NULL);
521                 }
522         else
523                 {
524                 g_object_set(GTK_CELL_RENDERER(cell), "active", FALSE, NULL);
525                 }
526 }
527
528 static void editor_list_window_create()
529 {
530         GtkWidget *win_vbox;
531         GtkWidget *hbox;
532         GtkWidget *button;
533         GtkWidget *scrolled;
534         GtkCellRenderer *renderer;
535         GtkTreeSelection *selection;
536         GtkTreeViewColumn *column;
537         GtkTreeModel *store;
538         GtkTreeSortable *sortable;
539         EditorListWindow *ewl;
540
541         editor_list_window = ewl = g_new0(EditorListWindow, 1);
542
543         ewl->window = window_new(GTK_WINDOW_TOPLEVEL, "editors", PIXBUF_INLINE_ICON_CONFIG, nullptr, _("Plugins"));
544         DEBUG_NAME(ewl->window);
545         gtk_window_set_type_hint(GTK_WINDOW(ewl->window), GDK_WINDOW_TYPE_HINT_DIALOG);
546         g_signal_connect(G_OBJECT(ewl->window), "delete_event",
547                          G_CALLBACK(editor_list_window_delete), NULL);
548         gtk_window_set_default_size(GTK_WINDOW(ewl->window), CONFIG_WINDOW_DEF_WIDTH, CONFIG_WINDOW_DEF_HEIGHT);
549         gtk_window_set_resizable(GTK_WINDOW(ewl->window), TRUE);
550         gtk_container_set_border_width(GTK_CONTAINER(ewl->window), PREF_PAD_BORDER);
551
552         win_vbox = gtk_box_new(GTK_ORIENTATION_VERTICAL, PREF_PAD_SPACE);
553         gtk_container_add(GTK_CONTAINER(ewl->window), win_vbox);
554         gtk_widget_show(win_vbox);
555
556         hbox = gtk_hbutton_box_new();
557         gtk_button_box_set_layout(GTK_BUTTON_BOX(hbox), GTK_BUTTONBOX_END);
558         gtk_box_set_spacing(GTK_BOX(hbox), PREF_PAD_BUTTON_GAP);
559         gtk_box_pack_end(GTK_BOX(win_vbox), hbox, FALSE, FALSE, 0);
560         gtk_widget_show(hbox);
561
562
563         button = pref_button_new(nullptr, GTK_STOCK_HELP, nullptr, FALSE,
564                                  G_CALLBACK(editor_list_window_help_cb), ewl);
565         gtk_container_add(GTK_CONTAINER(hbox), button);
566         gtk_widget_set_can_default(button, TRUE);
567         gtk_widget_show(button);
568
569         button = pref_button_new(nullptr, GTK_STOCK_NEW, nullptr, FALSE,
570                                  G_CALLBACK(editor_list_window_new_cb), ewl);
571         gtk_container_add(GTK_CONTAINER(hbox), button);
572         gtk_widget_set_can_default(button, TRUE);
573         gtk_widget_show(button);
574
575         button = pref_button_new(nullptr, GTK_STOCK_EDIT, nullptr, FALSE,
576                                  G_CALLBACK(editor_list_window_edit_cb), ewl);
577         gtk_container_add(GTK_CONTAINER(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, GTK_STOCK_DELETE, nullptr, FALSE,
584                                  G_CALLBACK(editor_list_window_delete_cb), ewl);
585         gtk_container_add(GTK_CONTAINER(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, GTK_STOCK_CLOSE, nullptr, FALSE,
592                                  G_CALLBACK(editor_list_window_close_cb), ewl);
593         gtk_container_add(GTK_CONTAINER(hbox), button);
594         gtk_widget_set_can_default(button, TRUE);
595         gtk_widget_show(button);
596
597         scrolled = gtk_scrolled_window_new(nullptr, nullptr);
598         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         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         gtk_container_add(GTK_CONTAINER(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: */