removing some compiler warnings
[drnoksnes] / gui / keys.c
1 /*
2 * This file is part of DrNokSnes
3 *
4 * Copyright (C) 2009 Javier S. Pedro <maemo@javispedro.com>
5 *
6 * This software is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU Lesser General Public License
8 * as published by the Free Software Foundation; either version 2.1 of
9 * the License, or (at your option) any later version.
10 *
11 * This software is distributed in the hope that it will be useful, but
12 * WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 * Lesser General Public License for more details.
15 *
16 * You should have received a copy of the GNU Lesser General Public
17 * License along with this software; if not, write to the Free Software
18 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
19 * 02110-1301 USA
20 *
21 */
22
23 #include <string.h>
24 #include <gtk/gtk.h>
25 #include <hildon/hildon-helper.h>
26
27 #if MAEMO_VERSION >= 5
28 #include <hildon/hildon-gtk.h>
29 #include <hildon/hildon-pannable-area.h>
30 #include <hildon/hildon-check-button.h>
31 #endif
32
33 #include "plugin.h"
34 #include "gconf.h"
35 #include "cellrendererkey.h"
36 #include "i18n.h"
37
38 static GtkDialog* dialog;
39 static int current_player;
40 #if MAEMO_VERSION >= 5
41 static HildonPannableArea* keys_scroll;
42 #else
43 static GtkScrolledWindow* keys_scroll;
44 #endif
45 static GtkListStore* keys_store;
46 static GtkTreeView* keys_list;
47
48 #define DIALOG_RESPONSE_DEFAULTS 1
49
50 enum
51 {
52   BUTTON_COLUMN,
53   BUTTONENTRY_COLUMN,
54   N_COLUMNS
55 };
56
57 typedef struct ButtonEntry {
58         const char * name;
59         const char * gconf_key;
60         unsigned char scancode;
61         gboolean changed;
62 } ButtonEntry;
63
64 static ButtonEntry buttons[] = {
65 #define HELP(...)
66 #define BUTTON(description, slug, actions, d, f) \
67         { description, G_STRINGIFY(slug), 0 },
68 #define ACTION(description, slug, actions, d, f) \
69         { description, G_STRINGIFY(slug), 0 },
70 #define LAST \
71         { 0 }
72 #include "buttons.inc"
73 #undef HELP
74 #undef BUTTON
75 #undef ACTION
76 #undef LAST
77 };
78
79 typedef struct 
80 {
81         gchar key_base[kGConfPlayerPathBufferLen];
82         int key_len;
83         gchar *key;
84 } IteratorData;
85
86 static gboolean load_key_config(GtkTreeModel *model, GtkTreePath *path,
87                                                                 GtkTreeIter *iter, gpointer data)
88 {
89         IteratorData *idata = (IteratorData*)data;
90         ButtonEntry *button_entry;
91
92         gtk_tree_model_get(model, iter,
93                 BUTTONENTRY_COLUMN, &button_entry,
94                 -1);
95
96         strcpy(idata->key, button_entry->gconf_key);
97         int scancode = gconf_client_get_int(gcc, idata->key_base, NULL);
98
99         button_entry->scancode = scancode;
100         button_entry->changed = FALSE;
101
102         gtk_tree_model_row_changed(GTK_TREE_MODEL(keys_store), path, iter);
103
104         return FALSE;
105 }
106
107 static void load_settings()
108 {
109         IteratorData idata;
110         idata.key_len = sprintf(idata.key_base,
111                 kGConfPlayerPath kGConfPlayerKeyboardPath "/", current_player);
112         idata.key = idata.key_base + idata.key_len;
113         gtk_tree_model_foreach(GTK_TREE_MODEL(keys_store), load_key_config, &idata);
114 }
115
116 static gboolean save_key_config(GtkTreeModel *model, GtkTreePath *path,
117                                                                 GtkTreeIter *iter, gpointer data)
118 {
119         IteratorData *idata = (IteratorData*)data;
120         ButtonEntry *button_entry;
121
122         gtk_tree_model_get(model, iter,
123                 BUTTONENTRY_COLUMN, &button_entry,
124                 -1);
125
126         if (button_entry->changed) {
127                 strcpy(idata->key, button_entry->gconf_key);
128                 gconf_client_set_int(gcc, idata->key_base, button_entry->scancode, NULL);
129                 button_entry->changed = FALSE;
130         }
131
132         gtk_tree_model_row_changed(GTK_TREE_MODEL(keys_store), path, iter);
133
134         return FALSE;
135 }
136
137 static void save_settings()
138 {
139         IteratorData idata;
140         idata.key_len = sprintf(idata.key_base,
141                 kGConfPlayerPath kGConfPlayerKeyboardPath "/", current_player);
142         idata.key = idata.key_base + idata.key_len;
143         gtk_tree_model_foreach(GTK_TREE_MODEL(keys_store), save_key_config, &idata);
144 }
145
146 static gboolean get_default_key_config(GtkTreeModel *model, GtkTreePath *path,
147                                                                 GtkTreeIter *iter, gpointer data)
148 {
149         IteratorData *idata = (IteratorData*)data;
150         ButtonEntry *button_entry;
151
152         gtk_tree_model_get(model, iter,
153                 BUTTONENTRY_COLUMN, &button_entry,
154                 -1);
155
156         strcpy(idata->key, button_entry->gconf_key);
157         GConfValue *value = gconf_client_get_default_from_schema(gcc,
158                 idata->key_base, NULL);
159         if (value) {
160                 int scancode = gconf_value_get_int(value);
161                 if (button_entry->scancode != scancode) {
162                         button_entry->scancode = scancode;
163                         button_entry->changed = TRUE;
164                 }
165                 gconf_value_free(value);
166         }
167
168         gtk_tree_model_row_changed(GTK_TREE_MODEL(keys_store), path, iter);
169
170         return FALSE;
171 }
172
173 static void get_default_settings()
174 {
175         IteratorData idata;
176         idata.key_len = sprintf(idata.key_base,
177                 kGConfPlayerPath kGConfPlayerKeyboardPath "/", current_player);
178         idata.key = idata.key_base + idata.key_len;
179         gtk_tree_model_foreach(GTK_TREE_MODEL(keys_store),
180                 get_default_key_config, &idata);
181 }
182
183 static void
184 accel_set_func (GtkTreeViewColumn *tree_column,
185                 GtkCellRenderer   *cell,
186                 GtkTreeModel      *model,
187                 GtkTreeIter       *iter,
188                 gpointer           data)
189 {
190         ButtonEntry *button_entry;
191
192         gtk_tree_model_get (model, iter,
193                                                 BUTTONENTRY_COLUMN, &button_entry,
194                                                 -1);
195
196         if (button_entry == NULL) {
197                 g_object_set (G_OBJECT (cell),
198                         "visible", FALSE,
199                         NULL);
200         } else {
201                 g_object_set (G_OBJECT (cell),
202                         "visible", TRUE,
203                         "editable", TRUE,
204                         "scancode", button_entry->scancode,
205                         "style", PANGO_STYLE_NORMAL,
206                         NULL);
207         }
208 }
209
210 static void
211 cb_key_edited(GtkCellRendererText *cell, const char *path_string,
212         guint scancode, gpointer data)
213 {
214         GtkTreePath *path = gtk_tree_path_new_from_string(path_string);
215         GtkTreeIter iter;
216         ButtonEntry *button_entry;
217
218         gtk_tree_model_get_iter(GTK_TREE_MODEL(keys_store), &iter, path);
219         gtk_tree_model_get(GTK_TREE_MODEL(keys_store), &iter,
220                 BUTTONENTRY_COLUMN, &button_entry,
221                 -1);
222
223         button_entry->scancode = scancode;
224         button_entry->changed = TRUE;
225
226         gtk_tree_model_row_changed(GTK_TREE_MODEL(keys_store), path, &iter);
227         gtk_tree_path_free(path);
228 }
229
230 static void
231 cb_key_cleared(GtkCellRendererText *cell, const char *path_string,
232         gpointer data)
233 {
234         GtkTreePath *path = gtk_tree_path_new_from_string(path_string);
235         GtkTreeIter iter;
236         ButtonEntry *button_entry;
237
238         gtk_tree_model_get_iter(GTK_TREE_MODEL(keys_store), &iter, path);
239         gtk_tree_model_get(GTK_TREE_MODEL(keys_store), &iter,
240                 BUTTONENTRY_COLUMN, &button_entry,
241                 -1);
242
243         button_entry->scancode = 0;
244         button_entry->changed = TRUE;
245
246         gtk_tree_model_row_changed(GTK_TREE_MODEL(keys_store), path, &iter);
247         gtk_tree_path_free(path);
248 }
249
250 static void cb_dialog_response(GtkWidget * sender, gint response, gpointer data)
251 {
252         if (response == DIALOG_RESPONSE_DEFAULTS) {
253                 get_default_settings();
254                 return;
255         }
256
257         if (response == GTK_RESPONSE_OK) {
258                 save_settings();
259         }
260
261         gtk_widget_destroy(GTK_WIDGET(dialog));
262 }
263
264 void keys_dialog(GtkWindow* parent, int player)
265 {
266         gchar* title = g_strdup_printf(_("Player %d keys"), player);
267         dialog = GTK_DIALOG(gtk_dialog_new_with_buttons(title,
268                 parent, GTK_DIALOG_MODAL,
269                 _("Defaults"), DIALOG_RESPONSE_DEFAULTS,
270                 GTK_STOCK_SAVE, GTK_RESPONSE_OK,
271                 GTK_STOCK_CLOSE, GTK_RESPONSE_CLOSE, NULL));
272         g_free(title);
273
274         current_player = player;
275
276         keys_store = GTK_LIST_STORE(gtk_list_store_new(N_COLUMNS,
277                 G_TYPE_STRING, G_TYPE_POINTER));
278 #if MAEMO_VERSION >= 5
279         keys_list = GTK_TREE_VIEW(hildon_gtk_tree_view_new_with_model(
280                 HILDON_UI_MODE_EDIT, GTK_TREE_MODEL(keys_store)));
281         keys_scroll = HILDON_PANNABLE_AREA(hildon_pannable_area_new());
282 #else
283         keys_list = GTK_TREE_VIEW(
284                 gtk_tree_view_new_with_model(GTK_TREE_MODEL(keys_store)));
285         keys_scroll = GTK_SCROLLED_WINDOW(gtk_scrolled_window_new(NULL, NULL));
286         gtk_scrolled_window_set_policy(keys_scroll,
287                 GTK_POLICY_NEVER, GTK_POLICY_AUTOMATIC);
288 #endif
289
290         GtkCellRenderer* renderer = GTK_CELL_RENDERER(gtk_cell_renderer_text_new());
291         GtkTreeViewColumn * column =
292                  gtk_tree_view_column_new_with_attributes (_("Button"),
293                         gtk_cell_renderer_text_new(),
294                         "text", BUTTON_COLUMN,
295                         NULL);
296         gtk_tree_view_column_set_resizable(column, FALSE);
297         gtk_tree_view_column_set_expand(column, TRUE);
298         gtk_tree_view_append_column(keys_list, column);
299
300         renderer = GTK_CELL_RENDERER(cell_renderer_key_new());
301         column = gtk_tree_view_column_new_with_attributes(_("Key"), renderer, NULL);
302         gtk_tree_view_column_set_cell_data_func(column, renderer, accel_set_func, NULL, NULL);
303         gtk_tree_view_column_set_resizable(column, FALSE);
304 #if MAEMO_VERSION >= 5
305         gtk_tree_view_column_set_min_width(column, 340);
306 #else
307         gtk_tree_view_column_set_min_width(column, 250);
308 #endif
309         gtk_tree_view_append_column(keys_list, column);
310         gtk_tree_view_set_headers_visible(keys_list, TRUE);
311
312         int i;
313         for (i = 0; buttons[i].name; i++) {
314                 GtkTreeIter iter;
315                 gtk_list_store_append(keys_store, &iter);
316                 gtk_list_store_set(keys_store, &iter,
317                         BUTTON_COLUMN, _(buttons[i].name),
318                         BUTTONENTRY_COLUMN, &buttons[i],
319                         -1);
320         }
321
322 #if MAEMO_VERSION >= 5
323         gtk_window_resize(GTK_WINDOW(dialog), 800, 340);
324 #else
325         gtk_window_resize(GTK_WINDOW(dialog), 600, 340);
326 #endif
327         gtk_container_add(GTK_CONTAINER(keys_scroll), GTK_WIDGET(keys_list));
328         gtk_box_pack_start_defaults(GTK_BOX(dialog->vbox), GTK_WIDGET(keys_scroll));
329
330         load_settings();
331
332         g_signal_connect(G_OBJECT(dialog), "response",
333                                         G_CALLBACK (cb_dialog_response), NULL);
334         g_signal_connect(G_OBJECT(renderer), "accel_edited",
335                                         G_CALLBACK(cb_key_edited), NULL);
336         g_signal_connect(G_OBJECT(renderer), "accel_cleared",
337                     G_CALLBACK(cb_key_cleared), NULL);
338
339         gtk_widget_show_all(GTK_WIDGET(dialog));
340 }
341