base/config/kconfig/gconf.c

Go to the documentation of this file.
00001 /* Hey EMACS -*- linux-c -*- */ 00002 /* 00003 * 00004 * Copyright (C) 2002-2003 Romain Lievin <roms@lpg.ticalc.org> 00005 * Released under the terms of the GNU GPL v2.0. 00006 * 00007 */ 00008 00009 #ifdef HAVE_CONFIG_H 00010 # include <config.h> 00011 #endif 00012 00013 #include "lkc.h" 00014 #include "images.c" 00015 00016 #include <glade/glade.h> 00017 #include <gtk/gtk.h> 00018 #include <glib.h> 00019 #include <gdk/gdkkeysyms.h> 00020 00021 #include <stdio.h> 00022 #include <string.h> 00023 #include <unistd.h> 00024 #include <time.h> 00025 #include <stdlib.h> 00026 00027 //#define DEBUG 00028 00029 enum { 00030 SINGLE_VIEW, SPLIT_VIEW, FULL_VIEW 00031 }; 00032 00033 static gint view_mode = FULL_VIEW; 00034 static gboolean show_name = TRUE; 00035 static gboolean show_range = TRUE; 00036 static gboolean show_value = TRUE; 00037 static gboolean show_all = FALSE; 00038 static gboolean show_debug = FALSE; 00039 static gboolean resizeable = FALSE; 00040 00041 static gboolean config_changed = FALSE; 00042 00043 static char nohelp_text[] = 00044 "Sorry, no help available for this option yet.\n"; 00045 00046 GtkWidget *main_wnd = NULL; 00047 GtkWidget *tree1_w = NULL; // left frame 00048 GtkWidget *tree2_w = NULL; // right frame 00049 GtkWidget *text_w = NULL; 00050 GtkWidget *hpaned = NULL; 00051 GtkWidget *vpaned = NULL; 00052 GtkWidget *back_btn = NULL; 00053 00054 GtkTextTag *tag1, *tag2; 00055 GdkColor color; 00056 00057 GtkTreeStore *tree1, *tree2, *tree; 00058 GtkTreeModel *model1, *model2; 00059 static GtkTreeIter *parents[256]; 00060 static gint indent; 00061 00062 static struct menu *current; // current node for SINGLE view 00063 static struct menu *browsed; // browsed node for SPLIT view 00064 00065 enum { 00066 COL_OPTION, COL_NAME, COL_NO, COL_MOD, COL_YES, COL_VALUE, 00067 COL_MENU, COL_COLOR, COL_EDIT, COL_PIXBUF, 00068 COL_PIXVIS, COL_BTNVIS, COL_BTNACT, COL_BTNINC, COL_BTNRAD, 00069 COL_NUMBER 00070 }; 00071 00072 static void display_list(void); 00073 static void display_tree(struct menu *menu); 00074 static void display_tree_part(void); 00075 static void update_tree(struct menu *src, GtkTreeIter * dst); 00076 static void set_node(GtkTreeIter * node, struct menu *menu, gchar ** row); 00077 static gchar **fill_row(struct menu *menu); 00078 00079 00080 /* Helping/Debugging Functions */ 00081 00082 00083 const char *dbg_print_stype(int val) 00084 { 00085 static char buf[256]; 00086 00087 bzero(buf, 256); 00088 00089 if (val == S_UNKNOWN) 00090 strcpy(buf, "unknown"); 00091 if (val == S_BOOLEAN) 00092 strcpy(buf, "boolean"); 00093 if (val == S_TRISTATE) 00094 strcpy(buf, "tristate"); 00095 if (val == S_INT) 00096 strcpy(buf, "int"); 00097 if (val == S_HEX) 00098 strcpy(buf, "hex"); 00099 if (val == S_STRING) 00100 strcpy(buf, "string"); 00101 if (val == S_OTHER) 00102 strcpy(buf, "other"); 00103 00104 #ifdef DEBUG 00105 printf("%s", buf); 00106 #endif 00107 00108 return buf; 00109 } 00110 00111 const char *dbg_print_flags(int val) 00112 { 00113 static char buf[256]; 00114 00115 bzero(buf, 256); 00116 00117 if (val & SYMBOL_YES) 00118 strcat(buf, "yes/"); 00119 if (val & SYMBOL_MOD) 00120 strcat(buf, "mod/"); 00121 if (val & SYMBOL_NO) 00122 strcat(buf, "no/"); 00123 if (val & SYMBOL_CONST) 00124 strcat(buf, "const/"); 00125 if (val & SYMBOL_CHECK) 00126 strcat(buf, "check/"); 00127 if (val & SYMBOL_CHOICE) 00128 strcat(buf, "choice/"); 00129 if (val & SYMBOL_CHOICEVAL) 00130 strcat(buf, "choiceval/"); 00131 if (val & SYMBOL_PRINTED) 00132 strcat(buf, "printed/"); 00133 if (val & SYMBOL_VALID) 00134 strcat(buf, "valid/"); 00135 if (val & SYMBOL_OPTIONAL) 00136 strcat(buf, "optional/"); 00137 if (val & SYMBOL_WRITE) 00138 strcat(buf, "write/"); 00139 if (val & SYMBOL_CHANGED) 00140 strcat(buf, "changed/"); 00141 if (val & SYMBOL_NEW) 00142 strcat(buf, "new/"); 00143 if (val & SYMBOL_AUTO) 00144 strcat(buf, "auto/"); 00145 00146 buf[strlen(buf) - 1] = '\0'; 00147 #ifdef DEBUG 00148 printf("%s", buf); 00149 #endif 00150 00151 return buf; 00152 } 00153 00154 const char *dbg_print_ptype(int val) 00155 { 00156 static char buf[256]; 00157 00158 bzero(buf, 256); 00159 00160 if (val == P_UNKNOWN) 00161 strcpy(buf, "unknown"); 00162 if (val == P_PROMPT) 00163 strcpy(buf, "prompt"); 00164 if (val == P_COMMENT) 00165 strcpy(buf, "comment"); 00166 if (val == P_MENU) 00167 strcpy(buf, "menu"); 00168 if (val == P_DEFAULT) 00169 strcpy(buf, "default"); 00170 if (val == P_CHOICE) 00171 strcpy(buf, "choice"); 00172 00173 #ifdef DEBUG 00174 printf("%s", buf); 00175 #endif 00176 00177 return buf; 00178 } 00179 00180 00181 /* Main Window Initialization */ 00182 00183 00184 void init_main_window(const gchar * glade_file) 00185 { 00186 GladeXML *xml; 00187 GtkWidget *widget; 00188 GtkTextBuffer *txtbuf; 00189 GdkPixmap *pixmap; 00190 GdkBitmap *mask; 00191 GtkStyle *style; 00192 00193 xml = glade_xml_new(glade_file, "window1", NULL); 00194 if (!xml) 00195 g_error("GUI loading failed !\n"); 00196 glade_xml_signal_autoconnect(xml); 00197 00198 main_wnd = glade_xml_get_widget(xml, "window1"); 00199 hpaned = glade_xml_get_widget(xml, "hpaned1"); 00200 vpaned = glade_xml_get_widget(xml, "vpaned1"); 00201 tree1_w = glade_xml_get_widget(xml, "treeview1"); 00202 tree2_w = glade_xml_get_widget(xml, "treeview2"); 00203 text_w = glade_xml_get_widget(xml, "textview3"); 00204 00205 back_btn = glade_xml_get_widget(xml, "button1"); 00206 gtk_widget_set_sensitive(back_btn, FALSE); 00207 00208 widget = glade_xml_get_widget(xml, "show_name1"); 00209 gtk_check_menu_item_set_active((GtkCheckMenuItem *) widget, 00210 show_name); 00211 00212 widget = glade_xml_get_widget(xml, "show_range1"); 00213 gtk_check_menu_item_set_active((GtkCheckMenuItem *) widget, 00214 show_range); 00215 00216 widget = glade_xml_get_widget(xml, "show_data1"); 00217 gtk_check_menu_item_set_active((GtkCheckMenuItem *) widget, 00218 show_value); 00219 00220 style = gtk_widget_get_style(main_wnd); 00221 widget = glade_xml_get_widget(xml, "toolbar1"); 00222 00223 pixmap = gdk_pixmap_create_from_xpm_d(main_wnd->window, &mask, 00224 &style->bg[GTK_STATE_NORMAL], 00225 (gchar **) xpm_single_view); 00226 gtk_image_set_from_pixmap(GTK_IMAGE 00227 (((GtkToolbarChild 00228 *) (g_list_nth(GTK_TOOLBAR(widget)-> 00229 children, 00230 5)->data))->icon), 00231 pixmap, mask); 00232 pixmap = 00233 gdk_pixmap_create_from_xpm_d(main_wnd->window, &mask, 00234 &style->bg[GTK_STATE_NORMAL], 00235 (gchar **) xpm_split_view); 00236 gtk_image_set_from_pixmap(GTK_IMAGE 00237 (((GtkToolbarChild 00238 *) (g_list_nth(GTK_TOOLBAR(widget)-> 00239 children, 00240 6)->data))->icon), 00241 pixmap, mask); 00242 pixmap = 00243 gdk_pixmap_create_from_xpm_d(main_wnd->window, &mask, 00244 &style->bg[GTK_STATE_NORMAL], 00245 (gchar **) xpm_tree_view); 00246 gtk_image_set_from_pixmap(GTK_IMAGE 00247 (((GtkToolbarChild 00248 *) (g_list_nth(GTK_TOOLBAR(widget)-> 00249 children, 00250 7)->data))->icon), 00251 pixmap, mask); 00252 00253 switch (view_mode) { 00254 case SINGLE_VIEW: 00255 widget = glade_xml_get_widget(xml, "button4"); 00256 gtk_button_clicked(GTK_BUTTON(widget)); 00257 break; 00258 case SPLIT_VIEW: 00259 widget = glade_xml_get_widget(xml, "button5"); 00260 gtk_button_clicked(GTK_BUTTON(widget)); 00261 break; 00262 case FULL_VIEW: 00263 widget = glade_xml_get_widget(xml, "button6"); 00264 gtk_button_clicked(GTK_BUTTON(widget)); 00265 break; 00266 } 00267 00268 txtbuf = gtk_text_view_get_buffer(GTK_TEXT_VIEW(text_w)); 00269 tag1 = gtk_text_buffer_create_tag(txtbuf, "mytag1", 00270 "foreground", "red", 00271 "weight", PANGO_WEIGHT_BOLD, 00272 NULL); 00273 tag2 = gtk_text_buffer_create_tag(txtbuf, "mytag2", 00274 /*"style", PANGO_STYLE_OBLIQUE, */ 00275 NULL); 00276 } 00277 00278 void init_tree_model(void) 00279 { 00280 gint i; 00281 00282 tree = tree2 = gtk_tree_store_new(COL_NUMBER, 00283 G_TYPE_STRING, G_TYPE_STRING, 00284 G_TYPE_STRING, G_TYPE_STRING, 00285 G_TYPE_STRING, G_TYPE_STRING, 00286 G_TYPE_POINTER, GDK_TYPE_COLOR, 00287 G_TYPE_BOOLEAN, GDK_TYPE_PIXBUF, 00288 G_TYPE_BOOLEAN, G_TYPE_BOOLEAN, 00289 G_TYPE_BOOLEAN, G_TYPE_BOOLEAN, 00290 G_TYPE_BOOLEAN); 00291 model2 = GTK_TREE_MODEL(tree2); 00292 00293 for (parents[0] = NULL, i = 1; i < 256; i++) 00294 parents[i] = (GtkTreeIter *) g_malloc(sizeof(GtkTreeIter)); 00295 00296 tree1 = gtk_tree_store_new(COL_NUMBER, 00297 G_TYPE_STRING, G_TYPE_STRING, 00298 G_TYPE_STRING, G_TYPE_STRING, 00299 G_TYPE_STRING, G_TYPE_STRING, 00300 G_TYPE_POINTER, GDK_TYPE_COLOR, 00301 G_TYPE_BOOLEAN, GDK_TYPE_PIXBUF, 00302 G_TYPE_BOOLEAN, G_TYPE_BOOLEAN, 00303 G_TYPE_BOOLEAN, G_TYPE_BOOLEAN, 00304 G_TYPE_BOOLEAN); 00305 model1 = GTK_TREE_MODEL(tree1); 00306 } 00307 00308 void init_left_tree(void) 00309 { 00310 GtkTreeView *view = GTK_TREE_VIEW(tree1_w); 00311 GtkCellRenderer *renderer; 00312 GtkTreeSelection *sel; 00313 GtkTreeViewColumn *column; 00314 00315 gtk_tree_view_set_model(view, model1); 00316 gtk_tree_view_set_headers_visible(view, TRUE); 00317 gtk_tree_view_set_rules_hint(view, FALSE); 00318 00319 column = gtk_tree_view_column_new(); 00320 gtk_tree_view_append_column(view, column); 00321 gtk_tree_view_column_set_title(column, "Options"); 00322 00323 renderer = gtk_cell_renderer_toggle_new(); 00324 gtk_tree_view_column_pack_start(GTK_TREE_VIEW_COLUMN(column), 00325 renderer, FALSE); 00326 gtk_tree_view_column_set_attributes(GTK_TREE_VIEW_COLUMN(column), 00327 renderer, 00328 "active", COL_BTNACT, 00329 "inconsistent", COL_BTNINC, 00330 "visible", COL_BTNVIS, 00331 "radio", COL_BTNRAD, NULL); 00332 renderer = gtk_cell_renderer_text_new(); 00333 gtk_tree_view_column_pack_start(GTK_TREE_VIEW_COLUMN(column), 00334 renderer, FALSE); 00335 gtk_tree_view_column_set_attributes(GTK_TREE_VIEW_COLUMN(column), 00336 renderer, 00337 "text", COL_OPTION, 00338 "foreground-gdk", 00339 COL_COLOR, NULL); 00340 00341 sel = gtk_tree_view_get_selection(view); 00342 gtk_tree_selection_set_mode(sel, GTK_SELECTION_SINGLE); 00343 gtk_widget_realize(tree1_w); 00344 } 00345 00346 static void renderer_edited(GtkCellRendererText * cell, 00347 const gchar * path_string, 00348 const gchar * new_text, gpointer user_data); 00349 static void renderer_toggled(GtkCellRendererToggle * cellrenderertoggle, 00350 gchar * arg1, gpointer user_data); 00351 00352 void init_right_tree(void) 00353 { 00354 GtkTreeView *view = GTK_TREE_VIEW(tree2_w); 00355 GtkCellRenderer *renderer; 00356 GtkTreeSelection *sel; 00357 GtkTreeViewColumn *column; 00358 gint i; 00359 00360 gtk_tree_view_set_model(view, model2); 00361 gtk_tree_view_set_headers_visible(view, TRUE); 00362 gtk_tree_view_set_rules_hint(view, FALSE); 00363 00364 column = gtk_tree_view_column_new(); 00365 gtk_tree_view_append_column(view, column); 00366 gtk_tree_view_column_set_title(column, "Options"); 00367 00368 renderer = gtk_cell_renderer_pixbuf_new(); 00369 gtk_tree_view_column_pack_start(GTK_TREE_VIEW_COLUMN(column), 00370 renderer, FALSE); 00371 gtk_tree_view_column_set_attributes(GTK_TREE_VIEW_COLUMN(column), 00372 renderer, 00373 "pixbuf", COL_PIXBUF, 00374 "visible", COL_PIXVIS, NULL); 00375 renderer = gtk_cell_renderer_toggle_new(); 00376 gtk_tree_view_column_pack_start(GTK_TREE_VIEW_COLUMN(column), 00377 renderer, FALSE); 00378 gtk_tree_view_column_set_attributes(GTK_TREE_VIEW_COLUMN(column), 00379 renderer, 00380 "active", COL_BTNACT, 00381 "inconsistent", COL_BTNINC, 00382 "visible", COL_BTNVIS, 00383 "radio", COL_BTNRAD, NULL); 00384 /*g_signal_connect(G_OBJECT(renderer), "toggled", 00385 G_CALLBACK(renderer_toggled), NULL); */ 00386 renderer = gtk_cell_renderer_text_new(); 00387 gtk_tree_view_column_pack_start(GTK_TREE_VIEW_COLUMN(column), 00388 renderer, FALSE); 00389 gtk_tree_view_column_set_attributes(GTK_TREE_VIEW_COLUMN(column), 00390 renderer, 00391 "text", COL_OPTION, 00392 "foreground-gdk", 00393 COL_COLOR, NULL); 00394 00395 renderer = gtk_cell_renderer_text_new(); 00396 gtk_tree_view_insert_column_with_attributes(view, -1, 00397 "Name", renderer, 00398 "text", COL_NAME, 00399 "foreground-gdk", 00400 COL_COLOR, NULL); 00401 renderer = gtk_cell_renderer_text_new(); 00402 gtk_tree_view_insert_column_with_attributes(view, -1, 00403 "N", renderer, 00404 "text", COL_NO, 00405 "foreground-gdk", 00406 COL_COLOR, NULL); 00407 renderer = gtk_cell_renderer_text_new(); 00408 gtk_tree_view_insert_column_with_attributes(view, -1, 00409 "M", renderer, 00410 "text", COL_MOD, 00411 "foreground-gdk", 00412 COL_COLOR, NULL); 00413 renderer = gtk_cell_renderer_text_new(); 00414 gtk_tree_view_insert_column_with_attributes(view, -1, 00415 "Y", renderer, 00416 "text", COL_YES, 00417 "foreground-gdk", 00418 COL_COLOR, NULL); 00419 renderer = gtk_cell_renderer_text_new(); 00420 gtk_tree_view_insert_column_with_attributes(view, -1, 00421 "Value", renderer, 00422 "text", COL_VALUE, 00423 "editable", 00424 COL_EDIT, 00425 "foreground-gdk", 00426 COL_COLOR, NULL); 00427 g_signal_connect(G_OBJECT(renderer), "edited", 00428 G_CALLBACK(renderer_edited), NULL); 00429 00430 column = gtk_tree_view_get_column(view, COL_NAME); 00431 gtk_tree_view_column_set_visible(column, show_name); 00432 column = gtk_tree_view_get_column(view, COL_NO); 00433 gtk_tree_view_column_set_visible(column, show_range); 00434 column = gtk_tree_view_get_column(view, COL_MOD); 00435 gtk_tree_view_column_set_visible(column, show_range); 00436 column = gtk_tree_view_get_column(view, COL_YES); 00437 gtk_tree_view_column_set_visible(column, show_range); 00438 column = gtk_tree_view_get_column(view, COL_VALUE); 00439 gtk_tree_view_column_set_visible(column, show_value); 00440 00441 if (resizeable) { 00442 for (i = 0; i < COL_VALUE; i++) { 00443 column = gtk_tree_view_get_column(view, i); 00444 gtk_tree_view_column_set_resizable(column, TRUE); 00445 } 00446 } 00447 00448 sel = gtk_tree_view_get_selection(view); 00449 gtk_tree_selection_set_mode(sel, GTK_SELECTION_SINGLE); 00450 } 00451 00452 00453 /* Utility Functions */ 00454 00455 00456 static void text_insert_help(struct menu *menu) 00457 { 00458 GtkTextBuffer *buffer; 00459 GtkTextIter start, end; 00460 const char *prompt = menu_get_prompt(menu); 00461 gchar *name; 00462 const char *help = nohelp_text; 00463 00464 if (!menu->sym) 00465 help = ""; 00466 else if (menu->sym->help) 00467 help = menu->sym->help; 00468 00469 if (menu->sym && menu->sym->name) 00470 name = g_strdup_printf(menu->sym->name); 00471 else 00472 name = g_strdup(""); 00473 00474 buffer = gtk_text_view_get_buffer(GTK_TEXT_VIEW(text_w)); 00475 gtk_text_buffer_get_bounds(buffer, &start, &end); 00476 gtk_text_buffer_delete(buffer, &start, &end); 00477 gtk_text_view_set_left_margin(GTK_TEXT_VIEW(text_w), 15); 00478 00479 gtk_text_buffer_get_end_iter(buffer, &end); 00480 gtk_text_buffer_insert_with_tags(buffer, &end, prompt, -1, tag1, 00481 NULL); 00482 gtk_text_buffer_insert_at_cursor(buffer, " ", 1); 00483 gtk_text_buffer_get_end_iter(buffer, &end); 00484 gtk_text_buffer_insert_with_tags(buffer, &end, name, -1, tag1, 00485 NULL); 00486 gtk_text_buffer_insert_at_cursor(buffer, "\n\n", 2); 00487 gtk_text_buffer_get_end_iter(buffer, &end); 00488 gtk_text_buffer_insert_with_tags(buffer, &end, help, -1, tag2, 00489 NULL); 00490 } 00491 00492 00493 static void text_insert_msg(const char *title, const char *message) 00494 { 00495 GtkTextBuffer *buffer; 00496 GtkTextIter start, end; 00497 const char *msg = message; 00498 00499 buffer = gtk_text_view_get_buffer(GTK_TEXT_VIEW(text_w)); 00500 gtk_text_buffer_get_bounds(buffer, &start, &end); 00501 gtk_text_buffer_delete(buffer, &start, &end); 00502 gtk_text_view_set_left_margin(GTK_TEXT_VIEW(text_w), 15); 00503 00504 gtk_text_buffer_get_end_iter(buffer, &end); 00505 gtk_text_buffer_insert_with_tags(buffer, &end, title, -1, tag1, 00506 NULL); 00507 gtk_text_buffer_insert_at_cursor(buffer, "\n\n", 2); 00508 gtk_text_buffer_get_end_iter(buffer, &end); 00509 gtk_text_buffer_insert_with_tags(buffer, &end, msg, -1, tag2, 00510 NULL); 00511 } 00512 00513 00514 /* Main Windows Callbacks */ 00515 00516 void on_save1_activate(GtkMenuItem * menuitem, gpointer user_data); 00517 gboolean on_window1_delete_event(GtkWidget * widget, GdkEvent * event, 00518 gpointer user_data) 00519 { 00520 GtkWidget *dialog, *label; 00521 gint result; 00522 00523 if (config_changed == FALSE) 00524 return FALSE; 00525 00526 dialog = gtk_dialog_new_with_buttons("Warning !", 00527 GTK_WINDOW(main_wnd), 00528 (GtkDialogFlags) 00529 (GTK_DIALOG_MODAL | 00530 GTK_DIALOG_DESTROY_WITH_PARENT), 00531 GTK_STOCK_OK, 00532 GTK_RESPONSE_YES, 00533 GTK_STOCK_NO, 00534 GTK_RESPONSE_NO, 00535 GTK_STOCK_CANCEL, 00536 GTK_RESPONSE_CANCEL, NULL); 00537 gtk_dialog_set_default_response(GTK_DIALOG(dialog), 00538 GTK_RESPONSE_CANCEL); 00539 00540 label = gtk_label_new("\nSave configuration ?\n"); 00541 gtk_container_add(GTK_CONTAINER(GTK_DIALOG(dialog)->vbox), label); 00542 gtk_widget_show(label); 00543 00544 result = gtk_dialog_run(GTK_DIALOG(dialog)); 00545 switch (result) { 00546 case GTK_RESPONSE_YES: 00547 on_save1_activate(NULL, NULL); 00548 return FALSE; 00549 case GTK_RESPONSE_NO: 00550 return FALSE; 00551 case GTK_RESPONSE_CANCEL: 00552 case GTK_RESPONSE_DELETE_EVENT: 00553 default: 00554 gtk_widget_destroy(dialog); 00555 return TRUE; 00556 } 00557 00558 return FALSE; 00559 } 00560 00561 00562 void on_window1_destroy(GtkObject * object, gpointer user_data) 00563 { 00564 gtk_main_quit(); 00565 } 00566 00567 00568 void 00569 on_window1_size_request(GtkWidget * widget, 00570 GtkRequisition * requisition, gpointer user_data) 00571 { 00572 static gint old_h; 00573 gint w, h; 00574 00575 if (widget->window == NULL) 00576 gtk_window_get_default_size(GTK_WINDOW(main_wnd), &w, &h); 00577 else 00578 gdk_window_get_size(widget->window, &w, &h); 00579 00580 if (h == old_h) 00581 return; 00582 old_h = h; 00583 00584 gtk_paned_set_position(GTK_PANED(vpaned), 2 * h / 3); 00585 } 00586 00587 00588 /* Menu & Toolbar Callbacks */ 00589 00590 00591 static void 00592 load_filename(GtkFileSelection * file_selector, gpointer user_data) 00593 { 00594 const gchar *fn; 00595 00596 fn = gtk_file_selection_get_filename(GTK_FILE_SELECTION 00597 (user_data)); 00598 00599 if (conf_read(fn)) 00600 text_insert_msg("Error", "Unable to load configuration !"); 00601 else 00602 display_tree(&rootmenu); 00603 } 00604 00605 void on_load1_activate(GtkMenuItem * menuitem, gpointer user_data) 00606 { 00607 GtkWidget *fs; 00608 00609 fs = gtk_file_selection_new("Load file..."); 00610 g_signal_connect(GTK_OBJECT(GTK_FILE_SELECTION(fs)->ok_button), 00611 "clicked", 00612 G_CALLBACK(load_filename), (gpointer) fs); 00613 g_signal_connect_swapped(GTK_OBJECT 00614 (GTK_FILE_SELECTION(fs)->ok_button), 00615 "clicked", G_CALLBACK(gtk_widget_destroy), 00616 (gpointer) fs); 00617 g_signal_connect_swapped(GTK_OBJECT 00618 (GTK_FILE_SELECTION(fs)->cancel_button), 00619 "clicked", G_CALLBACK(gtk_widget_destroy), 00620 (gpointer) fs); 00621 gtk_widget_show(fs); 00622 } 00623 00624 00625 void on_save1_activate(GtkMenuItem * menuitem, gpointer user_data) 00626 { 00627 if (conf_write(NULL)) 00628 text_insert_msg("Error", "Unable to save configuration !"); 00629 00630 config_changed = FALSE; 00631 } 00632 00633 00634 static void 00635 store_filename(GtkFileSelection * file_selector, gpointer user_data) 00636 { 00637 const gchar *fn; 00638 00639 fn = gtk_file_selection_get_filename(GTK_FILE_SELECTION 00640 (user_data)); 00641 00642 if (conf_write(fn)) 00643 text_insert_msg("Error", "Unable to save configuration !"); 00644 00645 gtk_widget_destroy(GTK_WIDGET(user_data)); 00646 } 00647 00648 void on_save_as1_activate(GtkMenuItem * menuitem, gpointer user_data) 00649 { 00650 GtkWidget *fs; 00651 00652 fs = gtk_file_selection_new("Save file as..."); 00653 g_signal_connect(GTK_OBJECT(GTK_FILE_SELECTION(fs)->ok_button), 00654 "clicked", 00655 G_CALLBACK(store_filename), (gpointer) fs); 00656 g_signal_connect_swapped(GTK_OBJECT 00657 (GTK_FILE_SELECTION(fs)->ok_button), 00658 "clicked", G_CALLBACK(gtk_widget_destroy), 00659 (gpointer) fs); 00660 g_signal_connect_swapped(GTK_OBJECT 00661 (GTK_FILE_SELECTION(fs)->cancel_button), 00662 "clicked", G_CALLBACK(gtk_widget_destroy), 00663 (gpointer) fs); 00664 gtk_widget_show(fs); 00665 } 00666 00667 00668 void on_quit1_activate(GtkMenuItem * menuitem, gpointer user_data) 00669 { 00670 if (!on_window1_delete_event(NULL, NULL, NULL)) 00671 gtk_widget_destroy(GTK_WIDGET(main_wnd)); 00672 } 00673 00674 00675 void on_show_name1_activate(GtkMenuItem * menuitem, gpointer user_data) 00676 { 00677 GtkTreeViewColumn *col; 00678 00679 show_name = GTK_CHECK_MENU_ITEM(menuitem)->active; 00680 col = gtk_tree_view_get_column(GTK_TREE_VIEW(tree2_w), COL_NAME); 00681 if (col) 00682 gtk_tree_view_column_set_visible(col, show_name); 00683 } 00684 00685 00686 void on_show_range1_activate(GtkMenuItem * menuitem, gpointer user_data) 00687 { 00688 GtkTreeViewColumn *col; 00689 00690 show_range = GTK_CHECK_MENU_ITEM(menuitem)->active; 00691 col = gtk_tree_view_get_column(GTK_TREE_VIEW(tree2_w), COL_NO); 00692 if (col) 00693 gtk_tree_view_column_set_visible(col, show_range); 00694 col = gtk_tree_view_get_column(GTK_TREE_VIEW(tree2_w), COL_MOD); 00695 if (col) 00696 gtk_tree_view_column_set_visible(col, show_range); 00697 col = gtk_tree_view_get_column(GTK_TREE_VIEW(tree2_w), COL_YES); 00698 if (col) 00699 gtk_tree_view_column_set_visible(col, show_range); 00700 00701 } 00702 00703 00704 void on_show_data1_activate(GtkMenuItem * menuitem, gpointer user_data) 00705 { 00706 GtkTreeViewColumn *col; 00707 00708 show_value = GTK_CHECK_MENU_ITEM(menuitem)->active; 00709 col = gtk_tree_view_get_column(GTK_TREE_VIEW(tree2_w), COL_VALUE); 00710 if (col) 00711 gtk_tree_view_column_set_visible(col, show_value); 00712 } 00713 00714 00715 void 00716 on_show_all_options1_activate(GtkMenuItem * menuitem, gpointer user_data) 00717 { 00718 show_all = GTK_CHECK_MENU_ITEM(menuitem)->active; 00719 00720 gtk_tree_store_clear(tree2); 00721 display_tree(&rootmenu); // instead of update_tree to speed-up 00722 } 00723 00724 00725 void 00726 on_show_debug_info1_activate(GtkMenuItem * menuitem, gpointer user_data) 00727 { 00728 show_debug = GTK_CHECK_MENU_ITEM(menuitem)->active; 00729 update_tree(&rootmenu, NULL); 00730 } 00731 00732 00733 void on_introduction1_activate(GtkMenuItem * menuitem, gpointer user_data) 00734 { 00735 GtkWidget *dialog; 00736 const gchar *intro_text = 00737 "Welcome to gkc, the GTK+ graphical configuration tool\n" 00738 "for RTAI.\n" 00739 "For each option, a blank box indicates the feature is disabled, a\n" 00740 "check indicates it is enabled, and a dot indicates that it is to\n" 00741 "be compiled as a module. Clicking on the box will cycle through the three states.\n" 00742 "\n" 00743 "If you do not see an option (e.g., a feature) that you\n" 00744 "believe should be present, try turning on Show All Options\n" 00745 "under the Options menu.\n" 00746 "Although there is no cross reference yet to help you figure out\n" 00747 "what other options must be enabled to support the option you\n" 00748 "are interested in, you can still view the help of a grayed-out\n" 00749 "option.\n" 00750 "\n" 00751 "Toggling Show Debug Info under the Options menu will show \n" 00752 "the dependencies, which you can then match by examining other options."; 00753 00754 dialog = gtk_message_dialog_new(GTK_WINDOW(main_wnd), 00755 GTK_DIALOG_DESTROY_WITH_PARENT, 00756 GTK_MESSAGE_INFO, 00757 GTK_BUTTONS_CLOSE, intro_text); 00758 g_signal_connect_swapped(GTK_OBJECT(dialog), "response", 00759 G_CALLBACK(gtk_widget_destroy), 00760 GTK_OBJECT(dialog)); 00761 gtk_widget_show_all(dialog); 00762 } 00763 00764 00765 void on_about1_activate(GtkMenuItem * menuitem, gpointer user_data) 00766 { 00767 GtkWidget *dialog; 00768 const gchar *about_text = 00769 "gkc is copyright (c) 2002 Romain Lievin <roms@lpg.ticalc.org>.\n" 00770 "Based on the source code from Roman Zippel.\n"; 00771 00772 dialog = gtk_message_dialog_new(GTK_WINDOW(main_wnd), 00773 GTK_DIALOG_DESTROY_WITH_PARENT, 00774 GTK_MESSAGE_INFO, 00775 GTK_BUTTONS_CLOSE, about_text); 00776 g_signal_connect_swapped(GTK_OBJECT(dialog), "response", 00777 G_CALLBACK(gtk_widget_destroy), 00778 GTK_OBJECT(dialog)); 00779 gtk_widget_show_all(dialog); 00780 } 00781 00782 00783 void on_license1_activate(GtkMenuItem * menuitem, gpointer user_data) 00784 { 00785 GtkWidget *dialog; 00786 const gchar *license_text = 00787 "gkc is released under the terms of the GNU GPL v2.\n" 00788 "For more information, please see the source code or\n" 00789 "visit http://www.fsf.org/licenses/licenses.html\n"; 00790 00791 dialog = gtk_message_dialog_new(GTK_WINDOW(main_wnd), 00792 GTK_DIALOG_DESTROY_WITH_PARENT, 00793 GTK_MESSAGE_INFO, 00794 GTK_BUTTONS_CLOSE, license_text); 00795 g_signal_connect_swapped(GTK_OBJECT(dialog), "response", 00796 G_CALLBACK(gtk_widget_destroy), 00797 GTK_OBJECT(dialog)); 00798 gtk_widget_show_all(dialog); 00799 } 00800 00801 00802 void on_back_pressed(GtkButton * button, gpointer user_data) 00803 { 00804 enum prop_type ptype; 00805 00806 current = current->parent; 00807 ptype = current->prompt ? current->prompt->type : P_UNKNOWN; 00808 if (ptype != P_MENU) 00809 current = current->parent; 00810 display_tree_part(); 00811 00812 if (current == &rootmenu) 00813 gtk_widget_set_sensitive(back_btn, FALSE); 00814 } 00815 00816 00817 void on_load_pressed(GtkButton * button, gpointer user_data) 00818 { 00819 on_load1_activate(NULL, user_data); 00820 } 00821 00822 00823 void on_save_pressed(GtkButton * button, gpointer user_data) 00824 { 00825 on_save1_activate(NULL, user_data); 00826 } 00827 00828 00829 void on_single_clicked(GtkButton * button, gpointer user_data) 00830 { 00831 view_mode = SINGLE_VIEW; 00832 gtk_paned_set_position(GTK_PANED(hpaned), 0); 00833 gtk_widget_hide(tree1_w); 00834 current = &rootmenu; 00835 display_tree_part(); 00836 } 00837 00838 00839 void on_split_clicked(GtkButton * button, gpointer user_data) 00840 { 00841 gint w, h; 00842 view_mode = SPLIT_VIEW; 00843 gtk_widget_show(tree1_w); 00844 gtk_window_get_default_size(GTK_WINDOW(main_wnd), &w, &h); 00845 gtk_paned_set_position(GTK_PANED(hpaned), w / 2); 00846 if (tree2) 00847 gtk_tree_store_clear(tree2); 00848 display_list(); 00849 } 00850 00851 00852 void on_full_clicked(GtkButton * button, gpointer user_data) 00853 { 00854 view_mode = FULL_VIEW; 00855 gtk_paned_set_position(GTK_PANED(hpaned), 0); 00856 gtk_widget_hide(tree1_w); 00857 if (tree2) 00858 gtk_tree_store_clear(tree2); 00859 display_tree(&rootmenu); 00860 gtk_widget_set_sensitive(back_btn, FALSE); 00861 } 00862 00863 00864 void on_collapse_pressed(GtkButton * button, gpointer user_data) 00865 { 00866 gtk_tree_view_collapse_all(GTK_TREE_VIEW(tree2_w)); 00867 } 00868 00869 00870 void on_expand_pressed(GtkButton * button, gpointer user_data) 00871 { 00872 gtk_tree_view_expand_all(GTK_TREE_VIEW(tree2_w)); 00873 } 00874 00875 00876 /* CTree Callbacks */ 00877 00878 /* Change hex/int/string value in the cell */ 00879 static void renderer_edited(GtkCellRendererText * cell, 00880 const gchar * path_string, 00881 const gchar * new_text, gpointer user_data) 00882 { 00883 GtkTreePath *path = gtk_tree_path_new_from_string(path_string); 00884 GtkTreeIter iter; 00885 const char *old_def, *new_def; 00886 struct menu *menu; 00887 struct symbol *sym; 00888 00889 if (!gtk_tree_model_get_iter(model2, &iter, path)) 00890 return; 00891 00892 gtk_tree_model_get(model2, &iter, COL_MENU, &menu, -1); 00893 sym = menu->sym; 00894 00895 gtk_tree_model_get(model2, &iter, COL_VALUE, &old_def, -1); 00896 new_def = new_text; 00897 00898 sym_set_string_value(sym, new_def); 00899 00900 config_changed = TRUE; 00901 update_tree(&rootmenu, NULL); 00902 00903 gtk_tree_path_free(path); 00904 } 00905 00906 /* Change the value of a symbol and update the tree */ 00907 static void change_sym_value(struct menu *menu, gint col) 00908 { 00909 struct symbol *sym = menu->sym; 00910 tristate oldval, newval; 00911 00912 if (!sym) 00913 return; 00914 00915 if (col == COL_NO) 00916 newval = no; 00917 else if (col == COL_MOD) 00918 newval = mod; 00919 else if (col == COL_YES) 00920 newval = yes; 00921 else 00922 return; 00923 00924 switch (sym_get_type(sym)) { 00925 case S_BOOLEAN: 00926 case S_TRISTATE: 00927 oldval = sym_get_tristate_value(sym); 00928 if (!sym_tristate_within_range(sym, newval)) 00929 newval = yes; 00930 sym_set_tristate_value(sym, newval); 00931 config_changed = TRUE; 00932 if (view_mode == FULL_VIEW) 00933 update_tree(&rootmenu, NULL); 00934 else if (view_mode == SPLIT_VIEW) { 00935 update_tree(browsed, NULL); 00936 display_list(); 00937 } 00938 else if (view_mode == SINGLE_VIEW) 00939 display_tree_part(); //fixme: keep exp/coll 00940 break; 00941 case S_INT: 00942 case S_HEX: 00943 case S_STRING: 00944 default: 00945 break; 00946 } 00947 } 00948 00949 static void toggle_sym_value(struct menu *menu) 00950 { 00951 const tristate next_val[3] = { no, mod, yes }; 00952 tristate newval; 00953 00954 if (!menu->sym) 00955 return; 00956 00957 newval = next_val[(sym_get_tristate_value(menu->sym) + 1) % 3]; 00958 if (!sym_tristate_within_range(menu->sym, newval)) 00959 newval = yes; 00960 sym_set_tristate_value(menu->sym, newval); 00961 if (view_mode == FULL_VIEW) 00962 update_tree(&rootmenu, NULL); 00963 else if (view_mode == SPLIT_VIEW) { 00964 update_tree(browsed, NULL); 00965 display_list(); 00966 } 00967 else if (view_mode == SINGLE_VIEW) 00968 display_tree_part(); //fixme: keep exp/coll 00969 } 00970 00971 static void renderer_toggled(GtkCellRendererToggle * cell, 00972 gchar * path_string, gpointer user_data) 00973 { 00974 GtkTreePath *path, *sel_path = NULL; 00975 GtkTreeIter iter, sel_iter; 00976 GtkTreeSelection *sel; 00977 struct menu *menu; 00978 00979 path = gtk_tree_path_new_from_string(path_string); 00980 if (!gtk_tree_model_get_iter(model2, &iter, path)) 00981 return; 00982 00983 sel = gtk_tree_view_get_selection(GTK_TREE_VIEW(tree2_w)); 00984 if (gtk_tree_selection_get_selected(sel, NULL, &sel_iter)) 00985 sel_path = gtk_tree_model_get_path(model2, &sel_iter); 00986 if (!sel_path) 00987 goto out1; 00988 if (gtk_tree_path_compare(path, sel_path)) 00989 goto out2; 00990 00991 gtk_tree_model_get(model2, &iter, COL_MENU, &menu, -1); 00992 toggle_sym_value(menu); 00993 00994 out2: 00995 gtk_tree_path_free(sel_path); 00996 out1: 00997 gtk_tree_path_free(path); 00998 } 00999 01000 static gint column2index(GtkTreeViewColumn * column) 01001 { 01002 gint i; 01003 01004 for (i = 0; i < COL_NUMBER; i++) { 01005 GtkTreeViewColumn *col; 01006 01007 col = gtk_tree_view_get_column(GTK_TREE_VIEW(tree2_w), i); 01008 if (col == column) 01009 return i; 01010 } 01011 01012 return -1; 01013 } 01014 01015 01016 /* User click: update choice (full) or goes down (single) */ 01017 gboolean 01018 on_treeview2_button_press_event(GtkWidget * widget, 01019 GdkEventButton * event, gpointer user_data) 01020 { 01021 GtkTreeView *view = GTK_TREE_VIEW(widget); 01022 GtkTreePath *path; 01023 GtkTreeViewColumn *column; 01024 GtkTreeIter iter; 01025 struct menu *menu; 01026 gint col; 01027 01028 #if GTK_CHECK_VERSION(2,1,4) // bug in ctree with earlier version of GTK 01029 gint tx = (gint) event->x; 01030 gint ty = (gint) event->y; 01031 gint cx, cy; 01032 01033 gtk_tree_view_get_path_at_pos(view, tx, ty, &path, &column, &cx, 01034 &cy); 01035 #else 01036 gtk_tree_view_get_cursor(view, &path, &column); 01037 #endif 01038 if (path == NULL) 01039 return FALSE; 01040 01041 gtk_tree_model_get_iter(model2, &iter, path); 01042 gtk_tree_model_get(model2, &iter, COL_MENU, &menu, -1); 01043 01044 col = column2index(column); 01045 if (event->type == GDK_2BUTTON_PRESS) { 01046 enum prop_type ptype; 01047 ptype = menu->prompt ? menu->prompt->type : P_UNKNOWN; 01048 01049 if (ptype == P_MENU && view_mode != FULL_VIEW && col == COL_OPTION) { 01050 // goes down into menu 01051 current = menu; 01052 display_tree_part(); 01053 gtk_widget_set_sensitive(back_btn, TRUE); 01054 } else if ((col == COL_OPTION)) { 01055 toggle_sym_value(menu); 01056 gtk_tree_view_expand_row(view, path, TRUE); 01057 } 01058 } else { 01059 if (col == COL_VALUE) { 01060 toggle_sym_value(menu); 01061 gtk_tree_view_expand_row(view, path, TRUE); 01062 } else if (col == COL_NO || col == COL_MOD 01063 || col == COL_YES) { 01064 change_sym_value(menu, col); 01065 gtk_tree_view_expand_row(view, path, TRUE); 01066 } 01067 } 01068 01069 return FALSE; 01070 } 01071 01072 /* Key pressed: update choice */ 01073 gboolean 01074 on_treeview2_key_press_event(GtkWidget * widget, 01075 GdkEventKey * event, gpointer user_data) 01076 { 01077 GtkTreeView *view = GTK_TREE_VIEW(widget); 01078 GtkTreePath *path; 01079 GtkTreeViewColumn *column; 01080 GtkTreeIter iter; 01081 struct menu *menu; 01082 gint col; 01083 01084 gtk_tree_view_get_cursor(view, &path, &column); 01085 if (path == NULL) 01086 return FALSE; 01087 01088 if (event->keyval == GDK_space) { 01089 if (gtk_tree_view_row_expanded(view, path)) 01090 gtk_tree_view_collapse_row(view, path); 01091 else 01092 gtk_tree_view_expand_row(view, path, FALSE); 01093 return TRUE; 01094 } 01095 if (event->keyval == GDK_KP_Enter) { 01096 } 01097 if (widget == tree1_w) 01098 return FALSE; 01099 01100 gtk_tree_model_get_iter(model2, &iter, path); 01101 gtk_tree_model_get(model2, &iter, COL_MENU, &menu, -1); 01102 01103 if (!strcasecmp(event->string, "n")) 01104 col = COL_NO; 01105 else if (!strcasecmp(event->string, "m")) 01106 col = COL_MOD; 01107 else if (!strcasecmp(event->string, "y")) 01108 col = COL_YES; 01109 else 01110 col = -1; 01111 change_sym_value(menu, col); 01112 01113 return FALSE; 01114 } 01115 01116 01117 /* Row selection changed: update help */ 01118 void 01119 on_treeview2_cursor_changed(GtkTreeView * treeview, gpointer user_data) 01120 { 01121 GtkTreeSelection *selection; 01122 GtkTreeIter iter; 01123 struct menu *menu; 01124 01125 selection = gtk_tree_view_get_selection(treeview); 01126 if (gtk_tree_selection_get_selected(selection, &model2, &iter)) { 01127 gtk_tree_model_get(model2, &iter, COL_MENU, &menu, -1); 01128 text_insert_help(menu); 01129 } 01130 } 01131 01132 01133 /* User click: display sub-tree in the right frame. */ 01134 gboolean 01135 on_treeview1_button_press_event(GtkWidget * widget, 01136 GdkEventButton * event, gpointer user_data) 01137 { 01138 GtkTreeView *view = GTK_TREE_VIEW(widget); 01139 GtkTreePath *path; 01140 GtkTreeViewColumn *column; 01141 GtkTreeIter iter; 01142 struct menu *menu; 01143 01144 gint tx = (gint) event->x; 01145 gint ty = (gint) event->y; 01146 gint cx, cy; 01147 01148 gtk_tree_view_get_path_at_pos(view, tx, ty, &path, &column, &cx, 01149 &cy); 01150 if (path == NULL) 01151 return FALSE; 01152 01153 gtk_tree_model_get_iter(model1, &iter, path); 01154 gtk_tree_model_get(model1, &iter, COL_MENU, &menu, -1); 01155 01156 if (event->type == GDK_2BUTTON_PRESS) { 01157 toggle_sym_value(menu); 01158 current = menu; 01159 display_tree_part(); 01160 } else { 01161 browsed = menu; 01162 display_tree_part(); 01163 } 01164 01165 gtk_widget_realize(tree2_w); 01166 gtk_tree_view_set_cursor(view, path, NULL, FALSE); 01167 gtk_widget_grab_focus(GTK_TREE_VIEW(tree2_w)); 01168 01169 return FALSE; 01170 } 01171 01172 01173 /* Conf management */ 01174 01175 01176 /* Fill a row of strings */ 01177 static gchar **fill_row(struct menu *menu) 01178 { 01179 static gchar *row[COL_NUMBER]; 01180 struct symbol *sym = menu->sym; 01181 const char *def; 01182 int stype; 01183 tristate val; 01184 enum prop_type ptype; 01185 int i; 01186 01187 for (i = COL_OPTION; i <= COL_COLOR; i++) 01188 g_free(row[i]); 01189 bzero(row, sizeof(row)); 01190 01191 row[COL_OPTION] = 01192 g_strdup_printf("%s %s", menu_get_prompt(menu), 01193 sym ? (sym-> 01194 flags & SYMBOL_NEW ? "(NEW)" : "") : 01195 ""); 01196 01197 if (show_all && !menu_is_visible(menu)) 01198 row[COL_COLOR] = g_strdup("DarkGray"); 01199 else 01200 row[COL_COLOR] = g_strdup("Black"); 01201 01202 ptype = menu->prompt ? menu->prompt->type : P_UNKNOWN; 01203 switch (ptype) { 01204 case P_MENU: 01205 row[COL_PIXBUF] = (gchar *) xpm_menu; 01206 if (view_mode == SINGLE_VIEW) 01207 row[COL_PIXVIS] = GINT_TO_POINTER(TRUE); 01208 row[COL_BTNVIS] = GINT_TO_POINTER(FALSE); 01209 break; 01210 case P_COMMENT: 01211 row[COL_PIXBUF] = (gchar *) xpm_void; 01212 row[COL_PIXVIS] = GINT_TO_POINTER(FALSE); 01213 row[COL_BTNVIS] = GINT_TO_POINTER(FALSE); 01214 break; 01215 default: 01216 row[COL_PIXBUF] = (gchar *) xpm_void; 01217 row[COL_PIXVIS] = GINT_TO_POINTER(FALSE); 01218 row[COL_BTNVIS] = GINT_TO_POINTER(TRUE); 01219 break; 01220 } 01221 01222 if (!sym) 01223 return row; 01224 row[COL_NAME] = g_strdup(sym->name); 01225 01226 sym_calc_value(sym); 01227 sym->flags &= ~SYMBOL_CHANGED; 01228 01229 if (sym_is_choice(sym)) { // parse childs for getting final value 01230 struct menu *child; 01231 struct symbol *def_sym = sym_get_choice_value(sym); 01232 struct menu *def_menu = NULL; 01233 01234 row[COL_BTNVIS] = GINT_TO_POINTER(FALSE); 01235 01236 for (child = menu->list; child; child = child->next) { 01237 if (menu_is_visible(child) 01238 && child->sym == def_sym) 01239 def_menu = child; 01240 } 01241 01242 if (def_menu) 01243 row[COL_VALUE] = 01244 g_strdup(menu_get_prompt(def_menu)); 01245 } 01246 if(sym->flags & SYMBOL_CHOICEVAL) 01247 row[COL_BTNRAD] = GINT_TO_POINTER(TRUE); 01248 01249 stype = sym_get_type(sym); 01250 switch (stype) { 01251 case S_BOOLEAN: 01252 if(GPOINTER_TO_INT(row[COL_PIXVIS]) == FALSE) 01253 row[COL_BTNVIS] = GINT_TO_POINTER(TRUE); 01254 if (sym_is_choice(sym)) 01255 break; 01256 case S_TRISTATE: 01257 val = sym_get_tristate_value(sym); 01258 switch (val) { 01259 case no: 01260 row[COL_NO] = g_strdup("N"); 01261 row[COL_VALUE] = g_strdup("N"); 01262 row[COL_BTNACT] = GINT_TO_POINTER(FALSE); 01263 row[COL_BTNINC] = GINT_TO_POINTER(FALSE); 01264 break; 01265 case mod: 01266 row[COL_MOD] = g_strdup("M"); 01267 row[COL_VALUE] = g_strdup("M"); 01268 row[COL_BTNINC] = GINT_TO_POINTER(TRUE); 01269 break; 01270 case yes: 01271 row[COL_YES] = g_strdup("Y"); 01272 row[COL_VALUE] = g_strdup("Y"); 01273 row[COL_BTNACT] = GINT_TO_POINTER(TRUE); 01274 row[COL_BTNINC] = GINT_TO_POINTER(FALSE); 01275 break; 01276 } 01277 01278 if (val != no && sym_tristate_within_range(sym, no)) 01279 row[COL_NO] = g_strdup("_"); 01280 if (val != mod && sym_tristate_within_range(sym, mod)) 01281 row[COL_MOD] = g_strdup("_"); 01282 if (val != yes && sym_tristate_within_range(sym, yes)) 01283 row[COL_YES] = g_strdup("_"); 01284 break; 01285 case S_INT: 01286 case S_HEX: 01287 case S_STRING: 01288 def = sym_get_string_value(sym); 01289 row[COL_VALUE] = g_strdup(def); 01290 row[COL_EDIT] = GINT_TO_POINTER(TRUE); 01291 row[COL_BTNVIS] = GINT_TO_POINTER(FALSE); 01292 break; 01293 } 01294 01295 return row; 01296 } 01297 01298 01299 /* Set the node content with a row of strings */ 01300 static void set_node(GtkTreeIter * node, struct menu *menu, gchar ** row) 01301 { 01302 GdkColor color; 01303 gboolean success; 01304 GdkPixbuf *pix; 01305 01306 pix = gdk_pixbuf_new_from_xpm_data((const char **) 01307 row[COL_PIXBUF]); 01308 01309 gdk_color_parse(row[COL_COLOR], &color); 01310 gdk_colormap_alloc_colors(gdk_colormap_get_system(), &color, 1, 01311 FALSE, FALSE, &success); 01312 01313 gtk_tree_store_set(tree, node, 01314 COL_OPTION, row[COL_OPTION], 01315 COL_NAME, row[COL_NAME], 01316 COL_NO, row[COL_NO], 01317 COL_MOD, row[COL_MOD], 01318 COL_YES, row[COL_YES], 01319 COL_VALUE, row[COL_VALUE], 01320 COL_MENU, (gpointer) menu, 01321 COL_COLOR, &color, 01322 COL_EDIT, GPOINTER_TO_INT(row[COL_EDIT]), 01323 COL_PIXBUF, pix, 01324 COL_PIXVIS, GPOINTER_TO_INT(row[COL_PIXVIS]), 01325 COL_BTNVIS, GPOINTER_TO_INT(row[COL_BTNVIS]), 01326 COL_BTNACT, GPOINTER_TO_INT(row[COL_BTNACT]), 01327 COL_BTNINC, GPOINTER_TO_INT(row[COL_BTNINC]), 01328 COL_BTNRAD, GPOINTER_TO_INT(row[COL_BTNRAD]), 01329 -1); 01330 01331 g_object_unref(pix); 01332 } 01333 01334 01335 /* Add a node to the tree */ 01336 static void place_node(struct menu *menu, char **row) 01337 { 01338 GtkTreeIter *parent = parents[indent - 1]; 01339 GtkTreeIter *node = parents[indent]; 01340 01341 gtk_tree_store_append(tree, node, parent); 01342 set_node(node, menu, row); 01343 } 01344 01345 01346 /* Find a node in the GTK+ tree */ 01347 static GtkTreeIter found; 01348 01349 /* 01350 * Find a menu in the GtkTree starting at parent. 01351 */ 01352 GtkTreeIter *gtktree_iter_find_node(GtkTreeIter * parent, 01353 struct menu *tofind) 01354 { 01355 GtkTreeIter iter; 01356 GtkTreeIter *child = &iter; 01357 gboolean valid; 01358 GtkTreeIter *ret; 01359 01360 valid = gtk_tree_model_iter_children(model2, child, parent); 01361 while (valid) { 01362 struct menu *menu; 01363 01364 gtk_tree_model_get(model2, child, 6, &menu, -1); 01365 01366 if (menu == tofind) { 01367 memcpy(&found, child, sizeof(GtkTreeIter)); 01368 return &found; 01369 } 01370 01371 ret = gtktree_iter_find_node(child, tofind); 01372 if (ret) 01373 return ret; 01374 01375 valid = gtk_tree_model_iter_next(model2, child); 01376 } 01377 01378 return NULL; 01379 } 01380 01381 01382 /* 01383 * Update the tree by adding/removing entries 01384 * Does not change other nodes 01385 */ 01386 static void update_tree(struct menu *src, GtkTreeIter * dst) 01387 { 01388 struct menu *child1; 01389 GtkTreeIter iter, tmp; 01390 GtkTreeIter *child2 = &iter; 01391 gboolean valid; 01392 GtkTreeIter *sibling; 01393 struct symbol *sym; 01394 struct property *prop; 01395 struct menu *menu1, *menu2; 01396 static GtkTreePath *path = NULL; 01397 01398 if (src == &rootmenu) 01399 indent = 1; 01400 01401 valid = gtk_tree_model_iter_children(model2, child2, dst); 01402 for (child1 = src->list; child1; child1 = child1->next) { 01403 01404 prop = child1->prompt; 01405 sym = child1->sym; 01406 01407 reparse: 01408 menu1 = child1; 01409 if (valid) 01410 gtk_tree_model_get(model2, child2, COL_MENU, 01411 &menu2, -1); 01412 else 01413 menu2 = NULL; // force adding of a first child 01414 01415 #ifdef DEBUG 01416 printf("%*c%s | %s\n", indent, ' ', 01417 menu1 ? menu_get_prompt(menu1) : "nil", 01418 menu2 ? menu_get_prompt(menu2) : "nil"); 01419 #endif 01420 01421 if (!menu_is_visible(child1) && !show_all) { // remove node 01422 if (gtktree_iter_find_node(dst, menu1) != NULL) { 01423 memcpy(&tmp, child2, sizeof(GtkTreeIter)); 01424 valid = gtk_tree_model_iter_next(model2, 01425 child2); 01426 gtk_tree_store_remove(tree2, &tmp); 01427 if (!valid) 01428 return; // next parent 01429 else 01430 goto reparse; // next child 01431 } else 01432 continue; 01433 } 01434 01435 if (menu1 != menu2) { 01436 if (gtktree_iter_find_node(dst, menu1) == NULL) { // add node 01437 if (!valid && !menu2) 01438 sibling = NULL; 01439 else 01440 sibling = child2; 01441 gtk_tree_store_insert_before(tree2, 01442 child2, 01443 dst, sibling); 01444 set_node(child2, menu1, fill_row(menu1)); 01445 if (menu2 == NULL) 01446 valid = TRUE; 01447 } else { // remove node 01448 memcpy(&tmp, child2, sizeof(GtkTreeIter)); 01449 valid = gtk_tree_model_iter_next(model2, 01450 child2); 01451 gtk_tree_store_remove(tree2, &tmp); 01452 if (!valid) 01453 return; // next parent 01454 else 01455 goto reparse; // next child 01456 } 01457 } else if (sym && (sym->flags & SYMBOL_CHANGED)) { 01458 set_node(child2, menu1, fill_row(menu1)); 01459 } 01460 01461 indent++; 01462 update_tree(child1, child2); 01463 indent--; 01464 01465 valid = gtk_tree_model_iter_next(model2, child2); 01466 } 01467 } 01468 01469 01470 /* Display the whole tree (single/split/full view) */ 01471 static void display_tree(struct menu *menu) 01472 { 01473 struct symbol *sym; 01474 struct property *prop; 01475 struct menu *child; 01476 enum prop_type ptype; 01477 01478 if (menu == &rootmenu) { 01479 indent = 1; 01480 current = &rootmenu; 01481 } 01482 01483 for (child = menu->list; child; child = child->next) { 01484 prop = child->prompt; 01485 sym = child->sym; 01486 ptype = prop ? prop->type : P_UNKNOWN; 01487 01488 if (sym) 01489 sym->flags &= ~SYMBOL_CHANGED; 01490 01491 if ((view_mode == SPLIT_VIEW) && !(child->flags & MENU_ROOT) && 01492 (tree == tree1)) 01493 continue; 01494 01495 if ((view_mode == SPLIT_VIEW) && (child->flags & MENU_ROOT) && 01496 (tree == tree2)) 01497 continue; 01498 01499 if (menu_is_visible(child) || show_all) 01500 place_node(child, fill_row(child)); 01501 #ifdef DEBUG 01502 printf("%*c%s: ", indent, ' ', menu_get_prompt(child)); 01503 printf("%s", child->flags & MENU_ROOT ? "rootmenu | " : ""); 01504 dbg_print_ptype(ptype); 01505 printf(" | "); 01506 if (sym) { 01507 dbg_print_stype(sym->type); 01508 printf(" | "); 01509 dbg_print_flags(sym->flags); 01510 printf("\n"); 01511 } else 01512 printf("\n"); 01513 #endif 01514 if ((view_mode != FULL_VIEW) && (ptype == P_MENU) 01515 && (tree == tree2)) 01516 continue; 01517 /* 01518 if (((menu != &rootmenu) && !(menu->flags & MENU_ROOT)) || 01519 (view_mode == FULL_VIEW) 01520 || (view_mode == SPLIT_VIEW))*/ 01521 if ((view_mode == SINGLE_VIEW) && (menu->flags & MENU_ROOT) 01522 || (view_mode == FULL_VIEW) || (view_mode == SPLIT_VIEW)) { 01523 indent++; 01524 display_tree(child); 01525 indent--; 01526 } 01527 } 01528 } 01529 01530 /* Display a part of the tree starting at current node (single/split view) */ 01531 static void display_tree_part(void) 01532 { 01533 if (tree2) 01534 gtk_tree_store_clear(tree2); 01535 if(view_mode == SINGLE_VIEW) 01536 display_tree(current); 01537 else if(view_mode == SPLIT_VIEW) 01538 display_tree(browsed); 01539 gtk_tree_view_expand_all(GTK_TREE_VIEW(tree2_w)); 01540 } 01541 01542 /* Display the list in the left frame (split view) */ 01543 static void display_list(void) 01544 { 01545 if (tree1) 01546 gtk_tree_store_clear(tree1); 01547 01548 tree = tree1; 01549 display_tree(&rootmenu); 01550 gtk_tree_view_expand_all(GTK_TREE_VIEW(tree1_w)); 01551 tree = tree2; 01552 } 01553 01554 void fixup_rootmenu(struct menu *menu) 01555 { 01556 struct menu *child; 01557 static int menu_cnt = 0; 01558 01559 menu->flags |= MENU_ROOT; 01560 for (child = menu->list; child; child = child->next) { 01561 if (child->prompt && child->prompt->type == P_MENU) { 01562 menu_cnt++; 01563 fixup_rootmenu(child); 01564 menu_cnt--; 01565 } else if (!menu_cnt) 01566 fixup_rootmenu(child); 01567 } 01568 } 01569 01570 01571 /* Main */ 01572 01573 01574 int main(int ac, char *av[]) 01575 { 01576 const char *name, *srctree; 01577 gchar *cur_dir, *exe_path; 01578 gchar *glade_file; 01579 struct symbol *sym; 01580 char title[256]; 01581 01582 #ifndef LKC_DIRECT_LINK 01583 kconfig_load(); 01584 #endif 01585 01586 /* GTK stuffs */ 01587 gtk_set_locale(); 01588 gtk_init(&ac, &av); 01589 glade_init(); 01590 01591 //add_pixmap_directory (PACKAGE_DATA_DIR "/" PACKAGE "/pixmaps"); 01592 //add_pixmap_directory (PACKAGE_SOURCE_DIR "/pixmaps"); 01593 01594 /* Determine GUI path */ 01595 01596 srctree = getenv(SRCTREE); 01597 glade_file = g_strconcat(srctree ?: ".", "/base/config/kconfig/",av[0], ".glade", NULL); 01598 01599 /* Load the interface and connect signals */ 01600 init_main_window(glade_file); 01601 gtk_widget_show(main_wnd); 01602 init_tree_model(); 01603 init_left_tree(); 01604 init_right_tree(); 01605 01606 /* Conf stuffs */ 01607 if (ac > 1 && av[1][0] == '-') { 01608 switch (av[1][1]) { 01609 case 'a': 01610 //showAll = 1; 01611 break; 01612 case 'h': 01613 case '?': 01614 printf("%s <config>\n", av[0]); 01615 exit(0); 01616 } 01617 name = av[2]; 01618 } else 01619 name = av[1]; 01620 01621 conf_parse(name); 01622 fixup_rootmenu(&rootmenu); 01623 conf_read(NULL); 01624 01625 switch (view_mode) { 01626 case SINGLE_VIEW: 01627 display_tree_part(); 01628 break; 01629 case SPLIT_VIEW: 01630 display_list(); 01631 break; 01632 case FULL_VIEW: 01633 display_tree(&rootmenu); 01634 break; 01635 } 01636 01637 sym = sym_lookup("RTAI_VERSION",0); 01638 sym_calc_value(sym); 01639 sprintf(title, "RTAI Configuration [ %s ]",sym_get_string_value(sym)); 01640 gtk_window_set_title(GTK_WINDOW(main_wnd), title); 01641 01642 gtk_main(); 01643 01644 return 0; 01645 }

Generated on Thu Nov 20 11:49:47 2008 for RTAI API by doxygen 1.3.8