20130320
[gdash.git] / src / gtk / gtkuisettings.cpp
blob8beb983ab399399807cfc34a7f1f151380b26354
1 /*
2 * Copyright (c) 2007-2013, Czirkos Zoltan http://code.google.com/p/gdash/
4 * Permission to use, copy, modify, and distribute this software for any
5 * purpose with or without fee is hereby granted, provided that the above
6 * copyright notice and this permission notice appear in all copies.
8 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
9 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
10 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
11 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
12 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
13 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
14 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
17 #include "config.h"
19 #include <gtk/gtk.h>
20 #include <glib/gi18n.h>
21 #include "gtk/gtkui.hpp"
22 #include "framework/thememanager.hpp"
23 #include "gtk/gtkuisettings.hpp"
24 #include "settings.hpp"
25 #include "misc/printf.hpp"
27 #define GDASH_KEYSIM_WHAT_FOR "gdash-keysim-what-for"
28 #define GDASH_RESTAT_BOOL "gdash-restart-bool"
30 gboolean SettingsWindow::keysim_button_keypress_event(GtkWidget *widget, GdkEventKey *event, gpointer data) {
31 g_assert(event->type==GDK_KEY_PRESS); /* must be true. */
32 gtk_dialog_response(GTK_DIALOG(widget), event->keyval);
33 return TRUE; /* and say that we processed the key. */
36 void SettingsWindow::keysim_button_clicked_cb(GtkWidget *button, gpointer data) {
37 const char *what_for=(const char *)g_object_get_data(G_OBJECT(button), GDASH_KEYSIM_WHAT_FOR);
38 int *keyval=(int *) data;
40 /* dialog which has its keypress event connected to the handler above */
41 GtkWidget *dialog=gtk_dialog_new_with_buttons(_("Select Key"), GTK_WINDOW(gtk_widget_get_toplevel(button)),
42 GtkDialogFlags(GTK_DIALOG_MODAL | GTK_DIALOG_NO_SEPARATOR),
43 GTK_STOCK_CANCEL, GTK_RESPONSE_CANCEL, NULL);
44 GtkWidget *table = gtk_table_new(1,1, FALSE);
45 gtk_table_set_row_spacings(GTK_TABLE(table), 6);
46 gtk_table_set_col_spacings(GTK_TABLE(table), 6);
47 gtk_container_set_border_width(GTK_CONTAINER(table), 6);
48 gtk_box_pack_start_defaults(GTK_BOX(GTK_DIALOG(dialog)->vbox), table);
49 gtk_table_attach_defaults(GTK_TABLE(table), gd_label_new_leftaligned(_("Press key for action:")), 0, 1, 0, 1);
50 gtk_table_attach_defaults(GTK_TABLE(table), gd_label_new_leftaligned(CPrintf("<b>%s</b>") % what_for), 0, 1, 1, 2);
51 g_signal_connect(G_OBJECT(dialog), "key_press_event", G_CALLBACK(keysim_button_keypress_event), dialog);
53 gtk_window_set_resizable(GTK_WINDOW(dialog), FALSE);
54 gtk_widget_show_all(dialog);
55 int result=gtk_dialog_run(GTK_DIALOG(dialog));
56 if (result>=0) {
57 /* if positive, it must be a keyval. gtk_response_cancel and gtk_response delete is negative. */
58 *keyval = result;
59 gtk_button_set_label(GTK_BUTTON(button), gdk_keyval_name(*keyval));
61 gtk_widget_destroy(dialog);
64 GtkWidget *SettingsWindow::gd_keysim_button(Setting *setting) {
65 char const *what_for = setting->name;
66 int *keyval = (int *) setting->var;
67 g_assert(keyval!=NULL);
69 /* the button shows the current value in its name */
70 GtkWidget *button = gtk_button_new_with_label(gdk_keyval_name(*keyval));
71 g_signal_connect(G_OBJECT(button), "clicked", G_CALLBACK(keysim_button_clicked_cb), keyval);
72 g_object_set_data(G_OBJECT(button), GDASH_KEYSIM_WHAT_FOR, (gpointer) what_for);
73 gtk_widget_set_tooltip_text(button, CPrintf(_("Click here to set the key for action: %s")) % what_for);
75 return button;
79 /* settings window */
80 void SettingsWindow::bool_toggle(GtkWidget *widget, gpointer data) {
81 bool *restart_bool = (bool *)g_object_get_data(G_OBJECT(widget), GDASH_RESTAT_BOOL);
82 Setting *setting = static_cast<Setting *>(data);
83 bool *bl = (bool *) setting->var;
85 *bl = gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(widget));
86 if (setting->restart && restart_bool)
87 *restart_bool = true;
91 void SettingsWindow::int_change(GtkWidget *widget, gpointer data) {
92 bool *restart_bool = (bool *)g_object_get_data(G_OBJECT(widget), GDASH_RESTAT_BOOL);
93 Setting *setting = static_cast<Setting *>(data);
94 int *value = (int *) setting->var;
95 *value = gtk_spin_button_get_value_as_int(GTK_SPIN_BUTTON(widget));
96 if (setting->restart && restart_bool)
97 *restart_bool = true;
101 void SettingsWindow::stringv_change(GtkWidget *widget, gpointer data) {
102 bool *restart_bool = (bool *)g_object_get_data(G_OBJECT(widget), GDASH_RESTAT_BOOL);
103 Setting *setting = static_cast<Setting *>(data);
104 int *ptr = (int *) setting->var;
105 *ptr = gtk_combo_box_get_active(GTK_COMBO_BOX(widget));
106 /* if nothing selected (for some reason), set to zero. */
107 if (*ptr==-1)
108 *ptr=0;
109 if (setting->restart && restart_bool)
110 *restart_bool = true;
114 void SettingsWindow::theme_change(GtkWidget *widget, gpointer data) {
115 bool *restart_bool = (bool *)g_object_get_data(G_OBJECT(widget), GDASH_RESTAT_BOOL);
116 int *ptr = (int *) data;
117 *ptr = gtk_combo_box_get_active(GTK_COMBO_BOX(widget));
118 /* if nothing selected (for some reason), set to zero. */
119 if (*ptr==-1)
120 *ptr=0;
121 if (restart_bool)
122 *restart_bool = true;
126 GtkWidget *SettingsWindow::combo_box_new_from_stringv(const char **str) {
127 GtkWidget *combo = gtk_combo_box_new_text();
128 for (unsigned i=0; str[i]!=NULL; i++)
129 gtk_combo_box_append_text(GTK_COMBO_BOX(combo), _(str[i])); // also translate
130 return combo;
134 GtkWidget *SettingsWindow::combo_box_new_from_themelist(std::vector<std::string> const &strings) {
135 GtkWidget *combo = gtk_combo_box_new_text();
136 for (unsigned i=0; i != strings.size(); i++) {
137 if (strings[i] == "")
138 gtk_combo_box_append_text(GTK_COMBO_BOX(combo), _("[Default]"));
139 else {
140 char *thm = g_filename_display_basename(strings[i].c_str());
141 if (strrchr(thm, '.')) /* remove extension */
142 *strrchr(thm, '.')='\0';
143 gtk_combo_box_append_text(GTK_COMBO_BOX(combo), thm);
144 g_free(thm);
147 return combo;
152 * @return true, if a restart is required by some setting changed
154 bool SettingsWindow::do_settings_dialog(Setting *settings, PixbufFactory &pf) {
155 bool request_restart = false;
157 GtkWidget *dialog=gtk_dialog_new_with_buttons(_("GDash Preferences"), guess_active_toplevel(),
158 GTK_DIALOG_DESTROY_WITH_PARENT, GTK_STOCK_CLOSE, GTK_RESPONSE_ACCEPT, NULL);
159 gtk_dialog_set_has_separator(GTK_DIALOG(dialog), FALSE);
161 GtkWidget *notebook=gtk_notebook_new();
162 gtk_container_set_border_width(GTK_CONTAINER(notebook), 9);
163 gtk_box_pack_start_defaults(GTK_BOX(GTK_DIALOG(dialog)->vbox), notebook);
165 std::vector<std::string> themes;
166 int themenum;
167 load_themes_list(pf, themes, themenum);
169 int row = 0;
170 GtkWidget *table = NULL;
171 for (unsigned i=0; settings[i].name != NULL; i++) {
173 GtkWidget *widget = NULL;
175 switch (settings[i].type) {
176 case TypePage:
177 table = gtk_table_new(1, 1, FALSE);
178 gtk_container_set_border_width(GTK_CONTAINER(table), 9);
179 gtk_table_set_row_spacings(GTK_TABLE(table), 6);
180 gtk_table_set_col_spacings(GTK_TABLE(table), 12);
181 gtk_notebook_append_page(GTK_NOTEBOOK(notebook), table, gd_label_new_leftaligned(settings[i].name));
182 row = 0;
183 break;
185 case TypeBoolean:
186 widget = gtk_check_button_new();
187 gtk_widget_set_tooltip_text(widget, _(settings[i].description));
188 gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(widget), *(bool *)settings[i].var);
189 gtk_table_attach(GTK_TABLE(table), widget, 1, 2, row, row+1, GtkAttachOptions(GTK_EXPAND|GTK_FILL), GtkAttachOptions(0), 0, 0);
190 g_signal_connect(G_OBJECT(widget), "toggled", G_CALLBACK(SettingsWindow::bool_toggle), &settings[i]);
191 break;
193 case TypePercent:
194 widget = gtk_spin_button_new_with_range(0, 100, 5);
195 gtk_widget_set_tooltip_text(widget, _(settings[i].description));
196 gtk_spin_button_set_value(GTK_SPIN_BUTTON(widget), *(int *)settings[i].var);
197 g_signal_connect(G_OBJECT(widget), "value-changed", G_CALLBACK(SettingsWindow::int_change), &settings[i]);
198 gtk_table_attach(GTK_TABLE(table), widget, 1, 2, row, row+1, GtkAttachOptions(GTK_EXPAND|GTK_FILL), GtkAttachOptions(0), 0, 0);
199 break;
201 case TypeStringv:
202 widget=SettingsWindow::combo_box_new_from_stringv(settings[i].stringv);
203 gtk_widget_set_tooltip_text(widget, _(settings[i].description));
204 gtk_combo_box_set_active(GTK_COMBO_BOX(widget), *(int *)settings[i].var);
205 g_signal_connect(G_OBJECT(widget), "changed", G_CALLBACK(SettingsWindow::stringv_change), &settings[i]);
206 gtk_table_attach(GTK_TABLE(table), widget, 1, 2, row, row+1, GtkAttachOptions(GTK_EXPAND|GTK_FILL), GtkAttachOptions(0), 0, 0);
207 break;
209 case TypeTheme:
210 widget=SettingsWindow::combo_box_new_from_themelist(themes);
211 gtk_widget_set_tooltip_text(widget, _(settings[i].description));
212 gtk_combo_box_set_active(GTK_COMBO_BOX(widget), themenum);
213 g_signal_connect(G_OBJECT(widget), "changed", G_CALLBACK(SettingsWindow::theme_change), &themenum);
214 gtk_table_attach(GTK_TABLE(table), widget, 1, 2, row, row+1, GtkAttachOptions(GTK_EXPAND|GTK_FILL), GtkAttachOptions(0), 0, 0);
215 break;
217 case TypeKey:
218 widget = gd_keysim_button(&settings[i]);
219 gtk_widget_set_tooltip_text(widget, _(settings[i].description));
220 gtk_table_attach(GTK_TABLE(table), widget, 1, 2, row, row+1, GtkAttachOptions(GTK_EXPAND|GTK_FILL), GtkAttachOptions(0), 0, 0);
221 break;
224 if (widget) {
225 g_object_set_data(G_OBJECT(widget), GDASH_RESTAT_BOOL, &request_restart);
226 GtkWidget *label = gd_label_new_leftaligned(_(settings[i].name));
227 gtk_table_attach(GTK_TABLE(table), label, 0, 1, row, row+1, GtkAttachOptions(GTK_EXPAND|GTK_FILL), GtkAttachOptions(0), 0, 0);
228 gtk_label_set_mnemonic_widget(GTK_LABEL(label), widget);
231 row ++;
234 gtk_widget_show_all(dialog);
235 gtk_dialog_run(GTK_DIALOG(dialog));
237 gtk_widget_destroy(dialog);
239 gd_theme = themes[themenum];
241 return request_restart;