Merge pull request #3948 from techee/warning_fix2
[geany-mirror.git] / src / prefs.c
blob02f51214c00ce73a541e5be423e69f6a74324c7b
1 /*
2 * prefs.c - this file is part of Geany, a fast and lightweight IDE
4 * Copyright 2005 The Geany contributors
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation; either version 2 of the License, or
9 * (at your option) any later version.
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
16 * You should have received a copy of the GNU General Public License along
17 * with this program; if not, write to the Free Software Foundation, Inc.,
18 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
22 * @file prefs.h
23 * Preferences dialog.
27 * Preferences dialog support functions.
28 * New 'simple' prefs should use Stash code in keyfile.c - init_pref_groups().
31 #ifdef HAVE_CONFIG_H
32 # include "config.h"
33 #endif
35 #include "prefs.h"
37 #include "app.h"
38 #include "dialogs.h"
39 #include "documentprivate.h"
40 #include "editor.h"
41 #include "encodingsprivate.h"
42 #include "filetypes.h"
43 #include "geanywraplabel.h"
44 #include "keybindingsprivate.h"
45 #include "keyfile.h"
46 #include "msgwindow.h"
47 #include "prefs.h"
48 #include "printing.h"
49 #include "sidebar.h"
50 #include "stash.h"
51 #include "support.h"
52 #include "templates.h"
53 #include "toolbar.h"
54 #include "tools.h"
55 #include "ui_utils.h"
56 #include "utils.h"
57 #include "vte.h"
58 #include "osx.h"
60 #include <stdlib.h>
61 #include <string.h>
62 #include <gtk/gtk.h>
63 #include <gdk/gdkkeysyms.h>
66 GeanyPrefs prefs;
67 GeanyToolPrefs tool_prefs;
70 typedef struct
72 GtkTreeStore *store;
73 GtkTreeView *tree;
74 gboolean edited;
76 KbData;
78 static KbData global_kb_data = { NULL, NULL, FALSE };
79 static GtkTreeView *various_treeview = NULL;
81 static GeanyKeyBinding *kb_index(guint gidx, guint kid);
82 static void kb_cell_edited_cb(GtkCellRendererText *cellrenderertext, gchar *path, gchar *new_text, KbData *kbdata);
83 static gboolean kb_grab_key_dialog_key_press_cb(GtkWidget *dialog, GdkEventKey *event, GtkLabel *label);
84 static void kb_change_iter_shortcut(KbData *kbdata, GtkTreeIter *iter, const gchar *new_text);
85 static gboolean kb_find_duplicate(GtkTreeStore *store, GtkWidget *parent, GtkTreeIter *old_iter,
86 guint key, GdkModifierType mods, const gchar *shortcut);
87 static void on_toolbar_show_toggled(GtkToggleButton *togglebutton, gpointer user_data);
88 static void on_show_notebook_tabs_toggled(GtkToggleButton *togglebutton, gpointer user_data);
89 static void on_enable_plugins_toggled(GtkToggleButton *togglebutton, gpointer user_data);
90 static void on_use_folding_toggled(GtkToggleButton *togglebutton, gpointer user_data);
91 static void on_check_line_end_toggled(GtkToggleButton *togglebutton, gpointer user_data);
92 static void on_sidebar_visible_toggled(GtkToggleButton *togglebutton, gpointer user_data);
93 static void on_prefs_print_radio_button_toggled(GtkToggleButton *togglebutton, gpointer user_data);
94 static void on_prefs_print_page_header_toggled(GtkToggleButton *togglebutton, gpointer user_data);
95 static void open_preferences_help(void);
98 typedef enum PrefCallbackAction
100 PREF_DISPLAY,
101 PREF_UPDATE
103 PrefCallbackAction;
106 /* Synchronize Stash settings with widgets (see keyfile.c - init_pref_groups()). */
107 static void prefs_action(PrefCallbackAction action)
109 StashGroup *group;
110 guint i;
112 foreach_ptr_array(group, i, pref_groups)
114 switch (action)
116 case PREF_DISPLAY:
117 stash_group_display(group, ui_widgets.prefs_dialog);
118 break;
119 case PREF_UPDATE:
120 stash_group_update(group, ui_widgets.prefs_dialog);
121 break;
125 switch (action)
127 case PREF_DISPLAY:
128 stash_tree_display(various_treeview);
129 break;
130 case PREF_UPDATE:
131 stash_tree_update(various_treeview);
132 break;
137 enum
139 KB_TREE_ACTION,
140 KB_TREE_SHORTCUT,
141 KB_TREE_INDEX,
142 KB_TREE_EDITABLE,
143 KB_TREE_WEIGHT,
144 KB_TREE_COLUMNS
148 static void kb_tree_view_change_button_clicked_cb(GtkWidget *button, KbData *kbdata)
150 GtkTreeModel *model;
151 GtkTreeIter iter;
152 GtkTreeSelection *selection;
153 gchar *name;
155 selection = gtk_tree_view_get_selection(kbdata->tree);
156 if (gtk_tree_selection_get_selected(selection, &model, &iter))
158 if (gtk_tree_model_iter_has_child(model, &iter))
159 { /* double click on a section to expand or collapse it */
160 GtkTreePath *path = gtk_tree_model_get_path(model, &iter);
162 if (gtk_tree_view_row_expanded(kbdata->tree, path))
163 gtk_tree_view_collapse_row(kbdata->tree, path);
164 else
165 gtk_tree_view_expand_row(kbdata->tree, path, FALSE);
167 gtk_tree_path_free(path);
168 return;
171 gtk_tree_model_get(model, &iter, KB_TREE_ACTION, &name, -1);
172 if (name != NULL)
174 GtkWidget *dialog;
175 GtkWidget *label;
176 GtkWidget *accel_label;
177 gchar *str;
179 dialog = gtk_dialog_new_with_buttons(_("Grab Key"), GTK_WINDOW(ui_widgets.prefs_dialog),
180 GTK_DIALOG_MODAL | GTK_DIALOG_DESTROY_WITH_PARENT,
181 GTK_STOCK_CANCEL, GTK_RESPONSE_CANCEL,
182 GTK_STOCK_OK, GTK_RESPONSE_ACCEPT, NULL);
184 str = g_strdup_printf(
185 _("Press the combination of the keys you want to use for \"%s\"."), name);
186 label = gtk_label_new(str);
187 gtk_misc_set_padding(GTK_MISC(label), 5, 10);
188 gtk_container_add(GTK_CONTAINER(gtk_dialog_get_content_area(GTK_DIALOG(dialog))), label);
190 accel_label = gtk_label_new("");
191 gtk_misc_set_padding(GTK_MISC(accel_label), 5, 10);
192 gtk_container_add(GTK_CONTAINER(gtk_dialog_get_content_area(GTK_DIALOG(dialog))), accel_label);
194 g_signal_connect(dialog, "key-press-event",
195 G_CALLBACK(kb_grab_key_dialog_key_press_cb), accel_label);
197 gtk_widget_show_all(dialog);
198 if (gtk_dialog_run(GTK_DIALOG(dialog)) == GTK_RESPONSE_ACCEPT)
200 const gchar *new_text = gtk_label_get_text(GTK_LABEL(accel_label));
202 kb_change_iter_shortcut(kbdata, &iter, new_text);
204 gtk_widget_destroy(dialog);
206 g_free(str);
207 g_free(name);
213 static void kb_show_popup_menu(KbData *kbdata, GtkWidget *widget, GdkEventButton *event)
215 static GtkWidget *menu = NULL;
217 if (menu == NULL)
219 GtkWidget *item;
221 menu = gtk_menu_new();
223 item = ui_image_menu_item_new(GTK_STOCK_ADD, _("_Expand All"));
224 gtk_widget_show(item);
225 gtk_container_add(GTK_CONTAINER(menu), item);
226 g_signal_connect_swapped(item, "activate", G_CALLBACK(gtk_tree_view_expand_all), kbdata->tree);
228 item = ui_image_menu_item_new(GTK_STOCK_REMOVE, _("_Collapse All"));
229 gtk_widget_show(item);
230 gtk_container_add(GTK_CONTAINER(menu), item);
231 g_signal_connect_swapped(item, "activate", G_CALLBACK(gtk_tree_view_collapse_all), kbdata->tree);
233 gtk_menu_attach_to_widget(GTK_MENU(menu), widget, NULL);
236 gtk_menu_popup_at_pointer(GTK_MENU(menu), (GdkEvent *) event);
240 static gboolean kb_popup_menu_cb(GtkWidget *widget, KbData *kbdata)
242 kb_show_popup_menu(kbdata, widget, NULL);
243 return TRUE;
247 static gboolean kb_tree_view_button_press_event_cb(GtkWidget *widget, GdkEventButton *event,
248 KbData *kbdata)
250 if (event->button == 3 && event->type == GDK_BUTTON_PRESS)
252 kb_show_popup_menu(kbdata, widget, event);
253 return TRUE;
255 else if (event->type == GDK_2BUTTON_PRESS)
257 kb_tree_view_change_button_clicked_cb(NULL, kbdata);
258 return TRUE;
260 return FALSE;
264 static void kb_init_tree(KbData *kbdata)
266 GtkCellRenderer *renderer;
267 GtkTreeViewColumn *column;
269 kbdata->tree = GTK_TREE_VIEW(ui_lookup_widget(ui_widgets.prefs_dialog, "treeview7"));
271 kbdata->store = gtk_tree_store_new(KB_TREE_COLUMNS,
272 G_TYPE_STRING, G_TYPE_STRING, G_TYPE_INT, G_TYPE_BOOLEAN, G_TYPE_INT);
273 gtk_tree_view_set_model(GTK_TREE_VIEW(kbdata->tree), GTK_TREE_MODEL(kbdata->store));
274 g_object_unref(kbdata->store);
276 renderer = gtk_cell_renderer_text_new();
277 column = gtk_tree_view_column_new_with_attributes(_("Action"), renderer,
278 "text", KB_TREE_ACTION, "weight", KB_TREE_WEIGHT, NULL);
279 gtk_tree_view_append_column(GTK_TREE_VIEW(kbdata->tree), column);
281 renderer = gtk_cell_renderer_text_new();
282 column = gtk_tree_view_column_new_with_attributes(_("Shortcut"), renderer,
283 "text", KB_TREE_SHORTCUT, "editable", KB_TREE_EDITABLE,
284 "weight", KB_TREE_WEIGHT, NULL);
285 gtk_tree_view_append_column(GTK_TREE_VIEW(kbdata->tree), column);
287 /* set policy settings for the scrolled window around the treeview again, because glade
288 * doesn't keep the settings */
289 gtk_scrolled_window_set_policy(
290 GTK_SCROLLED_WINDOW(ui_lookup_widget(ui_widgets.prefs_dialog, "scrolledwindow8")),
291 GTK_POLICY_NEVER, GTK_POLICY_AUTOMATIC);
293 g_signal_connect(renderer, "edited", G_CALLBACK(kb_cell_edited_cb), kbdata);
294 g_signal_connect(kbdata->tree, "button-press-event", G_CALLBACK(kb_tree_view_button_press_event_cb), kbdata);
295 g_signal_connect(kbdata->tree, "popup-menu", G_CALLBACK(kb_popup_menu_cb), kbdata);
296 g_signal_connect(ui_lookup_widget(ui_widgets.prefs_dialog, "button2"), "clicked",
297 G_CALLBACK(kb_tree_view_change_button_clicked_cb), kbdata);
301 static void kb_set_shortcut(GtkTreeStore *store, GtkTreeIter *iter,
302 guint key, GdkModifierType mods)
304 gchar *key_string = gtk_accelerator_name(key, mods);
305 GtkTreeIter parent;
306 guint kid, gid;
307 GeanyKeyBinding *kb;
308 gboolean bold;
310 gtk_tree_store_set(store, iter, KB_TREE_SHORTCUT, key_string, -1);
311 g_free(key_string);
313 gtk_tree_model_get(GTK_TREE_MODEL(store), iter, KB_TREE_INDEX, &kid, -1);
314 gtk_tree_model_iter_parent(GTK_TREE_MODEL(store), &parent, iter);
315 gtk_tree_model_get(GTK_TREE_MODEL(store), &parent, KB_TREE_INDEX, &gid, -1);
316 kb = kb_index(gid, kid);
317 bold = key != kb->default_key || mods != kb->default_mods;
318 gtk_tree_store_set(store, iter, KB_TREE_WEIGHT,
319 bold ? PANGO_WEIGHT_BOLD : PANGO_WEIGHT_NORMAL, -1);
323 void prefs_kb_search_name(const gchar *search)
325 GtkTreeIter iter;
326 gboolean valid;
327 GtkTreeModel *model;
328 KbData *kbdata = &global_kb_data;
330 model = gtk_tree_view_get_model(kbdata->tree);
331 valid = gtk_tree_model_get_iter_first(model, &iter);
332 while (valid)
334 gchar *name;
336 gtk_tree_model_get(model, &iter, KB_TREE_ACTION, &name, -1);
337 if (g_strcmp0(name, search) == 0)
339 GtkTreePath *path = gtk_tree_model_get_path(model, &iter);
340 gtk_tree_view_scroll_to_cell(kbdata->tree, path, NULL, TRUE, .0f, .0f);
341 gtk_tree_path_free(path);
342 g_free(name);
343 break;
345 g_free(name);
346 valid = gtk_tree_model_iter_next(model, &iter);
351 static void kb_init(KbData *kbdata)
353 GtkTreeIter parent, iter;
354 gsize g, i;
355 gchar *label;
356 GeanyKeyGroup *group;
357 GeanyKeyBinding *kb;
359 if (kbdata->store == NULL)
360 kb_init_tree(kbdata);
362 foreach_ptr_array(group, g, keybinding_groups)
364 gtk_tree_store_append(kbdata->store, &parent, NULL);
365 gtk_tree_store_set(kbdata->store, &parent, KB_TREE_ACTION, group->label,
366 KB_TREE_INDEX, g, -1);
368 foreach_ptr_array(kb, i, group->key_items)
370 label = keybindings_get_label(kb);
371 gtk_tree_store_append(kbdata->store, &iter, &parent);
372 gtk_tree_store_set(kbdata->store, &iter, KB_TREE_ACTION, label,
373 KB_TREE_EDITABLE, TRUE, KB_TREE_INDEX, kb->id, -1);
374 kb_set_shortcut(kbdata->store, &iter, kb->key, kb->mods);
375 g_free(label);
378 gtk_tree_view_expand_all(GTK_TREE_VIEW(kbdata->tree));
382 /* note: new 'simple' prefs should use Stash code in keyfile.c */
383 static void prefs_init_dialog(void)
385 GtkWidget *widget;
386 GdkColor color = {0};
388 /* Synchronize with Stash settings */
389 prefs_action(PREF_DISPLAY);
391 widget = ui_lookup_widget(ui_widgets.prefs_dialog, "label_project_indent_warning");
392 ui_widget_show_hide(widget, app->project != NULL);
394 /* General settings */
395 /* startup */
396 widget = ui_lookup_widget(ui_widgets.prefs_dialog, "check_load_session");
397 gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(widget), prefs.load_session);
399 widget = ui_lookup_widget(ui_widgets.prefs_dialog, "check_project_file_in_basedir");
400 gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(widget), project_prefs.project_file_in_basedir);
402 widget = ui_lookup_widget(ui_widgets.prefs_dialog, "check_save_win_pos");
403 gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(widget), prefs.save_winpos);
405 widget = ui_lookup_widget(ui_widgets.prefs_dialog, "check_save_win_geom");
406 gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(widget), prefs.save_wingeom);
408 widget = ui_lookup_widget(ui_widgets.prefs_dialog, "check_ask_for_quit");
409 gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(widget), prefs.confirm_exit);
411 /* behaviour */
412 widget = ui_lookup_widget(ui_widgets.prefs_dialog, "check_beep");
413 gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(widget), prefs.beep_on_errors);
415 widget = ui_lookup_widget(ui_widgets.prefs_dialog, "check_switch_pages");
416 gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(widget), prefs.switch_to_status);
418 widget = ui_lookup_widget(ui_widgets.prefs_dialog, "check_suppress_status_msgs");
419 gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(widget), prefs.suppress_status_messages);
421 widget = ui_lookup_widget(ui_widgets.prefs_dialog, "check_auto_focus");
422 gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(widget), prefs.auto_focus);
424 widget = ui_lookup_widget(ui_widgets.prefs_dialog, "entry_contextaction");
425 gtk_entry_set_text(GTK_ENTRY(widget), tool_prefs.context_action_cmd);
427 widget = ui_lookup_widget(ui_widgets.prefs_dialog, "check_native_dialogs");
428 gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(widget),
429 interface_prefs.use_native_windows_dialogs);
431 project_setup_prefs(); /* project files path */
434 /* Interface settings */
435 widget = ui_lookup_widget(ui_widgets.prefs_dialog, "check_sidebar_visible");
436 gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(widget), ui_prefs.sidebar_visible);
437 on_sidebar_visible_toggled(GTK_TOGGLE_BUTTON(widget), NULL);
439 widget = ui_lookup_widget(ui_widgets.prefs_dialog, "check_list_symbol");
440 gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(widget), interface_prefs.sidebar_symbol_visible);
442 widget = ui_lookup_widget(ui_widgets.prefs_dialog, "check_list_openfiles");
443 gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(widget), interface_prefs.sidebar_openfiles_visible);
445 widget = ui_lookup_widget(ui_widgets.prefs_dialog, "tagbar_font");
446 gtk_font_button_set_font_name(GTK_FONT_BUTTON(widget), interface_prefs.tagbar_font);
448 widget = ui_lookup_widget(ui_widgets.prefs_dialog, "msgwin_font");
449 gtk_font_button_set_font_name(GTK_FONT_BUTTON(widget), interface_prefs.msgwin_font);
451 widget = ui_lookup_widget(ui_widgets.prefs_dialog, "editor_font");
452 gtk_font_button_set_font_name(GTK_FONT_BUTTON(widget), interface_prefs.editor_font);
454 widget = ui_lookup_widget(ui_widgets.prefs_dialog, "spin_long_line");
455 gtk_spin_button_set_value(GTK_SPIN_BUTTON(widget), editor_prefs.long_line_column);
457 widget = ui_lookup_widget(ui_widgets.prefs_dialog, "check_long_line");
458 gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(widget), editor_prefs.long_line_enabled);
460 switch (editor_prefs.long_line_type)
462 case 0: widget = ui_lookup_widget(ui_widgets.prefs_dialog, "radio_long_line_line"); break;
463 case 1: widget = ui_lookup_widget(ui_widgets.prefs_dialog, "radio_long_line_background"); break;
465 gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(widget), TRUE);
467 utils_parse_color(editor_prefs.long_line_color, &color);
468 widget = ui_lookup_widget(ui_widgets.prefs_dialog, "long_line_color");
469 gtk_color_button_set_color(GTK_COLOR_BUTTON(widget), &color);
471 widget = ui_lookup_widget(ui_widgets.prefs_dialog, "check_show_notebook_tabs");
472 gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(widget), interface_prefs.show_notebook_tabs);
473 /* disable following setting if notebook tabs are hidden */
474 on_show_notebook_tabs_toggled(GTK_TOGGLE_BUTTON(
475 ui_lookup_widget(ui_widgets.prefs_dialog, "check_show_notebook_tabs")), NULL);
477 widget = ui_lookup_widget(ui_widgets.prefs_dialog, "check_show_tab_cross");
478 gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(widget), file_prefs.show_tab_cross);
480 widget = ui_lookup_widget(ui_widgets.prefs_dialog, "combo_tab_editor");
481 gtk_combo_box_set_active(GTK_COMBO_BOX(widget), interface_prefs.tab_pos_editor);
483 widget = ui_lookup_widget(ui_widgets.prefs_dialog, "combo_tab_msgwin");
484 gtk_combo_box_set_active(GTK_COMBO_BOX(widget), interface_prefs.tab_pos_msgwin);
486 widget = ui_lookup_widget(ui_widgets.prefs_dialog, "combo_tab_sidebar");
487 gtk_combo_box_set_active(GTK_COMBO_BOX(widget), interface_prefs.tab_pos_sidebar);
489 widget = ui_lookup_widget(ui_widgets.prefs_dialog, "check_statusbar_visible");
490 gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(widget), interface_prefs.statusbar_visible);
493 /* Toolbar settings */
494 widget = ui_lookup_widget(ui_widgets.prefs_dialog, "check_toolbar_show");
495 gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(widget), toolbar_prefs.visible);
496 widget = ui_lookup_widget(ui_widgets.prefs_dialog, "check_toolbar_in_menu");
497 gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(widget), toolbar_prefs.append_to_menu);
499 switch (toolbar_prefs.icon_style)
501 case 0: widget = ui_lookup_widget(ui_widgets.prefs_dialog, "radio_toolbar_image"); break;
502 case 1: widget = ui_lookup_widget(ui_widgets.prefs_dialog, "radio_toolbar_text"); break;
503 default: widget = ui_lookup_widget(ui_widgets.prefs_dialog, "radio_toolbar_imagetext"); break;
505 if (toolbar_prefs.use_gtk_default_style)
506 widget = ui_lookup_widget(ui_widgets.prefs_dialog, "radio_toolbar_style_default");
507 gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(widget), TRUE);
509 switch (toolbar_prefs.icon_size)
511 case GTK_ICON_SIZE_LARGE_TOOLBAR:
512 widget = ui_lookup_widget(ui_widgets.prefs_dialog, "radio_toolbar_large"); break;
513 case GTK_ICON_SIZE_SMALL_TOOLBAR:
514 widget = ui_lookup_widget(ui_widgets.prefs_dialog, "radio_toolbar_small"); break;
515 default: widget = ui_lookup_widget(ui_widgets.prefs_dialog, "radio_toolbar_verysmall"); break;
517 if (toolbar_prefs.use_gtk_default_icon)
518 widget = ui_lookup_widget(ui_widgets.prefs_dialog, "radio_toolbar_icon_default");
519 gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(widget), TRUE);
521 /* disable elements if toolbar is hidden */
522 on_toolbar_show_toggled(GTK_TOGGLE_BUTTON(
523 ui_lookup_widget(ui_widgets.prefs_dialog, "check_toolbar_show")), NULL);
526 /* Files settings */
527 if (file_prefs.tab_order_ltr)
528 widget = ui_lookup_widget(ui_widgets.prefs_dialog, "radio_tab_right");
529 else
530 widget = ui_lookup_widget(ui_widgets.prefs_dialog, "radio_tab_left");
531 gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(widget), TRUE);
533 widget = ui_lookup_widget(ui_widgets.prefs_dialog, "check_tab_beside");
534 gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(widget), file_prefs.tab_order_beside);
536 widget = ui_lookup_widget(ui_widgets.prefs_dialog, "combo_new_encoding");
537 ui_encodings_combo_box_set_active_encoding(GTK_COMBO_BOX(widget), file_prefs.default_new_encoding);
539 widget = ui_lookup_widget(ui_widgets.prefs_dialog, "combo_open_encoding");
540 if (file_prefs.default_open_encoding >= 0)
541 ui_encodings_combo_box_set_active_encoding(GTK_COMBO_BOX(widget), file_prefs.default_open_encoding);
542 else
543 ui_encodings_combo_box_set_active_encoding(GTK_COMBO_BOX(widget), GEANY_ENCODINGS_MAX);
545 widget = ui_lookup_widget(ui_widgets.prefs_dialog, "combo_eol");
546 if (file_prefs.default_eol_character >= 0 && file_prefs.default_eol_character < 3)
548 gtk_combo_box_set_active(GTK_COMBO_BOX(widget), file_prefs.default_eol_character);
550 else
551 gtk_combo_box_set_active(GTK_COMBO_BOX(widget), GEANY_DEFAULT_EOL_CHARACTER);
553 widget = ui_lookup_widget(ui_widgets.prefs_dialog, "check_trailing_spaces");
554 gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(widget), file_prefs.strip_trailing_spaces);
556 widget = ui_lookup_widget(ui_widgets.prefs_dialog, "check_new_line");
557 gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(widget), file_prefs.final_new_line);
559 widget = ui_lookup_widget(ui_widgets.prefs_dialog, "check_ensure_convert_new_lines");
560 gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(widget), file_prefs.ensure_convert_new_lines);
562 /* Editor settings */
563 widget = ui_lookup_widget(ui_widgets.prefs_dialog, "entry_toggle_mark");
564 gtk_entry_set_text(GTK_ENTRY(widget), editor_prefs.comment_toggle_mark);
566 widget = ui_lookup_widget(ui_widgets.prefs_dialog, "check_replace_tabs");
567 gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(widget), file_prefs.replace_tabs);
569 widget = ui_lookup_widget(ui_widgets.prefs_dialog, "check_indent");
570 gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(widget), editor_prefs.show_indent_guide);
572 widget = ui_lookup_widget(ui_widgets.prefs_dialog, "check_white_space");
573 gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(widget), editor_prefs.show_white_space);
575 widget = ui_lookup_widget(ui_widgets.prefs_dialog, "check_line_end");
576 gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(widget), editor_prefs.show_line_endings);
578 widget = ui_lookup_widget(ui_widgets.prefs_dialog, "check_line_endings_only_when_differ");
579 gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(widget),
580 editor_prefs.show_line_endings_only_when_differ);
582 widget = ui_lookup_widget(ui_widgets.prefs_dialog, "check_line_numbers");
583 gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(widget), editor_prefs.show_linenumber_margin);
585 widget = ui_lookup_widget(ui_widgets.prefs_dialog, "check_markers_margin");
586 gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(widget), editor_prefs.show_markers_margin);
588 widget = ui_lookup_widget(ui_widgets.prefs_dialog, "check_scroll_stop_at_last_line");
589 gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(widget), editor_prefs.scroll_stop_at_last_line);
591 widget = ui_lookup_widget(ui_widgets.prefs_dialog, "check_line_wrapping");
592 gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(widget), editor_prefs.line_wrapping);
594 widget = ui_lookup_widget(ui_widgets.prefs_dialog, "check_complete_snippets");
595 gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(widget), editor_prefs.complete_snippets);
597 widget = ui_lookup_widget(ui_widgets.prefs_dialog, "check_xmltag");
598 gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(widget), editor_prefs.auto_close_xml_tags);
600 widget = ui_lookup_widget(ui_widgets.prefs_dialog, "check_folding");
601 gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(widget), editor_prefs.folding);
603 widget = ui_lookup_widget(ui_widgets.prefs_dialog, "check_unfold_children");
604 gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(widget), editor_prefs.unfold_all_children);
605 on_use_folding_toggled(GTK_TOGGLE_BUTTON(
606 ui_lookup_widget(ui_widgets.prefs_dialog, "check_folding")), NULL);
608 widget = ui_lookup_widget(ui_widgets.prefs_dialog, "check_disable_dnd");
609 gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(widget), editor_prefs.disable_dnd);
611 widget = ui_lookup_widget(ui_widgets.prefs_dialog, "check_smart_home");
612 gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(widget), editor_prefs.smart_home_key);
614 widget = ui_lookup_widget(ui_widgets.prefs_dialog, "check_newline_strip");
615 gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(widget), editor_prefs.newline_strip);
617 widget = ui_lookup_widget(ui_widgets.prefs_dialog, "check_indicators");
618 gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(widget), editor_prefs.use_indicators);
620 widget = ui_lookup_widget(ui_widgets.prefs_dialog, "check_auto_multiline");
621 gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(widget), editor_prefs.auto_continue_multiline);
623 widget = ui_lookup_widget(ui_widgets.prefs_dialog, "check_symbol_auto_completion");
624 gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(widget), editor_prefs.auto_complete_symbols);
626 widget = ui_lookup_widget(ui_widgets.prefs_dialog, "spin_symbollistheight");
627 gtk_spin_button_set_value(GTK_SPIN_BUTTON(widget), editor_prefs.symbolcompletion_max_height);
629 widget = ui_lookup_widget(ui_widgets.prefs_dialog, "spin_symbol_complete_chars");
630 gtk_spin_button_set_value(GTK_SPIN_BUTTON(widget), editor_prefs.symbolcompletion_min_chars);
632 widget = ui_lookup_widget(ui_widgets.prefs_dialog, "spin_line_break");
633 gtk_spin_button_set_value(GTK_SPIN_BUTTON(widget), editor_prefs.line_break_column);
635 widget = ui_lookup_widget(ui_widgets.prefs_dialog, "check_autoclose_parenthesis");
636 gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(widget),
637 (editor_prefs.autoclose_chars & GEANY_AC_PARENTHESIS));
639 widget = ui_lookup_widget(ui_widgets.prefs_dialog, "check_autoclose_cbracket");
640 gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(widget),
641 (editor_prefs.autoclose_chars & GEANY_AC_CBRACKET));
643 widget = ui_lookup_widget(ui_widgets.prefs_dialog, "check_autoclose_sbracket");
644 gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(widget),
645 (editor_prefs.autoclose_chars & GEANY_AC_SBRACKET));
647 widget = ui_lookup_widget(ui_widgets.prefs_dialog, "check_autoclose_squote");
648 gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(widget),
649 (editor_prefs.autoclose_chars & GEANY_AC_SQUOTE));
651 widget = ui_lookup_widget(ui_widgets.prefs_dialog, "check_autoclose_dquote");
652 gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(widget),
653 (editor_prefs.autoclose_chars & GEANY_AC_DQUOTE));
655 /* Tools Settings */
657 if (tool_prefs.term_cmd)
658 gtk_entry_set_text(GTK_ENTRY(ui_lookup_widget(ui_widgets.prefs_dialog, "entry_com_term")), tool_prefs.term_cmd);
660 if (tool_prefs.browser_cmd)
661 gtk_entry_set_text(GTK_ENTRY(ui_lookup_widget(ui_widgets.prefs_dialog, "entry_browser")), tool_prefs.browser_cmd);
663 if (tool_prefs.grep_cmd)
664 gtk_entry_set_text(GTK_ENTRY(ui_lookup_widget(ui_widgets.prefs_dialog, "entry_grep")), tool_prefs.grep_cmd);
667 /* Template settings */
668 widget = ui_lookup_widget(ui_widgets.prefs_dialog, "entry_template_developer");
669 gtk_entry_set_text(GTK_ENTRY(widget), template_prefs.developer);
671 widget = ui_lookup_widget(ui_widgets.prefs_dialog, "entry_template_company");
672 gtk_entry_set_text(GTK_ENTRY(widget), template_prefs.company);
674 widget = ui_lookup_widget(ui_widgets.prefs_dialog, "entry_template_mail");
675 gtk_entry_set_text(GTK_ENTRY(widget), template_prefs.mail);
677 widget = ui_lookup_widget(ui_widgets.prefs_dialog, "entry_template_initial");
678 gtk_entry_set_text(GTK_ENTRY(widget), template_prefs.initials);
680 widget = ui_lookup_widget(ui_widgets.prefs_dialog, "entry_template_version");
681 gtk_entry_set_text(GTK_ENTRY(widget), template_prefs.version);
683 widget = ui_lookup_widget(ui_widgets.prefs_dialog, "entry_template_year");
684 gtk_entry_set_text(GTK_ENTRY(widget), template_prefs.year_format);
686 widget = ui_lookup_widget(ui_widgets.prefs_dialog, "entry_template_date");
687 gtk_entry_set_text(GTK_ENTRY(widget), template_prefs.date_format);
689 widget = ui_lookup_widget(ui_widgets.prefs_dialog, "entry_template_datetime");
690 gtk_entry_set_text(GTK_ENTRY(widget), template_prefs.datetime_format);
693 /* Keybindings */
694 kb_init(&global_kb_data);
696 /* Printing */
698 GtkWidget *widget_gtk = ui_lookup_widget(ui_widgets.prefs_dialog, "radio_print_gtk");
699 if (printing_prefs.use_gtk_printing)
700 widget = widget_gtk;
701 else
702 widget = ui_lookup_widget(ui_widgets.prefs_dialog, "radio_print_external");
704 gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(widget), TRUE);
706 on_prefs_print_radio_button_toggled(GTK_TOGGLE_BUTTON(widget_gtk), NULL);
708 if (printing_prefs.external_print_cmd)
709 gtk_entry_set_text(
710 GTK_ENTRY(ui_lookup_widget(ui_widgets.prefs_dialog, "entry_print_external_cmd")),
711 printing_prefs.external_print_cmd);
713 widget = ui_lookup_widget(ui_widgets.prefs_dialog, "check_print_linenumbers");
714 gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(widget), printing_prefs.print_line_numbers);
716 widget = ui_lookup_widget(ui_widgets.prefs_dialog, "check_print_pagenumbers");
717 gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(widget), printing_prefs.print_page_numbers);
719 widget = ui_lookup_widget(ui_widgets.prefs_dialog, "check_print_pageheader");
720 gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(widget), printing_prefs.print_page_header);
721 on_prefs_print_page_header_toggled(GTK_TOGGLE_BUTTON(widget), NULL);
723 widget = ui_lookup_widget(ui_widgets.prefs_dialog, "check_print_basename");
724 gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(widget), printing_prefs.page_header_basename);
726 if (printing_prefs.page_header_datefmt)
727 gtk_entry_set_text(
728 GTK_ENTRY(ui_lookup_widget(ui_widgets.prefs_dialog, "entry_print_dateformat")),
729 printing_prefs.page_header_datefmt);
732 #ifndef HAVE_PLUGINS
733 gtk_widget_set_sensitive(ui_lookup_widget(ui_widgets.prefs_dialog, "check_plugins"), FALSE);
734 #endif
735 on_enable_plugins_toggled(GTK_TOGGLE_BUTTON( ui_lookup_widget(ui_widgets.prefs_dialog, "check_plugins")), NULL);
737 #ifdef HAVE_VTE
738 /* make VTE switch visible only when VTE is compiled in, it is hidden by default */
739 widget = ui_lookup_widget(ui_widgets.prefs_dialog, "check_vte");
740 gtk_widget_show(widget);
741 gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(widget), vte_info.load_vte);
743 /* VTE settings */
744 if (vte_info.have_vte)
746 VteConfig *vc = &vte_config;
748 widget = ui_lookup_widget(ui_widgets.prefs_dialog, "font_term");
749 gtk_font_button_set_font_name(GTK_FONT_BUTTON(widget), vc->font);
751 widget = ui_lookup_widget(ui_widgets.prefs_dialog, "color_fore");
752 gtk_color_button_set_color(GTK_COLOR_BUTTON(widget), &vc->colour_fore);
754 widget = ui_lookup_widget(ui_widgets.prefs_dialog, "color_back");
755 gtk_color_button_set_color(GTK_COLOR_BUTTON(widget), &vc->colour_back);
757 widget = ui_lookup_widget(ui_widgets.prefs_dialog, "spin_scrollback");
758 gtk_spin_button_set_value(GTK_SPIN_BUTTON(widget), vc->scrollback_lines);
760 widget = ui_lookup_widget(ui_widgets.prefs_dialog, "entry_shell");
761 gtk_entry_set_text(GTK_ENTRY(widget), vc->shell);
763 widget = ui_lookup_widget(ui_widgets.prefs_dialog, "check_scroll_key");
764 gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(widget), vc->scroll_on_key);
766 widget = ui_lookup_widget(ui_widgets.prefs_dialog, "check_scroll_out");
767 gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(widget), vc->scroll_on_out);
769 widget = ui_lookup_widget(ui_widgets.prefs_dialog, "check_enable_bash_keys");
770 gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(widget), vc->enable_bash_keys);
772 widget = ui_lookup_widget(ui_widgets.prefs_dialog, "check_ignore_menu_key");
773 gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(widget), vc->ignore_menu_bar_accel);
775 widget = ui_lookup_widget(ui_widgets.prefs_dialog, "check_follow_path");
776 gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(widget), vc->follow_path);
778 widget = ui_lookup_widget(ui_widgets.prefs_dialog, "check_run_in_vte");
779 gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(widget), vc->run_in_vte);
781 widget = ui_lookup_widget(ui_widgets.prefs_dialog, "check_skip_script");
782 gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(widget), vc->skip_run_script);
784 widget = ui_lookup_widget(ui_widgets.prefs_dialog, "check_cursor_blinks");
785 gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(widget), vc->cursor_blinks);
787 #endif
791 /* note: uses group index, not group id, unlike keybindings_lookup_item(). */
792 static GeanyKeyBinding *kb_index(guint gidx, guint kid)
794 GeanyKeyGroup *group;
796 group = g_ptr_array_index(keybinding_groups, gidx);
797 return keybindings_get_item(group, kid);
801 /* read the treeview shortcut fields into keybindings */
802 static void kb_update(KbData *kbdata)
804 GtkTreeModel *model = GTK_TREE_MODEL(kbdata->store);
805 GtkTreeIter child, parent;
806 guint gid = 0;
808 /* get first parent */
809 if (! gtk_tree_model_iter_children(model, &parent, NULL))
810 return;
812 /* foreach parent */
813 while (TRUE)
815 /* get first child */
816 if (! gtk_tree_model_iter_children(model, &child, &parent))
817 return;
819 /* foreach child */
820 while (TRUE)
822 guint kid;
823 gchar *str;
824 guint key;
825 GdkModifierType mods;
826 GeanyKeyBinding *kb;
828 gtk_tree_model_get(model, &child, KB_TREE_INDEX, &kid, KB_TREE_SHORTCUT, &str, -1);
829 gtk_accelerator_parse(str, &key, &mods);
830 g_free(str);
831 kb = kb_index(gid, kid);
832 if (kb->key != key || kb->mods != mods)
833 keybindings_update_combo(kb, key, mods);
835 if (! gtk_tree_model_iter_next(model, &child))
836 break;
838 if (! gtk_tree_model_iter_next(model, &parent))
839 return;
840 gid++;
846 * callbacks
848 /* note: new 'simple' prefs should use Stash code in keyfile.c */
849 static void
850 on_prefs_dialog_response(GtkDialog *dialog, gint response, gpointer user_data)
852 if (response == GTK_RESPONSE_OK || response == GTK_RESPONSE_APPLY)
854 GtkWidget *widget;
855 guint i;
856 gboolean autoclose_brackets[5];
857 gboolean old_invert_all = interface_prefs.highlighting_invert_all;
858 gboolean old_sidebar_pos = interface_prefs.sidebar_pos;
859 GeanyDocument *doc = document_get_current();
861 /* Synchronize Stash settings */
862 prefs_action(PREF_UPDATE);
864 if (interface_prefs.highlighting_invert_all != old_invert_all)
865 filetypes_reload();
867 if (interface_prefs.sidebar_pos != old_sidebar_pos)
868 ui_swap_sidebar_pos();
870 widget = ui_lookup_widget(main_widgets.window, "vpaned1");
871 gtk_orientable_set_orientation(GTK_ORIENTABLE(widget), interface_prefs.msgwin_orientation);
873 /* General settings */
874 /* startup */
875 widget = ui_lookup_widget(ui_widgets.prefs_dialog, "check_load_session");
876 prefs.load_session = gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(widget));
878 widget = ui_lookup_widget(ui_widgets.prefs_dialog, "check_project_file_in_basedir");
879 project_prefs.project_file_in_basedir = gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(widget));
881 widget = ui_lookup_widget(ui_widgets.prefs_dialog, "check_save_win_pos");
882 prefs.save_winpos = gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(widget));
884 widget = ui_lookup_widget(ui_widgets.prefs_dialog, "check_save_win_geom");
885 prefs.save_wingeom = gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(widget));
887 widget = ui_lookup_widget(ui_widgets.prefs_dialog, "check_ask_for_quit");
888 prefs.confirm_exit = gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(widget));
890 /* behaviour */
891 widget = ui_lookup_widget(ui_widgets.prefs_dialog, "check_beep");
892 prefs.beep_on_errors = gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(widget));
894 widget = ui_lookup_widget(ui_widgets.prefs_dialog, "check_switch_pages");
895 prefs.switch_to_status = gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(widget));
897 widget = ui_lookup_widget(ui_widgets.prefs_dialog, "check_suppress_status_msgs");
898 prefs.suppress_status_messages = gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(widget));
900 widget = ui_lookup_widget(ui_widgets.prefs_dialog, "check_auto_focus");
901 prefs.auto_focus = gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(widget));
903 widget = ui_lookup_widget(ui_widgets.prefs_dialog, "entry_contextaction");
904 g_free(tool_prefs.context_action_cmd);
905 tool_prefs.context_action_cmd = g_strdup(gtk_entry_get_text(GTK_ENTRY(widget)));
907 widget = ui_lookup_widget(ui_widgets.prefs_dialog, "check_native_dialogs");
908 interface_prefs.use_native_windows_dialogs =
909 gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(widget));
911 project_apply_prefs(); /* project file path */
914 /* Interface settings */
915 widget = ui_lookup_widget(ui_widgets.prefs_dialog, "check_sidebar_visible");
916 ui_prefs.sidebar_visible = gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(widget));
918 widget = ui_lookup_widget(ui_widgets.prefs_dialog, "check_list_symbol");
919 interface_prefs.sidebar_symbol_visible = gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(widget));
921 widget = ui_lookup_widget(ui_widgets.prefs_dialog, "check_list_openfiles");
922 interface_prefs.sidebar_openfiles_visible = gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(widget));
924 widget = ui_lookup_widget(ui_widgets.prefs_dialog, "check_long_line");
925 editor_prefs.long_line_enabled = gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(widget));
927 widget = ui_lookup_widget(ui_widgets.prefs_dialog, "radio_long_line_line");
928 if (gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(widget)))
929 editor_prefs.long_line_type = 0;
930 else
931 /* now only the "background" radio remains */
932 editor_prefs.long_line_type = 1;
934 if (editor_prefs.long_line_column == 0)
935 editor_prefs.long_line_enabled = FALSE;
937 widget = ui_lookup_widget(ui_widgets.prefs_dialog, "check_show_notebook_tabs");
938 interface_prefs.show_notebook_tabs = gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(widget));
940 widget = ui_lookup_widget(ui_widgets.prefs_dialog, "check_show_tab_cross");
941 file_prefs.show_tab_cross = gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(widget));
943 widget = ui_lookup_widget(ui_widgets.prefs_dialog, "combo_tab_editor");
944 interface_prefs.tab_pos_editor = gtk_combo_box_get_active(GTK_COMBO_BOX(widget));
946 widget = ui_lookup_widget(ui_widgets.prefs_dialog, "combo_tab_msgwin");
947 interface_prefs.tab_pos_msgwin = gtk_combo_box_get_active(GTK_COMBO_BOX(widget));
949 widget = ui_lookup_widget(ui_widgets.prefs_dialog, "combo_tab_sidebar");
950 interface_prefs.tab_pos_sidebar = gtk_combo_box_get_active(GTK_COMBO_BOX(widget));
952 widget = ui_lookup_widget(ui_widgets.prefs_dialog, "check_statusbar_visible");
953 interface_prefs.statusbar_visible = gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(widget));
955 widget = ui_lookup_widget(ui_widgets.prefs_dialog, "spin_tab_label_len");
956 interface_prefs.tab_label_len = gtk_spin_button_get_value_as_int(GTK_SPIN_BUTTON(widget));
958 /* Toolbar settings */
959 widget = ui_lookup_widget(ui_widgets.prefs_dialog, "check_toolbar_show");
960 toolbar_prefs.visible = gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(widget));
961 widget = ui_lookup_widget(ui_widgets.prefs_dialog, "check_toolbar_in_menu");
962 toolbar_prefs.append_to_menu = gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(widget));
964 widget = ui_lookup_widget(ui_widgets.prefs_dialog, "radio_toolbar_style_default");
965 toolbar_prefs.use_gtk_default_style = gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(widget));
966 if (! toolbar_prefs.use_gtk_default_style)
968 widget = ui_lookup_widget(ui_widgets.prefs_dialog, "radio_toolbar_imagetext");
969 if (gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(widget)))
970 toolbar_prefs.icon_style = 2;
971 else
973 widget = ui_lookup_widget(ui_widgets.prefs_dialog, "radio_toolbar_image");
974 if (gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(widget)))
975 toolbar_prefs.icon_style = 0;
976 else
977 /* now only the text only radio remains, so set text only */
978 toolbar_prefs.icon_style = 1;
982 widget = ui_lookup_widget(ui_widgets.prefs_dialog, "radio_toolbar_icon_default");
983 toolbar_prefs.use_gtk_default_icon = gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(widget));
984 if (! toolbar_prefs.use_gtk_default_icon)
985 { toolbar_prefs.icon_size = GTK_ICON_SIZE_LARGE_TOOLBAR;
986 widget = ui_lookup_widget(ui_widgets.prefs_dialog, "radio_toolbar_large");
987 if (gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(widget)))
988 toolbar_prefs.icon_size = GTK_ICON_SIZE_LARGE_TOOLBAR;
989 else
991 widget = ui_lookup_widget(ui_widgets.prefs_dialog, "radio_toolbar_small");
992 if (gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(widget)))
993 toolbar_prefs.icon_size = GTK_ICON_SIZE_SMALL_TOOLBAR;
994 else
995 toolbar_prefs.icon_size = GTK_ICON_SIZE_MENU;
999 /* Files settings */
1000 widget = ui_lookup_widget(ui_widgets.prefs_dialog, "radio_tab_right");
1001 file_prefs.tab_order_ltr = gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(widget));
1003 widget = ui_lookup_widget(ui_widgets.prefs_dialog, "check_tab_beside");
1004 file_prefs.tab_order_beside = gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(widget));
1006 widget = ui_lookup_widget(ui_widgets.prefs_dialog, "combo_new_encoding");
1007 file_prefs.default_new_encoding = ui_encodings_combo_box_get_active_encoding(GTK_COMBO_BOX(widget));
1009 widget = ui_lookup_widget(ui_widgets.prefs_dialog, "combo_open_encoding");
1010 file_prefs.default_open_encoding = ui_encodings_combo_box_get_active_encoding(GTK_COMBO_BOX(widget));
1011 if (file_prefs.default_open_encoding >= GEANY_ENCODINGS_MAX)
1012 file_prefs.default_open_encoding = -1;
1014 widget = ui_lookup_widget(ui_widgets.prefs_dialog, "combo_eol");
1015 file_prefs.default_eol_character = gtk_combo_box_get_active(GTK_COMBO_BOX(widget));
1017 widget = ui_lookup_widget(ui_widgets.prefs_dialog, "check_trailing_spaces");
1018 file_prefs.strip_trailing_spaces = gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(widget));
1020 widget = ui_lookup_widget(ui_widgets.prefs_dialog, "check_new_line");
1021 file_prefs.final_new_line = gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(widget));
1023 widget = ui_lookup_widget(ui_widgets.prefs_dialog, "check_ensure_convert_new_lines");
1024 file_prefs.ensure_convert_new_lines = gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(widget));
1026 widget = ui_lookup_widget(ui_widgets.prefs_dialog, "check_replace_tabs");
1027 file_prefs.replace_tabs = gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(widget));
1030 /* Editor settings */
1031 widget = ui_lookup_widget(ui_widgets.prefs_dialog, "entry_toggle_mark");
1032 SETPTR(editor_prefs.comment_toggle_mark,
1033 gtk_editable_get_chars(GTK_EDITABLE(widget), 0, -1));
1035 widget = ui_lookup_widget(ui_widgets.prefs_dialog, "spin_long_line");
1036 /* note: use stash for new code - it updates spin buttons itself */
1037 gtk_spin_button_update(GTK_SPIN_BUTTON(widget));
1038 editor_prefs.long_line_column = gtk_spin_button_get_value_as_int(GTK_SPIN_BUTTON(widget));
1040 widget = ui_lookup_widget(ui_widgets.prefs_dialog, "check_folding");
1041 editor_prefs.folding = gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(widget));
1042 ui_update_fold_items();
1044 widget = ui_lookup_widget(ui_widgets.prefs_dialog, "check_unfold_children");
1045 editor_prefs.unfold_all_children = gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(widget));
1047 widget = ui_lookup_widget(ui_widgets.prefs_dialog, "check_indent");
1048 editor_prefs.show_indent_guide = gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(widget));
1050 widget = ui_lookup_widget(ui_widgets.prefs_dialog, "check_white_space");
1051 editor_prefs.show_white_space = gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(widget));
1053 widget = ui_lookup_widget(ui_widgets.prefs_dialog, "check_line_end");
1054 editor_prefs.show_line_endings = gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(widget));
1056 widget = ui_lookup_widget(ui_widgets.prefs_dialog, "check_line_endings_only_when_differ");
1057 editor_prefs.show_line_endings_only_when_differ = gtk_toggle_button_get_active(
1058 GTK_TOGGLE_BUTTON(widget));
1060 widget = ui_lookup_widget(ui_widgets.prefs_dialog, "check_line_numbers");
1061 editor_prefs.show_linenumber_margin = gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(widget));
1063 widget = ui_lookup_widget(ui_widgets.prefs_dialog, "check_markers_margin");
1064 editor_prefs.show_markers_margin = gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(widget));
1066 widget = ui_lookup_widget(ui_widgets.prefs_dialog, "check_scroll_stop_at_last_line");
1067 editor_prefs.scroll_stop_at_last_line = gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(widget));
1069 widget = ui_lookup_widget(ui_widgets.prefs_dialog, "check_line_wrapping");
1070 editor_prefs.line_wrapping = gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(widget));
1072 widget = ui_lookup_widget(ui_widgets.prefs_dialog, "check_complete_snippets");
1073 editor_prefs.complete_snippets = gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(widget));
1075 widget = ui_lookup_widget(ui_widgets.prefs_dialog, "check_xmltag");
1076 editor_prefs.auto_close_xml_tags = gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(widget));
1078 widget = ui_lookup_widget(ui_widgets.prefs_dialog, "check_indicators");
1079 editor_prefs.use_indicators = gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(widget));
1081 widget = ui_lookup_widget(ui_widgets.prefs_dialog, "check_disable_dnd");
1082 editor_prefs.disable_dnd = gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(widget));
1084 widget = ui_lookup_widget(ui_widgets.prefs_dialog, "check_smart_home");
1085 editor_prefs.smart_home_key = gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(widget));
1087 widget = ui_lookup_widget(ui_widgets.prefs_dialog, "check_newline_strip");
1088 editor_prefs.newline_strip = gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(widget));
1090 widget = ui_lookup_widget(ui_widgets.prefs_dialog, "check_auto_multiline");
1091 editor_prefs.auto_continue_multiline = gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(widget));
1093 widget = ui_lookup_widget(ui_widgets.prefs_dialog, "check_symbol_auto_completion");
1094 editor_prefs.auto_complete_symbols = gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(widget));
1096 widget = ui_lookup_widget(ui_widgets.prefs_dialog, "spin_symbol_complete_chars");
1097 gtk_spin_button_update(GTK_SPIN_BUTTON(widget));
1098 editor_prefs.symbolcompletion_min_chars = gtk_spin_button_get_value_as_int(GTK_SPIN_BUTTON(widget));
1100 widget = ui_lookup_widget(ui_widgets.prefs_dialog, "spin_symbollistheight");
1101 gtk_spin_button_update(GTK_SPIN_BUTTON(widget));
1102 editor_prefs.symbolcompletion_max_height = gtk_spin_button_get_value_as_int(GTK_SPIN_BUTTON(widget));
1104 widget = ui_lookup_widget(ui_widgets.prefs_dialog, "spin_line_break");
1105 gtk_spin_button_update(GTK_SPIN_BUTTON(widget));
1106 editor_prefs.line_break_column = gtk_spin_button_get_value_as_int(GTK_SPIN_BUTTON(widget));
1108 widget = ui_lookup_widget(ui_widgets.prefs_dialog, "check_autoclose_parenthesis");
1109 autoclose_brackets[0] = gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(widget));
1111 widget = ui_lookup_widget(ui_widgets.prefs_dialog, "check_autoclose_cbracket");
1112 autoclose_brackets[1] = gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(widget));
1114 widget = ui_lookup_widget(ui_widgets.prefs_dialog, "check_autoclose_sbracket");
1115 autoclose_brackets[2] = gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(widget));
1117 widget = ui_lookup_widget(ui_widgets.prefs_dialog, "check_autoclose_squote");
1118 autoclose_brackets[3] = gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(widget));
1120 widget = ui_lookup_widget(ui_widgets.prefs_dialog, "check_autoclose_dquote");
1121 autoclose_brackets[4] = gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(widget));
1123 editor_prefs.autoclose_chars =
1124 (autoclose_brackets[0] ? GEANY_AC_PARENTHESIS : 0u)
1125 | (autoclose_brackets[1] ? GEANY_AC_CBRACKET : 0u)
1126 | (autoclose_brackets[2] ? GEANY_AC_SBRACKET : 0u)
1127 | (autoclose_brackets[3] ? GEANY_AC_SQUOTE : 0u)
1128 | (autoclose_brackets[4] ? GEANY_AC_DQUOTE : 0u);
1130 /* Tools Settings */
1132 widget = ui_lookup_widget(ui_widgets.prefs_dialog, "entry_com_term");
1133 g_free(tool_prefs.term_cmd);
1134 tool_prefs.term_cmd = g_strdup(gtk_entry_get_text(GTK_ENTRY(widget)));
1136 widget = ui_lookup_widget(ui_widgets.prefs_dialog, "entry_browser");
1137 g_free(tool_prefs.browser_cmd);
1138 tool_prefs.browser_cmd = g_strdup(gtk_entry_get_text(GTK_ENTRY(widget)));
1140 widget = ui_lookup_widget(ui_widgets.prefs_dialog, "entry_grep");
1141 g_free(tool_prefs.grep_cmd);
1142 tool_prefs.grep_cmd = g_strdup(gtk_entry_get_text(GTK_ENTRY(widget)));
1145 /* Template settings */
1146 widget = ui_lookup_widget(ui_widgets.prefs_dialog, "entry_template_developer");
1147 g_free(template_prefs.developer);
1148 template_prefs.developer = g_strdup(gtk_entry_get_text(GTK_ENTRY(widget)));
1150 widget = ui_lookup_widget(ui_widgets.prefs_dialog, "entry_template_company");
1151 g_free(template_prefs.company);
1152 template_prefs.company = g_strdup(gtk_entry_get_text(GTK_ENTRY(widget)));
1154 widget = ui_lookup_widget(ui_widgets.prefs_dialog, "entry_template_mail");
1155 g_free(template_prefs.mail);
1156 template_prefs.mail = g_strdup(gtk_entry_get_text(GTK_ENTRY(widget)));
1158 widget = ui_lookup_widget(ui_widgets.prefs_dialog, "entry_template_initial");
1159 g_free(template_prefs.initials);
1160 template_prefs.initials = g_strdup(gtk_entry_get_text(GTK_ENTRY(widget)));
1162 widget = ui_lookup_widget(ui_widgets.prefs_dialog, "entry_template_version");
1163 g_free(template_prefs.version);
1164 template_prefs.version = g_strdup(gtk_entry_get_text(GTK_ENTRY(widget)));
1166 widget = ui_lookup_widget(ui_widgets.prefs_dialog, "entry_template_year");
1167 g_free(template_prefs.year_format);
1168 template_prefs.year_format = g_strdup(gtk_entry_get_text(GTK_ENTRY(widget)));
1170 widget = ui_lookup_widget(ui_widgets.prefs_dialog, "entry_template_date");
1171 g_free(template_prefs.date_format);
1172 template_prefs.date_format = g_strdup(gtk_entry_get_text(GTK_ENTRY(widget)));
1174 widget = ui_lookup_widget(ui_widgets.prefs_dialog, "entry_template_datetime");
1175 g_free(template_prefs.datetime_format);
1176 template_prefs.datetime_format = g_strdup(gtk_entry_get_text(GTK_ENTRY(widget)));
1179 /* Keybindings */
1180 if (global_kb_data.edited)
1182 kb_update(&global_kb_data);
1183 tools_create_insert_custom_command_menu_items();
1184 keybindings_write_to_file();
1185 #ifdef MAC_INTEGRATION
1186 /* Force re-syncing the menubar to update displayed keybindings. */
1187 gtkosx_application_sync_menubar(gtkosx_application_get());
1188 #endif
1191 /* Printing */
1192 widget = ui_lookup_widget(ui_widgets.prefs_dialog, "radio_print_gtk");
1193 printing_prefs.use_gtk_printing = gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(widget));
1195 widget = ui_lookup_widget(ui_widgets.prefs_dialog, "entry_print_external_cmd");
1196 g_free(printing_prefs.external_print_cmd);
1197 printing_prefs.external_print_cmd = g_strdup(gtk_entry_get_text(GTK_ENTRY(widget)));
1199 widget = ui_lookup_widget(ui_widgets.prefs_dialog, "check_print_linenumbers");
1200 printing_prefs.print_line_numbers = gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(widget));
1202 widget = ui_lookup_widget(ui_widgets.prefs_dialog, "check_print_pagenumbers");
1203 printing_prefs.print_page_numbers = gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(widget));
1205 widget = ui_lookup_widget(ui_widgets.prefs_dialog, "check_print_pageheader");
1206 printing_prefs.print_page_header = gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(widget));
1208 widget = ui_lookup_widget(ui_widgets.prefs_dialog, "check_print_basename");
1209 printing_prefs.page_header_basename = gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(widget));
1211 widget = ui_lookup_widget(ui_widgets.prefs_dialog, "entry_print_dateformat");
1212 g_free(printing_prefs.page_header_datefmt);
1213 printing_prefs.page_header_datefmt = g_strdup(gtk_entry_get_text(GTK_ENTRY(widget)));
1216 #ifdef HAVE_VTE
1217 widget = ui_lookup_widget(ui_widgets.prefs_dialog, "check_vte");
1218 vte_info.load_vte = gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(widget));
1220 /* VTE settings */
1221 if (vte_info.have_vte)
1223 VteConfig *vc = &vte_config;
1225 widget = ui_lookup_widget(ui_widgets.prefs_dialog, "spin_scrollback");
1226 gtk_spin_button_update(GTK_SPIN_BUTTON(widget));
1227 vc->scrollback_lines = gtk_spin_button_get_value_as_int(GTK_SPIN_BUTTON(widget));
1229 widget = ui_lookup_widget(ui_widgets.prefs_dialog, "entry_shell");
1230 g_free(vc->shell);
1231 vc->shell = g_strdup(gtk_entry_get_text(GTK_ENTRY(widget)));
1233 widget = ui_lookup_widget(ui_widgets.prefs_dialog, "check_scroll_key");
1234 vc->scroll_on_key = gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(widget));
1236 widget = ui_lookup_widget(ui_widgets.prefs_dialog, "check_scroll_out");
1237 vc->scroll_on_out = gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(widget));
1239 widget = ui_lookup_widget(ui_widgets.prefs_dialog, "check_enable_bash_keys");
1240 vc->enable_bash_keys = gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(widget));
1242 widget = ui_lookup_widget(ui_widgets.prefs_dialog, "check_ignore_menu_key");
1243 vc->ignore_menu_bar_accel = gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(widget));
1245 widget = ui_lookup_widget(ui_widgets.prefs_dialog, "check_follow_path");
1246 vc->follow_path = gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(widget));
1248 widget = ui_lookup_widget(ui_widgets.prefs_dialog, "check_run_in_vte");
1249 vc->run_in_vte = gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(widget));
1251 widget = ui_lookup_widget(ui_widgets.prefs_dialog, "check_skip_script");
1252 vc->skip_run_script = gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(widget));
1254 widget = ui_lookup_widget(ui_widgets.prefs_dialog, "check_cursor_blinks");
1255 vc->cursor_blinks = gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(widget));
1257 vte_apply_user_settings();
1259 #endif
1261 /* apply the changes made */
1262 ui_statusbar_showhide(interface_prefs.statusbar_visible);
1263 sidebar_openfiles_update_all(); /* to update if full path setting has changed */
1264 toolbar_apply_settings();
1265 toolbar_update_ui();
1266 toolbar_show_hide();
1267 ui_sidebar_show_hide();
1268 gtk_notebook_set_show_tabs(GTK_NOTEBOOK(main_widgets.notebook), interface_prefs.show_notebook_tabs);
1270 gtk_notebook_set_tab_pos(GTK_NOTEBOOK(main_widgets.notebook), interface_prefs.tab_pos_editor);
1271 gtk_notebook_set_tab_pos(GTK_NOTEBOOK(msgwindow.notebook), interface_prefs.tab_pos_msgwin);
1272 gtk_notebook_set_tab_pos(GTK_NOTEBOOK(main_widgets.sidebar_notebook), interface_prefs.tab_pos_sidebar);
1274 /* re-colourise all open documents, if tab width or long line settings have changed */
1275 for (i = 0; i < documents_array->len; i++)
1277 if (documents[i]->is_valid)
1279 editor_apply_update_prefs(documents[i]->editor);
1280 if (! editor_prefs.folding)
1281 editor_unfold_all(documents[i]->editor);
1283 document_update_tab_label(documents[i]);
1286 ui_document_show_hide(NULL);
1287 ui_update_view_editor_menu_items();
1289 /* various preferences */
1290 ui_save_buttons_toggle((doc != NULL) ? doc->changed : FALSE);
1291 msgwin_show_hide_tabs();
1292 ui_update_statusbar(doc, -1);
1293 ui_set_window_title(doc);
1295 /* store all settings */
1296 configuration_save();
1299 if (response == GTK_RESPONSE_HELP)
1301 open_preferences_help();
1303 else if (response != GTK_RESPONSE_APPLY)
1305 gtk_tree_store_clear(global_kb_data.store);
1306 gtk_widget_hide(GTK_WIDGET(dialog));
1311 static void on_color_button_choose_cb(GtkColorButton *widget, gpointer user_data)
1313 GdkColor color;
1315 gtk_color_button_get_color(widget, &color);
1316 SETPTR(editor_prefs.long_line_color, utils_get_hex_from_color(&color));
1320 static void on_prefs_font_choosed(GtkFontButton *widget, gpointer user_data)
1322 const gchar *fontbtn = gtk_font_button_get_font_name(widget);
1323 guint i;
1325 switch (GPOINTER_TO_INT(user_data))
1327 case 1:
1329 if (strcmp(fontbtn, interface_prefs.tagbar_font) == 0)
1330 break;
1332 SETPTR(interface_prefs.tagbar_font, g_strdup(fontbtn));
1333 for (i = 0; i < documents_array->len; i++)
1335 GeanyDocument *doc = documents[i];
1337 if (documents[i]->is_valid && GTK_IS_WIDGET(doc->priv->tag_tree))
1338 ui_widget_modify_font_from_string(doc->priv->tag_tree,
1339 interface_prefs.tagbar_font);
1341 if (GTK_IS_WIDGET(tv.default_tag_tree))
1342 ui_widget_modify_font_from_string(tv.default_tag_tree, interface_prefs.tagbar_font);
1343 ui_widget_modify_font_from_string(tv.tree_openfiles, interface_prefs.tagbar_font);
1344 break;
1346 case 2:
1348 if (strcmp(fontbtn, interface_prefs.msgwin_font) == 0)
1349 break;
1350 SETPTR(interface_prefs.msgwin_font, g_strdup(fontbtn));
1351 ui_widget_modify_font_from_string(msgwindow.tree_compiler, interface_prefs.msgwin_font);
1352 ui_widget_modify_font_from_string(msgwindow.tree_msg, interface_prefs.msgwin_font);
1353 ui_widget_modify_font_from_string(msgwindow.tree_status, interface_prefs.msgwin_font);
1354 ui_widget_modify_font_from_string(msgwindow.scribble, interface_prefs.msgwin_font);
1355 break;
1357 case 3:
1359 ui_set_editor_font(fontbtn);
1360 break;
1366 static void kb_change_iter_shortcut(KbData *kbdata, GtkTreeIter *iter, const gchar *new_text)
1368 guint lkey;
1369 GdkModifierType lmods;
1371 gtk_accelerator_parse(new_text, &lkey, &lmods);
1373 if (kb_find_duplicate(kbdata->store, ui_widgets.prefs_dialog, iter, lkey, lmods, new_text))
1374 return;
1376 /* set the values here, because of the above check, setting it in
1377 * gtk_accelerator_parse would return a wrong key combination if it is duplicate */
1378 kb_set_shortcut(kbdata->store, iter, lkey, lmods);
1380 kbdata->edited = TRUE;
1384 static void kb_cell_edited_cb(GtkCellRendererText *cellrenderertext,
1385 gchar *path, gchar *new_text, KbData *kbdata)
1387 if (path != NULL && new_text != NULL)
1389 GtkTreeIter iter;
1391 gtk_tree_model_get_iter_from_string(GTK_TREE_MODEL(kbdata->store), &iter, path);
1392 if (gtk_tree_model_iter_has_child(GTK_TREE_MODEL(kbdata->store), &iter))
1393 return; /* ignore group items */
1395 kb_change_iter_shortcut(kbdata, &iter, new_text);
1400 static gboolean kb_grab_key_dialog_key_press_cb(GtkWidget *dialog, GdkEventKey *event, GtkLabel *label)
1402 gchar *str;
1403 guint state;
1405 g_return_val_if_fail(GTK_IS_LABEL(label), FALSE);
1407 state = keybindings_get_modifiers(event->state);
1409 if (event->keyval == GDK_KEY_Escape)
1410 return FALSE; /* close the dialog, don't allow escape when detecting keybindings. */
1412 str = gtk_accelerator_name(event->keyval, state);
1414 gtk_label_set_text(label, str);
1415 g_free(str);
1417 return TRUE;
1421 /* test if the entered key combination is already used
1422 * returns true if cancelling duplicate */
1423 static gboolean kb_find_duplicate(GtkTreeStore *store, GtkWidget *parent, GtkTreeIter *old_iter,
1424 guint key, GdkModifierType mods, const gchar *shortcut)
1426 GtkTreeModel *model = GTK_TREE_MODEL(store);
1427 GtkTreeIter parent_iter;
1428 gchar *kb_str;
1429 guint kb_key;
1430 GdkModifierType kb_mods;
1432 /* allow duplicate if there is no key combination */
1433 if (key == 0 && mods == 0)
1434 return FALSE;
1436 /* don't check if the new keybinding is the same as the old one */
1437 gtk_tree_model_get(model, old_iter, KB_TREE_SHORTCUT, &kb_str, -1);
1438 if (kb_str)
1440 gtk_accelerator_parse(kb_str, &kb_key, &kb_mods);
1441 g_free(kb_str);
1442 if (key == kb_key && mods == kb_mods)
1443 return FALSE;
1446 if (! gtk_tree_model_get_iter_first(model, &parent_iter))
1447 return FALSE;
1448 do /* foreach top level */
1450 GtkTreeIter iter;
1452 if (! gtk_tree_model_iter_children(model, &iter, &parent_iter))
1453 continue;
1454 do /* foreach children */
1456 gtk_tree_model_get(model, &iter, KB_TREE_SHORTCUT, &kb_str, -1);
1457 if (! kb_str)
1458 continue;
1460 gtk_accelerator_parse(kb_str, &kb_key, &kb_mods);
1461 g_free(kb_str);
1462 /* search another item with the same key and modifiers */
1463 if (kb_key == key && kb_mods == mods)
1465 gchar *label;
1466 gint ret;
1468 gtk_tree_model_get(model, &iter, KB_TREE_ACTION, &label, -1);
1469 ret = dialogs_show_prompt(parent,
1470 _("_Allow"), GTK_RESPONSE_APPLY,
1471 GTK_STOCK_CANCEL, GTK_RESPONSE_NO,
1472 _("_Override"), GTK_RESPONSE_YES,
1473 _("Override that keybinding?"),
1474 _("The combination '%s' is already used for \"%s\"."),
1475 shortcut, label);
1477 g_free(label);
1479 if (ret == GTK_RESPONSE_YES)
1481 kb_set_shortcut(store, &iter, 0, 0); /* clear shortcut */
1482 /* carry on looking for other duplicates if overriding */
1483 continue;
1485 return ret != GTK_RESPONSE_APPLY;
1488 while (gtk_tree_model_iter_next(model, &iter));
1490 while (gtk_tree_model_iter_next(model, &parent_iter));
1492 return FALSE;
1496 static void on_toolbar_show_toggled(GtkToggleButton *togglebutton, gpointer user_data)
1498 gboolean sens = gtk_toggle_button_get_active(togglebutton);
1500 gtk_widget_set_sensitive(
1501 ui_lookup_widget(ui_widgets.prefs_dialog, "frame_toolbar_style"), sens);
1502 gtk_widget_set_sensitive(
1503 ui_lookup_widget(ui_widgets.prefs_dialog, "frame_toolbar_icon"), sens);
1504 gtk_widget_set_sensitive(
1505 ui_lookup_widget(ui_widgets.prefs_dialog, "button_customize_toolbar"), sens);
1506 gtk_widget_set_sensitive(
1507 ui_lookup_widget(ui_widgets.prefs_dialog, "check_toolbar_in_menu"), sens);
1511 static void on_show_notebook_tabs_toggled(GtkToggleButton *togglebutton, gpointer user_data)
1513 gboolean sens = gtk_toggle_button_get_active(togglebutton);
1515 /* tab placement only enabled when tabs are visible */
1516 gtk_widget_set_sensitive(ui_lookup_widget(ui_widgets.prefs_dialog, "combo_tab_editor"), sens);
1517 gtk_widget_set_sensitive(ui_lookup_widget(ui_widgets.prefs_dialog, "check_show_tab_cross"), sens);
1521 static void on_use_folding_toggled(GtkToggleButton *togglebutton, gpointer user_data)
1523 gboolean sens = gtk_toggle_button_get_active(togglebutton);
1525 gtk_widget_set_sensitive(ui_lookup_widget(ui_widgets.prefs_dialog, "check_unfold_children"), sens);
1529 static void on_check_line_end_toggled(GtkToggleButton *togglebutton, gpointer user_data)
1531 gboolean sens = gtk_toggle_button_get_active(togglebutton);
1533 gtk_widget_set_sensitive(ui_lookup_widget(ui_widgets.prefs_dialog, "check_line_endings_only_when_differ"), sens);
1537 static void on_enable_plugins_toggled(GtkToggleButton *togglebutton, gpointer user_data)
1539 gboolean sens = gtk_toggle_button_get_active(togglebutton);
1541 gtk_widget_set_sensitive(ui_lookup_widget(ui_widgets.prefs_dialog, "extra_plugin_path_entry"), sens);
1542 gtk_widget_set_sensitive(ui_lookup_widget(ui_widgets.prefs_dialog, "extra_plugin_path_button"), sens);
1546 static void on_sidebar_visible_toggled(GtkToggleButton *togglebutton, gpointer user_data)
1548 gboolean sens = gtk_toggle_button_get_active(togglebutton);
1550 gtk_widget_set_sensitive(ui_lookup_widget(ui_widgets.prefs_dialog, "box_sidebar_visible_children"), sens);
1554 static void on_prefs_print_radio_button_toggled(GtkToggleButton *togglebutton, gpointer user_data)
1556 gboolean sens = gtk_toggle_button_get_active(togglebutton);
1558 gtk_widget_set_sensitive(ui_lookup_widget(ui_widgets.prefs_dialog, "vbox29"), sens);
1559 gtk_widget_set_sensitive(ui_lookup_widget(ui_widgets.prefs_dialog, "hbox9"), ! sens);
1563 static void on_prefs_print_page_header_toggled(GtkToggleButton *togglebutton, gpointer user_data)
1565 gboolean sens = gtk_toggle_button_get_active(togglebutton);
1567 gtk_widget_set_sensitive(ui_lookup_widget(ui_widgets.prefs_dialog, "check_print_basename"), sens);
1568 gtk_widget_set_sensitive(ui_lookup_widget(ui_widgets.prefs_dialog, "entry_print_dateformat"), sens);
1572 static void open_preferences_help(void)
1574 gchar *uri;
1575 const gchar *label, *suffix = NULL;
1576 GtkNotebook *notebook = GTK_NOTEBOOK(
1577 ui_lookup_widget(ui_widgets.prefs_dialog, "notebook2"));
1578 gint page_nr = gtk_notebook_get_current_page(notebook);
1579 GtkWidget *page = gtk_notebook_get_nth_page(notebook, page_nr);
1581 label = gtk_notebook_get_tab_label_text(notebook, page);
1583 /* TODO Find a better way to map the current notebook page to the
1584 * corresponding chapter in the documentation, comparing translatable
1585 * strings is easy to break. Maybe attach an identifying string to the
1586 * tab label object. */
1587 if (utils_str_equal(label, _("General")))
1588 suffix = "#general-startup-preferences";
1589 else if (utils_str_equal(label, _("Interface")))
1590 suffix = "#interface-preferences";
1591 else if (utils_str_equal(label, _("Toolbar")))
1592 suffix = "#toolbar-preferences";
1593 else if (utils_str_equal(label, _("Editor")))
1594 suffix = "#editor-features-preferences";
1595 else if (utils_str_equal(label, _("Files")))
1596 suffix = "#files-preferences";
1597 else if (utils_str_equal(label, _("Tools")))
1598 suffix = "#tools-preferences";
1599 else if (utils_str_equal(label, _("Templates")))
1600 suffix = "#template-preferences";
1601 else if (utils_str_equal(label, _("Keybindings")))
1602 suffix = "#keybinding-preferences";
1603 else if (utils_str_equal(label, _("Printing")))
1604 suffix = "#printing-preferences";
1605 else if (utils_str_equal(label, _("Various")))
1606 suffix = "#various-preferences";
1607 else if (utils_str_equal(label, _("Terminal")))
1608 suffix = "#terminal-vte-preferences";
1610 uri = utils_get_help_url(suffix);
1611 utils_open_browser(uri);
1612 g_free(uri);
1616 static gboolean prefs_dialog_key_press_response_cb(GtkWidget *dialog, GdkEventKey *event,
1617 gpointer data)
1619 GeanyKeyBinding *kb = keybindings_lookup_item(GEANY_KEY_GROUP_HELP, GEANY_KEYS_HELP_HELP);
1621 if (keybindings_check_event(event, kb))
1623 open_preferences_help();
1624 return TRUE;
1626 return FALSE;
1630 static void list_store_append_text(GtkListStore *list, const gchar *text)
1632 GtkTreeIter iter;
1634 gtk_list_store_append(list, &iter);
1635 gtk_list_store_set(list, &iter, 0, text, -1);
1639 void prefs_show_dialog(void)
1641 if (ui_widgets.prefs_dialog == NULL)
1643 GtkListStore *eol_list;
1644 GtkWidget *label;
1646 ui_widgets.prefs_dialog = create_prefs_dialog();
1647 gtk_widget_set_name(ui_widgets.prefs_dialog, "GeanyPrefsDialog");
1648 gtk_window_set_transient_for(GTK_WINDOW(ui_widgets.prefs_dialog), GTK_WINDOW(main_widgets.window));
1650 /* init the file encoding combo boxes */
1652 struct {
1653 const gchar *combo, *renderer;
1654 gboolean has_detect;
1655 } names[] = {
1656 { "combo_new_encoding", "combo_new_encoding_renderer", FALSE },
1657 { "combo_open_encoding", "combo_open_encoding_renderer", TRUE }
1659 guint i;
1661 for (i = 0; i < G_N_ELEMENTS(names); i++)
1663 GtkTreeStore *encoding_list = encodings_encoding_store_new(names[i].has_detect);
1664 GtkWidget *combo = ui_lookup_widget(ui_widgets.prefs_dialog, names[i].combo);
1666 gtk_cell_layout_set_cell_data_func(GTK_CELL_LAYOUT(combo),
1667 ui_builder_get_object(names[i].renderer),
1668 encodings_encoding_store_cell_data_func, NULL, NULL);
1669 gtk_combo_box_set_model(GTK_COMBO_BOX(combo), GTK_TREE_MODEL(encoding_list));
1670 g_object_unref(encoding_list);
1674 /* init the eol character combo box */
1675 eol_list = ui_builder_get_object("eol_list");
1676 list_store_append_text(eol_list, utils_get_eol_name(SC_EOL_CRLF));
1677 list_store_append_text(eol_list, utils_get_eol_name(SC_EOL_CR));
1678 list_store_append_text(eol_list, utils_get_eol_name(SC_EOL_LF));
1681 /* add manually GeanyWrapLabels because they can't be added with Glade */
1682 /* page Tools */
1683 label = geany_wrap_label_new(_("Enter tool paths below. Tools you do not need can be left blank."));
1684 gtk_widget_show(label);
1685 gtk_box_pack_start(GTK_BOX(ui_lookup_widget(ui_widgets.prefs_dialog, "vbox33")),
1686 label, FALSE, TRUE, 5);
1687 /* page Templates */
1688 label = geany_wrap_label_new(_("Set the information to be used in templates. See the documentation for details."));
1689 gtk_widget_show(label);
1690 gtk_box_pack_start(GTK_BOX(ui_lookup_widget(ui_widgets.prefs_dialog, "vbox31")),
1691 label, FALSE, TRUE, 5);
1692 /* page Keybindings */
1693 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."));
1694 gtk_widget_show(label);
1695 gtk_box_pack_start(GTK_BOX(ui_lookup_widget(ui_widgets.prefs_dialog, "vbox32")),
1696 label, FALSE, TRUE, 5);
1697 /* page Editor->Indentation */
1698 label = geany_wrap_label_new(_("<i>Warning: these settings are overridden by the current project. See <b>Project->Properties</b>.</i>"));
1699 gtk_widget_show(label);
1700 gtk_label_set_use_markup(GTK_LABEL(label), TRUE);
1701 gtk_misc_set_padding(GTK_MISC(label), 6, 0);
1702 gtk_box_pack_start(GTK_BOX(ui_lookup_widget(ui_widgets.prefs_dialog,
1703 "label_project_indent_warning")), label, FALSE, TRUE, 5);
1705 /* add the clear icon to GtkEntry widgets in the dialog */
1707 const gchar *names[] = {
1708 "startup_path_entry",
1709 "project_file_path_entry",
1710 "extra_plugin_path_entry",
1711 "entry_toggle_mark",
1712 /* "entry_com_make", */
1713 "entry_com_term",
1714 "entry_browser",
1715 "entry_grep",
1716 "entry_contextaction",
1717 "entry_template_developer",
1718 "entry_template_initial",
1719 "entry_template_mail",
1720 "entry_template_company",
1721 "entry_template_version",
1722 "entry_template_year",
1723 "entry_template_date",
1724 "entry_template_datetime",
1725 "entry_print_external_cmd",
1726 "entry_print_dateformat"};
1727 const gchar **name;
1729 foreach_c_array(name, names, G_N_ELEMENTS(names))
1730 ui_entry_add_clear_icon(GTK_ENTRY(ui_lookup_widget(ui_widgets.prefs_dialog, *name)));
1733 /* page Various */
1734 various_treeview = GTK_TREE_VIEW(ui_lookup_widget(ui_widgets.prefs_dialog,
1735 "various_treeview"));
1736 stash_tree_setup(pref_groups, various_treeview);
1738 #ifdef HAVE_VTE
1739 vte_append_preferences_tab();
1740 #endif
1742 ui_setup_open_button_callback(ui_lookup_widget(ui_widgets.prefs_dialog, "startup_path_button"), NULL,
1743 GTK_FILE_CHOOSER_ACTION_SELECT_FOLDER, GTK_ENTRY(ui_lookup_widget(ui_widgets.prefs_dialog, "startup_path_entry")));
1744 ui_setup_open_button_callback(ui_lookup_widget(ui_widgets.prefs_dialog, "extra_plugin_path_button"), NULL,
1745 GTK_FILE_CHOOSER_ACTION_SELECT_FOLDER, GTK_ENTRY(ui_lookup_widget(ui_widgets.prefs_dialog, "extra_plugin_path_entry")));
1747 g_signal_connect(ui_widgets.prefs_dialog, "response",
1748 G_CALLBACK(on_prefs_dialog_response), NULL);
1749 g_signal_connect(ui_widgets.prefs_dialog, "delete-event",
1750 G_CALLBACK(gtk_widget_hide_on_delete), NULL);
1752 g_signal_connect(ui_lookup_widget(ui_widgets.prefs_dialog, "tagbar_font"),
1753 "font-set", G_CALLBACK(on_prefs_font_choosed), GINT_TO_POINTER(1));
1754 g_signal_connect(ui_lookup_widget(ui_widgets.prefs_dialog, "msgwin_font"),
1755 "font-set", G_CALLBACK(on_prefs_font_choosed), GINT_TO_POINTER(2));
1756 g_signal_connect(ui_lookup_widget(ui_widgets.prefs_dialog, "editor_font"),
1757 "font-set", G_CALLBACK(on_prefs_font_choosed), GINT_TO_POINTER(3));
1758 g_signal_connect(ui_lookup_widget(ui_widgets.prefs_dialog, "long_line_color"),
1759 "color-set", G_CALLBACK(on_color_button_choose_cb), NULL);
1760 /* file chooser buttons in the tools tab */
1761 ui_setup_open_button_callback(ui_lookup_widget(ui_widgets.prefs_dialog, "button_term"),
1762 NULL,
1763 GTK_FILE_CHOOSER_ACTION_OPEN,
1764 GTK_ENTRY(ui_lookup_widget(ui_widgets.prefs_dialog, "entry_com_term")));
1765 ui_setup_open_button_callback(ui_lookup_widget(ui_widgets.prefs_dialog, "button_browser"),
1766 NULL,
1767 GTK_FILE_CHOOSER_ACTION_OPEN,
1768 GTK_ENTRY(ui_lookup_widget(ui_widgets.prefs_dialog, "entry_browser")));
1769 ui_setup_open_button_callback(ui_lookup_widget(ui_widgets.prefs_dialog, "button_grep"),
1770 NULL,
1771 GTK_FILE_CHOOSER_ACTION_OPEN,
1772 GTK_ENTRY(ui_lookup_widget(ui_widgets.prefs_dialog, "entry_grep")));
1774 /* tools commands */
1775 ui_setup_open_button_callback(ui_lookup_widget(ui_widgets.prefs_dialog, "button_contextaction"),
1776 NULL,
1777 GTK_FILE_CHOOSER_ACTION_OPEN,
1778 GTK_ENTRY(ui_lookup_widget(ui_widgets.prefs_dialog, "entry_contextaction")));
1780 /* printing */
1781 ui_setup_open_button_callback(ui_lookup_widget(ui_widgets.prefs_dialog, "button_print_external_cmd"),
1782 NULL,
1783 GTK_FILE_CHOOSER_ACTION_OPEN,
1784 GTK_ENTRY(ui_lookup_widget(ui_widgets.prefs_dialog, "entry_print_external_cmd")));
1786 g_signal_connect(ui_lookup_widget(ui_widgets.prefs_dialog, "radio_print_gtk"),
1787 "toggled", G_CALLBACK(on_prefs_print_radio_button_toggled), NULL);
1788 g_signal_connect(ui_lookup_widget(ui_widgets.prefs_dialog, "check_print_pageheader"),
1789 "toggled", G_CALLBACK(on_prefs_print_page_header_toggled), NULL);
1791 g_signal_connect(ui_lookup_widget(ui_widgets.prefs_dialog, "check_plugins"),
1792 "toggled", G_CALLBACK(on_enable_plugins_toggled), NULL);
1793 g_signal_connect(ui_lookup_widget(ui_widgets.prefs_dialog, "check_toolbar_show"),
1794 "toggled", G_CALLBACK(on_toolbar_show_toggled), NULL);
1795 g_signal_connect(ui_lookup_widget(ui_widgets.prefs_dialog, "check_show_notebook_tabs"),
1796 "toggled", G_CALLBACK(on_show_notebook_tabs_toggled), NULL);
1797 g_signal_connect(ui_lookup_widget(ui_widgets.prefs_dialog, "check_folding"),
1798 "toggled", G_CALLBACK(on_use_folding_toggled), NULL);
1799 g_signal_connect(ui_lookup_widget(ui_widgets.prefs_dialog, "check_line_end"),
1800 "toggled", G_CALLBACK(on_check_line_end_toggled), NULL);
1801 g_signal_connect(ui_lookup_widget(ui_widgets.prefs_dialog, "check_sidebar_visible"),
1802 "toggled", G_CALLBACK(on_sidebar_visible_toggled), NULL);
1804 g_signal_connect(ui_widgets.prefs_dialog,
1805 "key-press-event", G_CALLBACK(prefs_dialog_key_press_response_cb), NULL);
1808 prefs_init_dialog();
1809 gtk_window_present(GTK_WINDOW(ui_widgets.prefs_dialog));