review tweaks
[geany-mirror.git] / src / prefs.c
blob5d1b5fc970ca3a0ba3105b9feccfec9550363f84
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 "gtkcompat.h"
62 #include <stdlib.h>
63 #include <string.h>
64 #include <gdk/gdkkeysyms.h>
67 GeanyPrefs prefs;
68 GeanyToolPrefs tool_prefs;
71 typedef struct
73 GtkTreeStore *store;
74 GtkTreeView *tree;
75 gboolean edited;
77 KbData;
79 static KbData global_kb_data = { NULL, NULL, FALSE };
80 static GtkTreeView *various_treeview = NULL;
82 static GeanyKeyBinding *kb_index(guint gidx, guint kid);
83 static void kb_cell_edited_cb(GtkCellRendererText *cellrenderertext, gchar *path, gchar *new_text, KbData *kbdata);
84 static gboolean kb_grab_key_dialog_key_press_cb(GtkWidget *dialog, GdkEventKey *event, GtkLabel *label);
85 static void kb_change_iter_shortcut(KbData *kbdata, GtkTreeIter *iter, const gchar *new_text);
86 static gboolean kb_find_duplicate(GtkTreeStore *store, GtkWidget *parent, GtkTreeIter *old_iter,
87 guint key, GdkModifierType mods, const gchar *shortcut);
88 static void on_toolbar_show_toggled(GtkToggleButton *togglebutton, gpointer user_data);
89 static void on_show_notebook_tabs_toggled(GtkToggleButton *togglebutton, gpointer user_data);
90 static void on_enable_plugins_toggled(GtkToggleButton *togglebutton, gpointer user_data);
91 static void on_use_folding_toggled(GtkToggleButton *togglebutton, gpointer user_data);
92 static void on_open_encoding_toggled(GtkToggleButton *togglebutton, gpointer user_data);
93 static void on_sidebar_visible_toggled(GtkToggleButton *togglebutton, gpointer user_data);
94 static void on_prefs_print_radio_button_toggled(GtkToggleButton *togglebutton, gpointer user_data);
95 static void on_prefs_print_page_header_toggled(GtkToggleButton *togglebutton, gpointer user_data);
96 static void open_preferences_help(void);
99 typedef enum PrefCallbackAction
101 PREF_DISPLAY,
102 PREF_UPDATE
104 PrefCallbackAction;
107 /* Synchronize Stash settings with widgets (see keyfile.c - init_pref_groups()). */
108 static void prefs_action(PrefCallbackAction action)
110 StashGroup *group;
111 guint i;
113 foreach_ptr_array(group, i, pref_groups)
115 switch (action)
117 case PREF_DISPLAY:
118 stash_group_display(group, ui_widgets.prefs_dialog);
119 break;
120 case PREF_UPDATE:
121 stash_group_update(group, ui_widgets.prefs_dialog);
122 break;
126 switch (action)
128 case PREF_DISPLAY:
129 stash_tree_display(various_treeview);
130 break;
131 case PREF_UPDATE:
132 stash_tree_update(various_treeview);
133 break;
138 enum
140 KB_TREE_ACTION,
141 KB_TREE_SHORTCUT,
142 KB_TREE_INDEX,
143 KB_TREE_EDITABLE,
144 KB_TREE_WEIGHT,
145 KB_TREE_COLUMNS
149 static void kb_tree_view_change_button_clicked_cb(GtkWidget *button, KbData *kbdata)
151 GtkTreeModel *model;
152 GtkTreeIter iter;
153 GtkTreeSelection *selection;
154 gchar *name;
156 selection = gtk_tree_view_get_selection(kbdata->tree);
157 if (gtk_tree_selection_get_selected(selection, &model, &iter))
159 if (gtk_tree_model_iter_has_child(model, &iter))
160 { /* double click on a section to expand or collapse it */
161 GtkTreePath *path = gtk_tree_model_get_path(model, &iter);
163 if (gtk_tree_view_row_expanded(kbdata->tree, path))
164 gtk_tree_view_collapse_row(kbdata->tree, path);
165 else
166 gtk_tree_view_expand_row(kbdata->tree, path, FALSE);
168 gtk_tree_path_free(path);
169 return;
172 gtk_tree_model_get(model, &iter, KB_TREE_ACTION, &name, -1);
173 if (name != NULL)
175 GtkWidget *dialog;
176 GtkWidget *label;
177 GtkWidget *accel_label;
178 gchar *str;
180 dialog = gtk_dialog_new_with_buttons(_("Grab Key"), GTK_WINDOW(ui_widgets.prefs_dialog),
181 GTK_DIALOG_MODAL | GTK_DIALOG_DESTROY_WITH_PARENT,
182 GTK_STOCK_CANCEL, GTK_RESPONSE_CANCEL,
183 GTK_STOCK_OK, GTK_RESPONSE_ACCEPT, NULL);
185 str = g_strdup_printf(
186 _("Press the combination of the keys you want to use for \"%s\"."), name);
187 label = gtk_label_new(str);
188 gtk_misc_set_padding(GTK_MISC(label), 5, 10);
189 gtk_container_add(GTK_CONTAINER(gtk_dialog_get_content_area(GTK_DIALOG(dialog))), label);
191 accel_label = gtk_label_new("");
192 gtk_misc_set_padding(GTK_MISC(accel_label), 5, 10);
193 gtk_container_add(GTK_CONTAINER(gtk_dialog_get_content_area(GTK_DIALOG(dialog))), accel_label);
195 g_signal_connect(dialog, "key-press-event",
196 G_CALLBACK(kb_grab_key_dialog_key_press_cb), accel_label);
198 gtk_widget_show_all(dialog);
199 if (gtk_dialog_run(GTK_DIALOG(dialog)) == GTK_RESPONSE_ACCEPT)
201 const gchar *new_text = gtk_label_get_text(GTK_LABEL(accel_label));
203 kb_change_iter_shortcut(kbdata, &iter, new_text);
205 gtk_widget_destroy(dialog);
207 g_free(str);
208 g_free(name);
214 static void kb_show_popup_menu(KbData *kbdata, GtkWidget *widget, GdkEventButton *event)
216 static GtkWidget *menu = NULL;
217 guint button;
218 guint32 event_time;
220 if (menu == NULL)
222 GtkWidget *item;
224 menu = gtk_menu_new();
226 item = ui_image_menu_item_new(GTK_STOCK_ADD, _("_Expand All"));
227 gtk_widget_show(item);
228 gtk_container_add(GTK_CONTAINER(menu), item);
229 g_signal_connect_swapped(item, "activate", G_CALLBACK(gtk_tree_view_expand_all), kbdata->tree);
231 item = ui_image_menu_item_new(GTK_STOCK_REMOVE, _("_Collapse All"));
232 gtk_widget_show(item);
233 gtk_container_add(GTK_CONTAINER(menu), item);
234 g_signal_connect_swapped(item, "activate", G_CALLBACK(gtk_tree_view_collapse_all), kbdata->tree);
236 gtk_menu_attach_to_widget(GTK_MENU(menu), widget, NULL);
239 if (event != NULL)
241 button = event->button;
242 event_time = event->time;
244 else
246 button = 0;
247 event_time = gtk_get_current_event_time();
250 gtk_menu_popup(GTK_MENU(menu), NULL, NULL, NULL, NULL, button, event_time);
254 static gboolean kb_popup_menu_cb(GtkWidget *widget, KbData *kbdata)
256 kb_show_popup_menu(kbdata, widget, NULL);
257 return TRUE;
261 static gboolean kb_tree_view_button_press_event_cb(GtkWidget *widget, GdkEventButton *event,
262 KbData *kbdata)
264 if (event->button == 3 && event->type == GDK_BUTTON_PRESS)
266 kb_show_popup_menu(kbdata, widget, event);
267 return TRUE;
269 else if (event->type == GDK_2BUTTON_PRESS)
271 kb_tree_view_change_button_clicked_cb(NULL, kbdata);
272 return TRUE;
274 return FALSE;
278 static void kb_init_tree(KbData *kbdata)
280 GtkCellRenderer *renderer;
281 GtkTreeViewColumn *column;
283 kbdata->tree = GTK_TREE_VIEW(ui_lookup_widget(ui_widgets.prefs_dialog, "treeview7"));
285 kbdata->store = gtk_tree_store_new(KB_TREE_COLUMNS,
286 G_TYPE_STRING, G_TYPE_STRING, G_TYPE_INT, G_TYPE_BOOLEAN, G_TYPE_INT);
287 gtk_tree_view_set_model(GTK_TREE_VIEW(kbdata->tree), GTK_TREE_MODEL(kbdata->store));
288 g_object_unref(kbdata->store);
290 renderer = gtk_cell_renderer_text_new();
291 column = gtk_tree_view_column_new_with_attributes(_("Action"), renderer,
292 "text", KB_TREE_ACTION, "weight", KB_TREE_WEIGHT, NULL);
293 gtk_tree_view_append_column(GTK_TREE_VIEW(kbdata->tree), column);
295 renderer = gtk_cell_renderer_text_new();
296 column = gtk_tree_view_column_new_with_attributes(_("Shortcut"), renderer,
297 "text", KB_TREE_SHORTCUT, "editable", KB_TREE_EDITABLE,
298 "weight", KB_TREE_WEIGHT, NULL);
299 gtk_tree_view_append_column(GTK_TREE_VIEW(kbdata->tree), column);
301 /* set policy settings for the scrolled window around the treeview again, because glade
302 * doesn't keep the settings */
303 gtk_scrolled_window_set_policy(
304 GTK_SCROLLED_WINDOW(ui_lookup_widget(ui_widgets.prefs_dialog, "scrolledwindow8")),
305 GTK_POLICY_NEVER, GTK_POLICY_AUTOMATIC);
307 g_signal_connect(renderer, "edited", G_CALLBACK(kb_cell_edited_cb), kbdata);
308 g_signal_connect(kbdata->tree, "button-press-event", G_CALLBACK(kb_tree_view_button_press_event_cb), kbdata);
309 g_signal_connect(kbdata->tree, "popup-menu", G_CALLBACK(kb_popup_menu_cb), kbdata);
310 g_signal_connect(ui_lookup_widget(ui_widgets.prefs_dialog, "button2"), "clicked",
311 G_CALLBACK(kb_tree_view_change_button_clicked_cb), kbdata);
315 static void kb_set_shortcut(GtkTreeStore *store, GtkTreeIter *iter,
316 guint key, GdkModifierType mods)
318 gchar *key_string = gtk_accelerator_name(key, mods);
319 GtkTreeIter parent;
320 guint kid, gid;
321 GeanyKeyBinding *kb;
322 gboolean bold;
324 gtk_tree_store_set(store, iter, KB_TREE_SHORTCUT, key_string, -1);
325 g_free(key_string);
327 gtk_tree_model_get(GTK_TREE_MODEL(store), iter, KB_TREE_INDEX, &kid, -1);
328 gtk_tree_model_iter_parent(GTK_TREE_MODEL(store), &parent, iter);
329 gtk_tree_model_get(GTK_TREE_MODEL(store), &parent, KB_TREE_INDEX, &gid, -1);
330 kb = kb_index(gid, kid);
331 bold = key != kb->default_key || mods != kb->default_mods;
332 gtk_tree_store_set(store, iter, KB_TREE_WEIGHT,
333 bold ? PANGO_WEIGHT_BOLD : PANGO_WEIGHT_NORMAL, -1);
337 void prefs_kb_search_name(const gchar *search)
339 GtkTreeIter iter;
340 gboolean valid;
341 GtkTreeModel *model;
342 KbData *kbdata = &global_kb_data;
344 model = gtk_tree_view_get_model(kbdata->tree);
345 valid = gtk_tree_model_get_iter_first(model, &iter);
346 while (valid)
348 gchar *name;
350 gtk_tree_model_get(model, &iter, KB_TREE_ACTION, &name, -1);
351 if (g_strcmp0(name, search) == 0)
353 GtkTreePath *path = gtk_tree_model_get_path(model, &iter);
354 gtk_tree_view_scroll_to_cell(kbdata->tree, path, NULL, TRUE, .0f, .0f);
355 gtk_tree_path_free(path);
356 g_free(name);
357 break;
359 g_free(name);
360 valid = gtk_tree_model_iter_next(model, &iter);
365 static void kb_init(KbData *kbdata)
367 GtkTreeIter parent, iter;
368 gsize g, i;
369 gchar *label;
370 GeanyKeyGroup *group;
371 GeanyKeyBinding *kb;
373 if (kbdata->store == NULL)
374 kb_init_tree(kbdata);
376 foreach_ptr_array(group, g, keybinding_groups)
378 gtk_tree_store_append(kbdata->store, &parent, NULL);
379 gtk_tree_store_set(kbdata->store, &parent, KB_TREE_ACTION, group->label,
380 KB_TREE_INDEX, g, -1);
382 foreach_ptr_array(kb, i, group->key_items)
384 label = keybindings_get_label(kb);
385 gtk_tree_store_append(kbdata->store, &iter, &parent);
386 gtk_tree_store_set(kbdata->store, &iter, KB_TREE_ACTION, label,
387 KB_TREE_EDITABLE, TRUE, KB_TREE_INDEX, kb->id, -1);
388 kb_set_shortcut(kbdata->store, &iter, kb->key, kb->mods);
389 g_free(label);
392 gtk_tree_view_expand_all(GTK_TREE_VIEW(kbdata->tree));
396 /* note: new 'simple' prefs should use Stash code in keyfile.c */
397 static void prefs_init_dialog(void)
399 GtkWidget *widget;
400 GdkColor color = {0};
402 /* Synchronize with Stash settings */
403 prefs_action(PREF_DISPLAY);
405 widget = ui_lookup_widget(ui_widgets.prefs_dialog, "label_project_indent_warning");
406 ui_widget_show_hide(widget, app->project != NULL);
408 /* General settings */
409 /* startup */
410 widget = ui_lookup_widget(ui_widgets.prefs_dialog, "check_load_session");
411 gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(widget), prefs.load_session);
413 widget = ui_lookup_widget(ui_widgets.prefs_dialog, "check_project_session");
414 gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(widget), project_prefs.project_session);
416 widget = ui_lookup_widget(ui_widgets.prefs_dialog, "check_project_file_in_basedir");
417 gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(widget), project_prefs.project_file_in_basedir);
419 widget = ui_lookup_widget(ui_widgets.prefs_dialog, "check_save_win_pos");
420 gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(widget), prefs.save_winpos);
422 widget = ui_lookup_widget(ui_widgets.prefs_dialog, "check_save_win_geom");
423 gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(widget), prefs.save_wingeom);
425 widget = ui_lookup_widget(ui_widgets.prefs_dialog, "check_ask_for_quit");
426 gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(widget), prefs.confirm_exit);
428 /* behaviour */
429 widget = ui_lookup_widget(ui_widgets.prefs_dialog, "check_beep");
430 gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(widget), prefs.beep_on_errors);
432 widget = ui_lookup_widget(ui_widgets.prefs_dialog, "check_switch_pages");
433 gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(widget), prefs.switch_to_status);
435 widget = ui_lookup_widget(ui_widgets.prefs_dialog, "check_suppress_status_msgs");
436 gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(widget), prefs.suppress_status_messages);
438 widget = ui_lookup_widget(ui_widgets.prefs_dialog, "check_auto_focus");
439 gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(widget), prefs.auto_focus);
441 widget = ui_lookup_widget(ui_widgets.prefs_dialog, "check_native_windows_dialogs");
442 gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(widget),
443 interface_prefs.use_native_windows_dialogs);
445 widget = ui_lookup_widget(ui_widgets.prefs_dialog, "entry_contextaction");
446 gtk_entry_set_text(GTK_ENTRY(widget), tool_prefs.context_action_cmd);
448 project_setup_prefs(); /* project files path */
451 /* Interface settings */
452 widget = ui_lookup_widget(ui_widgets.prefs_dialog, "check_sidebar_visible");
453 gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(widget), ui_prefs.sidebar_visible);
454 on_sidebar_visible_toggled(GTK_TOGGLE_BUTTON(widget), NULL);
456 widget = ui_lookup_widget(ui_widgets.prefs_dialog, "check_list_symbol");
457 gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(widget), interface_prefs.sidebar_symbol_visible);
459 widget = ui_lookup_widget(ui_widgets.prefs_dialog, "check_list_openfiles");
460 gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(widget), interface_prefs.sidebar_openfiles_visible);
462 widget = ui_lookup_widget(ui_widgets.prefs_dialog, "tagbar_font");
463 gtk_font_button_set_font_name(GTK_FONT_BUTTON(widget), interface_prefs.tagbar_font);
465 widget = ui_lookup_widget(ui_widgets.prefs_dialog, "msgwin_font");
466 gtk_font_button_set_font_name(GTK_FONT_BUTTON(widget), interface_prefs.msgwin_font);
468 widget = ui_lookup_widget(ui_widgets.prefs_dialog, "editor_font");
469 gtk_font_button_set_font_name(GTK_FONT_BUTTON(widget), interface_prefs.editor_font);
471 widget = ui_lookup_widget(ui_widgets.prefs_dialog, "spin_long_line");
472 gtk_spin_button_set_value(GTK_SPIN_BUTTON(widget), editor_prefs.long_line_column);
474 widget = ui_lookup_widget(ui_widgets.prefs_dialog, "check_long_line");
475 gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(widget), editor_prefs.long_line_enabled);
477 switch (editor_prefs.long_line_type)
479 case 0: widget = ui_lookup_widget(ui_widgets.prefs_dialog, "radio_long_line_line"); break;
480 case 1: widget = ui_lookup_widget(ui_widgets.prefs_dialog, "radio_long_line_background"); break;
482 gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(widget), TRUE);
484 utils_parse_color(editor_prefs.long_line_color, &color);
485 widget = ui_lookup_widget(ui_widgets.prefs_dialog, "long_line_color");
486 gtk_color_button_set_color(GTK_COLOR_BUTTON(widget), &color);
488 widget = ui_lookup_widget(ui_widgets.prefs_dialog, "check_show_notebook_tabs");
489 gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(widget), interface_prefs.show_notebook_tabs);
490 /* disable following setting if notebook tabs are hidden */
491 on_show_notebook_tabs_toggled(GTK_TOGGLE_BUTTON(
492 ui_lookup_widget(ui_widgets.prefs_dialog, "check_show_notebook_tabs")), NULL);
494 widget = ui_lookup_widget(ui_widgets.prefs_dialog, "check_show_tab_cross");
495 gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(widget), file_prefs.show_tab_cross);
497 widget = ui_lookup_widget(ui_widgets.prefs_dialog, "combo_tab_editor");
498 gtk_combo_box_set_active(GTK_COMBO_BOX(widget), interface_prefs.tab_pos_editor);
500 widget = ui_lookup_widget(ui_widgets.prefs_dialog, "combo_tab_msgwin");
501 gtk_combo_box_set_active(GTK_COMBO_BOX(widget), interface_prefs.tab_pos_msgwin);
503 widget = ui_lookup_widget(ui_widgets.prefs_dialog, "combo_tab_sidebar");
504 gtk_combo_box_set_active(GTK_COMBO_BOX(widget), interface_prefs.tab_pos_sidebar);
506 widget = ui_lookup_widget(ui_widgets.prefs_dialog, "check_statusbar_visible");
507 gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(widget), interface_prefs.statusbar_visible);
510 /* Toolbar settings */
511 widget = ui_lookup_widget(ui_widgets.prefs_dialog, "check_toolbar_show");
512 gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(widget), toolbar_prefs.visible);
513 widget = ui_lookup_widget(ui_widgets.prefs_dialog, "check_toolbar_in_menu");
514 gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(widget), toolbar_prefs.append_to_menu);
516 switch (toolbar_prefs.icon_style)
518 case 0: widget = ui_lookup_widget(ui_widgets.prefs_dialog, "radio_toolbar_image"); break;
519 case 1: widget = ui_lookup_widget(ui_widgets.prefs_dialog, "radio_toolbar_text"); break;
520 default: widget = ui_lookup_widget(ui_widgets.prefs_dialog, "radio_toolbar_imagetext"); break;
522 if (toolbar_prefs.use_gtk_default_style)
523 widget = ui_lookup_widget(ui_widgets.prefs_dialog, "radio_toolbar_style_default");
524 gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(widget), TRUE);
526 switch (toolbar_prefs.icon_size)
528 case GTK_ICON_SIZE_LARGE_TOOLBAR:
529 widget = ui_lookup_widget(ui_widgets.prefs_dialog, "radio_toolbar_large"); break;
530 case GTK_ICON_SIZE_SMALL_TOOLBAR:
531 widget = ui_lookup_widget(ui_widgets.prefs_dialog, "radio_toolbar_small"); break;
532 default: widget = ui_lookup_widget(ui_widgets.prefs_dialog, "radio_toolbar_verysmall"); break;
534 if (toolbar_prefs.use_gtk_default_icon)
535 widget = ui_lookup_widget(ui_widgets.prefs_dialog, "radio_toolbar_icon_default");
536 gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(widget), TRUE);
538 /* disable elements if toolbar is hidden */
539 on_toolbar_show_toggled(GTK_TOGGLE_BUTTON(
540 ui_lookup_widget(ui_widgets.prefs_dialog, "check_toolbar_show")), NULL);
543 /* Files settings */
544 if (file_prefs.tab_order_ltr)
545 widget = ui_lookup_widget(ui_widgets.prefs_dialog, "radio_tab_right");
546 else
547 widget = ui_lookup_widget(ui_widgets.prefs_dialog, "radio_tab_left");
548 gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(widget), TRUE);
550 widget = ui_lookup_widget(ui_widgets.prefs_dialog, "check_tab_beside");
551 gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(widget), file_prefs.tab_order_beside);
553 widget = ui_lookup_widget(ui_widgets.prefs_dialog, "combo_new_encoding");
554 ui_encodings_combo_box_set_active_encoding(GTK_COMBO_BOX(widget), file_prefs.default_new_encoding);
556 widget = ui_lookup_widget(ui_widgets.prefs_dialog, "check_open_encoding");
557 gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(widget),
558 (file_prefs.default_open_encoding >= 0) ? TRUE : FALSE);
559 on_open_encoding_toggled(GTK_TOGGLE_BUTTON(widget), NULL);
561 widget = ui_lookup_widget(ui_widgets.prefs_dialog, "combo_open_encoding");
562 if (file_prefs.default_open_encoding >= 0)
564 ui_encodings_combo_box_set_active_encoding(GTK_COMBO_BOX(widget), file_prefs.default_open_encoding);
566 else
567 ui_encodings_combo_box_set_active_encoding(GTK_COMBO_BOX(widget), GEANY_ENCODING_UTF_8);
569 widget = ui_lookup_widget(ui_widgets.prefs_dialog, "combo_eol");
570 if (file_prefs.default_eol_character >= 0 && file_prefs.default_eol_character < 3)
572 gtk_combo_box_set_active(GTK_COMBO_BOX(widget), file_prefs.default_eol_character);
574 else
575 gtk_combo_box_set_active(GTK_COMBO_BOX(widget), GEANY_DEFAULT_EOL_CHARACTER);
577 widget = ui_lookup_widget(ui_widgets.prefs_dialog, "check_trailing_spaces");
578 gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(widget), file_prefs.strip_trailing_spaces);
580 widget = ui_lookup_widget(ui_widgets.prefs_dialog, "check_new_line");
581 gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(widget), file_prefs.final_new_line);
583 widget = ui_lookup_widget(ui_widgets.prefs_dialog, "check_ensure_convert_new_lines");
584 gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(widget), file_prefs.ensure_convert_new_lines);
586 /* Editor settings */
587 widget = ui_lookup_widget(ui_widgets.prefs_dialog, "entry_toggle_mark");
588 gtk_entry_set_text(GTK_ENTRY(widget), editor_prefs.comment_toggle_mark);
590 widget = ui_lookup_widget(ui_widgets.prefs_dialog, "check_replace_tabs");
591 gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(widget), file_prefs.replace_tabs);
593 widget = ui_lookup_widget(ui_widgets.prefs_dialog, "check_indent");
594 gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(widget), editor_prefs.show_indent_guide);
596 widget = ui_lookup_widget(ui_widgets.prefs_dialog, "check_white_space");
597 gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(widget), editor_prefs.show_white_space);
599 widget = ui_lookup_widget(ui_widgets.prefs_dialog, "check_line_end");
600 gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(widget), editor_prefs.show_line_endings);
602 widget = ui_lookup_widget(ui_widgets.prefs_dialog, "check_line_numbers");
603 gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(widget), editor_prefs.show_linenumber_margin);
605 widget = ui_lookup_widget(ui_widgets.prefs_dialog, "check_markers_margin");
606 gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(widget), editor_prefs.show_markers_margin);
608 widget = ui_lookup_widget(ui_widgets.prefs_dialog, "check_scroll_stop_at_last_line");
609 gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(widget), editor_prefs.scroll_stop_at_last_line);
611 widget = ui_lookup_widget(ui_widgets.prefs_dialog, "check_line_wrapping");
612 gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(widget), editor_prefs.line_wrapping);
614 widget = ui_lookup_widget(ui_widgets.prefs_dialog, "check_complete_snippets");
615 gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(widget), editor_prefs.complete_snippets);
617 widget = ui_lookup_widget(ui_widgets.prefs_dialog, "check_xmltag");
618 gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(widget), editor_prefs.auto_close_xml_tags);
620 widget = ui_lookup_widget(ui_widgets.prefs_dialog, "check_folding");
621 gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(widget), editor_prefs.folding);
623 widget = ui_lookup_widget(ui_widgets.prefs_dialog, "check_unfold_children");
624 gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(widget), editor_prefs.unfold_all_children);
625 on_use_folding_toggled(GTK_TOGGLE_BUTTON(
626 ui_lookup_widget(ui_widgets.prefs_dialog, "check_folding")), NULL);
628 widget = ui_lookup_widget(ui_widgets.prefs_dialog, "check_disable_dnd");
629 gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(widget), editor_prefs.disable_dnd);
631 widget = ui_lookup_widget(ui_widgets.prefs_dialog, "check_smart_home");
632 gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(widget), editor_prefs.smart_home_key);
634 widget = ui_lookup_widget(ui_widgets.prefs_dialog, "check_newline_strip");
635 gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(widget), editor_prefs.newline_strip);
637 widget = ui_lookup_widget(ui_widgets.prefs_dialog, "check_indicators");
638 gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(widget), editor_prefs.use_indicators);
640 widget = ui_lookup_widget(ui_widgets.prefs_dialog, "check_auto_multiline");
641 gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(widget), editor_prefs.auto_continue_multiline);
643 widget = ui_lookup_widget(ui_widgets.prefs_dialog, "check_symbol_auto_completion");
644 gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(widget), editor_prefs.auto_complete_symbols);
646 widget = ui_lookup_widget(ui_widgets.prefs_dialog, "spin_symbollistheight");
647 gtk_spin_button_set_value(GTK_SPIN_BUTTON(widget), editor_prefs.symbolcompletion_max_height);
649 widget = ui_lookup_widget(ui_widgets.prefs_dialog, "spin_symbol_complete_chars");
650 gtk_spin_button_set_value(GTK_SPIN_BUTTON(widget), editor_prefs.symbolcompletion_min_chars);
652 widget = ui_lookup_widget(ui_widgets.prefs_dialog, "spin_line_break");
653 gtk_spin_button_set_value(GTK_SPIN_BUTTON(widget), editor_prefs.line_break_column);
655 widget = ui_lookup_widget(ui_widgets.prefs_dialog, "check_autoclose_parenthesis");
656 gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(widget),
657 (editor_prefs.autoclose_chars & GEANY_AC_PARENTHESIS));
659 widget = ui_lookup_widget(ui_widgets.prefs_dialog, "check_autoclose_cbracket");
660 gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(widget),
661 (editor_prefs.autoclose_chars & GEANY_AC_CBRACKET));
663 widget = ui_lookup_widget(ui_widgets.prefs_dialog, "check_autoclose_sbracket");
664 gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(widget),
665 (editor_prefs.autoclose_chars & GEANY_AC_SBRACKET));
667 widget = ui_lookup_widget(ui_widgets.prefs_dialog, "check_autoclose_squote");
668 gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(widget),
669 (editor_prefs.autoclose_chars & GEANY_AC_SQUOTE));
671 widget = ui_lookup_widget(ui_widgets.prefs_dialog, "check_autoclose_dquote");
672 gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(widget),
673 (editor_prefs.autoclose_chars & GEANY_AC_DQUOTE));
675 /* Tools Settings */
677 if (tool_prefs.term_cmd)
678 gtk_entry_set_text(GTK_ENTRY(ui_lookup_widget(ui_widgets.prefs_dialog, "entry_com_term")), tool_prefs.term_cmd);
680 if (tool_prefs.browser_cmd)
681 gtk_entry_set_text(GTK_ENTRY(ui_lookup_widget(ui_widgets.prefs_dialog, "entry_browser")), tool_prefs.browser_cmd);
683 if (tool_prefs.grep_cmd)
684 gtk_entry_set_text(GTK_ENTRY(ui_lookup_widget(ui_widgets.prefs_dialog, "entry_grep")), tool_prefs.grep_cmd);
687 /* Template settings */
688 widget = ui_lookup_widget(ui_widgets.prefs_dialog, "entry_template_developer");
689 gtk_entry_set_text(GTK_ENTRY(widget), template_prefs.developer);
691 widget = ui_lookup_widget(ui_widgets.prefs_dialog, "entry_template_company");
692 gtk_entry_set_text(GTK_ENTRY(widget), template_prefs.company);
694 widget = ui_lookup_widget(ui_widgets.prefs_dialog, "entry_template_mail");
695 gtk_entry_set_text(GTK_ENTRY(widget), template_prefs.mail);
697 widget = ui_lookup_widget(ui_widgets.prefs_dialog, "entry_template_initial");
698 gtk_entry_set_text(GTK_ENTRY(widget), template_prefs.initials);
700 widget = ui_lookup_widget(ui_widgets.prefs_dialog, "entry_template_version");
701 gtk_entry_set_text(GTK_ENTRY(widget), template_prefs.version);
703 widget = ui_lookup_widget(ui_widgets.prefs_dialog, "entry_template_year");
704 gtk_entry_set_text(GTK_ENTRY(widget), template_prefs.year_format);
706 widget = ui_lookup_widget(ui_widgets.prefs_dialog, "entry_template_date");
707 gtk_entry_set_text(GTK_ENTRY(widget), template_prefs.date_format);
709 widget = ui_lookup_widget(ui_widgets.prefs_dialog, "entry_template_datetime");
710 gtk_entry_set_text(GTK_ENTRY(widget), template_prefs.datetime_format);
713 /* Keybindings */
714 kb_init(&global_kb_data);
716 /* Printing */
718 GtkWidget *widget_gtk = ui_lookup_widget(ui_widgets.prefs_dialog, "radio_print_gtk");
719 if (printing_prefs.use_gtk_printing)
720 widget = widget_gtk;
721 else
722 widget = ui_lookup_widget(ui_widgets.prefs_dialog, "radio_print_external");
724 gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(widget), TRUE);
726 on_prefs_print_radio_button_toggled(GTK_TOGGLE_BUTTON(widget_gtk), NULL);
728 if (printing_prefs.external_print_cmd)
729 gtk_entry_set_text(
730 GTK_ENTRY(ui_lookup_widget(ui_widgets.prefs_dialog, "entry_print_external_cmd")),
731 printing_prefs.external_print_cmd);
733 widget = ui_lookup_widget(ui_widgets.prefs_dialog, "check_print_linenumbers");
734 gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(widget), printing_prefs.print_line_numbers);
736 widget = ui_lookup_widget(ui_widgets.prefs_dialog, "check_print_pagenumbers");
737 gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(widget), printing_prefs.print_page_numbers);
739 widget = ui_lookup_widget(ui_widgets.prefs_dialog, "check_print_pageheader");
740 gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(widget), printing_prefs.print_page_header);
741 on_prefs_print_page_header_toggled(GTK_TOGGLE_BUTTON(widget), NULL);
743 widget = ui_lookup_widget(ui_widgets.prefs_dialog, "check_print_basename");
744 gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(widget), printing_prefs.page_header_basename);
746 if (printing_prefs.page_header_datefmt)
747 gtk_entry_set_text(
748 GTK_ENTRY(ui_lookup_widget(ui_widgets.prefs_dialog, "entry_print_dateformat")),
749 printing_prefs.page_header_datefmt);
752 #ifndef HAVE_PLUGINS
753 gtk_widget_set_sensitive(ui_lookup_widget(ui_widgets.prefs_dialog, "check_plugins"), FALSE);
754 #endif
755 on_enable_plugins_toggled(GTK_TOGGLE_BUTTON( ui_lookup_widget(ui_widgets.prefs_dialog, "check_plugins")), NULL);
757 #ifdef HAVE_VTE
758 /* make VTE switch visible only when VTE is compiled in, it is hidden by default */
759 widget = ui_lookup_widget(ui_widgets.prefs_dialog, "check_vte");
760 gtk_widget_show(widget);
761 gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(widget), vte_info.load_vte);
763 /* VTE settings */
764 if (vte_info.have_vte)
766 widget = ui_lookup_widget(ui_widgets.prefs_dialog, "font_term");
767 gtk_font_button_set_font_name(GTK_FONT_BUTTON(widget), vc->font);
769 widget = ui_lookup_widget(ui_widgets.prefs_dialog, "color_fore");
770 gtk_color_button_set_color(GTK_COLOR_BUTTON(widget), &vc->colour_fore);
772 widget = ui_lookup_widget(ui_widgets.prefs_dialog, "color_back");
773 gtk_color_button_set_color(GTK_COLOR_BUTTON(widget), &vc->colour_back);
775 widget = ui_lookup_widget(ui_widgets.prefs_dialog, "spin_scrollback");
776 gtk_spin_button_set_value(GTK_SPIN_BUTTON(widget), vc->scrollback_lines);
778 widget = ui_lookup_widget(ui_widgets.prefs_dialog, "entry_shell");
779 gtk_entry_set_text(GTK_ENTRY(widget), vc->shell);
781 widget = ui_lookup_widget(ui_widgets.prefs_dialog, "check_scroll_key");
782 gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(widget), vc->scroll_on_key);
784 widget = ui_lookup_widget(ui_widgets.prefs_dialog, "check_scroll_out");
785 gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(widget), vc->scroll_on_out);
787 widget = ui_lookup_widget(ui_widgets.prefs_dialog, "check_enable_bash_keys");
788 gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(widget), vc->enable_bash_keys);
790 widget = ui_lookup_widget(ui_widgets.prefs_dialog, "check_ignore_menu_key");
791 gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(widget), vc->ignore_menu_bar_accel);
793 widget = ui_lookup_widget(ui_widgets.prefs_dialog, "check_follow_path");
794 gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(widget), vc->follow_path);
796 widget = ui_lookup_widget(ui_widgets.prefs_dialog, "check_run_in_vte");
797 gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(widget), vc->run_in_vte);
799 widget = ui_lookup_widget(ui_widgets.prefs_dialog, "check_skip_script");
800 gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(widget), vc->skip_run_script);
802 widget = ui_lookup_widget(ui_widgets.prefs_dialog, "check_cursor_blinks");
803 gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(widget), vc->cursor_blinks);
805 #endif
809 /* note: uses group index, not group id, unlike keybindings_lookup_item(). */
810 static GeanyKeyBinding *kb_index(guint gidx, guint kid)
812 GeanyKeyGroup *group;
814 group = g_ptr_array_index(keybinding_groups, gidx);
815 return keybindings_get_item(group, kid);
819 /* read the treeview shortcut fields into keybindings */
820 static void kb_update(KbData *kbdata)
822 GtkTreeModel *model = GTK_TREE_MODEL(kbdata->store);
823 GtkTreeIter child, parent;
824 guint gid = 0;
826 /* get first parent */
827 if (! gtk_tree_model_iter_children(model, &parent, NULL))
828 return;
830 /* foreach parent */
831 while (TRUE)
833 /* get first child */
834 if (! gtk_tree_model_iter_children(model, &child, &parent))
835 return;
837 /* foreach child */
838 while (TRUE)
840 guint kid;
841 gchar *str;
842 guint key;
843 GdkModifierType mods;
844 GeanyKeyBinding *kb;
846 gtk_tree_model_get(model, &child, KB_TREE_INDEX, &kid, KB_TREE_SHORTCUT, &str, -1);
847 gtk_accelerator_parse(str, &key, &mods);
848 g_free(str);
849 kb = kb_index(gid, kid);
850 if (kb->key != key || kb->mods != mods)
851 keybindings_update_combo(kb, key, mods);
853 if (! gtk_tree_model_iter_next(model, &child))
854 break;
856 if (! gtk_tree_model_iter_next(model, &parent))
857 return;
858 gid++;
864 * callbacks
866 /* note: new 'simple' prefs should use Stash code in keyfile.c */
867 static void
868 on_prefs_dialog_response(GtkDialog *dialog, gint response, gpointer user_data)
870 if (response == GTK_RESPONSE_OK || response == GTK_RESPONSE_APPLY)
872 GtkWidget *widget;
873 guint i;
874 gboolean autoclose_brackets[5];
875 gboolean old_invert_all = interface_prefs.highlighting_invert_all;
876 gboolean old_sidebar_pos = interface_prefs.sidebar_pos;
877 GeanyDocument *doc = document_get_current();
879 /* Synchronize Stash settings */
880 prefs_action(PREF_UPDATE);
882 if (interface_prefs.highlighting_invert_all != old_invert_all)
883 filetypes_reload();
885 if (interface_prefs.sidebar_pos != old_sidebar_pos)
886 ui_swap_sidebar_pos();
888 widget = ui_lookup_widget(main_widgets.window, "vpaned1");
889 gtk_orientable_set_orientation(GTK_ORIENTABLE(widget), interface_prefs.msgwin_orientation);
891 /* General settings */
892 /* startup */
893 widget = ui_lookup_widget(ui_widgets.prefs_dialog, "check_load_session");
894 prefs.load_session = gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(widget));
896 widget = ui_lookup_widget(ui_widgets.prefs_dialog, "check_project_session");
897 project_prefs.project_session = gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(widget));
899 widget = ui_lookup_widget(ui_widgets.prefs_dialog, "check_project_file_in_basedir");
900 project_prefs.project_file_in_basedir = gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(widget));
902 widget = ui_lookup_widget(ui_widgets.prefs_dialog, "check_save_win_pos");
903 prefs.save_winpos = gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(widget));
905 widget = ui_lookup_widget(ui_widgets.prefs_dialog, "check_save_win_geom");
906 prefs.save_wingeom = gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(widget));
908 widget = ui_lookup_widget(ui_widgets.prefs_dialog, "check_ask_for_quit");
909 prefs.confirm_exit = gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(widget));
911 /* behaviour */
912 widget = ui_lookup_widget(ui_widgets.prefs_dialog, "check_beep");
913 prefs.beep_on_errors = gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(widget));
915 widget = ui_lookup_widget(ui_widgets.prefs_dialog, "check_switch_pages");
916 prefs.switch_to_status = gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(widget));
918 widget = ui_lookup_widget(ui_widgets.prefs_dialog, "check_suppress_status_msgs");
919 prefs.suppress_status_messages = gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(widget));
921 widget = ui_lookup_widget(ui_widgets.prefs_dialog, "check_auto_focus");
922 prefs.auto_focus = gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(widget));
924 widget = ui_lookup_widget(ui_widgets.prefs_dialog, "check_native_windows_dialogs");
925 interface_prefs.use_native_windows_dialogs =
926 gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(widget));
928 widget = ui_lookup_widget(ui_widgets.prefs_dialog, "entry_contextaction");
929 g_free(tool_prefs.context_action_cmd);
930 tool_prefs.context_action_cmd = g_strdup(gtk_entry_get_text(GTK_ENTRY(widget)));
932 project_apply_prefs(); /* project file path */
935 /* Interface settings */
936 widget = ui_lookup_widget(ui_widgets.prefs_dialog, "check_sidebar_visible");
937 ui_prefs.sidebar_visible = gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(widget));
939 widget = ui_lookup_widget(ui_widgets.prefs_dialog, "check_list_symbol");
940 interface_prefs.sidebar_symbol_visible = gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(widget));
942 widget = ui_lookup_widget(ui_widgets.prefs_dialog, "check_list_openfiles");
943 interface_prefs.sidebar_openfiles_visible = gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(widget));
945 widget = ui_lookup_widget(ui_widgets.prefs_dialog, "check_long_line");
946 editor_prefs.long_line_enabled = gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(widget));
948 widget = ui_lookup_widget(ui_widgets.prefs_dialog, "radio_long_line_line");
949 if (gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(widget)))
950 editor_prefs.long_line_type = 0;
951 else
952 /* now only the "background" radio remains */
953 editor_prefs.long_line_type = 1;
955 if (editor_prefs.long_line_column == 0)
956 editor_prefs.long_line_enabled = FALSE;
958 widget = ui_lookup_widget(ui_widgets.prefs_dialog, "check_show_notebook_tabs");
959 interface_prefs.show_notebook_tabs = gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(widget));
961 widget = ui_lookup_widget(ui_widgets.prefs_dialog, "check_show_tab_cross");
962 file_prefs.show_tab_cross = gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(widget));
964 widget = ui_lookup_widget(ui_widgets.prefs_dialog, "combo_tab_editor");
965 interface_prefs.tab_pos_editor = gtk_combo_box_get_active(GTK_COMBO_BOX(widget));
967 widget = ui_lookup_widget(ui_widgets.prefs_dialog, "combo_tab_msgwin");
968 interface_prefs.tab_pos_msgwin = gtk_combo_box_get_active(GTK_COMBO_BOX(widget));
970 widget = ui_lookup_widget(ui_widgets.prefs_dialog, "combo_tab_sidebar");
971 interface_prefs.tab_pos_sidebar = gtk_combo_box_get_active(GTK_COMBO_BOX(widget));
973 widget = ui_lookup_widget(ui_widgets.prefs_dialog, "check_statusbar_visible");
974 interface_prefs.statusbar_visible = gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(widget));
977 /* Toolbar settings */
978 widget = ui_lookup_widget(ui_widgets.prefs_dialog, "check_toolbar_show");
979 toolbar_prefs.visible = gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(widget));
980 widget = ui_lookup_widget(ui_widgets.prefs_dialog, "check_toolbar_in_menu");
981 toolbar_prefs.append_to_menu = gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(widget));
983 widget = ui_lookup_widget(ui_widgets.prefs_dialog, "radio_toolbar_style_default");
984 toolbar_prefs.use_gtk_default_style = gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(widget));
985 if (! toolbar_prefs.use_gtk_default_style)
987 widget = ui_lookup_widget(ui_widgets.prefs_dialog, "radio_toolbar_imagetext");
988 if (gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(widget)))
989 toolbar_prefs.icon_style = 2;
990 else
992 widget = ui_lookup_widget(ui_widgets.prefs_dialog, "radio_toolbar_image");
993 if (gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(widget)))
994 toolbar_prefs.icon_style = 0;
995 else
996 /* now only the text only radio remains, so set text only */
997 toolbar_prefs.icon_style = 1;
1001 widget = ui_lookup_widget(ui_widgets.prefs_dialog, "radio_toolbar_icon_default");
1002 toolbar_prefs.use_gtk_default_icon = gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(widget));
1003 if (! toolbar_prefs.use_gtk_default_icon)
1004 { toolbar_prefs.icon_size = GTK_ICON_SIZE_LARGE_TOOLBAR;
1005 widget = ui_lookup_widget(ui_widgets.prefs_dialog, "radio_toolbar_large");
1006 if (gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(widget)))
1007 toolbar_prefs.icon_size = GTK_ICON_SIZE_LARGE_TOOLBAR;
1008 else
1010 widget = ui_lookup_widget(ui_widgets.prefs_dialog, "radio_toolbar_small");
1011 if (gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(widget)))
1012 toolbar_prefs.icon_size = GTK_ICON_SIZE_SMALL_TOOLBAR;
1013 else
1014 toolbar_prefs.icon_size = GTK_ICON_SIZE_MENU;
1018 /* Files settings */
1019 widget = ui_lookup_widget(ui_widgets.prefs_dialog, "radio_tab_right");
1020 file_prefs.tab_order_ltr = gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(widget));
1022 widget = ui_lookup_widget(ui_widgets.prefs_dialog, "check_tab_beside");
1023 file_prefs.tab_order_beside = gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(widget));
1025 widget = ui_lookup_widget(ui_widgets.prefs_dialog, "combo_new_encoding");
1026 file_prefs.default_new_encoding = ui_encodings_combo_box_get_active_encoding(GTK_COMBO_BOX(widget));
1028 widget = ui_lookup_widget(ui_widgets.prefs_dialog, "check_open_encoding");
1029 if (gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(widget)))
1031 widget = ui_lookup_widget(ui_widgets.prefs_dialog, "combo_open_encoding");
1032 file_prefs.default_open_encoding = ui_encodings_combo_box_get_active_encoding(GTK_COMBO_BOX(widget));
1034 else
1035 file_prefs.default_open_encoding = -1;
1037 widget = ui_lookup_widget(ui_widgets.prefs_dialog, "combo_eol");
1038 file_prefs.default_eol_character = gtk_combo_box_get_active(GTK_COMBO_BOX(widget));
1040 widget = ui_lookup_widget(ui_widgets.prefs_dialog, "check_trailing_spaces");
1041 file_prefs.strip_trailing_spaces = gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(widget));
1043 widget = ui_lookup_widget(ui_widgets.prefs_dialog, "check_new_line");
1044 file_prefs.final_new_line = gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(widget));
1046 widget = ui_lookup_widget(ui_widgets.prefs_dialog, "check_ensure_convert_new_lines");
1047 file_prefs.ensure_convert_new_lines = gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(widget));
1049 widget = ui_lookup_widget(ui_widgets.prefs_dialog, "check_replace_tabs");
1050 file_prefs.replace_tabs = gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(widget));
1053 /* Editor settings */
1054 widget = ui_lookup_widget(ui_widgets.prefs_dialog, "entry_toggle_mark");
1055 SETPTR(editor_prefs.comment_toggle_mark,
1056 gtk_editable_get_chars(GTK_EDITABLE(widget), 0, -1));
1058 widget = ui_lookup_widget(ui_widgets.prefs_dialog, "spin_long_line");
1059 /* note: use stash for new code - it updates spin buttons itself */
1060 gtk_spin_button_update(GTK_SPIN_BUTTON(widget));
1061 editor_prefs.long_line_column = gtk_spin_button_get_value_as_int(GTK_SPIN_BUTTON(widget));
1063 widget = ui_lookup_widget(ui_widgets.prefs_dialog, "check_folding");
1064 editor_prefs.folding = gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(widget));
1065 ui_update_fold_items();
1067 widget = ui_lookup_widget(ui_widgets.prefs_dialog, "check_unfold_children");
1068 editor_prefs.unfold_all_children = gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(widget));
1070 widget = ui_lookup_widget(ui_widgets.prefs_dialog, "check_indent");
1071 editor_prefs.show_indent_guide = gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(widget));
1073 widget = ui_lookup_widget(ui_widgets.prefs_dialog, "check_white_space");
1074 editor_prefs.show_white_space = gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(widget));
1076 widget = ui_lookup_widget(ui_widgets.prefs_dialog, "check_line_end");
1077 editor_prefs.show_line_endings = gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(widget));
1079 widget = ui_lookup_widget(ui_widgets.prefs_dialog, "check_line_numbers");
1080 editor_prefs.show_linenumber_margin = gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(widget));
1082 widget = ui_lookup_widget(ui_widgets.prefs_dialog, "check_markers_margin");
1083 editor_prefs.show_markers_margin = gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(widget));
1085 widget = ui_lookup_widget(ui_widgets.prefs_dialog, "check_scroll_stop_at_last_line");
1086 editor_prefs.scroll_stop_at_last_line = gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(widget));
1088 widget = ui_lookup_widget(ui_widgets.prefs_dialog, "check_line_wrapping");
1089 editor_prefs.line_wrapping = gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(widget));
1091 widget = ui_lookup_widget(ui_widgets.prefs_dialog, "check_complete_snippets");
1092 editor_prefs.complete_snippets = gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(widget));
1094 widget = ui_lookup_widget(ui_widgets.prefs_dialog, "check_xmltag");
1095 editor_prefs.auto_close_xml_tags = gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(widget));
1097 widget = ui_lookup_widget(ui_widgets.prefs_dialog, "check_indicators");
1098 editor_prefs.use_indicators = gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(widget));
1100 widget = ui_lookup_widget(ui_widgets.prefs_dialog, "check_disable_dnd");
1101 editor_prefs.disable_dnd = gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(widget));
1103 widget = ui_lookup_widget(ui_widgets.prefs_dialog, "check_smart_home");
1104 editor_prefs.smart_home_key = gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(widget));
1106 widget = ui_lookup_widget(ui_widgets.prefs_dialog, "check_newline_strip");
1107 editor_prefs.newline_strip = gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(widget));
1109 widget = ui_lookup_widget(ui_widgets.prefs_dialog, "check_auto_multiline");
1110 editor_prefs.auto_continue_multiline = gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(widget));
1112 widget = ui_lookup_widget(ui_widgets.prefs_dialog, "check_symbol_auto_completion");
1113 editor_prefs.auto_complete_symbols = gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(widget));
1115 widget = ui_lookup_widget(ui_widgets.prefs_dialog, "spin_symbol_complete_chars");
1116 gtk_spin_button_update(GTK_SPIN_BUTTON(widget));
1117 editor_prefs.symbolcompletion_min_chars = gtk_spin_button_get_value_as_int(GTK_SPIN_BUTTON(widget));
1119 widget = ui_lookup_widget(ui_widgets.prefs_dialog, "spin_symbollistheight");
1120 gtk_spin_button_update(GTK_SPIN_BUTTON(widget));
1121 editor_prefs.symbolcompletion_max_height = gtk_spin_button_get_value_as_int(GTK_SPIN_BUTTON(widget));
1123 widget = ui_lookup_widget(ui_widgets.prefs_dialog, "spin_line_break");
1124 gtk_spin_button_update(GTK_SPIN_BUTTON(widget));
1125 editor_prefs.line_break_column = gtk_spin_button_get_value_as_int(GTK_SPIN_BUTTON(widget));
1127 widget = ui_lookup_widget(ui_widgets.prefs_dialog, "check_autoclose_parenthesis");
1128 autoclose_brackets[0] = gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(widget));
1130 widget = ui_lookup_widget(ui_widgets.prefs_dialog, "check_autoclose_cbracket");
1131 autoclose_brackets[1] = gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(widget));
1133 widget = ui_lookup_widget(ui_widgets.prefs_dialog, "check_autoclose_sbracket");
1134 autoclose_brackets[2] = gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(widget));
1136 widget = ui_lookup_widget(ui_widgets.prefs_dialog, "check_autoclose_squote");
1137 autoclose_brackets[3] = gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(widget));
1139 widget = ui_lookup_widget(ui_widgets.prefs_dialog, "check_autoclose_dquote");
1140 autoclose_brackets[4] = gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(widget));
1142 editor_prefs.autoclose_chars =
1143 (autoclose_brackets[0] ? GEANY_AC_PARENTHESIS : 0u)
1144 | (autoclose_brackets[1] ? GEANY_AC_CBRACKET : 0u)
1145 | (autoclose_brackets[2] ? GEANY_AC_SBRACKET : 0u)
1146 | (autoclose_brackets[3] ? GEANY_AC_SQUOTE : 0u)
1147 | (autoclose_brackets[4] ? GEANY_AC_DQUOTE : 0u);
1149 /* Tools Settings */
1151 widget = ui_lookup_widget(ui_widgets.prefs_dialog, "entry_com_term");
1152 g_free(tool_prefs.term_cmd);
1153 tool_prefs.term_cmd = g_strdup(gtk_entry_get_text(GTK_ENTRY(widget)));
1155 widget = ui_lookup_widget(ui_widgets.prefs_dialog, "entry_browser");
1156 g_free(tool_prefs.browser_cmd);
1157 tool_prefs.browser_cmd = g_strdup(gtk_entry_get_text(GTK_ENTRY(widget)));
1159 widget = ui_lookup_widget(ui_widgets.prefs_dialog, "entry_grep");
1160 g_free(tool_prefs.grep_cmd);
1161 tool_prefs.grep_cmd = g_strdup(gtk_entry_get_text(GTK_ENTRY(widget)));
1164 /* Template settings */
1165 widget = ui_lookup_widget(ui_widgets.prefs_dialog, "entry_template_developer");
1166 g_free(template_prefs.developer);
1167 template_prefs.developer = g_strdup(gtk_entry_get_text(GTK_ENTRY(widget)));
1169 widget = ui_lookup_widget(ui_widgets.prefs_dialog, "entry_template_company");
1170 g_free(template_prefs.company);
1171 template_prefs.company = g_strdup(gtk_entry_get_text(GTK_ENTRY(widget)));
1173 widget = ui_lookup_widget(ui_widgets.prefs_dialog, "entry_template_mail");
1174 g_free(template_prefs.mail);
1175 template_prefs.mail = g_strdup(gtk_entry_get_text(GTK_ENTRY(widget)));
1177 widget = ui_lookup_widget(ui_widgets.prefs_dialog, "entry_template_initial");
1178 g_free(template_prefs.initials);
1179 template_prefs.initials = g_strdup(gtk_entry_get_text(GTK_ENTRY(widget)));
1181 widget = ui_lookup_widget(ui_widgets.prefs_dialog, "entry_template_version");
1182 g_free(template_prefs.version);
1183 template_prefs.version = g_strdup(gtk_entry_get_text(GTK_ENTRY(widget)));
1185 widget = ui_lookup_widget(ui_widgets.prefs_dialog, "entry_template_year");
1186 g_free(template_prefs.year_format);
1187 template_prefs.year_format = g_strdup(gtk_entry_get_text(GTK_ENTRY(widget)));
1189 widget = ui_lookup_widget(ui_widgets.prefs_dialog, "entry_template_date");
1190 g_free(template_prefs.date_format);
1191 template_prefs.date_format = g_strdup(gtk_entry_get_text(GTK_ENTRY(widget)));
1193 widget = ui_lookup_widget(ui_widgets.prefs_dialog, "entry_template_datetime");
1194 g_free(template_prefs.datetime_format);
1195 template_prefs.datetime_format = g_strdup(gtk_entry_get_text(GTK_ENTRY(widget)));
1198 /* Keybindings */
1199 if (global_kb_data.edited)
1201 kb_update(&global_kb_data);
1202 tools_create_insert_custom_command_menu_items();
1203 keybindings_write_to_file();
1204 #ifdef MAC_INTEGRATION
1205 /* Force re-syncing the menubar to update displayed keybindings. */
1206 gtkosx_application_sync_menubar(gtkosx_application_get());
1207 #endif
1210 /* Printing */
1211 widget = ui_lookup_widget(ui_widgets.prefs_dialog, "radio_print_gtk");
1212 printing_prefs.use_gtk_printing = gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(widget));
1214 widget = ui_lookup_widget(ui_widgets.prefs_dialog, "entry_print_external_cmd");
1215 g_free(printing_prefs.external_print_cmd);
1216 printing_prefs.external_print_cmd = g_strdup(gtk_entry_get_text(GTK_ENTRY(widget)));
1218 widget = ui_lookup_widget(ui_widgets.prefs_dialog, "check_print_linenumbers");
1219 printing_prefs.print_line_numbers = gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(widget));
1221 widget = ui_lookup_widget(ui_widgets.prefs_dialog, "check_print_pagenumbers");
1222 printing_prefs.print_page_numbers = gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(widget));
1224 widget = ui_lookup_widget(ui_widgets.prefs_dialog, "check_print_pageheader");
1225 printing_prefs.print_page_header = gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(widget));
1227 widget = ui_lookup_widget(ui_widgets.prefs_dialog, "check_print_basename");
1228 printing_prefs.page_header_basename = gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(widget));
1230 widget = ui_lookup_widget(ui_widgets.prefs_dialog, "entry_print_dateformat");
1231 g_free(printing_prefs.page_header_datefmt);
1232 printing_prefs.page_header_datefmt = g_strdup(gtk_entry_get_text(GTK_ENTRY(widget)));
1235 #ifdef HAVE_VTE
1236 widget = ui_lookup_widget(ui_widgets.prefs_dialog, "check_vte");
1237 vte_info.load_vte = gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(widget));
1239 /* VTE settings */
1240 if (vte_info.have_vte)
1242 widget = ui_lookup_widget(ui_widgets.prefs_dialog, "spin_scrollback");
1243 gtk_spin_button_update(GTK_SPIN_BUTTON(widget));
1244 vc->scrollback_lines = gtk_spin_button_get_value_as_int(GTK_SPIN_BUTTON(widget));
1246 widget = ui_lookup_widget(ui_widgets.prefs_dialog, "entry_shell");
1247 g_free(vc->shell);
1248 vc->shell = g_strdup(gtk_entry_get_text(GTK_ENTRY(widget)));
1250 widget = ui_lookup_widget(ui_widgets.prefs_dialog, "check_scroll_key");
1251 vc->scroll_on_key = gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(widget));
1253 widget = ui_lookup_widget(ui_widgets.prefs_dialog, "check_scroll_out");
1254 vc->scroll_on_out = gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(widget));
1256 widget = ui_lookup_widget(ui_widgets.prefs_dialog, "check_enable_bash_keys");
1257 vc->enable_bash_keys = gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(widget));
1259 widget = ui_lookup_widget(ui_widgets.prefs_dialog, "check_ignore_menu_key");
1260 vc->ignore_menu_bar_accel = gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(widget));
1262 widget = ui_lookup_widget(ui_widgets.prefs_dialog, "check_follow_path");
1263 vc->follow_path = gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(widget));
1265 widget = ui_lookup_widget(ui_widgets.prefs_dialog, "check_run_in_vte");
1266 vc->run_in_vte = gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(widget));
1268 widget = ui_lookup_widget(ui_widgets.prefs_dialog, "check_skip_script");
1269 vc->skip_run_script = gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(widget));
1271 widget = ui_lookup_widget(ui_widgets.prefs_dialog, "check_cursor_blinks");
1272 vc->cursor_blinks = gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(widget));
1274 vte_apply_user_settings();
1276 #endif
1278 /* apply the changes made */
1279 ui_statusbar_showhide(interface_prefs.statusbar_visible);
1280 sidebar_openfiles_update_all(); /* to update if full path setting has changed */
1281 toolbar_apply_settings();
1282 toolbar_update_ui();
1283 toolbar_show_hide();
1284 ui_sidebar_show_hide();
1285 gtk_notebook_set_show_tabs(GTK_NOTEBOOK(main_widgets.notebook), interface_prefs.show_notebook_tabs);
1287 gtk_notebook_set_tab_pos(GTK_NOTEBOOK(main_widgets.notebook), interface_prefs.tab_pos_editor);
1288 gtk_notebook_set_tab_pos(GTK_NOTEBOOK(msgwindow.notebook), interface_prefs.tab_pos_msgwin);
1289 gtk_notebook_set_tab_pos(GTK_NOTEBOOK(main_widgets.sidebar_notebook), interface_prefs.tab_pos_sidebar);
1291 /* re-colourise all open documents, if tab width or long line settings have changed */
1292 for (i = 0; i < documents_array->len; i++)
1294 if (documents[i]->is_valid)
1296 editor_apply_update_prefs(documents[i]->editor);
1297 if (! editor_prefs.folding)
1298 editor_unfold_all(documents[i]->editor);
1301 ui_document_show_hide(NULL);
1302 ui_update_view_editor_menu_items();
1304 /* various preferences */
1305 ui_save_buttons_toggle((doc != NULL) ? doc->changed : FALSE);
1306 msgwin_show_hide_tabs();
1307 ui_update_statusbar(doc, -1);
1309 /* store all settings */
1310 configuration_save();
1313 if (response == GTK_RESPONSE_HELP)
1315 open_preferences_help();
1317 else if (response != GTK_RESPONSE_APPLY)
1319 gtk_tree_store_clear(global_kb_data.store);
1320 gtk_widget_hide(GTK_WIDGET(dialog));
1325 static void on_color_button_choose_cb(GtkColorButton *widget, gpointer user_data)
1327 GdkColor color;
1329 gtk_color_button_get_color(widget, &color);
1330 SETPTR(editor_prefs.long_line_color, utils_get_hex_from_color(&color));
1334 static void on_prefs_font_choosed(GtkFontButton *widget, gpointer user_data)
1336 const gchar *fontbtn = gtk_font_button_get_font_name(widget);
1337 guint i;
1339 switch (GPOINTER_TO_INT(user_data))
1341 case 1:
1343 if (strcmp(fontbtn, interface_prefs.tagbar_font) == 0)
1344 break;
1346 SETPTR(interface_prefs.tagbar_font, g_strdup(fontbtn));
1347 for (i = 0; i < documents_array->len; i++)
1349 GeanyDocument *doc = documents[i];
1351 if (documents[i]->is_valid && GTK_IS_WIDGET(doc->priv->tag_tree))
1352 ui_widget_modify_font_from_string(doc->priv->tag_tree,
1353 interface_prefs.tagbar_font);
1355 if (GTK_IS_WIDGET(tv.default_tag_tree))
1356 ui_widget_modify_font_from_string(tv.default_tag_tree, interface_prefs.tagbar_font);
1357 ui_widget_modify_font_from_string(tv.tree_openfiles, interface_prefs.tagbar_font);
1358 break;
1360 case 2:
1362 if (strcmp(fontbtn, interface_prefs.msgwin_font) == 0)
1363 break;
1364 SETPTR(interface_prefs.msgwin_font, g_strdup(fontbtn));
1365 ui_widget_modify_font_from_string(msgwindow.tree_compiler, interface_prefs.msgwin_font);
1366 ui_widget_modify_font_from_string(msgwindow.tree_msg, interface_prefs.msgwin_font);
1367 ui_widget_modify_font_from_string(msgwindow.tree_status, interface_prefs.msgwin_font);
1368 ui_widget_modify_font_from_string(msgwindow.scribble, interface_prefs.msgwin_font);
1369 break;
1371 case 3:
1373 ui_set_editor_font(fontbtn);
1374 break;
1380 static void kb_change_iter_shortcut(KbData *kbdata, GtkTreeIter *iter, const gchar *new_text)
1382 guint lkey;
1383 GdkModifierType lmods;
1385 gtk_accelerator_parse(new_text, &lkey, &lmods);
1387 if (kb_find_duplicate(kbdata->store, ui_widgets.prefs_dialog, iter, lkey, lmods, new_text))
1388 return;
1390 /* set the values here, because of the above check, setting it in
1391 * gtk_accelerator_parse would return a wrong key combination if it is duplicate */
1392 kb_set_shortcut(kbdata->store, iter, lkey, lmods);
1394 kbdata->edited = TRUE;
1398 static void kb_cell_edited_cb(GtkCellRendererText *cellrenderertext,
1399 gchar *path, gchar *new_text, KbData *kbdata)
1401 if (path != NULL && new_text != NULL)
1403 GtkTreeIter iter;
1405 gtk_tree_model_get_iter_from_string(GTK_TREE_MODEL(kbdata->store), &iter, path);
1406 if (gtk_tree_model_iter_has_child(GTK_TREE_MODEL(kbdata->store), &iter))
1407 return; /* ignore group items */
1409 kb_change_iter_shortcut(kbdata, &iter, new_text);
1414 static gboolean kb_grab_key_dialog_key_press_cb(GtkWidget *dialog, GdkEventKey *event, GtkLabel *label)
1416 gchar *str;
1417 guint state;
1419 g_return_val_if_fail(GTK_IS_LABEL(label), FALSE);
1421 state = keybindings_get_modifiers(event->state);
1423 if (event->keyval == GDK_Escape)
1424 return FALSE; /* close the dialog, don't allow escape when detecting keybindings. */
1426 str = gtk_accelerator_name(event->keyval, state);
1428 gtk_label_set_text(label, str);
1429 g_free(str);
1431 return TRUE;
1435 /* test if the entered key combination is already used
1436 * returns true if cancelling duplicate */
1437 static gboolean kb_find_duplicate(GtkTreeStore *store, GtkWidget *parent, GtkTreeIter *old_iter,
1438 guint key, GdkModifierType mods, const gchar *shortcut)
1440 GtkTreeModel *model = GTK_TREE_MODEL(store);
1441 GtkTreeIter parent_iter;
1442 gchar *kb_str;
1443 guint kb_key;
1444 GdkModifierType kb_mods;
1446 /* allow duplicate if there is no key combination */
1447 if (key == 0 && mods == 0)
1448 return FALSE;
1450 /* don't check if the new keybinding is the same as the old one */
1451 gtk_tree_model_get(model, old_iter, KB_TREE_SHORTCUT, &kb_str, -1);
1452 if (kb_str)
1454 gtk_accelerator_parse(kb_str, &kb_key, &kb_mods);
1455 g_free(kb_str);
1456 if (key == kb_key && mods == kb_mods)
1457 return FALSE;
1460 if (! gtk_tree_model_get_iter_first(model, &parent_iter))
1461 return FALSE;
1462 do /* foreach top level */
1464 GtkTreeIter iter;
1466 if (! gtk_tree_model_iter_children(model, &iter, &parent_iter))
1467 continue;
1468 do /* foreach children */
1470 gtk_tree_model_get(model, &iter, KB_TREE_SHORTCUT, &kb_str, -1);
1471 if (! kb_str)
1472 continue;
1474 gtk_accelerator_parse(kb_str, &kb_key, &kb_mods);
1475 g_free(kb_str);
1476 /* search another item with the same key and modifiers */
1477 if (kb_key == key && kb_mods == mods)
1479 gchar *label;
1480 gint ret;
1482 gtk_tree_model_get(model, &iter, KB_TREE_ACTION, &label, -1);
1483 ret = dialogs_show_prompt(parent,
1484 _("_Allow"), GTK_RESPONSE_APPLY,
1485 GTK_STOCK_CANCEL, GTK_RESPONSE_NO,
1486 _("_Override"), GTK_RESPONSE_YES,
1487 _("Override that keybinding?"),
1488 _("The combination '%s' is already used for \"%s\"."),
1489 shortcut, label);
1491 g_free(label);
1493 if (ret == GTK_RESPONSE_YES)
1495 kb_set_shortcut(store, &iter, 0, 0); /* clear shortcut */
1496 /* carry on looking for other duplicates if overriding */
1497 continue;
1499 return ret != GTK_RESPONSE_APPLY;
1502 while (gtk_tree_model_iter_next(model, &iter));
1504 while (gtk_tree_model_iter_next(model, &parent_iter));
1506 return FALSE;
1510 static void on_toolbar_show_toggled(GtkToggleButton *togglebutton, gpointer user_data)
1512 gboolean sens = gtk_toggle_button_get_active(togglebutton);
1514 gtk_widget_set_sensitive(
1515 ui_lookup_widget(ui_widgets.prefs_dialog, "frame_toolbar_style"), sens);
1516 gtk_widget_set_sensitive(
1517 ui_lookup_widget(ui_widgets.prefs_dialog, "frame_toolbar_icon"), sens);
1518 gtk_widget_set_sensitive(
1519 ui_lookup_widget(ui_widgets.prefs_dialog, "button_customize_toolbar"), sens);
1520 gtk_widget_set_sensitive(
1521 ui_lookup_widget(ui_widgets.prefs_dialog, "check_toolbar_in_menu"), sens);
1525 static void on_show_notebook_tabs_toggled(GtkToggleButton *togglebutton, gpointer user_data)
1527 gboolean sens = gtk_toggle_button_get_active(togglebutton);
1529 /* tab placement only enabled when tabs are visible */
1530 gtk_widget_set_sensitive(ui_lookup_widget(ui_widgets.prefs_dialog, "combo_tab_editor"), sens);
1531 gtk_widget_set_sensitive(ui_lookup_widget(ui_widgets.prefs_dialog, "check_show_tab_cross"), sens);
1535 static void on_use_folding_toggled(GtkToggleButton *togglebutton, gpointer user_data)
1537 gboolean sens = gtk_toggle_button_get_active(togglebutton);
1539 gtk_widget_set_sensitive(ui_lookup_widget(ui_widgets.prefs_dialog, "check_unfold_children"), sens);
1543 static void on_enable_plugins_toggled(GtkToggleButton *togglebutton, gpointer user_data)
1545 gboolean sens = gtk_toggle_button_get_active(togglebutton);
1547 gtk_widget_set_sensitive(ui_lookup_widget(ui_widgets.prefs_dialog, "extra_plugin_path_entry"), sens);
1548 gtk_widget_set_sensitive(ui_lookup_widget(ui_widgets.prefs_dialog, "extra_plugin_path_button"), sens);
1552 static void on_open_encoding_toggled(GtkToggleButton *togglebutton, gpointer user_data)
1554 gboolean sens = gtk_toggle_button_get_active(togglebutton);
1556 gtk_widget_set_sensitive(ui_lookup_widget(ui_widgets.prefs_dialog, "eventbox3"), sens);
1557 gtk_widget_set_sensitive(ui_lookup_widget(ui_widgets.prefs_dialog, "label_open_encoding"), sens);
1561 static void on_sidebar_visible_toggled(GtkToggleButton *togglebutton, gpointer user_data)
1563 gboolean sens = gtk_toggle_button_get_active(togglebutton);
1565 gtk_widget_set_sensitive(ui_lookup_widget(ui_widgets.prefs_dialog, "box_sidebar_visible_children"), sens);
1569 static void on_prefs_print_radio_button_toggled(GtkToggleButton *togglebutton, gpointer user_data)
1571 gboolean sens = gtk_toggle_button_get_active(togglebutton);
1573 gtk_widget_set_sensitive(ui_lookup_widget(ui_widgets.prefs_dialog, "vbox29"), sens);
1574 gtk_widget_set_sensitive(ui_lookup_widget(ui_widgets.prefs_dialog, "hbox9"), ! sens);
1578 static void on_prefs_print_page_header_toggled(GtkToggleButton *togglebutton, gpointer user_data)
1580 gboolean sens = gtk_toggle_button_get_active(togglebutton);
1582 gtk_widget_set_sensitive(ui_lookup_widget(ui_widgets.prefs_dialog, "check_print_basename"), sens);
1583 gtk_widget_set_sensitive(ui_lookup_widget(ui_widgets.prefs_dialog, "entry_print_dateformat"), sens);
1587 static void open_preferences_help(void)
1589 gchar *uri;
1590 const gchar *label, *suffix = NULL;
1591 GtkNotebook *notebook = GTK_NOTEBOOK(
1592 ui_lookup_widget(ui_widgets.prefs_dialog, "notebook2"));
1593 gint page_nr = gtk_notebook_get_current_page(notebook);
1594 GtkWidget *page = gtk_notebook_get_nth_page(notebook, page_nr);
1596 label = gtk_notebook_get_tab_label_text(notebook, page);
1598 /* TODO Find a better way to map the current notebook page to the
1599 * corresponding chapter in the documentation, comparing translatable
1600 * strings is easy to break. Maybe attach an identifying string to the
1601 * tab label object. */
1602 if (utils_str_equal(label, _("General")))
1603 suffix = "#general-startup-preferences";
1604 else if (utils_str_equal(label, _("Interface")))
1605 suffix = "#interface-preferences";
1606 else if (utils_str_equal(label, _("Toolbar")))
1607 suffix = "#toolbar-preferences";
1608 else if (utils_str_equal(label, _("Editor")))
1609 suffix = "#editor-features-preferences";
1610 else if (utils_str_equal(label, _("Files")))
1611 suffix = "#files-preferences";
1612 else if (utils_str_equal(label, _("Tools")))
1613 suffix = "#tools-preferences";
1614 else if (utils_str_equal(label, _("Templates")))
1615 suffix = "#template-preferences";
1616 else if (utils_str_equal(label, _("Keybindings")))
1617 suffix = "#keybinding-preferences";
1618 else if (utils_str_equal(label, _("Printing")))
1619 suffix = "#printing-preferences";
1620 else if (utils_str_equal(label, _("Various")))
1621 suffix = "#various-preferences";
1622 else if (utils_str_equal(label, _("Terminal")))
1623 suffix = "#terminal-vte-preferences";
1625 uri = utils_get_help_url(suffix);
1626 utils_open_browser(uri);
1627 g_free(uri);
1631 static gboolean prefs_dialog_key_press_response_cb(GtkWidget *dialog, GdkEventKey *event,
1632 gpointer data)
1634 GeanyKeyBinding *kb = keybindings_lookup_item(GEANY_KEY_GROUP_HELP, GEANY_KEYS_HELP_HELP);
1636 if (keybindings_check_event(event, kb))
1638 open_preferences_help();
1639 return TRUE;
1641 return FALSE;
1645 static void list_store_append_text(GtkListStore *list, const gchar *text)
1647 GtkTreeIter iter;
1649 gtk_list_store_append(list, &iter);
1650 gtk_list_store_set(list, &iter, 0, text, -1);
1654 void prefs_show_dialog(void)
1656 if (ui_widgets.prefs_dialog == NULL)
1658 GtkListStore *eol_list;
1659 GtkWidget *label;
1661 ui_widgets.prefs_dialog = create_prefs_dialog();
1662 gtk_widget_set_name(ui_widgets.prefs_dialog, "GeanyPrefsDialog");
1663 gtk_window_set_transient_for(GTK_WINDOW(ui_widgets.prefs_dialog), GTK_WINDOW(main_widgets.window));
1665 /* init the file encoding combo boxes */
1667 struct {
1668 const gchar *combo, *renderer;
1669 } names[] = {
1670 { "combo_new_encoding", "combo_new_encoding_renderer" },
1671 { "combo_open_encoding", "combo_open_encoding_renderer" }
1673 guint i;
1674 GtkTreeStore *encoding_list = encodings_encoding_store_new(FALSE);
1676 for (i = 0; i < G_N_ELEMENTS(names); i++)
1678 GtkWidget *combo = ui_lookup_widget(ui_widgets.prefs_dialog, names[i].combo);
1680 gtk_cell_layout_set_cell_data_func(GTK_CELL_LAYOUT(combo),
1681 ui_builder_get_object(names[i].renderer),
1682 encodings_encoding_store_cell_data_func, NULL, NULL);
1683 gtk_combo_box_set_model(GTK_COMBO_BOX(combo), GTK_TREE_MODEL(encoding_list));
1685 g_object_unref(encoding_list);
1688 /* init the eol character combo box */
1689 eol_list = ui_builder_get_object("eol_list");
1690 list_store_append_text(eol_list, utils_get_eol_name(SC_EOL_CRLF));
1691 list_store_append_text(eol_list, utils_get_eol_name(SC_EOL_CR));
1692 list_store_append_text(eol_list, utils_get_eol_name(SC_EOL_LF));
1695 /* add manually GeanyWrapLabels because they can't be added with Glade */
1696 /* page Tools */
1697 label = geany_wrap_label_new(_("Enter tool paths below. Tools you do not need can be left blank."));
1698 gtk_widget_show(label);
1699 gtk_box_pack_start(GTK_BOX(ui_lookup_widget(ui_widgets.prefs_dialog, "vbox33")),
1700 label, FALSE, TRUE, 5);
1701 /* page Templates */
1702 label = geany_wrap_label_new(_("Set the information to be used in templates. See the documentation for details."));
1703 gtk_widget_show(label);
1704 gtk_box_pack_start(GTK_BOX(ui_lookup_widget(ui_widgets.prefs_dialog, "vbox31")),
1705 label, FALSE, TRUE, 5);
1706 /* page Keybindings */
1707 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."));
1708 gtk_widget_show(label);
1709 gtk_box_pack_start(GTK_BOX(ui_lookup_widget(ui_widgets.prefs_dialog, "vbox32")),
1710 label, FALSE, TRUE, 5);
1711 /* page Editor->Indentation */
1712 label = geany_wrap_label_new(_("<i>Warning: these settings are overridden by the current project. See <b>Project->Properties</b>.</i>"));
1713 gtk_widget_show(label);
1714 gtk_label_set_use_markup(GTK_LABEL(label), TRUE);
1715 gtk_misc_set_padding(GTK_MISC(label), 6, 0);
1716 gtk_box_pack_start(GTK_BOX(ui_lookup_widget(ui_widgets.prefs_dialog,
1717 "label_project_indent_warning")), label, FALSE, TRUE, 5);
1719 /* add the clear icon to GtkEntry widgets in the dialog */
1721 const gchar *names[] = {
1722 "startup_path_entry",
1723 "project_file_path_entry",
1724 "extra_plugin_path_entry",
1725 "entry_toggle_mark",
1726 /* "entry_com_make", */
1727 "entry_com_term",
1728 "entry_browser",
1729 "entry_grep",
1730 "entry_contextaction",
1731 "entry_template_developer",
1732 "entry_template_initial",
1733 "entry_template_mail",
1734 "entry_template_company",
1735 "entry_template_version",
1736 "entry_template_year",
1737 "entry_template_date",
1738 "entry_template_datetime",
1739 "entry_print_external_cmd",
1740 "entry_print_dateformat"};
1741 const gchar **name;
1743 foreach_c_array(name, names, G_N_ELEMENTS(names))
1744 ui_entry_add_clear_icon(GTK_ENTRY(ui_lookup_widget(ui_widgets.prefs_dialog, *name)));
1747 /* page Various */
1748 various_treeview = GTK_TREE_VIEW(ui_lookup_widget(ui_widgets.prefs_dialog,
1749 "various_treeview"));
1750 stash_tree_setup(pref_groups, various_treeview);
1752 #ifdef HAVE_VTE
1753 vte_append_preferences_tab();
1754 #endif
1756 #ifndef G_OS_WIN32
1757 gtk_widget_hide(ui_lookup_widget(ui_widgets.prefs_dialog, "check_native_windows_dialogs"));
1758 #endif
1759 ui_setup_open_button_callback(ui_lookup_widget(ui_widgets.prefs_dialog, "startup_path_button"), NULL,
1760 GTK_FILE_CHOOSER_ACTION_SELECT_FOLDER, GTK_ENTRY(ui_lookup_widget(ui_widgets.prefs_dialog, "startup_path_entry")));
1761 ui_setup_open_button_callback(ui_lookup_widget(ui_widgets.prefs_dialog, "extra_plugin_path_button"), NULL,
1762 GTK_FILE_CHOOSER_ACTION_SELECT_FOLDER, GTK_ENTRY(ui_lookup_widget(ui_widgets.prefs_dialog, "extra_plugin_path_entry")));
1764 g_signal_connect(ui_widgets.prefs_dialog, "response",
1765 G_CALLBACK(on_prefs_dialog_response), NULL);
1766 g_signal_connect(ui_widgets.prefs_dialog, "delete-event",
1767 G_CALLBACK(gtk_widget_hide_on_delete), NULL);
1769 g_signal_connect(ui_lookup_widget(ui_widgets.prefs_dialog, "tagbar_font"),
1770 "font-set", G_CALLBACK(on_prefs_font_choosed), GINT_TO_POINTER(1));
1771 g_signal_connect(ui_lookup_widget(ui_widgets.prefs_dialog, "msgwin_font"),
1772 "font-set", G_CALLBACK(on_prefs_font_choosed), GINT_TO_POINTER(2));
1773 g_signal_connect(ui_lookup_widget(ui_widgets.prefs_dialog, "editor_font"),
1774 "font-set", G_CALLBACK(on_prefs_font_choosed), GINT_TO_POINTER(3));
1775 g_signal_connect(ui_lookup_widget(ui_widgets.prefs_dialog, "long_line_color"),
1776 "color-set", G_CALLBACK(on_color_button_choose_cb), NULL);
1777 /* file chooser buttons in the tools tab */
1778 ui_setup_open_button_callback(ui_lookup_widget(ui_widgets.prefs_dialog, "button_term"),
1779 NULL,
1780 GTK_FILE_CHOOSER_ACTION_OPEN,
1781 GTK_ENTRY(ui_lookup_widget(ui_widgets.prefs_dialog, "entry_com_term")));
1782 ui_setup_open_button_callback(ui_lookup_widget(ui_widgets.prefs_dialog, "button_browser"),
1783 NULL,
1784 GTK_FILE_CHOOSER_ACTION_OPEN,
1785 GTK_ENTRY(ui_lookup_widget(ui_widgets.prefs_dialog, "entry_browser")));
1786 ui_setup_open_button_callback(ui_lookup_widget(ui_widgets.prefs_dialog, "button_grep"),
1787 NULL,
1788 GTK_FILE_CHOOSER_ACTION_OPEN,
1789 GTK_ENTRY(ui_lookup_widget(ui_widgets.prefs_dialog, "entry_grep")));
1791 /* tools commands */
1792 ui_setup_open_button_callback(ui_lookup_widget(ui_widgets.prefs_dialog, "button_contextaction"),
1793 NULL,
1794 GTK_FILE_CHOOSER_ACTION_OPEN,
1795 GTK_ENTRY(ui_lookup_widget(ui_widgets.prefs_dialog, "entry_contextaction")));
1797 /* printing */
1798 ui_setup_open_button_callback(ui_lookup_widget(ui_widgets.prefs_dialog, "button_print_external_cmd"),
1799 NULL,
1800 GTK_FILE_CHOOSER_ACTION_OPEN,
1801 GTK_ENTRY(ui_lookup_widget(ui_widgets.prefs_dialog, "entry_print_external_cmd")));
1803 g_signal_connect(ui_lookup_widget(ui_widgets.prefs_dialog, "radio_print_gtk"),
1804 "toggled", G_CALLBACK(on_prefs_print_radio_button_toggled), NULL);
1805 g_signal_connect(ui_lookup_widget(ui_widgets.prefs_dialog, "check_print_pageheader"),
1806 "toggled", G_CALLBACK(on_prefs_print_page_header_toggled), NULL);
1808 g_signal_connect(ui_lookup_widget(ui_widgets.prefs_dialog, "check_plugins"),
1809 "toggled", G_CALLBACK(on_enable_plugins_toggled), NULL);
1810 g_signal_connect(ui_lookup_widget(ui_widgets.prefs_dialog, "check_toolbar_show"),
1811 "toggled", G_CALLBACK(on_toolbar_show_toggled), NULL);
1812 g_signal_connect(ui_lookup_widget(ui_widgets.prefs_dialog, "check_show_notebook_tabs"),
1813 "toggled", G_CALLBACK(on_show_notebook_tabs_toggled), NULL);
1814 g_signal_connect(ui_lookup_widget(ui_widgets.prefs_dialog, "check_folding"),
1815 "toggled", G_CALLBACK(on_use_folding_toggled), NULL);
1816 g_signal_connect(ui_lookup_widget(ui_widgets.prefs_dialog, "check_open_encoding"),
1817 "toggled", G_CALLBACK(on_open_encoding_toggled), NULL);
1818 g_signal_connect(ui_lookup_widget(ui_widgets.prefs_dialog, "check_sidebar_visible"),
1819 "toggled", G_CALLBACK(on_sidebar_visible_toggled), NULL);
1821 g_signal_connect(ui_widgets.prefs_dialog,
1822 "key-press-event", G_CALLBACK(prefs_dialog_key_press_response_cb), NULL);
1825 prefs_init_dialog();
1826 gtk_window_present(GTK_WINDOW(ui_widgets.prefs_dialog));