1 /* Hey EMACS -*- linux-c -*- */
4 * Copyright (C) 2002-2003 Romain Lievin <roms@tilp.info>
5 * Released under the terms of the GNU GPL v2.0.
16 #include <glade/glade.h>
19 #include <gdk/gdkkeysyms.h>
30 SINGLE_VIEW
, SPLIT_VIEW
, FULL_VIEW
33 static gint view_mode
= FULL_VIEW
;
34 static gboolean show_name
= TRUE
;
35 static gboolean show_range
= TRUE
;
36 static gboolean show_value
= TRUE
;
37 static gboolean show_all
= FALSE
;
38 static gboolean show_debug
= FALSE
;
39 static gboolean resizeable
= FALSE
;
41 GtkWidget
*main_wnd
= NULL
;
42 GtkWidget
*tree1_w
= NULL
; // left frame
43 GtkWidget
*tree2_w
= NULL
; // right frame
44 GtkWidget
*text_w
= NULL
;
45 GtkWidget
*hpaned
= NULL
;
46 GtkWidget
*vpaned
= NULL
;
47 GtkWidget
*back_btn
= NULL
;
48 GtkWidget
*save_btn
= NULL
;
49 GtkWidget
*save_menu_item
= NULL
;
51 GtkTextTag
*tag1
, *tag2
;
54 GtkTreeStore
*tree1
, *tree2
, *tree
;
55 GtkTreeModel
*model1
, *model2
;
56 static GtkTreeIter
*parents
[256];
59 static struct menu
*current
; // current node for SINGLE view
60 static struct menu
*browsed
; // browsed node for SPLIT view
63 COL_OPTION
, COL_NAME
, COL_NO
, COL_MOD
, COL_YES
, COL_VALUE
,
64 COL_MENU
, COL_COLOR
, COL_EDIT
, COL_PIXBUF
,
65 COL_PIXVIS
, COL_BTNVIS
, COL_BTNACT
, COL_BTNINC
, COL_BTNRAD
,
69 static void display_list(void);
70 static void display_tree(struct menu
*menu
);
71 static void display_tree_part(void);
72 static void update_tree(struct menu
*src
, GtkTreeIter
* dst
);
73 static void set_node(GtkTreeIter
* node
, struct menu
*menu
, gchar
** row
);
74 static gchar
**fill_row(struct menu
*menu
);
75 static void conf_changed(void);
77 /* Helping/Debugging Functions */
80 const char *dbg_print_stype(int val
)
87 strcpy(buf
, "unknown");
89 strcpy(buf
, "boolean");
90 if (val
== S_TRISTATE
)
91 strcpy(buf
, "tristate");
97 strcpy(buf
, "string");
108 const char *dbg_print_flags(int val
)
110 static char buf
[256];
114 if (val
& SYMBOL_CONST
)
115 strcat(buf
, "const/");
116 if (val
& SYMBOL_CHECK
)
117 strcat(buf
, "check/");
118 if (val
& SYMBOL_CHOICE
)
119 strcat(buf
, "choice/");
120 if (val
& SYMBOL_CHOICEVAL
)
121 strcat(buf
, "choiceval/");
122 if (val
& SYMBOL_VALID
)
123 strcat(buf
, "valid/");
124 if (val
& SYMBOL_OPTIONAL
)
125 strcat(buf
, "optional/");
126 if (val
& SYMBOL_WRITE
)
127 strcat(buf
, "write/");
128 if (val
& SYMBOL_CHANGED
)
129 strcat(buf
, "changed/");
130 if (val
& SYMBOL_AUTO
)
131 strcat(buf
, "auto/");
133 buf
[strlen(buf
) - 1] = '\0';
141 const char *dbg_print_ptype(int val
)
143 static char buf
[256];
147 if (val
== P_UNKNOWN
)
148 strcpy(buf
, "unknown");
150 strcpy(buf
, "prompt");
151 if (val
== P_COMMENT
)
152 strcpy(buf
, "comment");
155 if (val
== P_DEFAULT
)
156 strcpy(buf
, "default");
158 strcpy(buf
, "choice");
168 void replace_button_icon(GladeXML
* xml
, GdkDrawable
* window
,
169 GtkStyle
* style
, gchar
* btn_name
, gchar
** xpm
)
173 GtkToolButton
*button
;
176 pixmap
= gdk_pixmap_create_from_xpm_d(window
, &mask
,
177 &style
->bg
[GTK_STATE_NORMAL
],
180 button
= GTK_TOOL_BUTTON(glade_xml_get_widget(xml
, btn_name
));
181 image
= gtk_image_new_from_pixmap(pixmap
, mask
);
182 gtk_widget_show(image
);
183 gtk_tool_button_set_icon_widget(button
, image
);
186 /* Main Window Initialization */
187 void init_main_window(const gchar
* glade_file
)
191 GtkTextBuffer
*txtbuf
;
195 xml
= glade_xml_new(glade_file
, "window1", NULL
);
197 g_error(_("GUI loading failed !\n"));
198 glade_xml_signal_autoconnect(xml
);
200 main_wnd
= glade_xml_get_widget(xml
, "window1");
201 hpaned
= glade_xml_get_widget(xml
, "hpaned1");
202 vpaned
= glade_xml_get_widget(xml
, "vpaned1");
203 tree1_w
= glade_xml_get_widget(xml
, "treeview1");
204 tree2_w
= glade_xml_get_widget(xml
, "treeview2");
205 text_w
= glade_xml_get_widget(xml
, "textview3");
207 back_btn
= glade_xml_get_widget(xml
, "button1");
208 gtk_widget_set_sensitive(back_btn
, FALSE
);
210 widget
= glade_xml_get_widget(xml
, "show_name1");
211 gtk_check_menu_item_set_active((GtkCheckMenuItem
*) widget
,
214 widget
= glade_xml_get_widget(xml
, "show_range1");
215 gtk_check_menu_item_set_active((GtkCheckMenuItem
*) widget
,
218 widget
= glade_xml_get_widget(xml
, "show_data1");
219 gtk_check_menu_item_set_active((GtkCheckMenuItem
*) widget
,
222 save_btn
= glade_xml_get_widget(xml
, "button3");
223 save_menu_item
= glade_xml_get_widget(xml
, "save1");
224 conf_set_changed_callback(conf_changed
);
226 style
= gtk_widget_get_style(main_wnd
);
227 widget
= glade_xml_get_widget(xml
, "toolbar1");
229 #if 0 /* Use stock Gtk icons instead */
230 replace_button_icon(xml
, main_wnd
->window
, style
,
231 "button1", (gchar
**) xpm_back
);
232 replace_button_icon(xml
, main_wnd
->window
, style
,
233 "button2", (gchar
**) xpm_load
);
234 replace_button_icon(xml
, main_wnd
->window
, style
,
235 "button3", (gchar
**) xpm_save
);
237 replace_button_icon(xml
, main_wnd
->window
, style
,
238 "button4", (gchar
**) xpm_single_view
);
239 replace_button_icon(xml
, main_wnd
->window
, style
,
240 "button5", (gchar
**) xpm_split_view
);
241 replace_button_icon(xml
, main_wnd
->window
, style
,
242 "button6", (gchar
**) xpm_tree_view
);
247 widget
= glade_xml_get_widget(xml
, "button4");
248 g_signal_emit_by_name(widget
, "clicked");
251 widget
= glade_xml_get_widget(xml
, "button5");
252 g_signal_emit_by_name(widget
, "clicked");
255 widget
= glade_xml_get_widget(xml
, "button6");
256 g_signal_emit_by_name(widget
, "clicked");
260 txtbuf
= gtk_text_view_get_buffer(GTK_TEXT_VIEW(text_w
));
261 tag1
= gtk_text_buffer_create_tag(txtbuf
, "mytag1",
263 "weight", PANGO_WEIGHT_BOLD
,
265 tag2
= gtk_text_buffer_create_tag(txtbuf
, "mytag2",
266 /*"style", PANGO_STYLE_OBLIQUE, */
269 sprintf(title
, _("OpenADK Configuration"));
270 gtk_window_set_title(GTK_WINDOW(main_wnd
), title
);
272 gtk_widget_show(main_wnd
);
275 void init_tree_model(void)
279 tree
= tree2
= gtk_tree_store_new(COL_NUMBER
,
280 G_TYPE_STRING
, G_TYPE_STRING
,
281 G_TYPE_STRING
, G_TYPE_STRING
,
282 G_TYPE_STRING
, G_TYPE_STRING
,
283 G_TYPE_POINTER
, GDK_TYPE_COLOR
,
284 G_TYPE_BOOLEAN
, GDK_TYPE_PIXBUF
,
285 G_TYPE_BOOLEAN
, G_TYPE_BOOLEAN
,
286 G_TYPE_BOOLEAN
, G_TYPE_BOOLEAN
,
288 model2
= GTK_TREE_MODEL(tree2
);
290 for (parents
[0] = NULL
, i
= 1; i
< 256; i
++)
291 parents
[i
] = (GtkTreeIter
*) g_malloc(sizeof(GtkTreeIter
));
293 tree1
= gtk_tree_store_new(COL_NUMBER
,
294 G_TYPE_STRING
, G_TYPE_STRING
,
295 G_TYPE_STRING
, G_TYPE_STRING
,
296 G_TYPE_STRING
, G_TYPE_STRING
,
297 G_TYPE_POINTER
, GDK_TYPE_COLOR
,
298 G_TYPE_BOOLEAN
, GDK_TYPE_PIXBUF
,
299 G_TYPE_BOOLEAN
, G_TYPE_BOOLEAN
,
300 G_TYPE_BOOLEAN
, G_TYPE_BOOLEAN
,
302 model1
= GTK_TREE_MODEL(tree1
);
305 void init_left_tree(void)
307 GtkTreeView
*view
= GTK_TREE_VIEW(tree1_w
);
308 GtkCellRenderer
*renderer
;
309 GtkTreeSelection
*sel
;
310 GtkTreeViewColumn
*column
;
312 gtk_tree_view_set_model(view
, model1
);
313 gtk_tree_view_set_headers_visible(view
, TRUE
);
314 gtk_tree_view_set_rules_hint(view
, FALSE
);
316 column
= gtk_tree_view_column_new();
317 gtk_tree_view_append_column(view
, column
);
318 gtk_tree_view_column_set_title(column
, _("Options"));
320 renderer
= gtk_cell_renderer_toggle_new();
321 gtk_tree_view_column_pack_start(GTK_TREE_VIEW_COLUMN(column
),
323 gtk_tree_view_column_set_attributes(GTK_TREE_VIEW_COLUMN(column
),
325 "active", COL_BTNACT
,
326 "inconsistent", COL_BTNINC
,
327 "visible", COL_BTNVIS
,
328 "radio", COL_BTNRAD
, NULL
);
329 renderer
= gtk_cell_renderer_text_new();
330 gtk_tree_view_column_pack_start(GTK_TREE_VIEW_COLUMN(column
),
332 gtk_tree_view_column_set_attributes(GTK_TREE_VIEW_COLUMN(column
),
338 sel
= gtk_tree_view_get_selection(view
);
339 gtk_tree_selection_set_mode(sel
, GTK_SELECTION_SINGLE
);
340 gtk_widget_realize(tree1_w
);
343 static void renderer_edited(GtkCellRendererText
* cell
,
344 const gchar
* path_string
,
345 const gchar
* new_text
, gpointer user_data
);
346 static void renderer_toggled(GtkCellRendererToggle
* cellrenderertoggle
,
347 gchar
* arg1
, gpointer user_data
);
349 void init_right_tree(void)
351 GtkTreeView
*view
= GTK_TREE_VIEW(tree2_w
);
352 GtkCellRenderer
*renderer
;
353 GtkTreeSelection
*sel
;
354 GtkTreeViewColumn
*column
;
357 gtk_tree_view_set_model(view
, model2
);
358 gtk_tree_view_set_headers_visible(view
, TRUE
);
359 gtk_tree_view_set_rules_hint(view
, FALSE
);
361 column
= gtk_tree_view_column_new();
362 gtk_tree_view_append_column(view
, column
);
363 gtk_tree_view_column_set_title(column
, _("Options"));
365 renderer
= gtk_cell_renderer_pixbuf_new();
366 gtk_tree_view_column_pack_start(GTK_TREE_VIEW_COLUMN(column
),
368 gtk_tree_view_column_set_attributes(GTK_TREE_VIEW_COLUMN(column
),
370 "pixbuf", COL_PIXBUF
,
371 "visible", COL_PIXVIS
, NULL
);
372 renderer
= gtk_cell_renderer_toggle_new();
373 gtk_tree_view_column_pack_start(GTK_TREE_VIEW_COLUMN(column
),
375 gtk_tree_view_column_set_attributes(GTK_TREE_VIEW_COLUMN(column
),
377 "active", COL_BTNACT
,
378 "inconsistent", COL_BTNINC
,
379 "visible", COL_BTNVIS
,
380 "radio", COL_BTNRAD
, NULL
);
381 /*g_signal_connect(G_OBJECT(renderer), "toggled",
382 G_CALLBACK(renderer_toggled), NULL); */
383 renderer
= gtk_cell_renderer_text_new();
384 gtk_tree_view_column_pack_start(GTK_TREE_VIEW_COLUMN(column
),
386 gtk_tree_view_column_set_attributes(GTK_TREE_VIEW_COLUMN(column
),
392 renderer
= gtk_cell_renderer_text_new();
393 gtk_tree_view_insert_column_with_attributes(view
, -1,
398 renderer
= gtk_cell_renderer_text_new();
399 gtk_tree_view_insert_column_with_attributes(view
, -1,
404 renderer
= gtk_cell_renderer_text_new();
405 gtk_tree_view_insert_column_with_attributes(view
, -1,
410 renderer
= gtk_cell_renderer_text_new();
411 gtk_tree_view_insert_column_with_attributes(view
, -1,
416 renderer
= gtk_cell_renderer_text_new();
417 gtk_tree_view_insert_column_with_attributes(view
, -1,
418 _("Value"), renderer
,
424 g_signal_connect(G_OBJECT(renderer
), "edited",
425 G_CALLBACK(renderer_edited
), NULL
);
427 column
= gtk_tree_view_get_column(view
, COL_NAME
);
428 gtk_tree_view_column_set_visible(column
, show_name
);
429 column
= gtk_tree_view_get_column(view
, COL_NO
);
430 gtk_tree_view_column_set_visible(column
, show_range
);
431 column
= gtk_tree_view_get_column(view
, COL_MOD
);
432 gtk_tree_view_column_set_visible(column
, show_range
);
433 column
= gtk_tree_view_get_column(view
, COL_YES
);
434 gtk_tree_view_column_set_visible(column
, show_range
);
435 column
= gtk_tree_view_get_column(view
, COL_VALUE
);
436 gtk_tree_view_column_set_visible(column
, show_value
);
439 for (i
= 0; i
< COL_VALUE
; i
++) {
440 column
= gtk_tree_view_get_column(view
, i
);
441 gtk_tree_view_column_set_resizable(column
, TRUE
);
445 sel
= gtk_tree_view_get_selection(view
);
446 gtk_tree_selection_set_mode(sel
, GTK_SELECTION_SINGLE
);
450 /* Utility Functions */
453 static void text_insert_help(struct menu
*menu
)
455 GtkTextBuffer
*buffer
;
456 GtkTextIter start
, end
;
457 const char *prompt
= _(menu_get_prompt(menu
));
458 struct gstr help
= str_new();
460 menu_get_ext_help(menu
, &help
);
462 buffer
= gtk_text_view_get_buffer(GTK_TEXT_VIEW(text_w
));
463 gtk_text_buffer_get_bounds(buffer
, &start
, &end
);
464 gtk_text_buffer_delete(buffer
, &start
, &end
);
465 gtk_text_view_set_left_margin(GTK_TEXT_VIEW(text_w
), 15);
467 gtk_text_buffer_get_end_iter(buffer
, &end
);
468 gtk_text_buffer_insert_with_tags(buffer
, &end
, prompt
, -1, tag1
,
470 gtk_text_buffer_insert_at_cursor(buffer
, "\n\n", 2);
471 gtk_text_buffer_get_end_iter(buffer
, &end
);
472 gtk_text_buffer_insert_with_tags(buffer
, &end
, str_get(&help
), -1, tag2
,
478 static void text_insert_msg(const char *title
, const char *message
)
480 GtkTextBuffer
*buffer
;
481 GtkTextIter start
, end
;
482 const char *msg
= message
;
484 buffer
= gtk_text_view_get_buffer(GTK_TEXT_VIEW(text_w
));
485 gtk_text_buffer_get_bounds(buffer
, &start
, &end
);
486 gtk_text_buffer_delete(buffer
, &start
, &end
);
487 gtk_text_view_set_left_margin(GTK_TEXT_VIEW(text_w
), 15);
489 gtk_text_buffer_get_end_iter(buffer
, &end
);
490 gtk_text_buffer_insert_with_tags(buffer
, &end
, title
, -1, tag1
,
492 gtk_text_buffer_insert_at_cursor(buffer
, "\n\n", 2);
493 gtk_text_buffer_get_end_iter(buffer
, &end
);
494 gtk_text_buffer_insert_with_tags(buffer
, &end
, msg
, -1, tag2
,
499 /* Main Windows Callbacks */
501 void on_save_activate(GtkMenuItem
* menuitem
, gpointer user_data
);
502 gboolean
on_window1_delete_event(GtkWidget
* widget
, GdkEvent
* event
,
505 GtkWidget
*dialog
, *label
;
508 if (!conf_get_changed())
511 dialog
= gtk_dialog_new_with_buttons(_("Warning !"),
512 GTK_WINDOW(main_wnd
),
515 GTK_DIALOG_DESTROY_WITH_PARENT
),
521 GTK_RESPONSE_CANCEL
, NULL
);
522 gtk_dialog_set_default_response(GTK_DIALOG(dialog
),
523 GTK_RESPONSE_CANCEL
);
525 label
= gtk_label_new(_("\nSave configuration ?\n"));
526 gtk_container_add(GTK_CONTAINER(GTK_DIALOG(dialog
)->vbox
), label
);
527 gtk_widget_show(label
);
529 result
= gtk_dialog_run(GTK_DIALOG(dialog
));
531 case GTK_RESPONSE_YES
:
532 on_save_activate(NULL
, NULL
);
534 case GTK_RESPONSE_NO
:
536 case GTK_RESPONSE_CANCEL
:
537 case GTK_RESPONSE_DELETE_EVENT
:
539 gtk_widget_destroy(dialog
);
547 void on_window1_destroy(GtkObject
* object
, gpointer user_data
)
554 on_window1_size_request(GtkWidget
* widget
,
555 GtkRequisition
* requisition
, gpointer user_data
)
560 if (widget
->window
== NULL
)
561 gtk_window_get_default_size(GTK_WINDOW(main_wnd
), &w
, &h
);
563 gdk_window_get_size(widget
->window
, &w
, &h
);
569 gtk_paned_set_position(GTK_PANED(vpaned
), 2 * h
/ 3);
573 /* Menu & Toolbar Callbacks */
577 load_filename(GtkFileSelection
* file_selector
, gpointer user_data
)
581 fn
= gtk_file_selection_get_filename(GTK_FILE_SELECTION
585 text_insert_msg(_("Error"), _("Unable to load configuration !"));
587 display_tree(&rootmenu
);
590 void on_load1_activate(GtkMenuItem
* menuitem
, gpointer user_data
)
594 fs
= gtk_file_selection_new(_("Load file..."));
595 g_signal_connect(GTK_OBJECT(GTK_FILE_SELECTION(fs
)->ok_button
),
597 G_CALLBACK(load_filename
), (gpointer
) fs
);
598 g_signal_connect_swapped(GTK_OBJECT
599 (GTK_FILE_SELECTION(fs
)->ok_button
),
600 "clicked", G_CALLBACK(gtk_widget_destroy
),
602 g_signal_connect_swapped(GTK_OBJECT
603 (GTK_FILE_SELECTION(fs
)->cancel_button
),
604 "clicked", G_CALLBACK(gtk_widget_destroy
),
610 void on_save_activate(GtkMenuItem
* menuitem
, gpointer user_data
)
612 if (conf_write(NULL
))
613 text_insert_msg(_("Error"), _("Unable to save configuration !"));
618 store_filename(GtkFileSelection
* file_selector
, gpointer user_data
)
622 fn
= gtk_file_selection_get_filename(GTK_FILE_SELECTION
626 text_insert_msg(_("Error"), _("Unable to save configuration !"));
628 gtk_widget_destroy(GTK_WIDGET(user_data
));
631 void on_save_as1_activate(GtkMenuItem
* menuitem
, gpointer user_data
)
635 fs
= gtk_file_selection_new(_("Save file as..."));
636 g_signal_connect(GTK_OBJECT(GTK_FILE_SELECTION(fs
)->ok_button
),
638 G_CALLBACK(store_filename
), (gpointer
) fs
);
639 g_signal_connect_swapped(GTK_OBJECT
640 (GTK_FILE_SELECTION(fs
)->ok_button
),
641 "clicked", G_CALLBACK(gtk_widget_destroy
),
643 g_signal_connect_swapped(GTK_OBJECT
644 (GTK_FILE_SELECTION(fs
)->cancel_button
),
645 "clicked", G_CALLBACK(gtk_widget_destroy
),
651 void on_quit1_activate(GtkMenuItem
* menuitem
, gpointer user_data
)
653 if (!on_window1_delete_event(NULL
, NULL
, NULL
))
654 gtk_widget_destroy(GTK_WIDGET(main_wnd
));
658 void on_show_name1_activate(GtkMenuItem
* menuitem
, gpointer user_data
)
660 GtkTreeViewColumn
*col
;
662 show_name
= GTK_CHECK_MENU_ITEM(menuitem
)->active
;
663 col
= gtk_tree_view_get_column(GTK_TREE_VIEW(tree2_w
), COL_NAME
);
665 gtk_tree_view_column_set_visible(col
, show_name
);
669 void on_show_range1_activate(GtkMenuItem
* menuitem
, gpointer user_data
)
671 GtkTreeViewColumn
*col
;
673 show_range
= GTK_CHECK_MENU_ITEM(menuitem
)->active
;
674 col
= gtk_tree_view_get_column(GTK_TREE_VIEW(tree2_w
), COL_NO
);
676 gtk_tree_view_column_set_visible(col
, show_range
);
677 col
= gtk_tree_view_get_column(GTK_TREE_VIEW(tree2_w
), COL_MOD
);
679 gtk_tree_view_column_set_visible(col
, show_range
);
680 col
= gtk_tree_view_get_column(GTK_TREE_VIEW(tree2_w
), COL_YES
);
682 gtk_tree_view_column_set_visible(col
, show_range
);
687 void on_show_data1_activate(GtkMenuItem
* menuitem
, gpointer user_data
)
689 GtkTreeViewColumn
*col
;
691 show_value
= GTK_CHECK_MENU_ITEM(menuitem
)->active
;
692 col
= gtk_tree_view_get_column(GTK_TREE_VIEW(tree2_w
), COL_VALUE
);
694 gtk_tree_view_column_set_visible(col
, show_value
);
699 on_show_all_options1_activate(GtkMenuItem
* menuitem
, gpointer user_data
)
701 show_all
= GTK_CHECK_MENU_ITEM(menuitem
)->active
;
703 gtk_tree_store_clear(tree2
);
704 display_tree(&rootmenu
); // instead of update_tree to speed-up
709 on_show_debug_info1_activate(GtkMenuItem
* menuitem
, gpointer user_data
)
711 show_debug
= GTK_CHECK_MENU_ITEM(menuitem
)->active
;
712 update_tree(&rootmenu
, NULL
);
716 void on_introduction1_activate(GtkMenuItem
* menuitem
, gpointer user_data
)
719 const gchar
*intro_text
= _(
720 "Welcome to gkc, the GTK+ graphical kernel configuration tool\n"
722 "For each option, a blank box indicates the feature is disabled, a\n"
723 "check indicates it is enabled, and a dot indicates that it is to\n"
724 "be compiled as a module. Clicking on the box will cycle through the three states.\n"
726 "If you do not see an option (e.g., a device driver) that you\n"
727 "believe should be present, try turning on Show All Options\n"
728 "under the Options menu.\n"
729 "Although there is no cross reference yet to help you figure out\n"
730 "what other options must be enabled to support the option you\n"
731 "are interested in, you can still view the help of a grayed-out\n"
734 "Toggling Show Debug Info under the Options menu will show \n"
735 "the dependencies, which you can then match by examining other options.");
737 dialog
= gtk_message_dialog_new(GTK_WINDOW(main_wnd
),
738 GTK_DIALOG_DESTROY_WITH_PARENT
,
740 GTK_BUTTONS_CLOSE
, intro_text
);
741 g_signal_connect_swapped(GTK_OBJECT(dialog
), "response",
742 G_CALLBACK(gtk_widget_destroy
),
744 gtk_widget_show_all(dialog
);
748 void on_about1_activate(GtkMenuItem
* menuitem
, gpointer user_data
)
751 const gchar
*about_text
=
752 _("gkc is copyright (c) 2002 Romain Lievin <roms@lpg.ticalc.org>.\n"
753 "Based on the source code from Roman Zippel.\n");
755 dialog
= gtk_message_dialog_new(GTK_WINDOW(main_wnd
),
756 GTK_DIALOG_DESTROY_WITH_PARENT
,
758 GTK_BUTTONS_CLOSE
, about_text
);
759 g_signal_connect_swapped(GTK_OBJECT(dialog
), "response",
760 G_CALLBACK(gtk_widget_destroy
),
762 gtk_widget_show_all(dialog
);
766 void on_license1_activate(GtkMenuItem
* menuitem
, gpointer user_data
)
769 const gchar
*license_text
=
770 _("gkc is released under the terms of the GNU GPL v2.\n"
771 "For more information, please see the source code or\n"
772 "visit http://www.fsf.org/licenses/licenses.html\n");
774 dialog
= gtk_message_dialog_new(GTK_WINDOW(main_wnd
),
775 GTK_DIALOG_DESTROY_WITH_PARENT
,
777 GTK_BUTTONS_CLOSE
, license_text
);
778 g_signal_connect_swapped(GTK_OBJECT(dialog
), "response",
779 G_CALLBACK(gtk_widget_destroy
),
781 gtk_widget_show_all(dialog
);
785 void on_back_clicked(GtkButton
* button
, gpointer user_data
)
787 enum prop_type ptype
;
789 current
= current
->parent
;
790 ptype
= current
->prompt
? current
->prompt
->type
: P_UNKNOWN
;
792 current
= current
->parent
;
795 if (current
== &rootmenu
)
796 gtk_widget_set_sensitive(back_btn
, FALSE
);
800 void on_load_clicked(GtkButton
* button
, gpointer user_data
)
802 on_load1_activate(NULL
, user_data
);
806 void on_single_clicked(GtkButton
* button
, gpointer user_data
)
808 view_mode
= SINGLE_VIEW
;
809 gtk_paned_set_position(GTK_PANED(hpaned
), 0);
810 gtk_widget_hide(tree1_w
);
816 void on_split_clicked(GtkButton
* button
, gpointer user_data
)
819 view_mode
= SPLIT_VIEW
;
820 gtk_widget_show(tree1_w
);
821 gtk_window_get_default_size(GTK_WINDOW(main_wnd
), &w
, &h
);
822 gtk_paned_set_position(GTK_PANED(hpaned
), w
/ 2);
824 gtk_tree_store_clear(tree2
);
827 /* Disable back btn, like in full mode. */
828 gtk_widget_set_sensitive(back_btn
, FALSE
);
832 void on_full_clicked(GtkButton
* button
, gpointer user_data
)
834 view_mode
= FULL_VIEW
;
835 gtk_paned_set_position(GTK_PANED(hpaned
), 0);
836 gtk_widget_hide(tree1_w
);
838 gtk_tree_store_clear(tree2
);
839 display_tree(&rootmenu
);
840 gtk_widget_set_sensitive(back_btn
, FALSE
);
844 void on_collapse_clicked(GtkButton
* button
, gpointer user_data
)
846 gtk_tree_view_collapse_all(GTK_TREE_VIEW(tree2_w
));
850 void on_expand_clicked(GtkButton
* button
, gpointer user_data
)
852 gtk_tree_view_expand_all(GTK_TREE_VIEW(tree2_w
));
856 /* CTree Callbacks */
858 /* Change hex/int/string value in the cell */
859 static void renderer_edited(GtkCellRendererText
* cell
,
860 const gchar
* path_string
,
861 const gchar
* new_text
, gpointer user_data
)
863 GtkTreePath
*path
= gtk_tree_path_new_from_string(path_string
);
865 const char *old_def
, *new_def
;
869 if (!gtk_tree_model_get_iter(model2
, &iter
, path
))
872 gtk_tree_model_get(model2
, &iter
, COL_MENU
, &menu
, -1);
875 gtk_tree_model_get(model2
, &iter
, COL_VALUE
, &old_def
, -1);
878 sym_set_string_value(sym
, new_def
);
880 update_tree(&rootmenu
, NULL
);
882 gtk_tree_path_free(path
);
885 /* Change the value of a symbol and update the tree */
886 static void change_sym_value(struct menu
*menu
, gint col
)
888 struct symbol
*sym
= menu
->sym
;
889 tristate oldval
, newval
;
896 else if (col
== COL_MOD
)
898 else if (col
== COL_YES
)
903 switch (sym_get_type(sym
)) {
906 oldval
= sym_get_tristate_value(sym
);
907 if (!sym_tristate_within_range(sym
, newval
))
909 sym_set_tristate_value(sym
, newval
);
910 if (view_mode
== FULL_VIEW
)
911 update_tree(&rootmenu
, NULL
);
912 else if (view_mode
== SPLIT_VIEW
) {
913 update_tree(browsed
, NULL
);
916 else if (view_mode
== SINGLE_VIEW
)
917 display_tree_part(); //fixme: keep exp/coll
927 static void toggle_sym_value(struct menu
*menu
)
932 sym_toggle_tristate_value(menu
->sym
);
933 if (view_mode
== FULL_VIEW
)
934 update_tree(&rootmenu
, NULL
);
935 else if (view_mode
== SPLIT_VIEW
) {
936 update_tree(browsed
, NULL
);
939 else if (view_mode
== SINGLE_VIEW
)
940 display_tree_part(); //fixme: keep exp/coll
943 static void renderer_toggled(GtkCellRendererToggle
* cell
,
944 gchar
* path_string
, gpointer user_data
)
946 GtkTreePath
*path
, *sel_path
= NULL
;
947 GtkTreeIter iter
, sel_iter
;
948 GtkTreeSelection
*sel
;
951 path
= gtk_tree_path_new_from_string(path_string
);
952 if (!gtk_tree_model_get_iter(model2
, &iter
, path
))
955 sel
= gtk_tree_view_get_selection(GTK_TREE_VIEW(tree2_w
));
956 if (gtk_tree_selection_get_selected(sel
, NULL
, &sel_iter
))
957 sel_path
= gtk_tree_model_get_path(model2
, &sel_iter
);
960 if (gtk_tree_path_compare(path
, sel_path
))
963 gtk_tree_model_get(model2
, &iter
, COL_MENU
, &menu
, -1);
964 toggle_sym_value(menu
);
967 gtk_tree_path_free(sel_path
);
969 gtk_tree_path_free(path
);
972 static gint
column2index(GtkTreeViewColumn
* column
)
976 for (i
= 0; i
< COL_NUMBER
; i
++) {
977 GtkTreeViewColumn
*col
;
979 col
= gtk_tree_view_get_column(GTK_TREE_VIEW(tree2_w
), i
);
988 /* User click: update choice (full) or goes down (single) */
990 on_treeview2_button_press_event(GtkWidget
* widget
,
991 GdkEventButton
* event
, gpointer user_data
)
993 GtkTreeView
*view
= GTK_TREE_VIEW(widget
);
995 GtkTreeViewColumn
*column
;
1000 #if GTK_CHECK_VERSION(2,1,4) // bug in ctree with earlier version of GTK
1001 gint tx
= (gint
) event
->x
;
1002 gint ty
= (gint
) event
->y
;
1005 gtk_tree_view_get_path_at_pos(view
, tx
, ty
, &path
, &column
, &cx
,
1008 gtk_tree_view_get_cursor(view
, &path
, &column
);
1013 if (!gtk_tree_model_get_iter(model2
, &iter
, path
))
1015 gtk_tree_model_get(model2
, &iter
, COL_MENU
, &menu
, -1);
1017 col
= column2index(column
);
1018 if (event
->type
== GDK_2BUTTON_PRESS
) {
1019 enum prop_type ptype
;
1020 ptype
= menu
->prompt
? menu
->prompt
->type
: P_UNKNOWN
;
1022 if (ptype
== P_MENU
&& view_mode
!= FULL_VIEW
&& col
== COL_OPTION
) {
1023 // goes down into menu
1025 display_tree_part();
1026 gtk_widget_set_sensitive(back_btn
, TRUE
);
1027 } else if ((col
== COL_OPTION
)) {
1028 toggle_sym_value(menu
);
1029 gtk_tree_view_expand_row(view
, path
, TRUE
);
1032 if (col
== COL_VALUE
) {
1033 toggle_sym_value(menu
);
1034 gtk_tree_view_expand_row(view
, path
, TRUE
);
1035 } else if (col
== COL_NO
|| col
== COL_MOD
1036 || col
== COL_YES
) {
1037 change_sym_value(menu
, col
);
1038 gtk_tree_view_expand_row(view
, path
, TRUE
);
1045 /* Key pressed: update choice */
1047 on_treeview2_key_press_event(GtkWidget
* widget
,
1048 GdkEventKey
* event
, gpointer user_data
)
1050 GtkTreeView
*view
= GTK_TREE_VIEW(widget
);
1052 GtkTreeViewColumn
*column
;
1057 gtk_tree_view_get_cursor(view
, &path
, &column
);
1061 if (event
->keyval
== GDK_space
) {
1062 if (gtk_tree_view_row_expanded(view
, path
))
1063 gtk_tree_view_collapse_row(view
, path
);
1065 gtk_tree_view_expand_row(view
, path
, FALSE
);
1068 if (event
->keyval
== GDK_KP_Enter
) {
1070 if (widget
== tree1_w
)
1073 gtk_tree_model_get_iter(model2
, &iter
, path
);
1074 gtk_tree_model_get(model2
, &iter
, COL_MENU
, &menu
, -1);
1076 if (!strcasecmp(event
->string
, "n"))
1078 else if (!strcasecmp(event
->string
, "m"))
1080 else if (!strcasecmp(event
->string
, "y"))
1084 change_sym_value(menu
, col
);
1090 /* Row selection changed: update help */
1092 on_treeview2_cursor_changed(GtkTreeView
* treeview
, gpointer user_data
)
1094 GtkTreeSelection
*selection
;
1098 selection
= gtk_tree_view_get_selection(treeview
);
1099 if (gtk_tree_selection_get_selected(selection
, &model2
, &iter
)) {
1100 gtk_tree_model_get(model2
, &iter
, COL_MENU
, &menu
, -1);
1101 text_insert_help(menu
);
1106 /* User click: display sub-tree in the right frame. */
1108 on_treeview1_button_press_event(GtkWidget
* widget
,
1109 GdkEventButton
* event
, gpointer user_data
)
1111 GtkTreeView
*view
= GTK_TREE_VIEW(widget
);
1113 GtkTreeViewColumn
*column
;
1117 gint tx
= (gint
) event
->x
;
1118 gint ty
= (gint
) event
->y
;
1121 gtk_tree_view_get_path_at_pos(view
, tx
, ty
, &path
, &column
, &cx
,
1126 gtk_tree_model_get_iter(model1
, &iter
, path
);
1127 gtk_tree_model_get(model1
, &iter
, COL_MENU
, &menu
, -1);
1129 if (event
->type
== GDK_2BUTTON_PRESS
) {
1130 toggle_sym_value(menu
);
1132 display_tree_part();
1135 display_tree_part();
1138 gtk_widget_realize(tree2_w
);
1139 gtk_tree_view_set_cursor(view
, path
, NULL
, FALSE
);
1140 gtk_widget_grab_focus(tree2_w
);
1146 /* Fill a row of strings */
1147 static gchar
**fill_row(struct menu
*menu
)
1149 static gchar
*row
[COL_NUMBER
];
1150 struct symbol
*sym
= menu
->sym
;
1154 enum prop_type ptype
;
1157 for (i
= COL_OPTION
; i
<= COL_COLOR
; i
++)
1159 bzero(row
, sizeof(row
));
1162 g_strdup_printf("%s %s", _(menu_get_prompt(menu
)),
1163 sym
&& sym_has_value(sym
) ? "(NEW)" : "");
1165 if (show_all
&& !menu_is_visible(menu
))
1166 row
[COL_COLOR
] = g_strdup("DarkGray");
1168 row
[COL_COLOR
] = g_strdup("Black");
1170 ptype
= menu
->prompt
? menu
->prompt
->type
: P_UNKNOWN
;
1173 row
[COL_PIXBUF
] = (gchar
*) xpm_menu
;
1174 if (view_mode
== SINGLE_VIEW
)
1175 row
[COL_PIXVIS
] = GINT_TO_POINTER(TRUE
);
1176 row
[COL_BTNVIS
] = GINT_TO_POINTER(FALSE
);
1179 row
[COL_PIXBUF
] = (gchar
*) xpm_void
;
1180 row
[COL_PIXVIS
] = GINT_TO_POINTER(FALSE
);
1181 row
[COL_BTNVIS
] = GINT_TO_POINTER(FALSE
);
1184 row
[COL_PIXBUF
] = (gchar
*) xpm_void
;
1185 row
[COL_PIXVIS
] = GINT_TO_POINTER(FALSE
);
1186 row
[COL_BTNVIS
] = GINT_TO_POINTER(TRUE
);
1192 row
[COL_NAME
] = g_strdup(sym
->name
);
1194 sym_calc_value(sym
);
1195 sym
->flags
&= ~SYMBOL_CHANGED
;
1197 if (sym_is_choice(sym
)) { // parse childs for getting final value
1199 struct symbol
*def_sym
= sym_get_choice_value(sym
);
1200 struct menu
*def_menu
= NULL
;
1202 row
[COL_BTNVIS
] = GINT_TO_POINTER(FALSE
);
1204 for (child
= menu
->list
; child
; child
= child
->next
) {
1205 if (menu_is_visible(child
)
1206 && child
->sym
== def_sym
)
1212 g_strdup(_(menu_get_prompt(def_menu
)));
1214 if (sym
->flags
& SYMBOL_CHOICEVAL
)
1215 row
[COL_BTNRAD
] = GINT_TO_POINTER(TRUE
);
1217 stype
= sym_get_type(sym
);
1220 if (GPOINTER_TO_INT(row
[COL_PIXVIS
]) == FALSE
)
1221 row
[COL_BTNVIS
] = GINT_TO_POINTER(TRUE
);
1222 if (sym_is_choice(sym
))
1225 val
= sym_get_tristate_value(sym
);
1228 row
[COL_NO
] = g_strdup("N");
1229 row
[COL_VALUE
] = g_strdup("N");
1230 row
[COL_BTNACT
] = GINT_TO_POINTER(FALSE
);
1231 row
[COL_BTNINC
] = GINT_TO_POINTER(FALSE
);
1234 row
[COL_MOD
] = g_strdup("M");
1235 row
[COL_VALUE
] = g_strdup("M");
1236 row
[COL_BTNINC
] = GINT_TO_POINTER(TRUE
);
1239 row
[COL_YES
] = g_strdup("Y");
1240 row
[COL_VALUE
] = g_strdup("Y");
1241 row
[COL_BTNACT
] = GINT_TO_POINTER(TRUE
);
1242 row
[COL_BTNINC
] = GINT_TO_POINTER(FALSE
);
1246 if (val
!= no
&& sym_tristate_within_range(sym
, no
))
1247 row
[COL_NO
] = g_strdup("_");
1248 if (val
!= mod
&& sym_tristate_within_range(sym
, mod
))
1249 row
[COL_MOD
] = g_strdup("_");
1250 if (val
!= yes
&& sym_tristate_within_range(sym
, yes
))
1251 row
[COL_YES
] = g_strdup("_");
1256 def
= sym_get_string_value(sym
);
1257 row
[COL_VALUE
] = g_strdup(def
);
1258 row
[COL_EDIT
] = GINT_TO_POINTER(TRUE
);
1259 row
[COL_BTNVIS
] = GINT_TO_POINTER(FALSE
);
1267 /* Set the node content with a row of strings */
1268 static void set_node(GtkTreeIter
* node
, struct menu
*menu
, gchar
** row
)
1274 pix
= gdk_pixbuf_new_from_xpm_data((const char **)
1277 gdk_color_parse(row
[COL_COLOR
], &color
);
1278 gdk_colormap_alloc_colors(gdk_colormap_get_system(), &color
, 1,
1279 FALSE
, FALSE
, &success
);
1281 gtk_tree_store_set(tree
, node
,
1282 COL_OPTION
, row
[COL_OPTION
],
1283 COL_NAME
, row
[COL_NAME
],
1284 COL_NO
, row
[COL_NO
],
1285 COL_MOD
, row
[COL_MOD
],
1286 COL_YES
, row
[COL_YES
],
1287 COL_VALUE
, row
[COL_VALUE
],
1288 COL_MENU
, (gpointer
) menu
,
1290 COL_EDIT
, GPOINTER_TO_INT(row
[COL_EDIT
]),
1292 COL_PIXVIS
, GPOINTER_TO_INT(row
[COL_PIXVIS
]),
1293 COL_BTNVIS
, GPOINTER_TO_INT(row
[COL_BTNVIS
]),
1294 COL_BTNACT
, GPOINTER_TO_INT(row
[COL_BTNACT
]),
1295 COL_BTNINC
, GPOINTER_TO_INT(row
[COL_BTNINC
]),
1296 COL_BTNRAD
, GPOINTER_TO_INT(row
[COL_BTNRAD
]),
1299 g_object_unref(pix
);
1303 /* Add a node to the tree */
1304 static void place_node(struct menu
*menu
, char **row
)
1306 GtkTreeIter
*parent
= parents
[indent
- 1];
1307 GtkTreeIter
*node
= parents
[indent
];
1309 gtk_tree_store_append(tree
, node
, parent
);
1310 set_node(node
, menu
, row
);
1314 /* Find a node in the GTK+ tree */
1315 static GtkTreeIter found
;
1318 * Find a menu in the GtkTree starting at parent.
1320 GtkTreeIter
*gtktree_iter_find_node(GtkTreeIter
* parent
,
1321 struct menu
*tofind
)
1324 GtkTreeIter
*child
= &iter
;
1328 valid
= gtk_tree_model_iter_children(model2
, child
, parent
);
1332 gtk_tree_model_get(model2
, child
, 6, &menu
, -1);
1334 if (menu
== tofind
) {
1335 memcpy(&found
, child
, sizeof(GtkTreeIter
));
1339 ret
= gtktree_iter_find_node(child
, tofind
);
1343 valid
= gtk_tree_model_iter_next(model2
, child
);
1351 * Update the tree by adding/removing entries
1352 * Does not change other nodes
1354 static void update_tree(struct menu
*src
, GtkTreeIter
* dst
)
1356 struct menu
*child1
;
1357 GtkTreeIter iter
, tmp
;
1358 GtkTreeIter
*child2
= &iter
;
1360 GtkTreeIter
*sibling
;
1362 struct property
*prop
;
1363 struct menu
*menu1
, *menu2
;
1365 if (src
== &rootmenu
)
1368 valid
= gtk_tree_model_iter_children(model2
, child2
, dst
);
1369 for (child1
= src
->list
; child1
; child1
= child1
->next
) {
1371 prop
= child1
->prompt
;
1377 gtk_tree_model_get(model2
, child2
, COL_MENU
,
1380 menu2
= NULL
; // force adding of a first child
1383 printf("%*c%s | %s\n", indent
, ' ',
1384 menu1
? menu_get_prompt(menu1
) : "nil",
1385 menu2
? menu_get_prompt(menu2
) : "nil");
1388 if (!menu_is_visible(child1
) && !show_all
) { // remove node
1389 if (gtktree_iter_find_node(dst
, menu1
) != NULL
) {
1390 memcpy(&tmp
, child2
, sizeof(GtkTreeIter
));
1391 valid
= gtk_tree_model_iter_next(model2
,
1393 gtk_tree_store_remove(tree2
, &tmp
);
1395 return; // next parent
1397 goto reparse
; // next child
1402 if (menu1
!= menu2
) {
1403 if (gtktree_iter_find_node(dst
, menu1
) == NULL
) { // add node
1404 if (!valid
&& !menu2
)
1408 gtk_tree_store_insert_before(tree2
,
1411 set_node(child2
, menu1
, fill_row(menu1
));
1414 } else { // remove node
1415 memcpy(&tmp
, child2
, sizeof(GtkTreeIter
));
1416 valid
= gtk_tree_model_iter_next(model2
,
1418 gtk_tree_store_remove(tree2
, &tmp
);
1420 return; // next parent
1422 goto reparse
; // next child
1424 } else if (sym
&& (sym
->flags
& SYMBOL_CHANGED
)) {
1425 set_node(child2
, menu1
, fill_row(menu1
));
1429 update_tree(child1
, child2
);
1432 valid
= gtk_tree_model_iter_next(model2
, child2
);
1437 /* Display the whole tree (single/split/full view) */
1438 static void display_tree(struct menu
*menu
)
1441 struct property
*prop
;
1443 enum prop_type ptype
;
1445 if (menu
== &rootmenu
) {
1447 current
= &rootmenu
;
1450 for (child
= menu
->list
; child
; child
= child
->next
) {
1451 prop
= child
->prompt
;
1453 ptype
= prop
? prop
->type
: P_UNKNOWN
;
1456 sym
->flags
&= ~SYMBOL_CHANGED
;
1458 if ((view_mode
== SPLIT_VIEW
)
1459 && !(child
->flags
& MENU_ROOT
) && (tree
== tree1
))
1462 if ((view_mode
== SPLIT_VIEW
) && (child
->flags
& MENU_ROOT
)
1466 if (menu_is_visible(child
) || show_all
)
1467 place_node(child
, fill_row(child
));
1469 printf("%*c%s: ", indent
, ' ', menu_get_prompt(child
));
1470 printf("%s", child
->flags
& MENU_ROOT
? "rootmenu | " : "");
1471 dbg_print_ptype(ptype
);
1474 dbg_print_stype(sym
->type
);
1476 dbg_print_flags(sym
->flags
);
1481 if ((view_mode
!= FULL_VIEW
) && (ptype
== P_MENU
)
1485 if (((menu != &rootmenu) && !(menu->flags & MENU_ROOT))
1486 || (view_mode == FULL_VIEW)
1487 || (view_mode == SPLIT_VIEW))*/
1488 if (((view_mode
== SINGLE_VIEW
) && (menu
->flags
& MENU_ROOT
))
1489 || (view_mode
== FULL_VIEW
)
1490 || (view_mode
== SPLIT_VIEW
)) {
1492 display_tree(child
);
1498 /* Display a part of the tree starting at current node (single/split view) */
1499 static void display_tree_part(void)
1502 gtk_tree_store_clear(tree2
);
1503 if (view_mode
== SINGLE_VIEW
)
1504 display_tree(current
);
1505 else if (view_mode
== SPLIT_VIEW
)
1506 display_tree(browsed
);
1507 gtk_tree_view_expand_all(GTK_TREE_VIEW(tree2_w
));
1510 /* Display the list in the left frame (split view) */
1511 static void display_list(void)
1514 gtk_tree_store_clear(tree1
);
1517 display_tree(&rootmenu
);
1518 gtk_tree_view_expand_all(GTK_TREE_VIEW(tree1_w
));
1522 void fixup_rootmenu(struct menu
*menu
)
1525 static int menu_cnt
= 0;
1527 menu
->flags
|= MENU_ROOT
;
1528 for (child
= menu
->list
; child
; child
= child
->next
) {
1529 if (child
->prompt
&& child
->prompt
->type
== P_MENU
) {
1531 fixup_rootmenu(child
);
1533 } else if (!menu_cnt
)
1534 fixup_rootmenu(child
);
1540 int main(int ac
, char *av
[])
1546 #ifndef LKC_DIRECT_LINK
1550 bindtextdomain(PACKAGE
, LOCALEDIR
);
1551 bind_textdomain_codeset(PACKAGE
, "UTF-8");
1552 textdomain(PACKAGE
);
1559 //add_pixmap_directory (PACKAGE_DATA_DIR "/" PACKAGE "/pixmaps");
1560 //add_pixmap_directory (PACKAGE_SOURCE_DIR "/pixmaps");
1562 /* Determine GUI path */
1563 env
= getenv(SRCTREE
);
1565 glade_file
= g_strconcat(env
, "/scripts/kconfig/gconf.glade", NULL
);
1566 else if (av
[0][0] == '/')
1567 glade_file
= g_strconcat(av
[0], ".glade", NULL
);
1569 glade_file
= g_strconcat(g_get_current_dir(), "/", av
[0], ".glade", NULL
);
1571 /* Load the interface and connect signals */
1572 init_main_window(glade_file
);
1578 if (ac
> 1 && av
[1][0] == '-') {
1585 printf("%s <config>\n", av
[0]);
1593 fixup_rootmenu(&rootmenu
);
1596 switch (view_mode
) {
1598 display_tree_part();
1604 display_tree(&rootmenu
);
1613 static void conf_changed(void)
1615 bool changed
= conf_get_changed();
1616 gtk_widget_set_sensitive(save_btn
, changed
);
1617 gtk_widget_set_sensitive(save_menu_item
, changed
);