javascript: Partial highlighting of ES6 template strings
[geany-mirror.git] / src / prefs.c
blob714b7bc5cd917fd29e220622153af6600d57224b
1 /*
2 * prefs.c - this file is part of Geany, a fast and lightweight IDE
4 * Copyright 2005-2012 Enrico Tröger <enrico(dot)troeger(at)uvena(dot)de>
5 * Copyright 2006-2012 Nick Treleaven <nick(dot)treleaven(at)btinternet(dot)com>
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.
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.
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.
23 * @file prefs.h
24 * Preferences dialog.
28 * Preferences dialog support functions.
29 * New 'simple' prefs should use Stash code in keyfile.c - init_pref_groups().
32 #ifdef HAVE_CONFIG_H
33 # include "config.h"
34 #endif
36 #include "prefs.h"
38 #include "app.h"
39 #include "dialogs.h"
40 #include "documentprivate.h"
41 #include "editor.h"
42 #include "encodingsprivate.h"
43 #include "filetypes.h"
44 #include "geanywraplabel.h"
45 #include "keybindingsprivate.h"
46 #include "keyfile.h"
47 #include "msgwindow.h"
48 #include "prefs.h"
49 #include "printing.h"
50 #include "sidebar.h"
51 #include "stash.h"
52 #include "support.h"
53 #include "templates.h"
54 #include "toolbar.h"
55 #include "tools.h"
56 #include "ui_utils.h"
57 #include "utils.h"
58 #include "vte.h"
59 #include "osx.h"
61 #include "gtkcompat.h"
63 #include <stdlib.h>
64 #include <string.h>
65 #include <gdk/gdkkeysyms.h>
68 GeanyPrefs prefs;
69 GeanyToolPrefs tool_prefs;
72 typedef struct
74 GtkTreeStore *store;
75 GtkTreeView *tree;
76 gboolean edited;
78 KbData;
80 static KbData global_kb_data = { NULL, NULL, FALSE };
81 static GtkTreeView *various_treeview = NULL;
83 static GeanyKeyBinding *kb_index(guint gidx, guint kid);
84 static void kb_cell_edited_cb(GtkCellRendererText *cellrenderertext, gchar *path, gchar *new_text, KbData *kbdata);
85 static gboolean kb_grab_key_dialog_key_press_cb(GtkWidget *dialog, GdkEventKey *event, GtkLabel *label);
86 static void kb_change_iter_shortcut(KbData *kbdata, GtkTreeIter *iter, const gchar *new_text);
87 static gboolean kb_find_duplicate(GtkTreeStore *store, GtkWidget *parent, GtkTreeIter *old_iter,
88 guint key, GdkModifierType mods, const gchar *shortcut);
89 static void on_toolbar_show_toggled(GtkToggleButton *togglebutton, gpointer user_data);
90 static void on_show_notebook_tabs_toggled(GtkToggleButton *togglebutton, gpointer user_data);
91 static void on_enable_plugins_toggled(GtkToggleButton *togglebutton, gpointer user_data);
92 static void on_use_folding_toggled(GtkToggleButton *togglebutton, gpointer user_data);
93 static void on_open_encoding_toggled(GtkToggleButton *togglebutton, gpointer user_data);
94 static void on_sidebar_visible_toggled(GtkToggleButton *togglebutton, gpointer user_data);
95 static void on_prefs_print_radio_button_toggled(GtkToggleButton *togglebutton, gpointer user_data);
96 static void on_prefs_print_page_header_toggled(GtkToggleButton *togglebutton, gpointer user_data);
97 static void open_preferences_help(void);
100 typedef enum PrefCallbackAction
102 PREF_DISPLAY,
103 PREF_UPDATE
105 PrefCallbackAction;
108 /* Synchronize Stash settings with widgets (see keyfile.c - init_pref_groups()). */
109 static void prefs_action(PrefCallbackAction action)
111 StashGroup *group;
112 guint i;
114 foreach_ptr_array(group, i, pref_groups)
116 switch (action)
118 case PREF_DISPLAY:
119 stash_group_display(group, ui_widgets.prefs_dialog);
120 break;
121 case PREF_UPDATE:
122 stash_group_update(group, ui_widgets.prefs_dialog);
123 break;
127 switch (action)
129 case PREF_DISPLAY:
130 stash_tree_display(various_treeview);
131 break;
132 case PREF_UPDATE:
133 stash_tree_update(various_treeview);
134 break;
139 enum
141 KB_TREE_ACTION,
142 KB_TREE_SHORTCUT,
143 KB_TREE_INDEX,
144 KB_TREE_EDITABLE,
145 KB_TREE_WEIGHT,
146 KB_TREE_COLUMNS
150 static void kb_tree_view_change_button_clicked_cb(GtkWidget *button, KbData *kbdata)
152 GtkTreeModel *model;
153 GtkTreeIter iter;
154 GtkTreeSelection *selection;
155 gchar *name;
157 selection = gtk_tree_view_get_selection(kbdata->tree);
158 if (gtk_tree_selection_get_selected(selection, &model, &iter))
160 if (gtk_tree_model_iter_has_child(model, &iter))
161 { /* double click on a section to expand or collapse it */
162 GtkTreePath *path = gtk_tree_model_get_path(model, &iter);
164 if (gtk_tree_view_row_expanded(kbdata->tree, path))
165 gtk_tree_view_collapse_row(kbdata->tree, path);
166 else
167 gtk_tree_view_expand_row(kbdata->tree, path, FALSE);
169 gtk_tree_path_free(path);
170 return;
173 gtk_tree_model_get(model, &iter, KB_TREE_ACTION, &name, -1);
174 if (name != NULL)
176 GtkWidget *dialog;
177 GtkWidget *label;
178 GtkWidget *accel_label;
179 gchar *str;
181 dialog = gtk_dialog_new_with_buttons(_("Grab Key"), GTK_WINDOW(ui_widgets.prefs_dialog),
182 GTK_DIALOG_MODAL | GTK_DIALOG_DESTROY_WITH_PARENT,
183 GTK_STOCK_CANCEL, GTK_RESPONSE_CANCEL,
184 GTK_STOCK_OK, GTK_RESPONSE_ACCEPT, NULL);
186 str = g_strdup_printf(
187 _("Press the combination of the keys you want to use for \"%s\"."), name);
188 label = gtk_label_new(str);
189 gtk_misc_set_padding(GTK_MISC(label), 5, 10);
190 gtk_container_add(GTK_CONTAINER(gtk_dialog_get_content_area(GTK_DIALOG(dialog))), label);
192 accel_label = gtk_label_new("");
193 gtk_misc_set_padding(GTK_MISC(accel_label), 5, 10);
194 gtk_container_add(GTK_CONTAINER(gtk_dialog_get_content_area(GTK_DIALOG(dialog))), accel_label);
196 g_signal_connect(dialog, "key-press-event",
197 G_CALLBACK(kb_grab_key_dialog_key_press_cb), accel_label);
199 gtk_widget_show_all(dialog);
200 if (gtk_dialog_run(GTK_DIALOG(dialog)) == GTK_RESPONSE_ACCEPT)
202 const gchar *new_text = gtk_label_get_text(GTK_LABEL(accel_label));
204 kb_change_iter_shortcut(kbdata, &iter, new_text);
206 gtk_widget_destroy(dialog);
208 g_free(str);
209 g_free(name);
215 static void kb_show_popup_menu(KbData *kbdata, GtkWidget *widget, GdkEventButton *event)
217 static GtkWidget *menu = NULL;
218 guint button;
219 guint32 event_time;
221 if (menu == NULL)
223 GtkWidget *item;
225 menu = gtk_menu_new();
227 item = ui_image_menu_item_new(GTK_STOCK_ADD, _("_Expand All"));
228 gtk_widget_show(item);
229 gtk_container_add(GTK_CONTAINER(menu), item);
230 g_signal_connect_swapped(item, "activate", G_CALLBACK(gtk_tree_view_expand_all), kbdata->tree);
232 item = ui_image_menu_item_new(GTK_STOCK_REMOVE, _("_Collapse All"));
233 gtk_widget_show(item);
234 gtk_container_add(GTK_CONTAINER(menu), item);
235 g_signal_connect_swapped(item, "activate", G_CALLBACK(gtk_tree_view_collapse_all), kbdata->tree);
237 gtk_menu_attach_to_widget(GTK_MENU(menu), widget, NULL);
240 if (event != NULL)
242 button = event->button;
243 event_time = event->time;
245 else
247 button = 0;
248 event_time = gtk_get_current_event_time();
251 gtk_menu_popup(GTK_MENU(menu), NULL, NULL, NULL, NULL, button, event_time);
255 static gboolean kb_popup_menu_cb(GtkWidget *widget, KbData *kbdata)
257 kb_show_popup_menu(kbdata, widget, NULL);
258 return TRUE;
262 static gboolean kb_tree_view_button_press_event_cb(GtkWidget *widget, GdkEventButton *event,
263 KbData *kbdata)
265 if (event->button == 3 && event->type == GDK_BUTTON_PRESS)
267 kb_show_popup_menu(kbdata, widget, event);
268 return TRUE;
270 else if (event->type == GDK_2BUTTON_PRESS)
272 kb_tree_view_change_button_clicked_cb(NULL, kbdata);
273 return TRUE;
275 return FALSE;
279 static void kb_init_tree(KbData *kbdata)
281 GtkCellRenderer *renderer;
282 GtkTreeViewColumn *column;
284 kbdata->tree = GTK_TREE_VIEW(ui_lookup_widget(ui_widgets.prefs_dialog, "treeview7"));
286 kbdata->store = gtk_tree_store_new(KB_TREE_COLUMNS,
287 G_TYPE_STRING, G_TYPE_STRING, G_TYPE_INT, G_TYPE_BOOLEAN, G_TYPE_INT);
288 gtk_tree_view_set_model(GTK_TREE_VIEW(kbdata->tree), GTK_TREE_MODEL(kbdata->store));
289 g_object_unref(kbdata->store);
291 renderer = gtk_cell_renderer_text_new();
292 column = gtk_tree_view_column_new_with_attributes(_("Action"), renderer,
293 "text", KB_TREE_ACTION, "weight", KB_TREE_WEIGHT, NULL);
294 gtk_tree_view_append_column(GTK_TREE_VIEW(kbdata->tree), column);
296 renderer = gtk_cell_renderer_text_new();
297 column = gtk_tree_view_column_new_with_attributes(_("Shortcut"), renderer,
298 "text", KB_TREE_SHORTCUT, "editable", KB_TREE_EDITABLE,
299 "weight", KB_TREE_WEIGHT, NULL);
300 gtk_tree_view_append_column(GTK_TREE_VIEW(kbdata->tree), column);
302 /* set policy settings for the scrolled window around the treeview again, because glade
303 * doesn't keep the settings */
304 gtk_scrolled_window_set_policy(
305 GTK_SCROLLED_WINDOW(ui_lookup_widget(ui_widgets.prefs_dialog, "scrolledwindow8")),
306 GTK_POLICY_NEVER, GTK_POLICY_AUTOMATIC);
308 g_signal_connect(renderer, "edited", G_CALLBACK(kb_cell_edited_cb), kbdata);
309 g_signal_connect(kbdata->tree, "button-press-event", G_CALLBACK(kb_tree_view_button_press_event_cb), kbdata);
310 g_signal_connect(kbdata->tree, "popup-menu", G_CALLBACK(kb_popup_menu_cb), kbdata);
311 g_signal_connect(ui_lookup_widget(ui_widgets.prefs_dialog, "button2"), "clicked",
312 G_CALLBACK(kb_tree_view_change_button_clicked_cb), kbdata);
316 static void kb_set_shortcut(GtkTreeStore *store, GtkTreeIter *iter,
317 guint key, GdkModifierType mods)
319 gchar *key_string = gtk_accelerator_name(key, mods);
320 GtkTreeIter parent;
321 guint kid, gid;
322 GeanyKeyBinding *kb;
323 gboolean bold;
325 gtk_tree_store_set(store, iter, KB_TREE_SHORTCUT, key_string, -1);
326 g_free(key_string);
328 gtk_tree_model_get(GTK_TREE_MODEL(store), iter, KB_TREE_INDEX, &kid, -1);
329 gtk_tree_model_iter_parent(GTK_TREE_MODEL(store), &parent, iter);
330 gtk_tree_model_get(GTK_TREE_MODEL(store), &parent, KB_TREE_INDEX, &gid, -1);
331 kb = kb_index(gid, kid);
332 bold = key != kb->default_key || mods != kb->default_mods;
333 gtk_tree_store_set(store, iter, KB_TREE_WEIGHT,
334 bold ? PANGO_WEIGHT_BOLD : PANGO_WEIGHT_NORMAL, -1);
338 void prefs_kb_search_name(const gchar *search)
340 GtkTreeIter iter;
341 gboolean valid;
342 GtkTreeModel *model;
343 KbData *kbdata = &global_kb_data;
345 model = gtk_tree_view_get_model(kbdata->tree);
346 valid = gtk_tree_model_get_iter_first(model, &iter);
347 while (valid)
349 gchar *name;
351 gtk_tree_model_get(model, &iter, KB_TREE_ACTION, &name, -1);
352 if (g_strcmp0(name, search) == 0)
354 GtkTreePath *path = gtk_tree_model_get_path(model, &iter);
355 gtk_tree_view_scroll_to_cell(kbdata->tree, path, NULL, TRUE, .0f, .0f);
356 gtk_tree_path_free(path);
357 g_free(name);
358 break;
360 g_free(name);
361 valid = gtk_tree_model_iter_next(model, &iter);
366 static void kb_init(KbData *kbdata)
368 GtkTreeIter parent, iter;
369 gsize g, i;
370 gchar *label;
371 GeanyKeyGroup *group;
372 GeanyKeyBinding *kb;
374 if (kbdata->store == NULL)
375 kb_init_tree(kbdata);
377 foreach_ptr_array(group, g, keybinding_groups)
379 gtk_tree_store_append(kbdata->store, &parent, NULL);
380 gtk_tree_store_set(kbdata->store, &parent, KB_TREE_ACTION, group->label,
381 KB_TREE_INDEX, g, -1);
383 foreach_ptr_array(kb, i, group->key_items)
385 label = keybindings_get_label(kb);
386 gtk_tree_store_append(kbdata->store, &iter, &parent);
387 gtk_tree_store_set(kbdata->store, &iter, KB_TREE_ACTION, label,
388 KB_TREE_EDITABLE, TRUE, KB_TREE_INDEX, kb->id, -1);
389 kb_set_shortcut(kbdata->store, &iter, kb->key, kb->mods);
390 g_free(label);
393 gtk_tree_view_expand_all(GTK_TREE_VIEW(kbdata->tree));
397 /* note: new 'simple' prefs should use Stash code in keyfile.c */
398 static void prefs_init_dialog(void)
400 GtkWidget *widget;
401 GdkColor color = {0};
403 /* Synchronize with Stash settings */
404 prefs_action(PREF_DISPLAY);
406 widget = ui_lookup_widget(ui_widgets.prefs_dialog, "label_project_indent_warning");
407 ui_widget_show_hide(widget, app->project != NULL);
409 /* General settings */
410 /* startup */
411 widget = ui_lookup_widget(ui_widgets.prefs_dialog, "check_load_session");
412 gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(widget), prefs.load_session);
414 widget = ui_lookup_widget(ui_widgets.prefs_dialog, "check_project_session");
415 gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(widget), project_prefs.project_session);
417 widget = ui_lookup_widget(ui_widgets.prefs_dialog, "check_project_file_in_basedir");
418 gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(widget), project_prefs.project_file_in_basedir);
420 widget = ui_lookup_widget(ui_widgets.prefs_dialog, "check_save_win_pos");
421 gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(widget), prefs.save_winpos);
423 widget = ui_lookup_widget(ui_widgets.prefs_dialog, "check_ask_for_quit");
424 gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(widget), prefs.confirm_exit);
426 /* behaviour */
427 widget = ui_lookup_widget(ui_widgets.prefs_dialog, "check_beep");
428 gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(widget), prefs.beep_on_errors);
430 widget = ui_lookup_widget(ui_widgets.prefs_dialog, "check_switch_pages");
431 gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(widget), prefs.switch_to_status);
433 widget = ui_lookup_widget(ui_widgets.prefs_dialog, "check_suppress_status_msgs");
434 gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(widget), prefs.suppress_status_messages);
436 widget = ui_lookup_widget(ui_widgets.prefs_dialog, "check_auto_focus");
437 gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(widget), prefs.auto_focus);
439 widget = ui_lookup_widget(ui_widgets.prefs_dialog, "check_native_windows_dialogs");
440 gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(widget),
441 interface_prefs.use_native_windows_dialogs);
443 widget = ui_lookup_widget(ui_widgets.prefs_dialog, "entry_contextaction");
444 gtk_entry_set_text(GTK_ENTRY(widget), tool_prefs.context_action_cmd);
446 project_setup_prefs(); /* project files path */
449 /* Interface settings */
450 widget = ui_lookup_widget(ui_widgets.prefs_dialog, "check_sidebar_visible");
451 gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(widget), ui_prefs.sidebar_visible);
452 on_sidebar_visible_toggled(GTK_TOGGLE_BUTTON(widget), NULL);
454 widget = ui_lookup_widget(ui_widgets.prefs_dialog, "check_list_symbol");
455 gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(widget), interface_prefs.sidebar_symbol_visible);
457 widget = ui_lookup_widget(ui_widgets.prefs_dialog, "check_list_openfiles");
458 gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(widget), interface_prefs.sidebar_openfiles_visible);
460 widget = ui_lookup_widget(ui_widgets.prefs_dialog, "tagbar_font");
461 gtk_font_button_set_font_name(GTK_FONT_BUTTON(widget), interface_prefs.tagbar_font);
463 widget = ui_lookup_widget(ui_widgets.prefs_dialog, "msgwin_font");
464 gtk_font_button_set_font_name(GTK_FONT_BUTTON(widget), interface_prefs.msgwin_font);
466 widget = ui_lookup_widget(ui_widgets.prefs_dialog, "editor_font");
467 gtk_font_button_set_font_name(GTK_FONT_BUTTON(widget), interface_prefs.editor_font);
469 widget = ui_lookup_widget(ui_widgets.prefs_dialog, "spin_long_line");
470 gtk_spin_button_set_value(GTK_SPIN_BUTTON(widget), editor_prefs.long_line_column);
472 widget = ui_lookup_widget(ui_widgets.prefs_dialog, "check_long_line");
473 gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(widget), editor_prefs.long_line_enabled);
475 switch (editor_prefs.long_line_type)
477 case 0: widget = ui_lookup_widget(ui_widgets.prefs_dialog, "radio_long_line_line"); break;
478 case 1: widget = ui_lookup_widget(ui_widgets.prefs_dialog, "radio_long_line_background"); break;
480 gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(widget), TRUE);
482 utils_parse_color(editor_prefs.long_line_color, &color);
483 widget = ui_lookup_widget(ui_widgets.prefs_dialog, "long_line_color");
484 gtk_color_button_set_color(GTK_COLOR_BUTTON(widget), &color);
486 widget = ui_lookup_widget(ui_widgets.prefs_dialog, "check_show_notebook_tabs");
487 gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(widget), interface_prefs.show_notebook_tabs);
488 /* disable following setting if notebook tabs are hidden */
489 on_show_notebook_tabs_toggled(GTK_TOGGLE_BUTTON(
490 ui_lookup_widget(ui_widgets.prefs_dialog, "check_show_notebook_tabs")), NULL);
492 widget = ui_lookup_widget(ui_widgets.prefs_dialog, "check_show_tab_cross");
493 gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(widget), file_prefs.show_tab_cross);
495 widget = ui_lookup_widget(ui_widgets.prefs_dialog, "combo_tab_editor");
496 gtk_combo_box_set_active(GTK_COMBO_BOX(widget), interface_prefs.tab_pos_editor);
498 widget = ui_lookup_widget(ui_widgets.prefs_dialog, "combo_tab_msgwin");
499 gtk_combo_box_set_active(GTK_COMBO_BOX(widget), interface_prefs.tab_pos_msgwin);
501 widget = ui_lookup_widget(ui_widgets.prefs_dialog, "combo_tab_sidebar");
502 gtk_combo_box_set_active(GTK_COMBO_BOX(widget), interface_prefs.tab_pos_sidebar);
504 widget = ui_lookup_widget(ui_widgets.prefs_dialog, "check_statusbar_visible");
505 gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(widget), interface_prefs.statusbar_visible);
508 /* Toolbar settings */
509 widget = ui_lookup_widget(ui_widgets.prefs_dialog, "check_toolbar_show");
510 gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(widget), toolbar_prefs.visible);
511 widget = ui_lookup_widget(ui_widgets.prefs_dialog, "check_toolbar_in_menu");
512 gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(widget), toolbar_prefs.append_to_menu);
514 switch (toolbar_prefs.icon_style)
516 case 0: widget = ui_lookup_widget(ui_widgets.prefs_dialog, "radio_toolbar_image"); break;
517 case 1: widget = ui_lookup_widget(ui_widgets.prefs_dialog, "radio_toolbar_text"); break;
518 default: widget = ui_lookup_widget(ui_widgets.prefs_dialog, "radio_toolbar_imagetext"); break;
520 if (toolbar_prefs.use_gtk_default_style)
521 widget = ui_lookup_widget(ui_widgets.prefs_dialog, "radio_toolbar_style_default");
522 gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(widget), TRUE);
524 switch (toolbar_prefs.icon_size)
526 case GTK_ICON_SIZE_LARGE_TOOLBAR:
527 widget = ui_lookup_widget(ui_widgets.prefs_dialog, "radio_toolbar_large"); break;
528 case GTK_ICON_SIZE_SMALL_TOOLBAR:
529 widget = ui_lookup_widget(ui_widgets.prefs_dialog, "radio_toolbar_small"); break;
530 default: widget = ui_lookup_widget(ui_widgets.prefs_dialog, "radio_toolbar_verysmall"); break;
532 if (toolbar_prefs.use_gtk_default_icon)
533 widget = ui_lookup_widget(ui_widgets.prefs_dialog, "radio_toolbar_icon_default");
534 gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(widget), TRUE);
536 /* disable elements if toolbar is hidden */
537 on_toolbar_show_toggled(GTK_TOGGLE_BUTTON(
538 ui_lookup_widget(ui_widgets.prefs_dialog, "check_toolbar_show")), NULL);
541 /* Files settings */
542 if (file_prefs.tab_order_ltr)
543 widget = ui_lookup_widget(ui_widgets.prefs_dialog, "radio_tab_right");
544 else
545 widget = ui_lookup_widget(ui_widgets.prefs_dialog, "radio_tab_left");
546 gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(widget), TRUE);
548 widget = ui_lookup_widget(ui_widgets.prefs_dialog, "check_tab_beside");
549 gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(widget), file_prefs.tab_order_beside);
551 widget = ui_lookup_widget(ui_widgets.prefs_dialog, "combo_new_encoding");
552 ui_encodings_combo_box_set_active_encoding(GTK_COMBO_BOX(widget), file_prefs.default_new_encoding);
554 widget = ui_lookup_widget(ui_widgets.prefs_dialog, "check_open_encoding");
555 gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(widget),
556 (file_prefs.default_open_encoding >= 0) ? TRUE : FALSE);
557 on_open_encoding_toggled(GTK_TOGGLE_BUTTON(widget), NULL);
559 widget = ui_lookup_widget(ui_widgets.prefs_dialog, "combo_open_encoding");
560 if (file_prefs.default_open_encoding >= 0)
562 ui_encodings_combo_box_set_active_encoding(GTK_COMBO_BOX(widget), file_prefs.default_open_encoding);
564 else
565 ui_encodings_combo_box_set_active_encoding(GTK_COMBO_BOX(widget), GEANY_ENCODING_UTF_8);
567 widget = ui_lookup_widget(ui_widgets.prefs_dialog, "combo_eol");
568 if (file_prefs.default_eol_character >= 0 && file_prefs.default_eol_character < 3)
570 gtk_combo_box_set_active(GTK_COMBO_BOX(widget), file_prefs.default_eol_character);
572 else
573 gtk_combo_box_set_active(GTK_COMBO_BOX(widget), GEANY_DEFAULT_EOL_CHARACTER);
575 widget = ui_lookup_widget(ui_widgets.prefs_dialog, "check_trailing_spaces");
576 gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(widget), file_prefs.strip_trailing_spaces);
578 widget = ui_lookup_widget(ui_widgets.prefs_dialog, "check_new_line");
579 gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(widget), file_prefs.final_new_line);
581 widget = ui_lookup_widget(ui_widgets.prefs_dialog, "check_ensure_convert_new_lines");
582 gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(widget), file_prefs.ensure_convert_new_lines);
584 /* Editor settings */
585 widget = ui_lookup_widget(ui_widgets.prefs_dialog, "entry_toggle_mark");
586 gtk_entry_set_text(GTK_ENTRY(widget), editor_prefs.comment_toggle_mark);
588 widget = ui_lookup_widget(ui_widgets.prefs_dialog, "check_replace_tabs");
589 gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(widget), file_prefs.replace_tabs);
591 widget = ui_lookup_widget(ui_widgets.prefs_dialog, "check_indent");
592 gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(widget), editor_prefs.show_indent_guide);
594 widget = ui_lookup_widget(ui_widgets.prefs_dialog, "check_white_space");
595 gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(widget), editor_prefs.show_white_space);
597 widget = ui_lookup_widget(ui_widgets.prefs_dialog, "check_line_end");
598 gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(widget), editor_prefs.show_line_endings);
600 widget = ui_lookup_widget(ui_widgets.prefs_dialog, "check_line_numbers");
601 gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(widget), editor_prefs.show_linenumber_margin);
603 widget = ui_lookup_widget(ui_widgets.prefs_dialog, "check_markers_margin");
604 gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(widget), editor_prefs.show_markers_margin);
606 widget = ui_lookup_widget(ui_widgets.prefs_dialog, "check_scroll_stop_at_last_line");
607 gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(widget), editor_prefs.scroll_stop_at_last_line);
609 widget = ui_lookup_widget(ui_widgets.prefs_dialog, "check_line_wrapping");
610 gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(widget), editor_prefs.line_wrapping);
612 widget = ui_lookup_widget(ui_widgets.prefs_dialog, "check_complete_snippets");
613 gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(widget), editor_prefs.complete_snippets);
615 widget = ui_lookup_widget(ui_widgets.prefs_dialog, "check_xmltag");
616 gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(widget), editor_prefs.auto_close_xml_tags);
618 widget = ui_lookup_widget(ui_widgets.prefs_dialog, "check_folding");
619 gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(widget), editor_prefs.folding);
621 widget = ui_lookup_widget(ui_widgets.prefs_dialog, "check_unfold_children");
622 gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(widget), editor_prefs.unfold_all_children);
623 on_use_folding_toggled(GTK_TOGGLE_BUTTON(
624 ui_lookup_widget(ui_widgets.prefs_dialog, "check_folding")), NULL);
626 widget = ui_lookup_widget(ui_widgets.prefs_dialog, "check_disable_dnd");
627 gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(widget), editor_prefs.disable_dnd);
629 widget = ui_lookup_widget(ui_widgets.prefs_dialog, "check_smart_home");
630 gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(widget), editor_prefs.smart_home_key);
632 widget = ui_lookup_widget(ui_widgets.prefs_dialog, "check_newline_strip");
633 gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(widget), editor_prefs.newline_strip);
635 widget = ui_lookup_widget(ui_widgets.prefs_dialog, "check_indicators");
636 gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(widget), editor_prefs.use_indicators);
638 widget = ui_lookup_widget(ui_widgets.prefs_dialog, "check_auto_multiline");
639 gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(widget), editor_prefs.auto_continue_multiline);
641 widget = ui_lookup_widget(ui_widgets.prefs_dialog, "check_symbol_auto_completion");
642 gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(widget), editor_prefs.auto_complete_symbols);
644 widget = ui_lookup_widget(ui_widgets.prefs_dialog, "spin_symbollistheight");
645 gtk_spin_button_set_value(GTK_SPIN_BUTTON(widget), editor_prefs.symbolcompletion_max_height);
647 widget = ui_lookup_widget(ui_widgets.prefs_dialog, "spin_symbol_complete_chars");
648 gtk_spin_button_set_value(GTK_SPIN_BUTTON(widget), editor_prefs.symbolcompletion_min_chars);
650 widget = ui_lookup_widget(ui_widgets.prefs_dialog, "spin_line_break");
651 gtk_spin_button_set_value(GTK_SPIN_BUTTON(widget), editor_prefs.line_break_column);
653 widget = ui_lookup_widget(ui_widgets.prefs_dialog, "check_autoclose_parenthesis");
654 gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(widget),
655 (editor_prefs.autoclose_chars & GEANY_AC_PARENTHESIS));
657 widget = ui_lookup_widget(ui_widgets.prefs_dialog, "check_autoclose_cbracket");
658 gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(widget),
659 (editor_prefs.autoclose_chars & GEANY_AC_CBRACKET));
661 widget = ui_lookup_widget(ui_widgets.prefs_dialog, "check_autoclose_sbracket");
662 gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(widget),
663 (editor_prefs.autoclose_chars & GEANY_AC_SBRACKET));
665 widget = ui_lookup_widget(ui_widgets.prefs_dialog, "check_autoclose_squote");
666 gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(widget),
667 (editor_prefs.autoclose_chars & GEANY_AC_SQUOTE));
669 widget = ui_lookup_widget(ui_widgets.prefs_dialog, "check_autoclose_dquote");
670 gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(widget),
671 (editor_prefs.autoclose_chars & GEANY_AC_DQUOTE));
673 /* Tools Settings */
675 if (tool_prefs.term_cmd)
676 gtk_entry_set_text(GTK_ENTRY(ui_lookup_widget(ui_widgets.prefs_dialog, "entry_com_term")), tool_prefs.term_cmd);
678 if (tool_prefs.browser_cmd)
679 gtk_entry_set_text(GTK_ENTRY(ui_lookup_widget(ui_widgets.prefs_dialog, "entry_browser")), tool_prefs.browser_cmd);
681 if (tool_prefs.grep_cmd)
682 gtk_entry_set_text(GTK_ENTRY(ui_lookup_widget(ui_widgets.prefs_dialog, "entry_grep")), tool_prefs.grep_cmd);
685 /* Template settings */
686 widget = ui_lookup_widget(ui_widgets.prefs_dialog, "entry_template_developer");
687 gtk_entry_set_text(GTK_ENTRY(widget), template_prefs.developer);
689 widget = ui_lookup_widget(ui_widgets.prefs_dialog, "entry_template_company");
690 gtk_entry_set_text(GTK_ENTRY(widget), template_prefs.company);
692 widget = ui_lookup_widget(ui_widgets.prefs_dialog, "entry_template_mail");
693 gtk_entry_set_text(GTK_ENTRY(widget), template_prefs.mail);
695 widget = ui_lookup_widget(ui_widgets.prefs_dialog, "entry_template_initial");
696 gtk_entry_set_text(GTK_ENTRY(widget), template_prefs.initials);
698 widget = ui_lookup_widget(ui_widgets.prefs_dialog, "entry_template_version");
699 gtk_entry_set_text(GTK_ENTRY(widget), template_prefs.version);
701 widget = ui_lookup_widget(ui_widgets.prefs_dialog, "entry_template_year");
702 gtk_entry_set_text(GTK_ENTRY(widget), template_prefs.year_format);
704 widget = ui_lookup_widget(ui_widgets.prefs_dialog, "entry_template_date");
705 gtk_entry_set_text(GTK_ENTRY(widget), template_prefs.date_format);
707 widget = ui_lookup_widget(ui_widgets.prefs_dialog, "entry_template_datetime");
708 gtk_entry_set_text(GTK_ENTRY(widget), template_prefs.datetime_format);
711 /* Keybindings */
712 kb_init(&global_kb_data);
714 /* Printing */
716 GtkWidget *widget_gtk = ui_lookup_widget(ui_widgets.prefs_dialog, "radio_print_gtk");
717 if (printing_prefs.use_gtk_printing)
718 widget = widget_gtk;
719 else
720 widget = ui_lookup_widget(ui_widgets.prefs_dialog, "radio_print_external");
722 gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(widget), TRUE);
724 on_prefs_print_radio_button_toggled(GTK_TOGGLE_BUTTON(widget_gtk), NULL);
726 if (printing_prefs.external_print_cmd)
727 gtk_entry_set_text(
728 GTK_ENTRY(ui_lookup_widget(ui_widgets.prefs_dialog, "entry_print_external_cmd")),
729 printing_prefs.external_print_cmd);
731 widget = ui_lookup_widget(ui_widgets.prefs_dialog, "check_print_linenumbers");
732 gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(widget), printing_prefs.print_line_numbers);
734 widget = ui_lookup_widget(ui_widgets.prefs_dialog, "check_print_pagenumbers");
735 gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(widget), printing_prefs.print_page_numbers);
737 widget = ui_lookup_widget(ui_widgets.prefs_dialog, "check_print_pageheader");
738 gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(widget), printing_prefs.print_page_header);
739 on_prefs_print_page_header_toggled(GTK_TOGGLE_BUTTON(widget), NULL);
741 widget = ui_lookup_widget(ui_widgets.prefs_dialog, "check_print_basename");
742 gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(widget), printing_prefs.page_header_basename);
744 if (printing_prefs.page_header_datefmt)
745 gtk_entry_set_text(
746 GTK_ENTRY(ui_lookup_widget(ui_widgets.prefs_dialog, "entry_print_dateformat")),
747 printing_prefs.page_header_datefmt);
750 #ifndef HAVE_PLUGINS
751 gtk_widget_set_sensitive(ui_lookup_widget(ui_widgets.prefs_dialog, "check_plugins"), FALSE);
752 #endif
753 on_enable_plugins_toggled(GTK_TOGGLE_BUTTON( ui_lookup_widget(ui_widgets.prefs_dialog, "check_plugins")), NULL);
755 #ifdef HAVE_VTE
756 /* make VTE switch visible only when VTE is compiled in, it is hidden by default */
757 widget = ui_lookup_widget(ui_widgets.prefs_dialog, "check_vte");
758 gtk_widget_show(widget);
759 gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(widget), vte_info.load_vte);
761 /* VTE settings */
762 if (vte_info.have_vte)
764 widget = ui_lookup_widget(ui_widgets.prefs_dialog, "font_term");
765 gtk_font_button_set_font_name(GTK_FONT_BUTTON(widget), vc->font);
767 widget = ui_lookup_widget(ui_widgets.prefs_dialog, "color_fore");
768 gtk_color_button_set_color(GTK_COLOR_BUTTON(widget), &vc->colour_fore);
770 widget = ui_lookup_widget(ui_widgets.prefs_dialog, "color_back");
771 gtk_color_button_set_color(GTK_COLOR_BUTTON(widget), &vc->colour_back);
773 widget = ui_lookup_widget(ui_widgets.prefs_dialog, "spin_scrollback");
774 gtk_spin_button_set_value(GTK_SPIN_BUTTON(widget), vc->scrollback_lines);
776 widget = ui_lookup_widget(ui_widgets.prefs_dialog, "entry_shell");
777 gtk_entry_set_text(GTK_ENTRY(widget), vc->shell);
779 widget = ui_lookup_widget(ui_widgets.prefs_dialog, "check_scroll_key");
780 gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(widget), vc->scroll_on_key);
782 widget = ui_lookup_widget(ui_widgets.prefs_dialog, "check_scroll_out");
783 gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(widget), vc->scroll_on_out);
785 widget = ui_lookup_widget(ui_widgets.prefs_dialog, "check_enable_bash_keys");
786 gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(widget), vc->enable_bash_keys);
788 widget = ui_lookup_widget(ui_widgets.prefs_dialog, "check_ignore_menu_key");
789 gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(widget), vc->ignore_menu_bar_accel);
791 widget = ui_lookup_widget(ui_widgets.prefs_dialog, "check_follow_path");
792 gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(widget), vc->follow_path);
794 widget = ui_lookup_widget(ui_widgets.prefs_dialog, "check_run_in_vte");
795 gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(widget), vc->run_in_vte);
797 widget = ui_lookup_widget(ui_widgets.prefs_dialog, "check_skip_script");
798 gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(widget), vc->skip_run_script);
800 widget = ui_lookup_widget(ui_widgets.prefs_dialog, "check_cursor_blinks");
801 gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(widget), vc->cursor_blinks);
803 #endif
807 /* note: uses group index, not group id, unlike keybindings_lookup_item(). */
808 static GeanyKeyBinding *kb_index(guint gidx, guint kid)
810 GeanyKeyGroup *group;
812 group = g_ptr_array_index(keybinding_groups, gidx);
813 return keybindings_get_item(group, kid);
817 /* read the treeview shortcut fields into keybindings */
818 static void kb_update(KbData *kbdata)
820 GtkTreeModel *model = GTK_TREE_MODEL(kbdata->store);
821 GtkTreeIter child, parent;
822 guint gid = 0;
824 /* get first parent */
825 if (! gtk_tree_model_iter_children(model, &parent, NULL))
826 return;
828 /* foreach parent */
829 while (TRUE)
831 /* get first child */
832 if (! gtk_tree_model_iter_children(model, &child, &parent))
833 return;
835 /* foreach child */
836 while (TRUE)
838 guint kid;
839 gchar *str;
840 guint key;
841 GdkModifierType mods;
842 GeanyKeyBinding *kb;
844 gtk_tree_model_get(model, &child, KB_TREE_INDEX, &kid, KB_TREE_SHORTCUT, &str, -1);
845 gtk_accelerator_parse(str, &key, &mods);
846 g_free(str);
847 kb = kb_index(gid, kid);
848 if (kb->key != key || kb->mods != mods)
849 keybindings_update_combo(kb, key, mods);
851 if (! gtk_tree_model_iter_next(model, &child))
852 break;
854 if (! gtk_tree_model_iter_next(model, &parent))
855 return;
856 gid++;
862 * callbacks
864 /* note: new 'simple' prefs should use Stash code in keyfile.c */
865 static void
866 on_prefs_dialog_response(GtkDialog *dialog, gint response, gpointer user_data)
868 if (response == GTK_RESPONSE_OK || response == GTK_RESPONSE_APPLY)
870 GtkWidget *widget;
871 guint i;
872 gboolean autoclose_brackets[5];
873 gboolean old_invert_all = interface_prefs.highlighting_invert_all;
874 gboolean old_sidebar_pos = interface_prefs.sidebar_pos;
875 GeanyDocument *doc = document_get_current();
877 /* Synchronize Stash settings */
878 prefs_action(PREF_UPDATE);
880 if (interface_prefs.highlighting_invert_all != old_invert_all)
881 filetypes_reload();
883 if (interface_prefs.sidebar_pos != old_sidebar_pos)
884 ui_swap_sidebar_pos();
886 widget = ui_lookup_widget(main_widgets.window, "vpaned1");
887 gtk_orientable_set_orientation(GTK_ORIENTABLE(widget), interface_prefs.msgwin_orientation);
889 /* General settings */
890 /* startup */
891 widget = ui_lookup_widget(ui_widgets.prefs_dialog, "check_load_session");
892 prefs.load_session = gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(widget));
894 widget = ui_lookup_widget(ui_widgets.prefs_dialog, "check_project_session");
895 project_prefs.project_session = gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(widget));
897 widget = ui_lookup_widget(ui_widgets.prefs_dialog, "check_project_file_in_basedir");
898 project_prefs.project_file_in_basedir = gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(widget));
900 widget = ui_lookup_widget(ui_widgets.prefs_dialog, "check_save_win_pos");
901 prefs.save_winpos = gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(widget));
903 widget = ui_lookup_widget(ui_widgets.prefs_dialog, "check_ask_for_quit");
904 prefs.confirm_exit = gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(widget));
906 /* behaviour */
907 widget = ui_lookup_widget(ui_widgets.prefs_dialog, "check_beep");
908 prefs.beep_on_errors = gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(widget));
910 widget = ui_lookup_widget(ui_widgets.prefs_dialog, "check_switch_pages");
911 prefs.switch_to_status = gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(widget));
913 widget = ui_lookup_widget(ui_widgets.prefs_dialog, "check_suppress_status_msgs");
914 prefs.suppress_status_messages = gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(widget));
916 widget = ui_lookup_widget(ui_widgets.prefs_dialog, "check_auto_focus");
917 prefs.auto_focus = gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(widget));
919 widget = ui_lookup_widget(ui_widgets.prefs_dialog, "check_native_windows_dialogs");
920 interface_prefs.use_native_windows_dialogs =
921 gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(widget));
923 widget = ui_lookup_widget(ui_widgets.prefs_dialog, "entry_contextaction");
924 g_free(tool_prefs.context_action_cmd);
925 tool_prefs.context_action_cmd = g_strdup(gtk_entry_get_text(GTK_ENTRY(widget)));
927 project_apply_prefs(); /* project file path */
930 /* Interface settings */
931 widget = ui_lookup_widget(ui_widgets.prefs_dialog, "check_sidebar_visible");
932 ui_prefs.sidebar_visible = gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(widget));
934 widget = ui_lookup_widget(ui_widgets.prefs_dialog, "check_list_symbol");
935 interface_prefs.sidebar_symbol_visible = gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(widget));
937 widget = ui_lookup_widget(ui_widgets.prefs_dialog, "check_list_openfiles");
938 interface_prefs.sidebar_openfiles_visible = gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(widget));
940 widget = ui_lookup_widget(ui_widgets.prefs_dialog, "check_long_line");
941 editor_prefs.long_line_enabled = gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(widget));
943 widget = ui_lookup_widget(ui_widgets.prefs_dialog, "radio_long_line_line");
944 if (gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(widget)))
945 editor_prefs.long_line_type = 0;
946 else
947 /* now only the "background" radio remains */
948 editor_prefs.long_line_type = 1;
950 if (editor_prefs.long_line_column == 0)
951 editor_prefs.long_line_enabled = FALSE;
953 widget = ui_lookup_widget(ui_widgets.prefs_dialog, "check_show_notebook_tabs");
954 interface_prefs.show_notebook_tabs = gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(widget));
956 widget = ui_lookup_widget(ui_widgets.prefs_dialog, "check_show_tab_cross");
957 file_prefs.show_tab_cross = gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(widget));
959 widget = ui_lookup_widget(ui_widgets.prefs_dialog, "combo_tab_editor");
960 interface_prefs.tab_pos_editor = gtk_combo_box_get_active(GTK_COMBO_BOX(widget));
962 widget = ui_lookup_widget(ui_widgets.prefs_dialog, "combo_tab_msgwin");
963 interface_prefs.tab_pos_msgwin = gtk_combo_box_get_active(GTK_COMBO_BOX(widget));
965 widget = ui_lookup_widget(ui_widgets.prefs_dialog, "combo_tab_sidebar");
966 interface_prefs.tab_pos_sidebar = gtk_combo_box_get_active(GTK_COMBO_BOX(widget));
968 widget = ui_lookup_widget(ui_widgets.prefs_dialog, "check_statusbar_visible");
969 interface_prefs.statusbar_visible = gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(widget));
972 /* Toolbar settings */
973 widget = ui_lookup_widget(ui_widgets.prefs_dialog, "check_toolbar_show");
974 toolbar_prefs.visible = gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(widget));
975 widget = ui_lookup_widget(ui_widgets.prefs_dialog, "check_toolbar_in_menu");
976 toolbar_prefs.append_to_menu = gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(widget));
978 widget = ui_lookup_widget(ui_widgets.prefs_dialog, "radio_toolbar_style_default");
979 toolbar_prefs.use_gtk_default_style = gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(widget));
980 if (! toolbar_prefs.use_gtk_default_style)
982 widget = ui_lookup_widget(ui_widgets.prefs_dialog, "radio_toolbar_imagetext");
983 if (gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(widget)))
984 toolbar_prefs.icon_style = 2;
985 else
987 widget = ui_lookup_widget(ui_widgets.prefs_dialog, "radio_toolbar_image");
988 if (gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(widget)))
989 toolbar_prefs.icon_style = 0;
990 else
991 /* now only the text only radio remains, so set text only */
992 toolbar_prefs.icon_style = 1;
996 widget = ui_lookup_widget(ui_widgets.prefs_dialog, "radio_toolbar_icon_default");
997 toolbar_prefs.use_gtk_default_icon = gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(widget));
998 if (! toolbar_prefs.use_gtk_default_icon)
999 { toolbar_prefs.icon_size = GTK_ICON_SIZE_LARGE_TOOLBAR;
1000 widget = ui_lookup_widget(ui_widgets.prefs_dialog, "radio_toolbar_large");
1001 if (gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(widget)))
1002 toolbar_prefs.icon_size = GTK_ICON_SIZE_LARGE_TOOLBAR;
1003 else
1005 widget = ui_lookup_widget(ui_widgets.prefs_dialog, "radio_toolbar_small");
1006 if (gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(widget)))
1007 toolbar_prefs.icon_size = GTK_ICON_SIZE_SMALL_TOOLBAR;
1008 else
1009 toolbar_prefs.icon_size = GTK_ICON_SIZE_MENU;
1013 /* Files settings */
1014 widget = ui_lookup_widget(ui_widgets.prefs_dialog, "radio_tab_right");
1015 file_prefs.tab_order_ltr = gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(widget));
1017 widget = ui_lookup_widget(ui_widgets.prefs_dialog, "check_tab_beside");
1018 file_prefs.tab_order_beside = gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(widget));
1020 widget = ui_lookup_widget(ui_widgets.prefs_dialog, "combo_new_encoding");
1021 file_prefs.default_new_encoding = ui_encodings_combo_box_get_active_encoding(GTK_COMBO_BOX(widget));
1023 widget = ui_lookup_widget(ui_widgets.prefs_dialog, "check_open_encoding");
1024 if (gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(widget)))
1026 widget = ui_lookup_widget(ui_widgets.prefs_dialog, "combo_open_encoding");
1027 file_prefs.default_open_encoding = ui_encodings_combo_box_get_active_encoding(GTK_COMBO_BOX(widget));
1029 else
1030 file_prefs.default_open_encoding = -1;
1032 widget = ui_lookup_widget(ui_widgets.prefs_dialog, "combo_eol");
1033 file_prefs.default_eol_character = gtk_combo_box_get_active(GTK_COMBO_BOX(widget));
1035 widget = ui_lookup_widget(ui_widgets.prefs_dialog, "check_trailing_spaces");
1036 file_prefs.strip_trailing_spaces = gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(widget));
1038 widget = ui_lookup_widget(ui_widgets.prefs_dialog, "check_new_line");
1039 file_prefs.final_new_line = gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(widget));
1041 widget = ui_lookup_widget(ui_widgets.prefs_dialog, "check_ensure_convert_new_lines");
1042 file_prefs.ensure_convert_new_lines = gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(widget));
1044 widget = ui_lookup_widget(ui_widgets.prefs_dialog, "check_replace_tabs");
1045 file_prefs.replace_tabs = gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(widget));
1048 /* Editor settings */
1049 widget = ui_lookup_widget(ui_widgets.prefs_dialog, "entry_toggle_mark");
1050 SETPTR(editor_prefs.comment_toggle_mark,
1051 gtk_editable_get_chars(GTK_EDITABLE(widget), 0, -1));
1053 widget = ui_lookup_widget(ui_widgets.prefs_dialog, "spin_long_line");
1054 /* note: use stash for new code - it updates spin buttons itself */
1055 gtk_spin_button_update(GTK_SPIN_BUTTON(widget));
1056 editor_prefs.long_line_column = gtk_spin_button_get_value_as_int(GTK_SPIN_BUTTON(widget));
1058 widget = ui_lookup_widget(ui_widgets.prefs_dialog, "check_folding");
1059 editor_prefs.folding = gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(widget));
1060 ui_update_fold_items();
1062 widget = ui_lookup_widget(ui_widgets.prefs_dialog, "check_unfold_children");
1063 editor_prefs.unfold_all_children = gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(widget));
1065 widget = ui_lookup_widget(ui_widgets.prefs_dialog, "check_indent");
1066 editor_prefs.show_indent_guide = gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(widget));
1068 widget = ui_lookup_widget(ui_widgets.prefs_dialog, "check_white_space");
1069 editor_prefs.show_white_space = gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(widget));
1071 widget = ui_lookup_widget(ui_widgets.prefs_dialog, "check_line_end");
1072 editor_prefs.show_line_endings = gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(widget));
1074 widget = ui_lookup_widget(ui_widgets.prefs_dialog, "check_line_numbers");
1075 editor_prefs.show_linenumber_margin = gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(widget));
1077 widget = ui_lookup_widget(ui_widgets.prefs_dialog, "check_markers_margin");
1078 editor_prefs.show_markers_margin = gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(widget));
1080 widget = ui_lookup_widget(ui_widgets.prefs_dialog, "check_scroll_stop_at_last_line");
1081 editor_prefs.scroll_stop_at_last_line = gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(widget));
1083 widget = ui_lookup_widget(ui_widgets.prefs_dialog, "check_line_wrapping");
1084 editor_prefs.line_wrapping = gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(widget));
1086 widget = ui_lookup_widget(ui_widgets.prefs_dialog, "check_complete_snippets");
1087 editor_prefs.complete_snippets = gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(widget));
1089 widget = ui_lookup_widget(ui_widgets.prefs_dialog, "check_xmltag");
1090 editor_prefs.auto_close_xml_tags = gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(widget));
1092 widget = ui_lookup_widget(ui_widgets.prefs_dialog, "check_indicators");
1093 editor_prefs.use_indicators = gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(widget));
1095 widget = ui_lookup_widget(ui_widgets.prefs_dialog, "check_disable_dnd");
1096 editor_prefs.disable_dnd = gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(widget));
1098 widget = ui_lookup_widget(ui_widgets.prefs_dialog, "check_smart_home");
1099 editor_prefs.smart_home_key = gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(widget));
1101 widget = ui_lookup_widget(ui_widgets.prefs_dialog, "check_newline_strip");
1102 editor_prefs.newline_strip = gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(widget));
1104 widget = ui_lookup_widget(ui_widgets.prefs_dialog, "check_auto_multiline");
1105 editor_prefs.auto_continue_multiline = gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(widget));
1107 widget = ui_lookup_widget(ui_widgets.prefs_dialog, "check_symbol_auto_completion");
1108 editor_prefs.auto_complete_symbols = gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(widget));
1110 widget = ui_lookup_widget(ui_widgets.prefs_dialog, "spin_symbol_complete_chars");
1111 gtk_spin_button_update(GTK_SPIN_BUTTON(widget));
1112 editor_prefs.symbolcompletion_min_chars = gtk_spin_button_get_value_as_int(GTK_SPIN_BUTTON(widget));
1114 widget = ui_lookup_widget(ui_widgets.prefs_dialog, "spin_symbollistheight");
1115 gtk_spin_button_update(GTK_SPIN_BUTTON(widget));
1116 editor_prefs.symbolcompletion_max_height = gtk_spin_button_get_value_as_int(GTK_SPIN_BUTTON(widget));
1118 widget = ui_lookup_widget(ui_widgets.prefs_dialog, "spin_line_break");
1119 gtk_spin_button_update(GTK_SPIN_BUTTON(widget));
1120 editor_prefs.line_break_column = gtk_spin_button_get_value_as_int(GTK_SPIN_BUTTON(widget));
1122 widget = ui_lookup_widget(ui_widgets.prefs_dialog, "check_autoclose_parenthesis");
1123 autoclose_brackets[0] = gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(widget));
1125 widget = ui_lookup_widget(ui_widgets.prefs_dialog, "check_autoclose_cbracket");
1126 autoclose_brackets[1] = gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(widget));
1128 widget = ui_lookup_widget(ui_widgets.prefs_dialog, "check_autoclose_sbracket");
1129 autoclose_brackets[2] = gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(widget));
1131 widget = ui_lookup_widget(ui_widgets.prefs_dialog, "check_autoclose_squote");
1132 autoclose_brackets[3] = gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(widget));
1134 widget = ui_lookup_widget(ui_widgets.prefs_dialog, "check_autoclose_dquote");
1135 autoclose_brackets[4] = gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(widget));
1137 editor_prefs.autoclose_chars =
1138 (autoclose_brackets[0] ? GEANY_AC_PARENTHESIS : 0u)
1139 | (autoclose_brackets[1] ? GEANY_AC_CBRACKET : 0u)
1140 | (autoclose_brackets[2] ? GEANY_AC_SBRACKET : 0u)
1141 | (autoclose_brackets[3] ? GEANY_AC_SQUOTE : 0u)
1142 | (autoclose_brackets[4] ? GEANY_AC_DQUOTE : 0u);
1144 /* Tools Settings */
1146 widget = ui_lookup_widget(ui_widgets.prefs_dialog, "entry_com_term");
1147 g_free(tool_prefs.term_cmd);
1148 tool_prefs.term_cmd = g_strdup(gtk_entry_get_text(GTK_ENTRY(widget)));
1150 widget = ui_lookup_widget(ui_widgets.prefs_dialog, "entry_browser");
1151 g_free(tool_prefs.browser_cmd);
1152 tool_prefs.browser_cmd = g_strdup(gtk_entry_get_text(GTK_ENTRY(widget)));
1154 widget = ui_lookup_widget(ui_widgets.prefs_dialog, "entry_grep");
1155 g_free(tool_prefs.grep_cmd);
1156 tool_prefs.grep_cmd = g_strdup(gtk_entry_get_text(GTK_ENTRY(widget)));
1159 /* Template settings */
1160 widget = ui_lookup_widget(ui_widgets.prefs_dialog, "entry_template_developer");
1161 g_free(template_prefs.developer);
1162 template_prefs.developer = g_strdup(gtk_entry_get_text(GTK_ENTRY(widget)));
1164 widget = ui_lookup_widget(ui_widgets.prefs_dialog, "entry_template_company");
1165 g_free(template_prefs.company);
1166 template_prefs.company = g_strdup(gtk_entry_get_text(GTK_ENTRY(widget)));
1168 widget = ui_lookup_widget(ui_widgets.prefs_dialog, "entry_template_mail");
1169 g_free(template_prefs.mail);
1170 template_prefs.mail = g_strdup(gtk_entry_get_text(GTK_ENTRY(widget)));
1172 widget = ui_lookup_widget(ui_widgets.prefs_dialog, "entry_template_initial");
1173 g_free(template_prefs.initials);
1174 template_prefs.initials = g_strdup(gtk_entry_get_text(GTK_ENTRY(widget)));
1176 widget = ui_lookup_widget(ui_widgets.prefs_dialog, "entry_template_version");
1177 g_free(template_prefs.version);
1178 template_prefs.version = g_strdup(gtk_entry_get_text(GTK_ENTRY(widget)));
1180 widget = ui_lookup_widget(ui_widgets.prefs_dialog, "entry_template_year");
1181 g_free(template_prefs.year_format);
1182 template_prefs.year_format = g_strdup(gtk_entry_get_text(GTK_ENTRY(widget)));
1184 widget = ui_lookup_widget(ui_widgets.prefs_dialog, "entry_template_date");
1185 g_free(template_prefs.date_format);
1186 template_prefs.date_format = g_strdup(gtk_entry_get_text(GTK_ENTRY(widget)));
1188 widget = ui_lookup_widget(ui_widgets.prefs_dialog, "entry_template_datetime");
1189 g_free(template_prefs.datetime_format);
1190 template_prefs.datetime_format = g_strdup(gtk_entry_get_text(GTK_ENTRY(widget)));
1193 /* Keybindings */
1194 if (global_kb_data.edited)
1196 kb_update(&global_kb_data);
1197 tools_create_insert_custom_command_menu_items();
1198 keybindings_write_to_file();
1199 #ifdef MAC_INTEGRATION
1200 /* Force re-syncing the menubar to update displayed keybindings. */
1201 gtkosx_application_sync_menubar(gtkosx_application_get());
1202 #endif
1205 /* Printing */
1206 widget = ui_lookup_widget(ui_widgets.prefs_dialog, "radio_print_gtk");
1207 printing_prefs.use_gtk_printing = gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(widget));
1209 widget = ui_lookup_widget(ui_widgets.prefs_dialog, "entry_print_external_cmd");
1210 g_free(printing_prefs.external_print_cmd);
1211 printing_prefs.external_print_cmd = g_strdup(gtk_entry_get_text(GTK_ENTRY(widget)));
1213 widget = ui_lookup_widget(ui_widgets.prefs_dialog, "check_print_linenumbers");
1214 printing_prefs.print_line_numbers = gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(widget));
1216 widget = ui_lookup_widget(ui_widgets.prefs_dialog, "check_print_pagenumbers");
1217 printing_prefs.print_page_numbers = gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(widget));
1219 widget = ui_lookup_widget(ui_widgets.prefs_dialog, "check_print_pageheader");
1220 printing_prefs.print_page_header = gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(widget));
1222 widget = ui_lookup_widget(ui_widgets.prefs_dialog, "check_print_basename");
1223 printing_prefs.page_header_basename = gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(widget));
1225 widget = ui_lookup_widget(ui_widgets.prefs_dialog, "entry_print_dateformat");
1226 g_free(printing_prefs.page_header_datefmt);
1227 printing_prefs.page_header_datefmt = g_strdup(gtk_entry_get_text(GTK_ENTRY(widget)));
1230 #ifdef HAVE_VTE
1231 widget = ui_lookup_widget(ui_widgets.prefs_dialog, "check_vte");
1232 vte_info.load_vte = gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(widget));
1234 /* VTE settings */
1235 if (vte_info.have_vte)
1237 widget = ui_lookup_widget(ui_widgets.prefs_dialog, "spin_scrollback");
1238 gtk_spin_button_update(GTK_SPIN_BUTTON(widget));
1239 vc->scrollback_lines = gtk_spin_button_get_value_as_int(GTK_SPIN_BUTTON(widget));
1241 widget = ui_lookup_widget(ui_widgets.prefs_dialog, "entry_shell");
1242 g_free(vc->shell);
1243 vc->shell = g_strdup(gtk_entry_get_text(GTK_ENTRY(widget)));
1245 widget = ui_lookup_widget(ui_widgets.prefs_dialog, "check_scroll_key");
1246 vc->scroll_on_key = gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(widget));
1248 widget = ui_lookup_widget(ui_widgets.prefs_dialog, "check_scroll_out");
1249 vc->scroll_on_out = gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(widget));
1251 widget = ui_lookup_widget(ui_widgets.prefs_dialog, "check_enable_bash_keys");
1252 vc->enable_bash_keys = gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(widget));
1254 widget = ui_lookup_widget(ui_widgets.prefs_dialog, "check_ignore_menu_key");
1255 vc->ignore_menu_bar_accel = gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(widget));
1257 widget = ui_lookup_widget(ui_widgets.prefs_dialog, "check_follow_path");
1258 vc->follow_path = gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(widget));
1260 widget = ui_lookup_widget(ui_widgets.prefs_dialog, "check_run_in_vte");
1261 vc->run_in_vte = gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(widget));
1263 widget = ui_lookup_widget(ui_widgets.prefs_dialog, "check_skip_script");
1264 vc->skip_run_script = gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(widget));
1266 widget = ui_lookup_widget(ui_widgets.prefs_dialog, "check_cursor_blinks");
1267 vc->cursor_blinks = gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(widget));
1269 vte_apply_user_settings();
1271 #endif
1273 /* apply the changes made */
1274 ui_statusbar_showhide(interface_prefs.statusbar_visible);
1275 sidebar_openfiles_update_all(); /* to update if full path setting has changed */
1276 toolbar_apply_settings();
1277 toolbar_update_ui();
1278 toolbar_show_hide();
1279 ui_sidebar_show_hide();
1280 gtk_notebook_set_show_tabs(GTK_NOTEBOOK(main_widgets.notebook), interface_prefs.show_notebook_tabs);
1282 gtk_notebook_set_tab_pos(GTK_NOTEBOOK(main_widgets.notebook), interface_prefs.tab_pos_editor);
1283 gtk_notebook_set_tab_pos(GTK_NOTEBOOK(msgwindow.notebook), interface_prefs.tab_pos_msgwin);
1284 gtk_notebook_set_tab_pos(GTK_NOTEBOOK(main_widgets.sidebar_notebook), interface_prefs.tab_pos_sidebar);
1286 /* re-colourise all open documents, if tab width or long line settings have changed */
1287 for (i = 0; i < documents_array->len; i++)
1289 if (documents[i]->is_valid)
1291 editor_apply_update_prefs(documents[i]->editor);
1292 if (! editor_prefs.folding)
1293 editor_unfold_all(documents[i]->editor);
1296 ui_document_show_hide(NULL);
1297 ui_update_view_editor_menu_items();
1299 /* various preferences */
1300 ui_save_buttons_toggle((doc != NULL) ? doc->changed : FALSE);
1301 msgwin_show_hide_tabs();
1302 ui_update_statusbar(doc, -1);
1304 /* store all settings */
1305 configuration_save();
1308 if (response == GTK_RESPONSE_HELP)
1310 open_preferences_help();
1312 else if (response != GTK_RESPONSE_APPLY)
1314 gtk_tree_store_clear(global_kb_data.store);
1315 gtk_widget_hide(GTK_WIDGET(dialog));
1320 static void on_color_button_choose_cb(GtkColorButton *widget, gpointer user_data)
1322 GdkColor color;
1324 gtk_color_button_get_color(widget, &color);
1325 SETPTR(editor_prefs.long_line_color, utils_get_hex_from_color(&color));
1329 static void on_prefs_font_choosed(GtkFontButton *widget, gpointer user_data)
1331 const gchar *fontbtn = gtk_font_button_get_font_name(widget);
1332 guint i;
1334 switch (GPOINTER_TO_INT(user_data))
1336 case 1:
1338 if (strcmp(fontbtn, interface_prefs.tagbar_font) == 0)
1339 break;
1341 SETPTR(interface_prefs.tagbar_font, g_strdup(fontbtn));
1342 for (i = 0; i < documents_array->len; i++)
1344 GeanyDocument *doc = documents[i];
1346 if (documents[i]->is_valid && GTK_IS_WIDGET(doc->priv->tag_tree))
1347 ui_widget_modify_font_from_string(doc->priv->tag_tree,
1348 interface_prefs.tagbar_font);
1350 if (GTK_IS_WIDGET(tv.default_tag_tree))
1351 ui_widget_modify_font_from_string(tv.default_tag_tree, interface_prefs.tagbar_font);
1352 ui_widget_modify_font_from_string(tv.tree_openfiles, interface_prefs.tagbar_font);
1353 break;
1355 case 2:
1357 if (strcmp(fontbtn, interface_prefs.msgwin_font) == 0)
1358 break;
1359 SETPTR(interface_prefs.msgwin_font, g_strdup(fontbtn));
1360 ui_widget_modify_font_from_string(msgwindow.tree_compiler, interface_prefs.msgwin_font);
1361 ui_widget_modify_font_from_string(msgwindow.tree_msg, interface_prefs.msgwin_font);
1362 ui_widget_modify_font_from_string(msgwindow.tree_status, interface_prefs.msgwin_font);
1363 ui_widget_modify_font_from_string(msgwindow.scribble, interface_prefs.msgwin_font);
1364 break;
1366 case 3:
1368 ui_set_editor_font(fontbtn);
1369 break;
1375 static void kb_change_iter_shortcut(KbData *kbdata, GtkTreeIter *iter, const gchar *new_text)
1377 guint lkey;
1378 GdkModifierType lmods;
1380 gtk_accelerator_parse(new_text, &lkey, &lmods);
1382 if (kb_find_duplicate(kbdata->store, ui_widgets.prefs_dialog, iter, lkey, lmods, new_text))
1383 return;
1385 /* set the values here, because of the above check, setting it in
1386 * gtk_accelerator_parse would return a wrong key combination if it is duplicate */
1387 kb_set_shortcut(kbdata->store, iter, lkey, lmods);
1389 kbdata->edited = TRUE;
1393 static void kb_cell_edited_cb(GtkCellRendererText *cellrenderertext,
1394 gchar *path, gchar *new_text, KbData *kbdata)
1396 if (path != NULL && new_text != NULL)
1398 GtkTreeIter iter;
1400 gtk_tree_model_get_iter_from_string(GTK_TREE_MODEL(kbdata->store), &iter, path);
1401 if (gtk_tree_model_iter_has_child(GTK_TREE_MODEL(kbdata->store), &iter))
1402 return; /* ignore group items */
1404 kb_change_iter_shortcut(kbdata, &iter, new_text);
1409 static gboolean kb_grab_key_dialog_key_press_cb(GtkWidget *dialog, GdkEventKey *event, GtkLabel *label)
1411 gchar *str;
1412 guint state;
1414 g_return_val_if_fail(GTK_IS_LABEL(label), FALSE);
1416 state = keybindings_get_modifiers(event->state);
1418 if (event->keyval == GDK_Escape)
1419 return FALSE; /* close the dialog, don't allow escape when detecting keybindings. */
1421 str = gtk_accelerator_name(event->keyval, state);
1423 gtk_label_set_text(label, str);
1424 g_free(str);
1426 return TRUE;
1430 /* test if the entered key combination is already used
1431 * returns true if cancelling duplicate */
1432 static gboolean kb_find_duplicate(GtkTreeStore *store, GtkWidget *parent, GtkTreeIter *old_iter,
1433 guint key, GdkModifierType mods, const gchar *shortcut)
1435 GtkTreeModel *model = GTK_TREE_MODEL(store);
1436 GtkTreeIter parent_iter;
1437 gchar *kb_str;
1438 guint kb_key;
1439 GdkModifierType kb_mods;
1441 /* allow duplicate if there is no key combination */
1442 if (key == 0 && mods == 0)
1443 return FALSE;
1445 /* don't check if the new keybinding is the same as the old one */
1446 gtk_tree_model_get(model, old_iter, KB_TREE_SHORTCUT, &kb_str, -1);
1447 if (kb_str)
1449 gtk_accelerator_parse(kb_str, &kb_key, &kb_mods);
1450 g_free(kb_str);
1451 if (key == kb_key && mods == kb_mods)
1452 return FALSE;
1455 if (! gtk_tree_model_get_iter_first(model, &parent_iter))
1456 return FALSE;
1457 do /* foreach top level */
1459 GtkTreeIter iter;
1461 if (! gtk_tree_model_iter_children(model, &iter, &parent_iter))
1462 continue;
1463 do /* foreach children */
1465 gtk_tree_model_get(model, &iter, KB_TREE_SHORTCUT, &kb_str, -1);
1466 if (! kb_str)
1467 continue;
1469 gtk_accelerator_parse(kb_str, &kb_key, &kb_mods);
1470 g_free(kb_str);
1471 /* search another item with the same key and modifiers */
1472 if (kb_key == key && kb_mods == mods)
1474 gchar *label;
1475 gint ret;
1477 gtk_tree_model_get(model, &iter, KB_TREE_ACTION, &label, -1);
1478 ret = dialogs_show_prompt(parent,
1479 _("_Allow"), GTK_RESPONSE_APPLY,
1480 GTK_STOCK_CANCEL, GTK_RESPONSE_NO,
1481 _("_Override"), GTK_RESPONSE_YES,
1482 _("Override that keybinding?"),
1483 _("The combination '%s' is already used for \"%s\"."),
1484 shortcut, label);
1486 g_free(label);
1488 if (ret == GTK_RESPONSE_YES)
1490 kb_set_shortcut(store, &iter, 0, 0); /* clear shortcut */
1491 /* carry on looking for other duplicates if overriding */
1492 continue;
1494 return ret != GTK_RESPONSE_APPLY;
1497 while (gtk_tree_model_iter_next(model, &iter));
1499 while (gtk_tree_model_iter_next(model, &parent_iter));
1501 return FALSE;
1505 static void on_toolbar_show_toggled(GtkToggleButton *togglebutton, gpointer user_data)
1507 gboolean sens = gtk_toggle_button_get_active(togglebutton);
1509 gtk_widget_set_sensitive(
1510 ui_lookup_widget(ui_widgets.prefs_dialog, "frame_toolbar_style"), sens);
1511 gtk_widget_set_sensitive(
1512 ui_lookup_widget(ui_widgets.prefs_dialog, "frame_toolbar_icon"), sens);
1513 gtk_widget_set_sensitive(
1514 ui_lookup_widget(ui_widgets.prefs_dialog, "button_customize_toolbar"), sens);
1515 gtk_widget_set_sensitive(
1516 ui_lookup_widget(ui_widgets.prefs_dialog, "check_toolbar_in_menu"), sens);
1520 static void on_show_notebook_tabs_toggled(GtkToggleButton *togglebutton, gpointer user_data)
1522 gboolean sens = gtk_toggle_button_get_active(togglebutton);
1524 /* tab placement only enabled when tabs are visible */
1525 gtk_widget_set_sensitive(ui_lookup_widget(ui_widgets.prefs_dialog, "combo_tab_editor"), sens);
1526 gtk_widget_set_sensitive(ui_lookup_widget(ui_widgets.prefs_dialog, "check_show_tab_cross"), sens);
1530 static void on_use_folding_toggled(GtkToggleButton *togglebutton, gpointer user_data)
1532 gboolean sens = gtk_toggle_button_get_active(togglebutton);
1534 gtk_widget_set_sensitive(ui_lookup_widget(ui_widgets.prefs_dialog, "check_unfold_children"), sens);
1538 static void on_enable_plugins_toggled(GtkToggleButton *togglebutton, gpointer user_data)
1540 gboolean sens = gtk_toggle_button_get_active(togglebutton);
1542 gtk_widget_set_sensitive(ui_lookup_widget(ui_widgets.prefs_dialog, "extra_plugin_path_entry"), sens);
1543 gtk_widget_set_sensitive(ui_lookup_widget(ui_widgets.prefs_dialog, "extra_plugin_path_button"), sens);
1547 static void on_open_encoding_toggled(GtkToggleButton *togglebutton, gpointer user_data)
1549 gboolean sens = gtk_toggle_button_get_active(togglebutton);
1551 gtk_widget_set_sensitive(ui_lookup_widget(ui_widgets.prefs_dialog, "eventbox3"), sens);
1552 gtk_widget_set_sensitive(ui_lookup_widget(ui_widgets.prefs_dialog, "label_open_encoding"), sens);
1556 static void on_sidebar_visible_toggled(GtkToggleButton *togglebutton, gpointer user_data)
1558 gboolean sens = gtk_toggle_button_get_active(togglebutton);
1560 gtk_widget_set_sensitive(ui_lookup_widget(ui_widgets.prefs_dialog, "box_sidebar_visible_children"), sens);
1564 static void on_prefs_print_radio_button_toggled(GtkToggleButton *togglebutton, gpointer user_data)
1566 gboolean sens = gtk_toggle_button_get_active(togglebutton);
1568 gtk_widget_set_sensitive(ui_lookup_widget(ui_widgets.prefs_dialog, "vbox29"), sens);
1569 gtk_widget_set_sensitive(ui_lookup_widget(ui_widgets.prefs_dialog, "hbox9"), ! sens);
1573 static void on_prefs_print_page_header_toggled(GtkToggleButton *togglebutton, gpointer user_data)
1575 gboolean sens = gtk_toggle_button_get_active(togglebutton);
1577 gtk_widget_set_sensitive(ui_lookup_widget(ui_widgets.prefs_dialog, "check_print_basename"), sens);
1578 gtk_widget_set_sensitive(ui_lookup_widget(ui_widgets.prefs_dialog, "entry_print_dateformat"), sens);
1582 static void open_preferences_help(void)
1584 gchar *uri;
1585 const gchar *label, *suffix = NULL;
1586 GtkNotebook *notebook = GTK_NOTEBOOK(
1587 ui_lookup_widget(ui_widgets.prefs_dialog, "notebook2"));
1588 gint page_nr = gtk_notebook_get_current_page(notebook);
1589 GtkWidget *page = gtk_notebook_get_nth_page(notebook, page_nr);
1591 label = gtk_notebook_get_tab_label_text(notebook, page);
1593 /* TODO Find a better way to map the current notebook page to the
1594 * corresponding chapter in the documentation, comparing translatable
1595 * strings is easy to break. Maybe attach an identifying string to the
1596 * tab label object. */
1597 if (utils_str_equal(label, _("General")))
1598 suffix = "#general-startup-preferences";
1599 else if (utils_str_equal(label, _("Interface")))
1600 suffix = "#interface-preferences";
1601 else if (utils_str_equal(label, _("Toolbar")))
1602 suffix = "#toolbar-preferences";
1603 else if (utils_str_equal(label, _("Editor")))
1604 suffix = "#editor-features-preferences";
1605 else if (utils_str_equal(label, _("Files")))
1606 suffix = "#files-preferences";
1607 else if (utils_str_equal(label, _("Tools")))
1608 suffix = "#tools-preferences";
1609 else if (utils_str_equal(label, _("Templates")))
1610 suffix = "#template-preferences";
1611 else if (utils_str_equal(label, _("Keybindings")))
1612 suffix = "#keybinding-preferences";
1613 else if (utils_str_equal(label, _("Printing")))
1614 suffix = "#printing-preferences";
1615 else if (utils_str_equal(label, _("Various")))
1616 suffix = "#various-preferences";
1617 else if (utils_str_equal(label, _("Terminal")))
1618 suffix = "#terminal-vte-preferences";
1620 uri = utils_get_help_url(suffix);
1621 utils_open_browser(uri);
1622 g_free(uri);
1626 static gboolean prefs_dialog_key_press_response_cb(GtkWidget *dialog, GdkEventKey *event,
1627 gpointer data)
1629 GeanyKeyBinding *kb = keybindings_lookup_item(GEANY_KEY_GROUP_HELP, GEANY_KEYS_HELP_HELP);
1631 if (keybindings_check_event(event, kb))
1633 open_preferences_help();
1634 return TRUE;
1636 return FALSE;
1640 static void list_store_append_text(GtkListStore *list, const gchar *text)
1642 GtkTreeIter iter;
1644 gtk_list_store_append(list, &iter);
1645 gtk_list_store_set(list, &iter, 0, text, -1);
1649 void prefs_show_dialog(void)
1651 if (ui_widgets.prefs_dialog == NULL)
1653 GtkListStore *eol_list;
1654 GtkWidget *label;
1656 ui_widgets.prefs_dialog = create_prefs_dialog();
1657 gtk_widget_set_name(ui_widgets.prefs_dialog, "GeanyPrefsDialog");
1658 gtk_window_set_transient_for(GTK_WINDOW(ui_widgets.prefs_dialog), GTK_WINDOW(main_widgets.window));
1660 /* init the file encoding combo boxes */
1662 struct {
1663 const gchar *combo, *renderer;
1664 } names[] = {
1665 { "combo_new_encoding", "combo_new_encoding_renderer" },
1666 { "combo_open_encoding", "combo_open_encoding_renderer" }
1668 guint i;
1669 GtkTreeStore *encoding_list = encodings_encoding_store_new(FALSE);
1671 for (i = 0; i < G_N_ELEMENTS(names); i++)
1673 GtkWidget *combo = ui_lookup_widget(ui_widgets.prefs_dialog, names[i].combo);
1675 gtk_cell_layout_set_cell_data_func(GTK_CELL_LAYOUT(combo),
1676 ui_builder_get_object(names[i].renderer),
1677 encodings_encoding_store_cell_data_func, NULL, NULL);
1678 gtk_combo_box_set_model(GTK_COMBO_BOX(combo), GTK_TREE_MODEL(encoding_list));
1680 g_object_unref(encoding_list);
1683 /* init the eol character combo box */
1684 eol_list = ui_builder_get_object("eol_list");
1685 list_store_append_text(eol_list, utils_get_eol_name(SC_EOL_CRLF));
1686 list_store_append_text(eol_list, utils_get_eol_name(SC_EOL_CR));
1687 list_store_append_text(eol_list, utils_get_eol_name(SC_EOL_LF));
1690 /* add manually GeanyWrapLabels because they can't be added with Glade */
1691 /* page Tools */
1692 label = geany_wrap_label_new(_("Enter tool paths below. Tools you do not need can be left blank."));
1693 gtk_widget_show(label);
1694 gtk_box_pack_start(GTK_BOX(ui_lookup_widget(ui_widgets.prefs_dialog, "vbox33")),
1695 label, FALSE, TRUE, 5);
1696 /* page Templates */
1697 label = geany_wrap_label_new(_("Set the information to be used in templates. See the documentation for details."));
1698 gtk_widget_show(label);
1699 gtk_box_pack_start(GTK_BOX(ui_lookup_widget(ui_widgets.prefs_dialog, "vbox31")),
1700 label, FALSE, TRUE, 5);
1701 /* page Keybindings */
1702 label = geany_wrap_label_new(_("Here you can change keyboard shortcuts for various actions. Select one and press the Change button to enter a new shortcut, or double click on an action to edit the string representation of the shortcut directly."));
1703 gtk_widget_show(label);
1704 gtk_box_pack_start(GTK_BOX(ui_lookup_widget(ui_widgets.prefs_dialog, "vbox32")),
1705 label, FALSE, TRUE, 5);
1706 /* page Editor->Indentation */
1707 label = geany_wrap_label_new(_("<i>Warning: these settings are overridden by the current project. See <b>Project->Properties</b>.</i>"));
1708 gtk_widget_show(label);
1709 gtk_label_set_use_markup(GTK_LABEL(label), TRUE);
1710 gtk_misc_set_padding(GTK_MISC(label), 6, 0);
1711 gtk_box_pack_start(GTK_BOX(ui_lookup_widget(ui_widgets.prefs_dialog,
1712 "label_project_indent_warning")), label, FALSE, TRUE, 5);
1714 /* add the clear icon to GtkEntry widgets in the dialog */
1716 const gchar *names[] = {
1717 "startup_path_entry",
1718 "project_file_path_entry",
1719 "extra_plugin_path_entry",
1720 "entry_toggle_mark",
1721 /* "entry_com_make", */
1722 "entry_com_term",
1723 "entry_browser",
1724 "entry_grep",
1725 "entry_contextaction",
1726 "entry_template_developer",
1727 "entry_template_initial",
1728 "entry_template_mail",
1729 "entry_template_company",
1730 "entry_template_version",
1731 "entry_template_year",
1732 "entry_template_date",
1733 "entry_template_datetime",
1734 "entry_print_external_cmd",
1735 "entry_print_dateformat"};
1736 const gchar **name;
1738 foreach_c_array(name, names, G_N_ELEMENTS(names))
1739 ui_entry_add_clear_icon(GTK_ENTRY(ui_lookup_widget(ui_widgets.prefs_dialog, *name)));
1742 /* page Various */
1743 various_treeview = GTK_TREE_VIEW(ui_lookup_widget(ui_widgets.prefs_dialog,
1744 "various_treeview"));
1745 stash_tree_setup(pref_groups, various_treeview);
1747 #ifdef HAVE_VTE
1748 vte_append_preferences_tab();
1749 #endif
1751 #ifndef G_OS_WIN32
1752 gtk_widget_hide(ui_lookup_widget(ui_widgets.prefs_dialog, "check_native_windows_dialogs"));
1753 #endif
1754 ui_setup_open_button_callback(ui_lookup_widget(ui_widgets.prefs_dialog, "startup_path_button"), NULL,
1755 GTK_FILE_CHOOSER_ACTION_SELECT_FOLDER, GTK_ENTRY(ui_lookup_widget(ui_widgets.prefs_dialog, "startup_path_entry")));
1756 ui_setup_open_button_callback(ui_lookup_widget(ui_widgets.prefs_dialog, "extra_plugin_path_button"), NULL,
1757 GTK_FILE_CHOOSER_ACTION_SELECT_FOLDER, GTK_ENTRY(ui_lookup_widget(ui_widgets.prefs_dialog, "extra_plugin_path_entry")));
1759 g_signal_connect(ui_widgets.prefs_dialog, "response",
1760 G_CALLBACK(on_prefs_dialog_response), NULL);
1761 g_signal_connect(ui_widgets.prefs_dialog, "delete-event",
1762 G_CALLBACK(gtk_widget_hide_on_delete), NULL);
1764 g_signal_connect(ui_lookup_widget(ui_widgets.prefs_dialog, "tagbar_font"),
1765 "font-set", G_CALLBACK(on_prefs_font_choosed), GINT_TO_POINTER(1));
1766 g_signal_connect(ui_lookup_widget(ui_widgets.prefs_dialog, "msgwin_font"),
1767 "font-set", G_CALLBACK(on_prefs_font_choosed), GINT_TO_POINTER(2));
1768 g_signal_connect(ui_lookup_widget(ui_widgets.prefs_dialog, "editor_font"),
1769 "font-set", G_CALLBACK(on_prefs_font_choosed), GINT_TO_POINTER(3));
1770 g_signal_connect(ui_lookup_widget(ui_widgets.prefs_dialog, "long_line_color"),
1771 "color-set", G_CALLBACK(on_color_button_choose_cb), NULL);
1772 /* file chooser buttons in the tools tab */
1773 ui_setup_open_button_callback(ui_lookup_widget(ui_widgets.prefs_dialog, "button_term"),
1774 NULL,
1775 GTK_FILE_CHOOSER_ACTION_OPEN,
1776 GTK_ENTRY(ui_lookup_widget(ui_widgets.prefs_dialog, "entry_com_term")));
1777 ui_setup_open_button_callback(ui_lookup_widget(ui_widgets.prefs_dialog, "button_browser"),
1778 NULL,
1779 GTK_FILE_CHOOSER_ACTION_OPEN,
1780 GTK_ENTRY(ui_lookup_widget(ui_widgets.prefs_dialog, "entry_browser")));
1781 ui_setup_open_button_callback(ui_lookup_widget(ui_widgets.prefs_dialog, "button_grep"),
1782 NULL,
1783 GTK_FILE_CHOOSER_ACTION_OPEN,
1784 GTK_ENTRY(ui_lookup_widget(ui_widgets.prefs_dialog, "entry_grep")));
1786 /* tools commands */
1787 ui_setup_open_button_callback(ui_lookup_widget(ui_widgets.prefs_dialog, "button_contextaction"),
1788 NULL,
1789 GTK_FILE_CHOOSER_ACTION_OPEN,
1790 GTK_ENTRY(ui_lookup_widget(ui_widgets.prefs_dialog, "entry_contextaction")));
1792 /* printing */
1793 ui_setup_open_button_callback(ui_lookup_widget(ui_widgets.prefs_dialog, "button_print_external_cmd"),
1794 NULL,
1795 GTK_FILE_CHOOSER_ACTION_OPEN,
1796 GTK_ENTRY(ui_lookup_widget(ui_widgets.prefs_dialog, "entry_print_external_cmd")));
1798 g_signal_connect(ui_lookup_widget(ui_widgets.prefs_dialog, "radio_print_gtk"),
1799 "toggled", G_CALLBACK(on_prefs_print_radio_button_toggled), NULL);
1800 g_signal_connect(ui_lookup_widget(ui_widgets.prefs_dialog, "check_print_pageheader"),
1801 "toggled", G_CALLBACK(on_prefs_print_page_header_toggled), NULL);
1803 g_signal_connect(ui_lookup_widget(ui_widgets.prefs_dialog, "check_plugins"),
1804 "toggled", G_CALLBACK(on_enable_plugins_toggled), NULL);
1805 g_signal_connect(ui_lookup_widget(ui_widgets.prefs_dialog, "check_toolbar_show"),
1806 "toggled", G_CALLBACK(on_toolbar_show_toggled), NULL);
1807 g_signal_connect(ui_lookup_widget(ui_widgets.prefs_dialog, "check_show_notebook_tabs"),
1808 "toggled", G_CALLBACK(on_show_notebook_tabs_toggled), NULL);
1809 g_signal_connect(ui_lookup_widget(ui_widgets.prefs_dialog, "check_folding"),
1810 "toggled", G_CALLBACK(on_use_folding_toggled), NULL);
1811 g_signal_connect(ui_lookup_widget(ui_widgets.prefs_dialog, "check_open_encoding"),
1812 "toggled", G_CALLBACK(on_open_encoding_toggled), NULL);
1813 g_signal_connect(ui_lookup_widget(ui_widgets.prefs_dialog, "check_sidebar_visible"),
1814 "toggled", G_CALLBACK(on_sidebar_visible_toggled), NULL);
1816 g_signal_connect(ui_widgets.prefs_dialog,
1817 "key-press-event", G_CALLBACK(prefs_dialog_key_press_response_cb), NULL);
1820 prefs_init_dialog();
1821 gtk_window_present(GTK_WINDOW(ui_widgets.prefs_dialog));