fix .desktop file
[gconf-editor] / src / gconf-key-editor.c
1 /* -*- Mode: C; indent-tabs-mode: t; c-basic-offset: 8; tab-width: 8 -*- */
2 /* gconf-editor
3  *
4  * Copyright (C) 2001, 2002 Anders Carlsson <andersca@gnu.org>
5  *
6  * This program is free software; you can redistribute it and/or
7  * modify it under the terms of the GNU General Public License as
8  * published by the Free Software Foundation; either version 2 of the
9  * License, or (at your option) any later version.
10  *
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 GNU
14  * General Public License for more details.
15  *
16  * You should have received a copy of the GNU General Public License
17  * along with this program; if not, write to the Free Software
18  * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
19  */
20
21 #ifdef HAVE_CONFIG_H
22 #include <config.h>
23 #endif
24
25 #include "gconf-cell-renderer.h"
26 #include "gconf-key-editor.h"
27
28 #include <gtk/gtk.h>
29 #include <glib/gi18n.h>
30 #include <string.h>
31
32 enum
33 {
34   EDIT_INTEGER,
35   EDIT_BOOLEAN,
36   EDIT_STRING,
37   EDIT_FLOAT,
38   EDIT_LIST
39 };
40
41
42 static void
43 combo_box_changed (GtkWidget *combo_box,
44                    GConfKeyEditor *editor)
45 {
46         int index;
47
48         index = gtk_combo_box_get_active (GTK_COMBO_BOX (combo_box));
49
50         editor->active_type = index;
51                 
52         gtk_window_set_resizable (GTK_WINDOW (editor), FALSE);  
53         gtk_widget_hide (editor->int_box);
54         gtk_widget_hide (editor->bool_box);
55         gtk_widget_hide (editor->string_box);
56         gtk_widget_hide (editor->float_box);
57         gtk_widget_hide (editor->list_box);
58                                        
59         switch (index) {
60                 case EDIT_INTEGER:
61                         gtk_widget_show_all (editor->int_box);
62                         break;
63                 case EDIT_BOOLEAN:
64                         gtk_widget_show_all (editor->bool_box);
65                         break;
66                 case EDIT_STRING:
67                         gtk_widget_show_all (editor->string_box);
68                         break;
69                 case EDIT_FLOAT:
70                         gtk_widget_show_all (editor->float_box);
71                         break;
72                 case EDIT_LIST:
73                         gtk_window_set_resizable (GTK_WINDOW (editor), TRUE);
74                         gtk_widget_show_all (editor->list_box);
75                         break;
76                 default:
77                         g_assert_not_reached ();
78         }
79 }
80
81 static void
82 bool_button_toggled (GtkWidget *bool_button,
83                      gpointer   data)
84 {
85         if (gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (bool_button)))
86                 gtk_label_set_label (GTK_LABEL (GTK_BIN (bool_button)->child),
87                                      _("T_rue"));
88         else
89                 gtk_label_set_label (GTK_LABEL (GTK_BIN (bool_button)->child),
90                                      _("_False"));
91 }
92
93 static void
94 gconf_key_editor_list_entry_changed (GConfCellRenderer *cell, const gchar *path_str, GConfValue *new_value, GConfKeyEditor *editor)
95 {
96         GtkTreeIter iter;
97         GtkTreePath *path;
98
99         path = gtk_tree_path_new_from_string (path_str);
100         gtk_tree_model_get_iter (GTK_TREE_MODEL(editor->list_model), &iter, path);
101
102         gtk_list_store_set (editor->list_model, &iter,
103                             0, new_value,
104                             -1);
105 }
106
107 static void
108 list_type_menu_changed (GtkWidget *combobox,
109                         GConfKeyEditor *editor)
110 {
111         gtk_list_store_clear (editor->list_model);
112 }
113
114 static GtkWidget *
115 gconf_key_editor_create_combo_box (GConfKeyEditor *editor)
116 {
117         GtkWidget *combo_box;
118
119         combo_box = gtk_combo_box_new_text ();
120
121         /* These have to be ordered so the EDIT_ enum matches the
122          * menu indices
123          */
124
125         gtk_combo_box_append_text (GTK_COMBO_BOX (combo_box), _("Integer"));
126         gtk_combo_box_append_text (GTK_COMBO_BOX (combo_box), _("Boolean"));
127         gtk_combo_box_append_text (GTK_COMBO_BOX (combo_box), _("String"));
128         /* Translators: this refers to "Floating point":
129          * see http://en.wikipedia.org/wiki/Floating_point
130          */
131         gtk_combo_box_append_text (GTK_COMBO_BOX (combo_box), _("Float"));
132         gtk_combo_box_append_text (GTK_COMBO_BOX (combo_box), _("List"));
133
134         gtk_combo_box_set_active (GTK_COMBO_BOX (combo_box), 0);
135
136         g_signal_connect (combo_box, "changed",
137                           G_CALLBACK (combo_box_changed),
138                           editor);
139         
140         gtk_widget_show_all (combo_box);
141         return combo_box;
142 }
143
144 static GtkWidget *
145 gconf_key_editor_create_list_type_menu (GConfKeyEditor *editor)
146 {
147         GtkWidget *combo_box;
148
149         combo_box = gtk_combo_box_new_text ();
150
151         /* These have to be ordered so the EDIT_ enum matches the
152          * combobox indices
153          */
154
155         gtk_combo_box_append_text (GTK_COMBO_BOX (combo_box), _("Integer"));
156         gtk_combo_box_append_text (GTK_COMBO_BOX (combo_box), _("Boolean"));
157         gtk_combo_box_append_text (GTK_COMBO_BOX (combo_box), _("String"));
158
159         gtk_combo_box_set_active (GTK_COMBO_BOX (combo_box), 0);
160         
161         g_signal_connect (combo_box, "changed",
162                           G_CALLBACK (list_type_menu_changed),
163                           editor);
164
165         gtk_widget_show_all (combo_box);
166         return combo_box;
167 }
168
169 static void
170 update_list_buttons (GConfKeyEditor *editor)
171 {
172         GtkTreeSelection *selection;
173         GtkTreeIter iter;
174         GtkTreePath *path;
175         GtkTreeModel *model;
176         gint selected;
177         gboolean can_edit = FALSE, can_remove = FALSE, can_go_up = FALSE, can_go_down = FALSE;
178
179         selection = gtk_tree_view_get_selection (GTK_TREE_VIEW (editor->list_widget));
180
181         if (gtk_tree_selection_get_selected (selection, &model, &iter)) {
182                 path = gtk_tree_model_get_path (model, &iter);
183
184                 selected = gtk_tree_path_get_indices (path)[0];
185
186                 can_edit = can_remove = TRUE;
187                 can_go_up = selected > 0;
188                 can_go_down =  selected < gtk_tree_model_iter_n_children (model, NULL) - 1;
189
190                 gtk_tree_path_free (path);
191         }
192
193         gtk_widget_set_sensitive (editor->remove_button, can_remove);
194         gtk_widget_set_sensitive (editor->edit_button, can_edit);
195         gtk_widget_set_sensitive (editor->go_up_button, can_go_up);
196         gtk_widget_set_sensitive (editor->go_down_button, can_go_down);
197
198 }
199
200 static void
201 list_selection_changed (GtkTreeSelection *selection,
202                         GConfKeyEditor *editor)
203 {
204         update_list_buttons (editor);
205 }
206
207 static void
208 list_add_clicked (GtkButton *button,
209                   GConfKeyEditor *editor)
210 {
211         GtkWidget *dialog;
212         GtkWidget *hbox;
213         GtkWidget *value_widget;
214         GtkWidget *label;
215         gint response;
216         GtkTreeIter iter;
217         GtkTreeSelection *selection;
218
219         dialog = gtk_dialog_new_with_buttons (_("Add New List Entry"),
220                                               GTK_WINDOW (editor),
221                                               GTK_DIALOG_MODAL| GTK_DIALOG_DESTROY_WITH_PARENT,
222                                               GTK_STOCK_CANCEL, GTK_RESPONSE_CANCEL,
223                                               GTK_STOCK_OK, GTK_RESPONSE_OK,
224                                               NULL);
225         gtk_dialog_set_default_response (GTK_DIALOG (dialog), GTK_RESPONSE_OK);
226         gtk_container_set_border_width (GTK_CONTAINER (dialog), 5);
227         gtk_dialog_set_has_separator (GTK_DIALOG (dialog), FALSE);
228         gtk_window_set_resizable (GTK_WINDOW (dialog), FALSE);
229         gtk_box_set_spacing (GTK_BOX (GTK_DIALOG (editor)->vbox), 2);
230         
231         hbox = gtk_hbox_new (FALSE, 12);
232         gtk_container_set_border_width (GTK_CONTAINER (hbox), 5);
233         gtk_box_pack_start (GTK_BOX (GTK_DIALOG (dialog)->vbox), hbox, FALSE, FALSE, 0);
234
235         label = gtk_label_new_with_mnemonic (_("_New list value:"));
236         gtk_box_pack_start (GTK_BOX (hbox), label, FALSE, FALSE, 0);
237
238         switch (gtk_combo_box_get_active (GTK_COMBO_BOX (editor->list_type_menu))) {
239                 case EDIT_INTEGER:
240                         value_widget = gtk_spin_button_new_with_range (G_MININT, G_MAXINT, 1);
241                         gtk_spin_button_set_value (GTK_SPIN_BUTTON (value_widget), 0);
242                         break;
243                 case EDIT_BOOLEAN:
244                         value_widget = gtk_toggle_button_new_with_mnemonic (_("_False"));
245                         g_signal_connect (value_widget, "toggled",
246                                           G_CALLBACK (bool_button_toggled),
247                                           editor);
248                         break;
249                 case EDIT_STRING:
250                         value_widget = gtk_entry_new ();
251                         gtk_entry_set_activates_default (GTK_ENTRY (value_widget), TRUE);
252                         break;
253                 default:
254                         value_widget = NULL;
255                         g_assert_not_reached ();
256         }
257
258         gtk_label_set_mnemonic_widget (GTK_LABEL (label), value_widget);
259         gtk_box_pack_start (GTK_BOX (hbox), value_widget, TRUE, TRUE, 0);
260
261         gtk_widget_show_all (hbox);
262
263         response = gtk_dialog_run (GTK_DIALOG (dialog));
264
265         if (response == GTK_RESPONSE_OK) {
266                 GConfValue *value;
267                 
268                 value = NULL;
269
270                 switch (gtk_combo_box_get_active (GTK_COMBO_BOX (editor->list_type_menu))) {
271                         case EDIT_INTEGER:
272                                 value = gconf_value_new (GCONF_VALUE_INT);
273                                 gconf_value_set_int (value,
274                                                      gtk_spin_button_get_value (GTK_SPIN_BUTTON (value_widget)));
275                                 break;
276
277                         case EDIT_BOOLEAN:
278                                 value = gconf_value_new (GCONF_VALUE_BOOL);
279                                 gconf_value_set_bool (value,
280                                                       gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (value_widget)));
281                                 break;
282
283                         case EDIT_STRING:
284                                 {
285                                         char *text;
286                                 
287                                         text = gtk_editable_get_chars (GTK_EDITABLE (value_widget), 0, -1);
288                                         value = gconf_value_new (GCONF_VALUE_STRING);
289                                         gconf_value_set_string (value, text);
290                                         g_free (text);
291                                 }
292                                 break;
293                         default:
294                                 g_assert_not_reached ();
295                                 
296                 }
297
298                 gtk_list_store_append (editor->list_model, &iter);
299                 gtk_list_store_set (editor->list_model, &iter, 0, value, -1);
300
301                 selection = gtk_tree_view_get_selection (GTK_TREE_VIEW (editor->list_widget));
302                 gtk_tree_selection_select_iter(selection, &iter);
303         }
304         
305         gtk_widget_destroy (dialog);
306 }
307
308 static void
309 list_edit_element (GConfKeyEditor *editor)
310 {
311         GtkWidget *dialog;
312         GtkWidget *hbox;
313         GtkWidget *value_widget;
314         GtkWidget *label;
315         gint response;
316         GtkTreeIter iter;
317         GtkTreeSelection *selection;
318         GtkTreeModel *model;
319         GConfValue *value = NULL;
320
321         dialog = gtk_dialog_new_with_buttons (_("Edit List Entry"),
322                                               GTK_WINDOW (editor),
323                                               GTK_DIALOG_MODAL| GTK_DIALOG_DESTROY_WITH_PARENT,
324                                               GTK_STOCK_CANCEL, GTK_RESPONSE_CANCEL,
325                                               GTK_STOCK_OK, GTK_RESPONSE_OK,
326                                               NULL);
327         gtk_dialog_set_default_response (GTK_DIALOG (dialog), GTK_RESPONSE_OK);
328         gtk_container_set_border_width (GTK_CONTAINER (dialog), 5);
329         gtk_dialog_set_has_separator (GTK_DIALOG (dialog), FALSE);
330         gtk_window_set_resizable (GTK_WINDOW (dialog), FALSE);
331         gtk_box_set_spacing (GTK_BOX (GTK_DIALOG (editor)->vbox), 2);
332         
333         hbox = gtk_hbox_new (FALSE, 12);
334         gtk_container_set_border_width (GTK_CONTAINER (hbox), 5);
335         gtk_box_pack_start (GTK_BOX (GTK_DIALOG (dialog)->vbox), hbox, FALSE, FALSE, 0);
336
337         label = gtk_label_new_with_mnemonic (_("_Edit list value:"));
338         gtk_box_pack_start (GTK_BOX (hbox), label, FALSE, FALSE, 0);
339
340         selection = gtk_tree_view_get_selection (GTK_TREE_VIEW (editor->list_widget));
341         gtk_tree_selection_get_selected (selection, &model, &iter);
342         gtk_tree_model_get (GTK_TREE_MODEL (model), &iter, 0, &value, -1);
343         switch (gtk_combo_box_get_active (GTK_COMBO_BOX (editor->list_type_menu))) {
344                 case EDIT_INTEGER:
345                         value_widget = gtk_spin_button_new_with_range (G_MININT, G_MAXINT, 1);
346                         gtk_spin_button_set_value (GTK_SPIN_BUTTON (value_widget), gconf_value_get_int (value));
347                         break;
348                 case EDIT_BOOLEAN:
349                         value_widget = gtk_toggle_button_new_with_mnemonic (_("_False"));
350                         gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (value_widget), gconf_value_get_bool (value));
351                         break;
352                 case EDIT_STRING:
353                         value_widget = gtk_entry_new ();
354                         gtk_entry_set_text (GTK_ENTRY (value_widget), gconf_value_get_string (value));
355                         break;
356                 default:
357                         value_widget = NULL;
358                         g_assert_not_reached ();
359         }
360         gconf_value_free (value);
361
362         gtk_label_set_mnemonic_widget (GTK_LABEL (label), value_widget);
363         gtk_box_pack_start (GTK_BOX (hbox), value_widget, TRUE, TRUE, 0);
364
365         gtk_widget_show_all (hbox);
366
367         response = gtk_dialog_run (GTK_DIALOG (dialog));
368
369         if (response == GTK_RESPONSE_OK) {
370                 GConfValue *value;
371                 
372                 value = NULL;
373
374                 switch (gtk_combo_box_get_active (GTK_COMBO_BOX (editor->list_type_menu))) {
375                         case EDIT_INTEGER:
376                                 value = gconf_value_new (GCONF_VALUE_INT);
377                                 gconf_value_set_int (value,
378                                                      gtk_spin_button_get_value (GTK_SPIN_BUTTON (value_widget)));
379                                 break;
380
381                         case EDIT_BOOLEAN:
382                                 value = gconf_value_new (GCONF_VALUE_BOOL);
383                                 gconf_value_set_bool (value,
384                                                       gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (value_widget)));
385                                 break;
386
387                         case EDIT_STRING:
388                                 {
389                                         char *text;
390                                 
391                                         text = gtk_editable_get_chars (GTK_EDITABLE (value_widget), 0, -1);
392                                         value = gconf_value_new (GCONF_VALUE_STRING);
393                                         gconf_value_set_string (value, text);
394                                         g_free (text);
395                                 }
396                                 break;
397                         default:
398                                 g_assert_not_reached ();
399                                 
400                 }
401                 gtk_list_store_set (editor->list_model, &iter, 0, value, -1);
402
403         }
404         
405         gtk_widget_destroy (dialog);
406 }
407
408
409
410 static void
411 list_remove_clicked (GtkButton *button,
412                      GConfKeyEditor *editor)
413 {
414         GtkTreeIter iter;
415         GtkTreeIter tmp;
416         GtkTreeSelection *selection;
417
418         selection = gtk_tree_view_get_selection (GTK_TREE_VIEW (editor->list_widget));
419
420         if (gtk_tree_selection_get_selected (selection, NULL, &iter)) {
421                 tmp = iter;
422                 if (gtk_tree_model_iter_next (GTK_TREE_MODEL (editor->list_model), &tmp)) {
423                         gtk_tree_selection_select_iter (selection, &tmp);
424                 } else {
425                         GtkTreePath *path;
426                         path = gtk_tree_model_get_path (GTK_TREE_MODEL (editor->list_model), &iter);
427                         if (gtk_tree_path_prev (path)) {
428                                 gtk_tree_selection_select_path (selection, path);
429                         }
430                         gtk_tree_path_free (path);
431                 }
432                 gtk_list_store_remove (editor->list_model, &iter);
433         }
434 }
435
436 static void
437 list_go_up_clicked (GtkButton *button,
438                     GConfKeyEditor *editor)
439 {
440         GtkTreeIter iter_first;
441         GtkTreeIter iter_second;
442         GtkTreeSelection *selection;
443         
444         selection = gtk_tree_view_get_selection (GTK_TREE_VIEW (editor->list_widget));
445
446         if (gtk_tree_selection_get_selected (selection, NULL, &iter_second)) {
447                 GConfValue *first;
448                 GConfValue *second;
449                 GtkTreePath *path;
450                 
451                 path = gtk_tree_model_get_path (GTK_TREE_MODEL (editor->list_model), &iter_second);
452                 gtk_tree_path_prev (path);
453                 gtk_tree_model_get_iter (GTK_TREE_MODEL (editor->list_model), &iter_first, path);
454                 
455                 gtk_tree_model_get (GTK_TREE_MODEL (editor->list_model), &iter_first, 0, &first, -1);
456                 gtk_tree_model_get (GTK_TREE_MODEL (editor->list_model), &iter_second, 0, &second, -1);
457                                 
458                 gtk_list_store_set (editor->list_model, &iter_first, 0, second, -1);
459                 gtk_list_store_set (editor->list_model, &iter_second, 0, first, -1);
460
461                 gtk_tree_path_free (path);
462
463                 gtk_tree_selection_select_iter(selection, &iter_first);
464         }
465 }
466
467 static void
468 list_go_down_clicked (GtkButton *button,
469                       GConfKeyEditor *editor)
470 {
471         GtkTreeIter iter_first;
472         GtkTreeIter iter_second;
473         GtkTreeSelection *selection;
474         
475         selection = gtk_tree_view_get_selection (GTK_TREE_VIEW (editor->list_widget));
476
477         if (gtk_tree_selection_get_selected (selection, NULL, &iter_first)) {
478                 GConfValue *first;
479                 GConfValue *second;
480
481                 iter_second = iter_first;
482
483                 gtk_tree_model_iter_next (GTK_TREE_MODEL (editor->list_model), &iter_second);
484
485                 gtk_tree_model_get (GTK_TREE_MODEL (editor->list_model), &iter_first, 0, &first, -1);
486                 gtk_tree_model_get (GTK_TREE_MODEL (editor->list_model), &iter_second, 0, &second, -1);
487                                 
488                 gtk_list_store_set (editor->list_model, &iter_first, 0, second, -1);
489                 gtk_list_store_set (editor->list_model, &iter_second, 0, first, -1);
490                 gtk_tree_selection_select_iter(selection, &iter_second);
491         }
492 }
493
494 static void
495 list_edit_clicked (GtkWidget      *button,
496                    GConfKeyEditor *editor)
497 {
498         list_edit_element (editor);
499 }
500
501 static void
502 list_view_row_activated (GtkTreeView       *tree_view,
503                          GtkTreePath       *path,
504                          GtkTreeViewColumn *column,
505                          GConfKeyEditor    *editor)
506 {
507         list_edit_element (editor);
508 }
509
510 static void
511 fix_button_align (GtkWidget *button)
512 {
513         GtkWidget *child = gtk_bin_get_child (GTK_BIN (button));
514
515         if (GTK_IS_ALIGNMENT (child))
516                 g_object_set (G_OBJECT (child), "xalign", 0.0, NULL);
517         else if (GTK_IS_LABEL (child))
518                 g_object_set (G_OBJECT (child), "xalign", 0.0, NULL);
519 }
520
521
522 static void
523 gconf_key_editor_class_init (GConfKeyEditorClass *klass)
524 {
525 }
526
527 static void
528 gconf_key_editor_init (GConfKeyEditor *editor)
529 {
530         GtkWidget *hbox, *vbox, *framebox;
531         GtkWidget *label, *image;
532         GtkWidget *value_box;
533         GtkWidget *button_box, *button;
534         GtkSizeGroup *size_group;
535         GtkCellRenderer *cell_renderer;
536         GtkTreeSelection *list_selection;
537         GtkWidget *sw;
538
539         gtk_dialog_add_buttons (GTK_DIALOG (editor),
540                                 GTK_STOCK_CANCEL, GTK_RESPONSE_CANCEL, 
541                                 GTK_STOCK_OK, GTK_RESPONSE_OK,
542                                 NULL);
543         gtk_dialog_set_default_response (GTK_DIALOG (editor), GTK_RESPONSE_OK);
544         
545         gtk_container_set_border_width (GTK_CONTAINER (editor), 5);
546         gtk_dialog_set_has_separator (GTK_DIALOG (editor), FALSE);
547         gtk_window_set_resizable (GTK_WINDOW (editor), FALSE);
548         gtk_box_set_spacing (GTK_BOX (GTK_DIALOG (editor)->vbox), 2);
549
550         vbox = gtk_vbox_new (FALSE, 6);
551         gtk_box_pack_start (GTK_BOX (GTK_DIALOG (editor)->vbox), vbox, TRUE, TRUE, 0);
552         gtk_container_set_border_width (GTK_CONTAINER (vbox), 5);
553         gtk_widget_show_all (vbox);
554
555         size_group = gtk_size_group_new (GTK_SIZE_GROUP_BOTH);
556         
557         editor->path_box = gtk_hbox_new (FALSE, 12);
558         label = gtk_label_new (_("Path:"));
559         gtk_size_group_add_widget (size_group, label);
560         gtk_misc_set_alignment (GTK_MISC (label), 0.0, 0.5);
561         gtk_box_pack_start (GTK_BOX (editor->path_box), label, FALSE, FALSE, 0);
562         editor->path_label = gtk_label_new (NULL);
563         gtk_misc_set_alignment (GTK_MISC (editor->path_label), 0.0, 0.5);
564         gtk_box_pack_start (GTK_BOX (editor->path_box), editor->path_label, TRUE, TRUE, 0);
565         gtk_widget_show_all (editor->path_box);
566         gtk_box_pack_start (GTK_BOX (vbox), editor->path_box, FALSE, FALSE, 0);
567
568         hbox = gtk_hbox_new (FALSE, 12);
569         label = gtk_label_new_with_mnemonic (_("_Name:"));
570         gtk_size_group_add_widget (size_group, label);
571         gtk_box_pack_start (GTK_BOX (hbox), label, FALSE, FALSE, 0);
572         editor->name_entry = gtk_entry_new ();
573         gtk_widget_set_size_request (editor->name_entry, 250, -1);
574         gtk_entry_set_activates_default (GTK_ENTRY (editor->name_entry), TRUE);
575         gtk_box_pack_start (GTK_BOX (hbox), editor->name_entry, TRUE, TRUE, 0);
576         gtk_label_set_mnemonic_widget (GTK_LABEL (label), editor->name_entry);
577         gtk_widget_show_all (hbox);
578         gtk_box_pack_start (GTK_BOX (vbox), hbox, FALSE, FALSE, 0);
579
580         hbox = gtk_hbox_new (FALSE, 12);
581         label = gtk_label_new_with_mnemonic (_("_Type:"));
582         gtk_misc_set_alignment (GTK_MISC (label), 0.0, 0.5);
583         gtk_size_group_add_widget (size_group, label);
584         gtk_box_pack_start (GTK_BOX (hbox), label, FALSE, FALSE, 0);
585         editor->combobox = gconf_key_editor_create_combo_box (editor);
586         gtk_box_pack_start (GTK_BOX (hbox),
587                             editor->combobox,
588                             TRUE, TRUE, 0);
589         gtk_label_set_mnemonic_widget (GTK_LABEL (label), editor->combobox);
590         gtk_widget_show_all (hbox);
591         gtk_box_pack_start (GTK_BOX (vbox), hbox, FALSE, FALSE, 0);
592
593         g_object_unref (size_group);
594
595         framebox = gtk_vbox_new (FALSE, 6);
596         gtk_widget_show (framebox);
597         gtk_box_pack_start (GTK_BOX (vbox), framebox, FALSE, FALSE, 0);
598
599         editor->non_writable_label = gtk_hbox_new (FALSE, 12);
600         gtk_box_pack_start (GTK_BOX (framebox), editor->non_writable_label, FALSE, FALSE, 0);
601
602         image = gtk_image_new_from_stock (GTK_STOCK_DIALOG_WARNING, GTK_ICON_SIZE_BUTTON);
603         gtk_widget_show (image);
604         gtk_box_pack_start (GTK_BOX (editor->non_writable_label), image, FALSE, FALSE, 0);
605
606         label = gtk_label_new (_("This key is not writable"));
607         gtk_widget_show (label);
608         gtk_box_pack_start (GTK_BOX (editor->non_writable_label), label, FALSE, FALSE, 0);
609
610         editor->active_type = EDIT_INTEGER;
611
612         /* EDIT_INTEGER */
613         editor->int_box = gtk_hbox_new (FALSE, 0);
614         hbox = gtk_hbox_new (FALSE, 12);
615         label = gtk_label_new ("    ");
616         gtk_box_pack_start (GTK_BOX (editor->int_box), label, FALSE, FALSE, 0);
617
618         label = gtk_label_new_with_mnemonic (_("_Value:"));
619         editor->int_widget = gtk_spin_button_new_with_range (G_MININT, G_MAXINT, 1);
620
621         /* Set a nicer default value */
622         gtk_spin_button_set_value (GTK_SPIN_BUTTON (editor->int_widget), 0);
623         gtk_label_set_mnemonic_widget (GTK_LABEL (label), editor->int_widget);
624         gtk_box_pack_start (GTK_BOX (hbox), label, FALSE, FALSE, 0);
625         gtk_box_pack_start (GTK_BOX (hbox), editor->int_widget, TRUE, TRUE, 0);
626         gtk_box_pack_start (GTK_BOX (editor->int_box), hbox, TRUE, TRUE, 0);
627         gtk_box_pack_start (GTK_BOX (vbox), editor->int_box, FALSE, FALSE, 0);
628         gtk_widget_show_all (editor->int_box);
629         
630         /* EDIT_BOOLEAN */
631         editor->bool_box = gtk_hbox_new (FALSE, 0);
632         hbox = gtk_hbox_new (FALSE, 12);
633         label = gtk_label_new ("    ");
634         gtk_widget_show (label);
635         gtk_box_pack_start (GTK_BOX (editor->bool_box), label, FALSE, FALSE, 0);
636         label = gtk_label_new_with_mnemonic (_("_Value:"));
637         editor->bool_widget = gtk_toggle_button_new_with_mnemonic (_("_False"));
638         g_signal_connect (editor->bool_widget, "toggled",
639                           G_CALLBACK (bool_button_toggled),
640                           editor);
641         gtk_label_set_mnemonic_widget (GTK_LABEL (label), editor->bool_widget);
642         gtk_box_pack_start (GTK_BOX (hbox), label, FALSE, FALSE, 0);
643         gtk_box_pack_start (GTK_BOX (hbox), editor->bool_widget, TRUE, TRUE, 0);
644         gtk_box_pack_start (GTK_BOX (editor->bool_box), hbox, TRUE, TRUE, 0);
645         gtk_box_pack_start (GTK_BOX (vbox), editor->bool_box, FALSE, FALSE, 0);
646         gtk_widget_show_all (hbox);
647         gtk_widget_hide (editor->bool_box);
648
649         /* EDIT_STRING */
650         editor->string_box = gtk_hbox_new (FALSE, 0);
651         hbox = gtk_hbox_new (FALSE, 12);
652         label = gtk_label_new ("    ");
653         gtk_widget_show (label);
654         gtk_box_pack_start (GTK_BOX (editor->string_box), label, FALSE, FALSE, 0);
655         label = gtk_label_new_with_mnemonic (_("_Value:"));
656         editor->string_widget = gtk_entry_new ();
657         gtk_entry_set_activates_default (GTK_ENTRY (editor->string_widget), TRUE);
658         gtk_label_set_mnemonic_widget (GTK_LABEL (label), editor->string_widget);       
659         gtk_box_pack_start (GTK_BOX (hbox), label, FALSE, FALSE, 0);
660         gtk_box_pack_start (GTK_BOX (hbox), editor->string_widget, TRUE, TRUE, 0);
661         gtk_box_pack_start (GTK_BOX (editor->string_box), hbox, TRUE, TRUE, 0);
662         gtk_box_pack_start (GTK_BOX (vbox), editor->string_box, FALSE, FALSE, 0);
663         gtk_widget_show_all (hbox);
664         gtk_widget_hide (editor->string_box);
665
666         /* EDIT_FLOAT */
667         editor->float_box = gtk_hbox_new (FALSE, 0);
668         hbox = gtk_hbox_new (FALSE, 12);
669         label = gtk_label_new ("    ");
670         gtk_widget_show (label);
671         gtk_box_pack_start (GTK_BOX (editor->float_box), label, FALSE, FALSE, 0);
672         label = gtk_label_new_with_mnemonic (_("_Value:"));
673         editor->float_widget = gtk_spin_button_new_with_range (G_MINFLOAT, G_MAXFLOAT, 0.1);
674
675         /* Set a nicer default value */
676         gtk_spin_button_set_value (GTK_SPIN_BUTTON (editor->float_widget), 0.0);
677         gtk_label_set_mnemonic_widget (GTK_LABEL (label), editor->float_widget);
678         gtk_box_pack_start (GTK_BOX (hbox), label, FALSE, FALSE, 0);
679         gtk_box_pack_start (GTK_BOX (hbox), editor->float_widget, TRUE, TRUE, 0);
680         gtk_box_pack_start (GTK_BOX (editor->float_box), hbox, TRUE, TRUE, 0);
681         gtk_box_pack_start (GTK_BOX (vbox), editor->float_box, FALSE, FALSE, 0);
682         gtk_widget_show_all (hbox);
683         gtk_widget_hide (editor->float_box);
684
685         /* EDIT_LIST */
686         editor->list_box = gtk_hbox_new (FALSE, 0);
687         label = gtk_label_new ("    ");
688         gtk_widget_show (label);
689         gtk_box_pack_start (GTK_BOX (editor->list_box), label, FALSE, FALSE, 0);
690
691         value_box = gtk_vbox_new (FALSE, 6);
692
693         hbox = gtk_hbox_new (FALSE, 12);
694         label = gtk_label_new_with_mnemonic (_("List _type:"));
695         editor->list_type_menu = gconf_key_editor_create_list_type_menu (editor);
696         gtk_label_set_mnemonic_widget (GTK_LABEL (label), editor->list_type_menu);
697         gtk_box_pack_start (GTK_BOX (value_box), hbox, FALSE, FALSE, 0);
698         gtk_box_pack_start (GTK_BOX (hbox), label, FALSE, FALSE, 0);
699         gtk_box_pack_start (GTK_BOX (hbox),
700                             editor->list_type_menu, TRUE, TRUE, 0);
701
702         label = gtk_label_new_with_mnemonic (_("_Values:"));
703         gtk_misc_set_alignment(GTK_MISC (label), 0.0, 0.5);
704   
705         hbox = gtk_hbox_new (FALSE, 12);
706
707         sw = gtk_scrolled_window_new (NULL, NULL);
708         gtk_scrolled_window_set_shadow_type (GTK_SCROLLED_WINDOW (sw),
709                                              GTK_SHADOW_ETCHED_IN);
710         gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW (sw),
711                                         GTK_POLICY_AUTOMATIC,                                                           GTK_POLICY_AUTOMATIC);
712
713         editor->list_model = gtk_list_store_new (1, g_type_from_name("GConfValue"));
714         editor->list_widget = gtk_tree_view_new_with_model (GTK_TREE_MODEL (editor->list_model));
715         gtk_tree_view_set_headers_visible (GTK_TREE_VIEW (editor->list_widget), FALSE);
716         list_selection = gtk_tree_view_get_selection (GTK_TREE_VIEW (editor->list_widget));
717         g_signal_connect (G_OBJECT (editor->list_widget), "row_activated",
718                           G_CALLBACK (list_view_row_activated), editor);
719         g_signal_connect (G_OBJECT (list_selection), "changed",
720                           G_CALLBACK (list_selection_changed), editor);
721         
722         
723         cell_renderer = gconf_cell_renderer_new ();
724         g_signal_connect (G_OBJECT (cell_renderer), "changed", G_CALLBACK (gconf_key_editor_list_entry_changed), editor);
725
726         gtk_tree_view_insert_column_with_attributes (GTK_TREE_VIEW (editor->list_widget), -1, NULL, cell_renderer, "value", 0, NULL);
727
728         button_box = gtk_vbutton_box_new ();
729         gtk_button_box_set_layout (GTK_BUTTON_BOX (button_box), GTK_BUTTONBOX_START);
730         gtk_box_set_spacing (GTK_BOX (button_box), 6);
731         button = gtk_button_new_from_stock (GTK_STOCK_ADD);
732         fix_button_align (button);
733         editor->remove_button = gtk_button_new_from_stock (GTK_STOCK_REMOVE);
734         fix_button_align (editor->remove_button);
735         editor->edit_button = gtk_button_new_from_stock (GTK_STOCK_EDIT);
736         fix_button_align (editor->edit_button);
737         editor->go_up_button = gtk_button_new_from_stock (GTK_STOCK_GO_UP);
738         fix_button_align (editor->go_up_button);
739         editor->go_down_button = gtk_button_new_from_stock (GTK_STOCK_GO_DOWN);
740         fix_button_align (editor->go_down_button);
741         g_signal_connect (G_OBJECT (button), "clicked",
742                           G_CALLBACK (list_add_clicked), editor);
743         g_signal_connect (G_OBJECT (editor->edit_button), "clicked",
744                           G_CALLBACK (list_edit_clicked), editor);
745         g_signal_connect (G_OBJECT (editor->remove_button), "clicked",
746                           G_CALLBACK (list_remove_clicked), editor);
747         g_signal_connect (G_OBJECT (editor->go_up_button), "clicked",
748                           G_CALLBACK (list_go_up_clicked), editor);
749         g_signal_connect (G_OBJECT (editor->go_down_button), "clicked",
750                           G_CALLBACK (list_go_down_clicked), editor);
751         gtk_box_pack_start (GTK_BOX (button_box), button, FALSE, FALSE, 0);
752         gtk_box_pack_start (GTK_BOX (button_box), editor->remove_button, FALSE, FALSE, 0);
753         gtk_box_pack_start (GTK_BOX (button_box), editor->edit_button, FALSE, FALSE, 0);
754         gtk_box_pack_start (GTK_BOX (button_box), editor->go_up_button, FALSE, FALSE, 0);
755         gtk_box_pack_start (GTK_BOX (button_box), editor->go_down_button, FALSE, FALSE, 0);
756
757         update_list_buttons (editor);
758
759         gtk_label_set_mnemonic_widget (GTK_LABEL (label), editor->list_widget); 
760         gtk_box_pack_start (GTK_BOX (value_box), label, FALSE, FALSE, 0);
761         gtk_box_pack_start (GTK_BOX (value_box), hbox, TRUE, TRUE, 0);
762         gtk_box_pack_start (GTK_BOX (hbox), sw, TRUE, TRUE, 0);
763         gtk_box_pack_start (GTK_BOX (hbox), button_box, FALSE, FALSE, 0);
764         gtk_container_add (GTK_CONTAINER (sw), editor->list_widget);
765         gtk_box_pack_start (GTK_BOX (editor->list_box), value_box, TRUE, TRUE, 0);
766         gtk_box_pack_start (GTK_BOX (vbox), editor->list_box, TRUE, TRUE, 0);
767         gtk_widget_show_all (value_box);
768         gtk_widget_hide (editor->list_box);
769 }
770
771 GType
772 gconf_key_editor_get_type (void)
773 {
774         static GType object_type = 0;
775
776         if (!object_type) {
777                 static const GTypeInfo object_info = {
778                         sizeof (GConfKeyEditorClass),
779                         NULL,           /* base_init */
780                         NULL,           /* base_finalize */
781                         (GClassInitFunc) gconf_key_editor_class_init,
782                         NULL,           /* class_finalize */
783                         NULL,           /* class_data */
784                         sizeof (GConfKeyEditor),
785                         0,              /* n_preallocs */
786                         (GInstanceInitFunc) gconf_key_editor_init
787                 };
788
789                 object_type = g_type_register_static (GTK_TYPE_DIALOG, "GConfKeyEditor", &object_info, 0);
790         }
791
792         return object_type;
793 }
794
795 GtkWidget *
796 gconf_key_editor_new (GConfKeyEditorAction action)
797 {
798         GConfKeyEditor *dialog;
799
800         dialog = g_object_new (GCONF_TYPE_KEY_EDITOR, NULL);
801
802         switch (action) {
803         case GCONF_KEY_EDITOR_NEW_KEY:
804                 gtk_window_set_title (GTK_WINDOW (dialog), _("New Key"));
805                 gtk_widget_grab_focus (dialog->name_entry);
806                 break;
807         case GCONF_KEY_EDITOR_EDIT_KEY:
808                 gtk_window_set_title (GTK_WINDOW (dialog), _("Edit Key"));
809
810                 gtk_widget_set_sensitive (dialog->name_entry, FALSE);
811                 gtk_widget_hide (dialog->path_box);
812                 break;
813         default:
814                 break;
815         }
816         
817         return GTK_WIDGET (dialog);
818 }
819
820 void
821 gconf_key_editor_set_value (GConfKeyEditor *editor, GConfValue *value)
822 {
823         if (value == NULL) {
824                 g_print ("dealing with an unset value\n");
825                 return;
826         }
827
828         gtk_widget_set_sensitive (editor->combobox, FALSE);
829         gtk_widget_set_sensitive (editor->list_type_menu, FALSE);
830
831         switch (value->type) {
832         case GCONF_VALUE_INT:
833                 gtk_combo_box_set_active (GTK_COMBO_BOX (editor->combobox), EDIT_INTEGER);
834                 gtk_spin_button_set_value (GTK_SPIN_BUTTON (editor->int_widget), gconf_value_get_int (value));
835                 break;
836         case GCONF_VALUE_STRING:
837                 gtk_combo_box_set_active (GTK_COMBO_BOX (editor->combobox), EDIT_STRING);
838                 gtk_entry_set_text (GTK_ENTRY (editor->string_widget), gconf_value_get_string (value));
839                 break;
840         case GCONF_VALUE_BOOL:
841                 gtk_combo_box_set_active (GTK_COMBO_BOX (editor->combobox), EDIT_BOOLEAN);
842                 gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (editor->bool_widget), gconf_value_get_bool (value));
843                 break;
844         case GCONF_VALUE_FLOAT:
845                 gtk_combo_box_set_active (GTK_COMBO_BOX (editor->combobox), EDIT_FLOAT);
846                 gtk_spin_button_set_value (GTK_SPIN_BUTTON (editor->float_widget), gconf_value_get_float (value));
847                 break;
848         case GCONF_VALUE_LIST:
849                 {
850                         GSList* iter = gconf_value_get_list(value);
851                         
852                         switch (gconf_value_get_list_type(value)) {
853                                 case GCONF_VALUE_INT:
854                                         gtk_combo_box_set_active (GTK_COMBO_BOX (editor->list_type_menu), EDIT_INTEGER);
855                                         break;
856                                 case GCONF_VALUE_FLOAT:
857                                         gtk_combo_box_set_active (GTK_COMBO_BOX (editor->list_type_menu), EDIT_FLOAT);
858                                         break;
859                                 case GCONF_VALUE_STRING:
860                                         gtk_combo_box_set_active (GTK_COMBO_BOX (editor->list_type_menu), EDIT_STRING);
861                                         break;
862                                 case GCONF_VALUE_BOOL:
863                                         gtk_combo_box_set_active (GTK_COMBO_BOX (editor->list_type_menu), EDIT_BOOLEAN);
864                                         break;
865                                 default:
866                                         g_assert_not_reached ();
867                         }
868
869                         gtk_combo_box_set_active (GTK_COMBO_BOX (editor->combobox), EDIT_LIST);
870                                 
871                         while (iter != NULL) {
872                                 GConfValue* element = (GConfValue*) iter->data;
873                                 GtkTreeIter tree_iter;
874
875                                 gtk_list_store_append (editor->list_model, &tree_iter);
876                                 gtk_list_store_set (editor->list_model, &tree_iter, 0, element, -1);
877                                 iter = g_slist_next(iter);
878                         }
879                 }
880                 break;
881         default:
882                 g_assert_not_reached ();
883                 break;
884         }
885         
886 }
887
888 GConfValue*
889 gconf_key_editor_get_value (GConfKeyEditor *editor)
890 {
891         GConfValue *value;
892
893         value = NULL;
894         
895         switch (editor->active_type) {
896
897         case EDIT_INTEGER:
898                 value = gconf_value_new (GCONF_VALUE_INT);
899                 gconf_value_set_int (value,
900                                      gtk_spin_button_get_value (GTK_SPIN_BUTTON (editor->int_widget)));
901                 break;
902
903         case EDIT_BOOLEAN:
904                 value = gconf_value_new (GCONF_VALUE_BOOL);
905                 gconf_value_set_bool (value,
906                                       gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (editor->bool_widget)));
907                 break;
908
909         case EDIT_STRING:
910                 {
911                         char *text;
912                         
913                         text = gtk_editable_get_chars (GTK_EDITABLE (editor->string_widget), 0, -1);
914                         value = gconf_value_new (GCONF_VALUE_STRING);
915                         gconf_value_set_string (value, text);
916                         g_free (text);
917                 }
918                 break;
919         case EDIT_FLOAT:
920                 value = gconf_value_new (GCONF_VALUE_FLOAT);
921                 gconf_value_set_float (value,
922                                        gtk_spin_button_get_value (GTK_SPIN_BUTTON (editor->float_widget)));
923                 break;
924
925         case EDIT_LIST:
926                 {
927                         GSList* list = NULL;
928                         GtkTreeIter iter;
929                         GtkTreeModel* model = GTK_TREE_MODEL (editor->list_model);
930
931                         if (gtk_tree_model_get_iter_first (model, &iter)) {
932                                 do {
933                                         GConfValue *element;
934
935                                         gtk_tree_model_get (model, &iter, 0, &element, -1);
936                                         list = g_slist_append (list, element);
937                                 } while (gtk_tree_model_iter_next (model, &iter));
938                         }
939
940                         value = gconf_value_new (GCONF_VALUE_LIST);
941
942                         switch (gtk_combo_box_get_active (GTK_COMBO_BOX (editor->list_type_menu))) {
943                                 case EDIT_INTEGER:
944                                         gconf_value_set_list_type (value, GCONF_VALUE_INT);
945                                         break;
946                                 case EDIT_BOOLEAN:
947                                         gconf_value_set_list_type (value, GCONF_VALUE_BOOL);
948                                         break;
949                                 case EDIT_STRING:
950                                         gconf_value_set_list_type (value, GCONF_VALUE_STRING);
951                                         break;
952                                 default:
953                                         g_assert_not_reached ();
954                         }
955                         gconf_value_set_list_nocopy (value, list);
956                 }
957                 break;
958         }
959
960         return value;
961 }
962
963 void
964 gconf_key_editor_set_key_path (GConfKeyEditor *editor, const char *path)
965 {
966         gtk_label_set_text (GTK_LABEL (editor->path_label), path);
967 }
968
969 void
970 gconf_key_editor_set_key_name (GConfKeyEditor *editor, const char *path)
971 {
972         gtk_entry_set_text (GTK_ENTRY (editor->name_entry), path);
973 }
974
975 void
976 gconf_key_editor_set_writable (GConfKeyEditor *editor, gboolean writable)
977 {
978         if (writable)
979                 gtk_widget_hide (editor->non_writable_label);
980         else
981                 gtk_widget_show (editor->non_writable_label);
982
983         gtk_widget_set_sensitive (editor->bool_box, writable);
984         gtk_widget_set_sensitive (editor->int_box, writable);
985         gtk_widget_set_sensitive (editor->float_box, writable);
986         gtk_widget_set_sensitive (editor->list_box, writable);
987         gtk_widget_set_sensitive (editor->string_box, writable);
988 }
989
990 G_CONST_RETURN char *
991 gconf_key_editor_get_key_name (GConfKeyEditor *editor)
992 {
993         return gtk_entry_get_text (GTK_ENTRY (editor->name_entry));
994 }
995
996 char *
997 gconf_key_editor_get_full_key_path (GConfKeyEditor *editor)
998 {
999         char *full_key_path;
1000         const char *key_path;
1001
1002         key_path = gtk_label_get_text (GTK_LABEL (editor->path_label));
1003
1004         if (key_path[strlen(key_path) - 1] != '/') {
1005                 full_key_path = g_strdup_printf ("%s/%s",
1006                                                  key_path,
1007                                                  gtk_entry_get_text (GTK_ENTRY (editor->name_entry)));
1008         }
1009         else {
1010                 full_key_path = g_strdup_printf ("%s%s",
1011                                                  key_path,
1012                                                  gtk_entry_get_text (GTK_ENTRY (editor->name_entry)));
1013
1014         }
1015
1016         return full_key_path;
1017 }
1018