|
|
1.1 ! root 1: /* Hey EMACS -*- linux-c -*- */ ! 2: /* ! 3: * ! 4: * Copyright (C) 2002-2003 Romain Lievin <[email protected]> ! 5: * Released under the terms of the GNU GPL v2.0. ! 6: * ! 7: */ ! 8: ! 9: #ifdef HAVE_CONFIG_H ! 10: # include <config.h> ! 11: #endif ! 12: ! 13: #include "lkc.h" ! 14: #include "images.c" ! 15: ! 16: #include <glade/glade.h> ! 17: #include <gtk/gtk.h> ! 18: #include <glib.h> ! 19: #include <gdk/gdkkeysyms.h> ! 20: ! 21: #include <stdio.h> ! 22: #include <string.h> ! 23: #include <unistd.h> ! 24: #include <time.h> ! 25: #include <stdlib.h> ! 26: ! 27: //#define DEBUG ! 28: ! 29: enum { ! 30: SINGLE_VIEW, SPLIT_VIEW, FULL_VIEW ! 31: }; ! 32: ! 33: enum { ! 34: OPT_NORMAL, OPT_ALL, OPT_PROMPT ! 35: }; ! 36: ! 37: static gint view_mode = FULL_VIEW; ! 38: static gboolean show_name = TRUE; ! 39: static gboolean show_range = TRUE; ! 40: static gboolean show_value = TRUE; ! 41: static gboolean resizeable = FALSE; ! 42: static int opt_mode = OPT_NORMAL; ! 43: ! 44: GtkWidget *main_wnd = NULL; ! 45: GtkWidget *tree1_w = NULL; // left frame ! 46: GtkWidget *tree2_w = NULL; // right frame ! 47: GtkWidget *text_w = NULL; ! 48: GtkWidget *hpaned = NULL; ! 49: GtkWidget *vpaned = NULL; ! 50: GtkWidget *back_btn = NULL; ! 51: GtkWidget *save_btn = NULL; ! 52: GtkWidget *save_menu_item = NULL; ! 53: ! 54: GtkTextTag *tag1, *tag2; ! 55: GdkColor color; ! 56: ! 57: GtkTreeStore *tree1, *tree2, *tree; ! 58: GtkTreeModel *model1, *model2; ! 59: static GtkTreeIter *parents[256]; ! 60: static gint indent; ! 61: ! 62: static struct menu *current; // current node for SINGLE view ! 63: static struct menu *browsed; // browsed node for SPLIT view ! 64: ! 65: enum { ! 66: COL_OPTION, COL_NAME, COL_NO, COL_MOD, COL_YES, COL_VALUE, ! 67: COL_MENU, COL_COLOR, COL_EDIT, COL_PIXBUF, ! 68: COL_PIXVIS, COL_BTNVIS, COL_BTNACT, COL_BTNINC, COL_BTNRAD, ! 69: COL_NUMBER ! 70: }; ! 71: ! 72: static void display_list(void); ! 73: static void display_tree(struct menu *menu); ! 74: static void display_tree_part(void); ! 75: static void update_tree(struct menu *src, GtkTreeIter * dst); ! 76: static void set_node(GtkTreeIter * node, struct menu *menu, gchar ** row); ! 77: static gchar **fill_row(struct menu *menu); ! 78: static void conf_changed(void); ! 79: ! 80: /* Helping/Debugging Functions */ ! 81: ! 82: const char *dbg_sym_flags(int val) ! 83: { ! 84: static char buf[256]; ! 85: ! 86: bzero(buf, 256); ! 87: ! 88: if (val & SYMBOL_CONST) ! 89: strcat(buf, "const/"); ! 90: if (val & SYMBOL_CHECK) ! 91: strcat(buf, "check/"); ! 92: if (val & SYMBOL_CHOICE) ! 93: strcat(buf, "choice/"); ! 94: if (val & SYMBOL_CHOICEVAL) ! 95: strcat(buf, "choiceval/"); ! 96: if (val & SYMBOL_VALID) ! 97: strcat(buf, "valid/"); ! 98: if (val & SYMBOL_OPTIONAL) ! 99: strcat(buf, "optional/"); ! 100: if (val & SYMBOL_WRITE) ! 101: strcat(buf, "write/"); ! 102: if (val & SYMBOL_CHANGED) ! 103: strcat(buf, "changed/"); ! 104: if (val & SYMBOL_AUTO) ! 105: strcat(buf, "auto/"); ! 106: ! 107: buf[strlen(buf) - 1] = '\0'; ! 108: ! 109: return buf; ! 110: } ! 111: ! 112: void replace_button_icon(GladeXML * xml, GdkDrawable * window, ! 113: GtkStyle * style, gchar * btn_name, gchar ** xpm) ! 114: { ! 115: GdkPixmap *pixmap; ! 116: GdkBitmap *mask; ! 117: GtkToolButton *button; ! 118: GtkWidget *image; ! 119: ! 120: pixmap = gdk_pixmap_create_from_xpm_d(window, &mask, ! 121: &style->bg[GTK_STATE_NORMAL], ! 122: xpm); ! 123: ! 124: button = GTK_TOOL_BUTTON(glade_xml_get_widget(xml, btn_name)); ! 125: image = gtk_image_new_from_pixmap(pixmap, mask); ! 126: gtk_widget_show(image); ! 127: gtk_tool_button_set_icon_widget(button, image); ! 128: } ! 129: ! 130: /* Main Window Initialization */ ! 131: void init_main_window(const gchar * glade_file) ! 132: { ! 133: GladeXML *xml; ! 134: GtkWidget *widget; ! 135: GtkTextBuffer *txtbuf; ! 136: GtkStyle *style; ! 137: ! 138: xml = glade_xml_new(glade_file, "window1", NULL); ! 139: if (!xml) ! 140: g_error(_("GUI loading failed !\n")); ! 141: glade_xml_signal_autoconnect(xml); ! 142: ! 143: main_wnd = glade_xml_get_widget(xml, "window1"); ! 144: hpaned = glade_xml_get_widget(xml, "hpaned1"); ! 145: vpaned = glade_xml_get_widget(xml, "vpaned1"); ! 146: tree1_w = glade_xml_get_widget(xml, "treeview1"); ! 147: tree2_w = glade_xml_get_widget(xml, "treeview2"); ! 148: text_w = glade_xml_get_widget(xml, "textview3"); ! 149: ! 150: back_btn = glade_xml_get_widget(xml, "button1"); ! 151: gtk_widget_set_sensitive(back_btn, FALSE); ! 152: ! 153: widget = glade_xml_get_widget(xml, "show_name1"); ! 154: gtk_check_menu_item_set_active((GtkCheckMenuItem *) widget, ! 155: show_name); ! 156: ! 157: widget = glade_xml_get_widget(xml, "show_range1"); ! 158: gtk_check_menu_item_set_active((GtkCheckMenuItem *) widget, ! 159: show_range); ! 160: ! 161: widget = glade_xml_get_widget(xml, "show_data1"); ! 162: gtk_check_menu_item_set_active((GtkCheckMenuItem *) widget, ! 163: show_value); ! 164: ! 165: save_btn = glade_xml_get_widget(xml, "button3"); ! 166: save_menu_item = glade_xml_get_widget(xml, "save1"); ! 167: conf_set_changed_callback(conf_changed); ! 168: ! 169: style = gtk_widget_get_style(main_wnd); ! 170: widget = glade_xml_get_widget(xml, "toolbar1"); ! 171: ! 172: #if 0 /* Use stock Gtk icons instead */ ! 173: replace_button_icon(xml, main_wnd->window, style, ! 174: "button1", (gchar **) xpm_back); ! 175: replace_button_icon(xml, main_wnd->window, style, ! 176: "button2", (gchar **) xpm_load); ! 177: replace_button_icon(xml, main_wnd->window, style, ! 178: "button3", (gchar **) xpm_save); ! 179: #endif ! 180: replace_button_icon(xml, main_wnd->window, style, ! 181: "button4", (gchar **) xpm_single_view); ! 182: replace_button_icon(xml, main_wnd->window, style, ! 183: "button5", (gchar **) xpm_split_view); ! 184: replace_button_icon(xml, main_wnd->window, style, ! 185: "button6", (gchar **) xpm_tree_view); ! 186: ! 187: #if 0 ! 188: switch (view_mode) { ! 189: case SINGLE_VIEW: ! 190: widget = glade_xml_get_widget(xml, "button4"); ! 191: g_signal_emit_by_name(widget, "clicked"); ! 192: break; ! 193: case SPLIT_VIEW: ! 194: widget = glade_xml_get_widget(xml, "button5"); ! 195: g_signal_emit_by_name(widget, "clicked"); ! 196: break; ! 197: case FULL_VIEW: ! 198: widget = glade_xml_get_widget(xml, "button6"); ! 199: g_signal_emit_by_name(widget, "clicked"); ! 200: break; ! 201: } ! 202: #endif ! 203: txtbuf = gtk_text_view_get_buffer(GTK_TEXT_VIEW(text_w)); ! 204: tag1 = gtk_text_buffer_create_tag(txtbuf, "mytag1", ! 205: "foreground", "red", ! 206: "weight", PANGO_WEIGHT_BOLD, ! 207: NULL); ! 208: tag2 = gtk_text_buffer_create_tag(txtbuf, "mytag2", ! 209: /*"style", PANGO_STYLE_OBLIQUE, */ ! 210: NULL); ! 211: ! 212: gtk_window_set_title(GTK_WINDOW(main_wnd), rootmenu.prompt->text); ! 213: ! 214: gtk_widget_show(main_wnd); ! 215: } ! 216: ! 217: void init_tree_model(void) ! 218: { ! 219: gint i; ! 220: ! 221: tree = tree2 = gtk_tree_store_new(COL_NUMBER, ! 222: G_TYPE_STRING, G_TYPE_STRING, ! 223: G_TYPE_STRING, G_TYPE_STRING, ! 224: G_TYPE_STRING, G_TYPE_STRING, ! 225: G_TYPE_POINTER, GDK_TYPE_COLOR, ! 226: G_TYPE_BOOLEAN, GDK_TYPE_PIXBUF, ! 227: G_TYPE_BOOLEAN, G_TYPE_BOOLEAN, ! 228: G_TYPE_BOOLEAN, G_TYPE_BOOLEAN, ! 229: G_TYPE_BOOLEAN); ! 230: model2 = GTK_TREE_MODEL(tree2); ! 231: ! 232: for (parents[0] = NULL, i = 1; i < 256; i++) ! 233: parents[i] = (GtkTreeIter *) g_malloc(sizeof(GtkTreeIter)); ! 234: ! 235: tree1 = gtk_tree_store_new(COL_NUMBER, ! 236: G_TYPE_STRING, G_TYPE_STRING, ! 237: G_TYPE_STRING, G_TYPE_STRING, ! 238: G_TYPE_STRING, G_TYPE_STRING, ! 239: G_TYPE_POINTER, GDK_TYPE_COLOR, ! 240: G_TYPE_BOOLEAN, GDK_TYPE_PIXBUF, ! 241: G_TYPE_BOOLEAN, G_TYPE_BOOLEAN, ! 242: G_TYPE_BOOLEAN, G_TYPE_BOOLEAN, ! 243: G_TYPE_BOOLEAN); ! 244: model1 = GTK_TREE_MODEL(tree1); ! 245: } ! 246: ! 247: void init_left_tree(void) ! 248: { ! 249: GtkTreeView *view = GTK_TREE_VIEW(tree1_w); ! 250: GtkCellRenderer *renderer; ! 251: GtkTreeSelection *sel; ! 252: GtkTreeViewColumn *column; ! 253: ! 254: gtk_tree_view_set_model(view, model1); ! 255: gtk_tree_view_set_headers_visible(view, TRUE); ! 256: gtk_tree_view_set_rules_hint(view, FALSE); ! 257: ! 258: column = gtk_tree_view_column_new(); ! 259: gtk_tree_view_append_column(view, column); ! 260: gtk_tree_view_column_set_title(column, _("Options")); ! 261: ! 262: renderer = gtk_cell_renderer_toggle_new(); ! 263: gtk_tree_view_column_pack_start(GTK_TREE_VIEW_COLUMN(column), ! 264: renderer, FALSE); ! 265: gtk_tree_view_column_set_attributes(GTK_TREE_VIEW_COLUMN(column), ! 266: renderer, ! 267: "active", COL_BTNACT, ! 268: "inconsistent", COL_BTNINC, ! 269: "visible", COL_BTNVIS, ! 270: "radio", COL_BTNRAD, NULL); ! 271: renderer = gtk_cell_renderer_text_new(); ! 272: gtk_tree_view_column_pack_start(GTK_TREE_VIEW_COLUMN(column), ! 273: renderer, FALSE); ! 274: gtk_tree_view_column_set_attributes(GTK_TREE_VIEW_COLUMN(column), ! 275: renderer, ! 276: "text", COL_OPTION, ! 277: "foreground-gdk", ! 278: COL_COLOR, NULL); ! 279: ! 280: sel = gtk_tree_view_get_selection(view); ! 281: gtk_tree_selection_set_mode(sel, GTK_SELECTION_SINGLE); ! 282: gtk_widget_realize(tree1_w); ! 283: } ! 284: ! 285: static void renderer_edited(GtkCellRendererText * cell, ! 286: const gchar * path_string, ! 287: const gchar * new_text, gpointer user_data); ! 288: static void renderer_toggled(GtkCellRendererToggle * cellrenderertoggle, ! 289: gchar * arg1, gpointer user_data); ! 290: ! 291: void init_right_tree(void) ! 292: { ! 293: GtkTreeView *view = GTK_TREE_VIEW(tree2_w); ! 294: GtkCellRenderer *renderer; ! 295: GtkTreeSelection *sel; ! 296: GtkTreeViewColumn *column; ! 297: gint i; ! 298: ! 299: gtk_tree_view_set_model(view, model2); ! 300: gtk_tree_view_set_headers_visible(view, TRUE); ! 301: gtk_tree_view_set_rules_hint(view, FALSE); ! 302: ! 303: column = gtk_tree_view_column_new(); ! 304: gtk_tree_view_append_column(view, column); ! 305: gtk_tree_view_column_set_title(column, _("Options")); ! 306: ! 307: renderer = gtk_cell_renderer_pixbuf_new(); ! 308: gtk_tree_view_column_pack_start(GTK_TREE_VIEW_COLUMN(column), ! 309: renderer, FALSE); ! 310: gtk_tree_view_column_set_attributes(GTK_TREE_VIEW_COLUMN(column), ! 311: renderer, ! 312: "pixbuf", COL_PIXBUF, ! 313: "visible", COL_PIXVIS, NULL); ! 314: renderer = gtk_cell_renderer_toggle_new(); ! 315: gtk_tree_view_column_pack_start(GTK_TREE_VIEW_COLUMN(column), ! 316: renderer, FALSE); ! 317: gtk_tree_view_column_set_attributes(GTK_TREE_VIEW_COLUMN(column), ! 318: renderer, ! 319: "active", COL_BTNACT, ! 320: "inconsistent", COL_BTNINC, ! 321: "visible", COL_BTNVIS, ! 322: "radio", COL_BTNRAD, NULL); ! 323: /*g_signal_connect(G_OBJECT(renderer), "toggled", ! 324: G_CALLBACK(renderer_toggled), NULL); */ ! 325: renderer = gtk_cell_renderer_text_new(); ! 326: gtk_tree_view_column_pack_start(GTK_TREE_VIEW_COLUMN(column), ! 327: renderer, FALSE); ! 328: gtk_tree_view_column_set_attributes(GTK_TREE_VIEW_COLUMN(column), ! 329: renderer, ! 330: "text", COL_OPTION, ! 331: "foreground-gdk", ! 332: COL_COLOR, NULL); ! 333: ! 334: renderer = gtk_cell_renderer_text_new(); ! 335: gtk_tree_view_insert_column_with_attributes(view, -1, ! 336: _("Name"), renderer, ! 337: "text", COL_NAME, ! 338: "foreground-gdk", ! 339: COL_COLOR, NULL); ! 340: renderer = gtk_cell_renderer_text_new(); ! 341: gtk_tree_view_insert_column_with_attributes(view, -1, ! 342: "N", renderer, ! 343: "text", COL_NO, ! 344: "foreground-gdk", ! 345: COL_COLOR, NULL); ! 346: renderer = gtk_cell_renderer_text_new(); ! 347: gtk_tree_view_insert_column_with_attributes(view, -1, ! 348: "M", renderer, ! 349: "text", COL_MOD, ! 350: "foreground-gdk", ! 351: COL_COLOR, NULL); ! 352: renderer = gtk_cell_renderer_text_new(); ! 353: gtk_tree_view_insert_column_with_attributes(view, -1, ! 354: "Y", renderer, ! 355: "text", COL_YES, ! 356: "foreground-gdk", ! 357: COL_COLOR, NULL); ! 358: renderer = gtk_cell_renderer_text_new(); ! 359: gtk_tree_view_insert_column_with_attributes(view, -1, ! 360: _("Value"), renderer, ! 361: "text", COL_VALUE, ! 362: "editable", ! 363: COL_EDIT, ! 364: "foreground-gdk", ! 365: COL_COLOR, NULL); ! 366: g_signal_connect(G_OBJECT(renderer), "edited", ! 367: G_CALLBACK(renderer_edited), NULL); ! 368: ! 369: column = gtk_tree_view_get_column(view, COL_NAME); ! 370: gtk_tree_view_column_set_visible(column, show_name); ! 371: column = gtk_tree_view_get_column(view, COL_NO); ! 372: gtk_tree_view_column_set_visible(column, show_range); ! 373: column = gtk_tree_view_get_column(view, COL_MOD); ! 374: gtk_tree_view_column_set_visible(column, show_range); ! 375: column = gtk_tree_view_get_column(view, COL_YES); ! 376: gtk_tree_view_column_set_visible(column, show_range); ! 377: column = gtk_tree_view_get_column(view, COL_VALUE); ! 378: gtk_tree_view_column_set_visible(column, show_value); ! 379: ! 380: if (resizeable) { ! 381: for (i = 0; i < COL_VALUE; i++) { ! 382: column = gtk_tree_view_get_column(view, i); ! 383: gtk_tree_view_column_set_resizable(column, TRUE); ! 384: } ! 385: } ! 386: ! 387: sel = gtk_tree_view_get_selection(view); ! 388: gtk_tree_selection_set_mode(sel, GTK_SELECTION_SINGLE); ! 389: } ! 390: ! 391: ! 392: /* Utility Functions */ ! 393: ! 394: ! 395: static void text_insert_help(struct menu *menu) ! 396: { ! 397: GtkTextBuffer *buffer; ! 398: GtkTextIter start, end; ! 399: const char *prompt = _(menu_get_prompt(menu)); ! 400: struct gstr help = str_new(); ! 401: ! 402: menu_get_ext_help(menu, &help); ! 403: ! 404: buffer = gtk_text_view_get_buffer(GTK_TEXT_VIEW(text_w)); ! 405: gtk_text_buffer_get_bounds(buffer, &start, &end); ! 406: gtk_text_buffer_delete(buffer, &start, &end); ! 407: gtk_text_view_set_left_margin(GTK_TEXT_VIEW(text_w), 15); ! 408: ! 409: gtk_text_buffer_get_end_iter(buffer, &end); ! 410: gtk_text_buffer_insert_with_tags(buffer, &end, prompt, -1, tag1, ! 411: NULL); ! 412: gtk_text_buffer_insert_at_cursor(buffer, "\n\n", 2); ! 413: gtk_text_buffer_get_end_iter(buffer, &end); ! 414: gtk_text_buffer_insert_with_tags(buffer, &end, str_get(&help), -1, tag2, ! 415: NULL); ! 416: str_free(&help); ! 417: } ! 418: ! 419: ! 420: static void text_insert_msg(const char *title, const char *message) ! 421: { ! 422: GtkTextBuffer *buffer; ! 423: GtkTextIter start, end; ! 424: const char *msg = message; ! 425: ! 426: buffer = gtk_text_view_get_buffer(GTK_TEXT_VIEW(text_w)); ! 427: gtk_text_buffer_get_bounds(buffer, &start, &end); ! 428: gtk_text_buffer_delete(buffer, &start, &end); ! 429: gtk_text_view_set_left_margin(GTK_TEXT_VIEW(text_w), 15); ! 430: ! 431: gtk_text_buffer_get_end_iter(buffer, &end); ! 432: gtk_text_buffer_insert_with_tags(buffer, &end, title, -1, tag1, ! 433: NULL); ! 434: gtk_text_buffer_insert_at_cursor(buffer, "\n\n", 2); ! 435: gtk_text_buffer_get_end_iter(buffer, &end); ! 436: gtk_text_buffer_insert_with_tags(buffer, &end, msg, -1, tag2, ! 437: NULL); ! 438: } ! 439: ! 440: ! 441: /* Main Windows Callbacks */ ! 442: ! 443: void on_save_activate(GtkMenuItem * menuitem, gpointer user_data); ! 444: gboolean on_window1_delete_event(GtkWidget * widget, GdkEvent * event, ! 445: gpointer user_data) ! 446: { ! 447: GtkWidget *dialog, *label; ! 448: gint result; ! 449: ! 450: if (!conf_get_changed()) ! 451: return FALSE; ! 452: ! 453: dialog = gtk_dialog_new_with_buttons(_("Warning !"), ! 454: GTK_WINDOW(main_wnd), ! 455: (GtkDialogFlags) ! 456: (GTK_DIALOG_MODAL | ! 457: GTK_DIALOG_DESTROY_WITH_PARENT), ! 458: GTK_STOCK_OK, ! 459: GTK_RESPONSE_YES, ! 460: GTK_STOCK_NO, ! 461: GTK_RESPONSE_NO, ! 462: GTK_STOCK_CANCEL, ! 463: GTK_RESPONSE_CANCEL, NULL); ! 464: gtk_dialog_set_default_response(GTK_DIALOG(dialog), ! 465: GTK_RESPONSE_CANCEL); ! 466: ! 467: label = gtk_label_new(_("\nSave configuration ?\n")); ! 468: gtk_container_add(GTK_CONTAINER(GTK_DIALOG(dialog)->vbox), label); ! 469: gtk_widget_show(label); ! 470: ! 471: result = gtk_dialog_run(GTK_DIALOG(dialog)); ! 472: switch (result) { ! 473: case GTK_RESPONSE_YES: ! 474: on_save_activate(NULL, NULL); ! 475: return FALSE; ! 476: case GTK_RESPONSE_NO: ! 477: return FALSE; ! 478: case GTK_RESPONSE_CANCEL: ! 479: case GTK_RESPONSE_DELETE_EVENT: ! 480: default: ! 481: gtk_widget_destroy(dialog); ! 482: return TRUE; ! 483: } ! 484: ! 485: return FALSE; ! 486: } ! 487: ! 488: ! 489: void on_window1_destroy(GtkObject * object, gpointer user_data) ! 490: { ! 491: gtk_main_quit(); ! 492: } ! 493: ! 494: ! 495: void ! 496: on_window1_size_request(GtkWidget * widget, ! 497: GtkRequisition * requisition, gpointer user_data) ! 498: { ! 499: static gint old_h; ! 500: gint w, h; ! 501: ! 502: if (widget->window == NULL) ! 503: gtk_window_get_default_size(GTK_WINDOW(main_wnd), &w, &h); ! 504: else ! 505: gdk_window_get_size(widget->window, &w, &h); ! 506: ! 507: if (h == old_h) ! 508: return; ! 509: old_h = h; ! 510: ! 511: gtk_paned_set_position(GTK_PANED(vpaned), 2 * h / 3); ! 512: } ! 513: ! 514: ! 515: /* Menu & Toolbar Callbacks */ ! 516: ! 517: ! 518: static void ! 519: load_filename(GtkFileSelection * file_selector, gpointer user_data) ! 520: { ! 521: const gchar *fn; ! 522: ! 523: fn = gtk_file_selection_get_filename(GTK_FILE_SELECTION ! 524: (user_data)); ! 525: ! 526: if (conf_read(fn)) ! 527: text_insert_msg(_("Error"), _("Unable to load configuration !")); ! 528: else ! 529: display_tree(&rootmenu); ! 530: } ! 531: ! 532: void on_load1_activate(GtkMenuItem * menuitem, gpointer user_data) ! 533: { ! 534: GtkWidget *fs; ! 535: ! 536: fs = gtk_file_selection_new(_("Load file...")); ! 537: g_signal_connect(GTK_OBJECT(GTK_FILE_SELECTION(fs)->ok_button), ! 538: "clicked", ! 539: G_CALLBACK(load_filename), (gpointer) fs); ! 540: g_signal_connect_swapped(GTK_OBJECT ! 541: (GTK_FILE_SELECTION(fs)->ok_button), ! 542: "clicked", G_CALLBACK(gtk_widget_destroy), ! 543: (gpointer) fs); ! 544: g_signal_connect_swapped(GTK_OBJECT ! 545: (GTK_FILE_SELECTION(fs)->cancel_button), ! 546: "clicked", G_CALLBACK(gtk_widget_destroy), ! 547: (gpointer) fs); ! 548: gtk_widget_show(fs); ! 549: } ! 550: ! 551: ! 552: void on_save_activate(GtkMenuItem * menuitem, gpointer user_data) ! 553: { ! 554: if (conf_write(NULL)) ! 555: text_insert_msg(_("Error"), _("Unable to save configuration !")); ! 556: } ! 557: ! 558: ! 559: static void ! 560: store_filename(GtkFileSelection * file_selector, gpointer user_data) ! 561: { ! 562: const gchar *fn; ! 563: ! 564: fn = gtk_file_selection_get_filename(GTK_FILE_SELECTION ! 565: (user_data)); ! 566: ! 567: if (conf_write(fn)) ! 568: text_insert_msg(_("Error"), _("Unable to save configuration !")); ! 569: ! 570: gtk_widget_destroy(GTK_WIDGET(user_data)); ! 571: } ! 572: ! 573: void on_save_as1_activate(GtkMenuItem * menuitem, gpointer user_data) ! 574: { ! 575: GtkWidget *fs; ! 576: ! 577: fs = gtk_file_selection_new(_("Save file as...")); ! 578: g_signal_connect(GTK_OBJECT(GTK_FILE_SELECTION(fs)->ok_button), ! 579: "clicked", ! 580: G_CALLBACK(store_filename), (gpointer) fs); ! 581: g_signal_connect_swapped(GTK_OBJECT ! 582: (GTK_FILE_SELECTION(fs)->ok_button), ! 583: "clicked", G_CALLBACK(gtk_widget_destroy), ! 584: (gpointer) fs); ! 585: g_signal_connect_swapped(GTK_OBJECT ! 586: (GTK_FILE_SELECTION(fs)->cancel_button), ! 587: "clicked", G_CALLBACK(gtk_widget_destroy), ! 588: (gpointer) fs); ! 589: gtk_widget_show(fs); ! 590: } ! 591: ! 592: ! 593: void on_quit1_activate(GtkMenuItem * menuitem, gpointer user_data) ! 594: { ! 595: if (!on_window1_delete_event(NULL, NULL, NULL)) ! 596: gtk_widget_destroy(GTK_WIDGET(main_wnd)); ! 597: } ! 598: ! 599: ! 600: void on_show_name1_activate(GtkMenuItem * menuitem, gpointer user_data) ! 601: { ! 602: GtkTreeViewColumn *col; ! 603: ! 604: show_name = GTK_CHECK_MENU_ITEM(menuitem)->active; ! 605: col = gtk_tree_view_get_column(GTK_TREE_VIEW(tree2_w), COL_NAME); ! 606: if (col) ! 607: gtk_tree_view_column_set_visible(col, show_name); ! 608: } ! 609: ! 610: ! 611: void on_show_range1_activate(GtkMenuItem * menuitem, gpointer user_data) ! 612: { ! 613: GtkTreeViewColumn *col; ! 614: ! 615: show_range = GTK_CHECK_MENU_ITEM(menuitem)->active; ! 616: col = gtk_tree_view_get_column(GTK_TREE_VIEW(tree2_w), COL_NO); ! 617: if (col) ! 618: gtk_tree_view_column_set_visible(col, show_range); ! 619: col = gtk_tree_view_get_column(GTK_TREE_VIEW(tree2_w), COL_MOD); ! 620: if (col) ! 621: gtk_tree_view_column_set_visible(col, show_range); ! 622: col = gtk_tree_view_get_column(GTK_TREE_VIEW(tree2_w), COL_YES); ! 623: if (col) ! 624: gtk_tree_view_column_set_visible(col, show_range); ! 625: ! 626: } ! 627: ! 628: ! 629: void on_show_data1_activate(GtkMenuItem * menuitem, gpointer user_data) ! 630: { ! 631: GtkTreeViewColumn *col; ! 632: ! 633: show_value = GTK_CHECK_MENU_ITEM(menuitem)->active; ! 634: col = gtk_tree_view_get_column(GTK_TREE_VIEW(tree2_w), COL_VALUE); ! 635: if (col) ! 636: gtk_tree_view_column_set_visible(col, show_value); ! 637: } ! 638: ! 639: ! 640: void ! 641: on_set_option_mode1_activate(GtkMenuItem *menuitem, gpointer user_data) ! 642: { ! 643: opt_mode = OPT_NORMAL; ! 644: gtk_tree_store_clear(tree2); ! 645: display_tree(&rootmenu); /* instead of update_tree to speed-up */ ! 646: } ! 647: ! 648: ! 649: void ! 650: on_set_option_mode2_activate(GtkMenuItem *menuitem, gpointer user_data) ! 651: { ! 652: opt_mode = OPT_ALL; ! 653: gtk_tree_store_clear(tree2); ! 654: display_tree(&rootmenu); /* instead of update_tree to speed-up */ ! 655: } ! 656: ! 657: ! 658: void ! 659: on_set_option_mode3_activate(GtkMenuItem *menuitem, gpointer user_data) ! 660: { ! 661: opt_mode = OPT_PROMPT; ! 662: gtk_tree_store_clear(tree2); ! 663: display_tree(&rootmenu); /* instead of update_tree to speed-up */ ! 664: } ! 665: ! 666: ! 667: void on_introduction1_activate(GtkMenuItem * menuitem, gpointer user_data) ! 668: { ! 669: GtkWidget *dialog; ! 670: const gchar *intro_text = _( ! 671: "Welcome to gkc, the GTK+ graphical configuration tool\n" ! 672: "For each option, a blank box indicates the feature is disabled, a\n" ! 673: "check indicates it is enabled, and a dot indicates that it is to\n" ! 674: "be compiled as a module. Clicking on the box will cycle through the three states.\n" ! 675: "\n" ! 676: "If you do not see an option (e.g., a device driver) that you\n" ! 677: "believe should be present, try turning on Show All Options\n" ! 678: "under the Options menu.\n" ! 679: "Although there is no cross reference yet to help you figure out\n" ! 680: "what other options must be enabled to support the option you\n" ! 681: "are interested in, you can still view the help of a grayed-out\n" ! 682: "option.\n" ! 683: "\n" ! 684: "Toggling Show Debug Info under the Options menu will show \n" ! 685: "the dependencies, which you can then match by examining other options."); ! 686: ! 687: dialog = gtk_message_dialog_new(GTK_WINDOW(main_wnd), ! 688: GTK_DIALOG_DESTROY_WITH_PARENT, ! 689: GTK_MESSAGE_INFO, ! 690: GTK_BUTTONS_CLOSE, intro_text); ! 691: g_signal_connect_swapped(GTK_OBJECT(dialog), "response", ! 692: G_CALLBACK(gtk_widget_destroy), ! 693: GTK_OBJECT(dialog)); ! 694: gtk_widget_show_all(dialog); ! 695: } ! 696: ! 697: ! 698: void on_about1_activate(GtkMenuItem * menuitem, gpointer user_data) ! 699: { ! 700: GtkWidget *dialog; ! 701: const gchar *about_text = ! 702: _("gkc is copyright (c) 2002 Romain Lievin <[email protected]>.\n" ! 703: "Based on the source code from Roman Zippel.\n"); ! 704: ! 705: dialog = gtk_message_dialog_new(GTK_WINDOW(main_wnd), ! 706: GTK_DIALOG_DESTROY_WITH_PARENT, ! 707: GTK_MESSAGE_INFO, ! 708: GTK_BUTTONS_CLOSE, about_text); ! 709: g_signal_connect_swapped(GTK_OBJECT(dialog), "response", ! 710: G_CALLBACK(gtk_widget_destroy), ! 711: GTK_OBJECT(dialog)); ! 712: gtk_widget_show_all(dialog); ! 713: } ! 714: ! 715: ! 716: void on_license1_activate(GtkMenuItem * menuitem, gpointer user_data) ! 717: { ! 718: GtkWidget *dialog; ! 719: const gchar *license_text = ! 720: _("gkc is released under the terms of the GNU GPL v2.\n" ! 721: "For more information, please see the source code or\n" ! 722: "visit http://www.fsf.org/licenses/licenses.html\n"); ! 723: ! 724: dialog = gtk_message_dialog_new(GTK_WINDOW(main_wnd), ! 725: GTK_DIALOG_DESTROY_WITH_PARENT, ! 726: GTK_MESSAGE_INFO, ! 727: GTK_BUTTONS_CLOSE, license_text); ! 728: g_signal_connect_swapped(GTK_OBJECT(dialog), "response", ! 729: G_CALLBACK(gtk_widget_destroy), ! 730: GTK_OBJECT(dialog)); ! 731: gtk_widget_show_all(dialog); ! 732: } ! 733: ! 734: ! 735: void on_back_clicked(GtkButton * button, gpointer user_data) ! 736: { ! 737: enum prop_type ptype; ! 738: ! 739: current = current->parent; ! 740: ptype = current->prompt ? current->prompt->type : P_UNKNOWN; ! 741: if (ptype != P_MENU) ! 742: current = current->parent; ! 743: display_tree_part(); ! 744: ! 745: if (current == &rootmenu) ! 746: gtk_widget_set_sensitive(back_btn, FALSE); ! 747: } ! 748: ! 749: ! 750: void on_load_clicked(GtkButton * button, gpointer user_data) ! 751: { ! 752: on_load1_activate(NULL, user_data); ! 753: } ! 754: ! 755: ! 756: void on_single_clicked(GtkButton * button, gpointer user_data) ! 757: { ! 758: view_mode = SINGLE_VIEW; ! 759: gtk_paned_set_position(GTK_PANED(hpaned), 0); ! 760: gtk_widget_hide(tree1_w); ! 761: current = &rootmenu; ! 762: display_tree_part(); ! 763: } ! 764: ! 765: ! 766: void on_split_clicked(GtkButton * button, gpointer user_data) ! 767: { ! 768: gint w, h; ! 769: view_mode = SPLIT_VIEW; ! 770: gtk_widget_show(tree1_w); ! 771: gtk_window_get_default_size(GTK_WINDOW(main_wnd), &w, &h); ! 772: gtk_paned_set_position(GTK_PANED(hpaned), w / 2); ! 773: if (tree2) ! 774: gtk_tree_store_clear(tree2); ! 775: display_list(); ! 776: ! 777: /* Disable back btn, like in full mode. */ ! 778: gtk_widget_set_sensitive(back_btn, FALSE); ! 779: } ! 780: ! 781: ! 782: void on_full_clicked(GtkButton * button, gpointer user_data) ! 783: { ! 784: view_mode = FULL_VIEW; ! 785: gtk_paned_set_position(GTK_PANED(hpaned), 0); ! 786: gtk_widget_hide(tree1_w); ! 787: if (tree2) ! 788: gtk_tree_store_clear(tree2); ! 789: display_tree(&rootmenu); ! 790: gtk_widget_set_sensitive(back_btn, FALSE); ! 791: } ! 792: ! 793: ! 794: void on_collapse_clicked(GtkButton * button, gpointer user_data) ! 795: { ! 796: gtk_tree_view_collapse_all(GTK_TREE_VIEW(tree2_w)); ! 797: } ! 798: ! 799: ! 800: void on_expand_clicked(GtkButton * button, gpointer user_data) ! 801: { ! 802: gtk_tree_view_expand_all(GTK_TREE_VIEW(tree2_w)); ! 803: } ! 804: ! 805: ! 806: /* CTree Callbacks */ ! 807: ! 808: /* Change hex/int/string value in the cell */ ! 809: static void renderer_edited(GtkCellRendererText * cell, ! 810: const gchar * path_string, ! 811: const gchar * new_text, gpointer user_data) ! 812: { ! 813: GtkTreePath *path = gtk_tree_path_new_from_string(path_string); ! 814: GtkTreeIter iter; ! 815: const char *old_def, *new_def; ! 816: struct menu *menu; ! 817: struct symbol *sym; ! 818: ! 819: if (!gtk_tree_model_get_iter(model2, &iter, path)) ! 820: return; ! 821: ! 822: gtk_tree_model_get(model2, &iter, COL_MENU, &menu, -1); ! 823: sym = menu->sym; ! 824: ! 825: gtk_tree_model_get(model2, &iter, COL_VALUE, &old_def, -1); ! 826: new_def = new_text; ! 827: ! 828: sym_set_string_value(sym, new_def); ! 829: ! 830: update_tree(&rootmenu, NULL); ! 831: ! 832: gtk_tree_path_free(path); ! 833: } ! 834: ! 835: /* Change the value of a symbol and update the tree */ ! 836: static void change_sym_value(struct menu *menu, gint col) ! 837: { ! 838: struct symbol *sym = menu->sym; ! 839: tristate oldval, newval; ! 840: ! 841: if (!sym) ! 842: return; ! 843: ! 844: if (col == COL_NO) ! 845: newval = no; ! 846: else if (col == COL_MOD) ! 847: newval = mod; ! 848: else if (col == COL_YES) ! 849: newval = yes; ! 850: else ! 851: return; ! 852: ! 853: switch (sym_get_type(sym)) { ! 854: case S_BOOLEAN: ! 855: case S_TRISTATE: ! 856: oldval = sym_get_tristate_value(sym); ! 857: if (!sym_tristate_within_range(sym, newval)) ! 858: newval = yes; ! 859: sym_set_tristate_value(sym, newval); ! 860: if (view_mode == FULL_VIEW) ! 861: update_tree(&rootmenu, NULL); ! 862: else if (view_mode == SPLIT_VIEW) { ! 863: update_tree(browsed, NULL); ! 864: display_list(); ! 865: } ! 866: else if (view_mode == SINGLE_VIEW) ! 867: display_tree_part(); //fixme: keep exp/coll ! 868: break; ! 869: case S_INT: ! 870: case S_HEX: ! 871: case S_STRING: ! 872: default: ! 873: break; ! 874: } ! 875: } ! 876: ! 877: static void toggle_sym_value(struct menu *menu) ! 878: { ! 879: if (!menu->sym) ! 880: return; ! 881: ! 882: sym_toggle_tristate_value(menu->sym); ! 883: if (view_mode == FULL_VIEW) ! 884: update_tree(&rootmenu, NULL); ! 885: else if (view_mode == SPLIT_VIEW) { ! 886: update_tree(browsed, NULL); ! 887: display_list(); ! 888: } ! 889: else if (view_mode == SINGLE_VIEW) ! 890: display_tree_part(); //fixme: keep exp/coll ! 891: } ! 892: ! 893: static void renderer_toggled(GtkCellRendererToggle * cell, ! 894: gchar * path_string, gpointer user_data) ! 895: { ! 896: GtkTreePath *path, *sel_path = NULL; ! 897: GtkTreeIter iter, sel_iter; ! 898: GtkTreeSelection *sel; ! 899: struct menu *menu; ! 900: ! 901: path = gtk_tree_path_new_from_string(path_string); ! 902: if (!gtk_tree_model_get_iter(model2, &iter, path)) ! 903: return; ! 904: ! 905: sel = gtk_tree_view_get_selection(GTK_TREE_VIEW(tree2_w)); ! 906: if (gtk_tree_selection_get_selected(sel, NULL, &sel_iter)) ! 907: sel_path = gtk_tree_model_get_path(model2, &sel_iter); ! 908: if (!sel_path) ! 909: goto out1; ! 910: if (gtk_tree_path_compare(path, sel_path)) ! 911: goto out2; ! 912: ! 913: gtk_tree_model_get(model2, &iter, COL_MENU, &menu, -1); ! 914: toggle_sym_value(menu); ! 915: ! 916: out2: ! 917: gtk_tree_path_free(sel_path); ! 918: out1: ! 919: gtk_tree_path_free(path); ! 920: } ! 921: ! 922: static gint column2index(GtkTreeViewColumn * column) ! 923: { ! 924: gint i; ! 925: ! 926: for (i = 0; i < COL_NUMBER; i++) { ! 927: GtkTreeViewColumn *col; ! 928: ! 929: col = gtk_tree_view_get_column(GTK_TREE_VIEW(tree2_w), i); ! 930: if (col == column) ! 931: return i; ! 932: } ! 933: ! 934: return -1; ! 935: } ! 936: ! 937: ! 938: /* User click: update choice (full) or goes down (single) */ ! 939: gboolean ! 940: on_treeview2_button_press_event(GtkWidget * widget, ! 941: GdkEventButton * event, gpointer user_data) ! 942: { ! 943: GtkTreeView *view = GTK_TREE_VIEW(widget); ! 944: GtkTreePath *path; ! 945: GtkTreeViewColumn *column; ! 946: GtkTreeIter iter; ! 947: struct menu *menu; ! 948: gint col; ! 949: ! 950: #if GTK_CHECK_VERSION(2,1,4) // bug in ctree with earlier version of GTK ! 951: gint tx = (gint) event->x; ! 952: gint ty = (gint) event->y; ! 953: gint cx, cy; ! 954: ! 955: gtk_tree_view_get_path_at_pos(view, tx, ty, &path, &column, &cx, ! 956: &cy); ! 957: #else ! 958: gtk_tree_view_get_cursor(view, &path, &column); ! 959: #endif ! 960: if (path == NULL) ! 961: return FALSE; ! 962: ! 963: if (!gtk_tree_model_get_iter(model2, &iter, path)) ! 964: return FALSE; ! 965: gtk_tree_model_get(model2, &iter, COL_MENU, &menu, -1); ! 966: ! 967: col = column2index(column); ! 968: if (event->type == GDK_2BUTTON_PRESS) { ! 969: enum prop_type ptype; ! 970: ptype = menu->prompt ? menu->prompt->type : P_UNKNOWN; ! 971: ! 972: if (ptype == P_MENU && view_mode != FULL_VIEW && col == COL_OPTION) { ! 973: // goes down into menu ! 974: current = menu; ! 975: display_tree_part(); ! 976: gtk_widget_set_sensitive(back_btn, TRUE); ! 977: } else if ((col == COL_OPTION)) { ! 978: toggle_sym_value(menu); ! 979: gtk_tree_view_expand_row(view, path, TRUE); ! 980: } ! 981: } else { ! 982: if (col == COL_VALUE) { ! 983: toggle_sym_value(menu); ! 984: gtk_tree_view_expand_row(view, path, TRUE); ! 985: } else if (col == COL_NO || col == COL_MOD ! 986: || col == COL_YES) { ! 987: change_sym_value(menu, col); ! 988: gtk_tree_view_expand_row(view, path, TRUE); ! 989: } ! 990: } ! 991: ! 992: return FALSE; ! 993: } ! 994: ! 995: /* Key pressed: update choice */ ! 996: gboolean ! 997: on_treeview2_key_press_event(GtkWidget * widget, ! 998: GdkEventKey * event, gpointer user_data) ! 999: { ! 1000: GtkTreeView *view = GTK_TREE_VIEW(widget); ! 1001: GtkTreePath *path; ! 1002: GtkTreeViewColumn *column; ! 1003: GtkTreeIter iter; ! 1004: struct menu *menu; ! 1005: gint col; ! 1006: ! 1007: gtk_tree_view_get_cursor(view, &path, &column); ! 1008: if (path == NULL) ! 1009: return FALSE; ! 1010: ! 1011: if (event->keyval == GDK_space) { ! 1012: if (gtk_tree_view_row_expanded(view, path)) ! 1013: gtk_tree_view_collapse_row(view, path); ! 1014: else ! 1015: gtk_tree_view_expand_row(view, path, FALSE); ! 1016: return TRUE; ! 1017: } ! 1018: if (event->keyval == GDK_KP_Enter) { ! 1019: } ! 1020: if (widget == tree1_w) ! 1021: return FALSE; ! 1022: ! 1023: gtk_tree_model_get_iter(model2, &iter, path); ! 1024: gtk_tree_model_get(model2, &iter, COL_MENU, &menu, -1); ! 1025: ! 1026: if (!strcasecmp(event->string, "n")) ! 1027: col = COL_NO; ! 1028: else if (!strcasecmp(event->string, "m")) ! 1029: col = COL_MOD; ! 1030: else if (!strcasecmp(event->string, "y")) ! 1031: col = COL_YES; ! 1032: else ! 1033: col = -1; ! 1034: change_sym_value(menu, col); ! 1035: ! 1036: return FALSE; ! 1037: } ! 1038: ! 1039: ! 1040: /* Row selection changed: update help */ ! 1041: void ! 1042: on_treeview2_cursor_changed(GtkTreeView * treeview, gpointer user_data) ! 1043: { ! 1044: GtkTreeSelection *selection; ! 1045: GtkTreeIter iter; ! 1046: struct menu *menu; ! 1047: ! 1048: selection = gtk_tree_view_get_selection(treeview); ! 1049: if (gtk_tree_selection_get_selected(selection, &model2, &iter)) { ! 1050: gtk_tree_model_get(model2, &iter, COL_MENU, &menu, -1); ! 1051: text_insert_help(menu); ! 1052: } ! 1053: } ! 1054: ! 1055: ! 1056: /* User click: display sub-tree in the right frame. */ ! 1057: gboolean ! 1058: on_treeview1_button_press_event(GtkWidget * widget, ! 1059: GdkEventButton * event, gpointer user_data) ! 1060: { ! 1061: GtkTreeView *view = GTK_TREE_VIEW(widget); ! 1062: GtkTreePath *path; ! 1063: GtkTreeViewColumn *column; ! 1064: GtkTreeIter iter; ! 1065: struct menu *menu; ! 1066: ! 1067: gint tx = (gint) event->x; ! 1068: gint ty = (gint) event->y; ! 1069: gint cx, cy; ! 1070: ! 1071: gtk_tree_view_get_path_at_pos(view, tx, ty, &path, &column, &cx, ! 1072: &cy); ! 1073: if (path == NULL) ! 1074: return FALSE; ! 1075: ! 1076: gtk_tree_model_get_iter(model1, &iter, path); ! 1077: gtk_tree_model_get(model1, &iter, COL_MENU, &menu, -1); ! 1078: ! 1079: if (event->type == GDK_2BUTTON_PRESS) { ! 1080: toggle_sym_value(menu); ! 1081: current = menu; ! 1082: display_tree_part(); ! 1083: } else { ! 1084: browsed = menu; ! 1085: display_tree_part(); ! 1086: } ! 1087: ! 1088: gtk_widget_realize(tree2_w); ! 1089: gtk_tree_view_set_cursor(view, path, NULL, FALSE); ! 1090: gtk_widget_grab_focus(tree2_w); ! 1091: ! 1092: return FALSE; ! 1093: } ! 1094: ! 1095: ! 1096: /* Fill a row of strings */ ! 1097: static gchar **fill_row(struct menu *menu) ! 1098: { ! 1099: static gchar *row[COL_NUMBER]; ! 1100: struct symbol *sym = menu->sym; ! 1101: const char *def; ! 1102: int stype; ! 1103: tristate val; ! 1104: enum prop_type ptype; ! 1105: int i; ! 1106: ! 1107: for (i = COL_OPTION; i <= COL_COLOR; i++) ! 1108: g_free(row[i]); ! 1109: bzero(row, sizeof(row)); ! 1110: ! 1111: row[COL_OPTION] = ! 1112: g_strdup_printf("%s %s", _(menu_get_prompt(menu)), ! 1113: sym && !sym_has_value(sym) ? "(NEW)" : ""); ! 1114: ! 1115: if (opt_mode == OPT_ALL && !menu_is_visible(menu)) ! 1116: row[COL_COLOR] = g_strdup("DarkGray"); ! 1117: else if (opt_mode == OPT_PROMPT && ! 1118: menu_has_prompt(menu) && !menu_is_visible(menu)) ! 1119: row[COL_COLOR] = g_strdup("DarkGray"); ! 1120: else ! 1121: row[COL_COLOR] = g_strdup("Black"); ! 1122: ! 1123: ptype = menu->prompt ? menu->prompt->type : P_UNKNOWN; ! 1124: switch (ptype) { ! 1125: case P_MENU: ! 1126: row[COL_PIXBUF] = (gchar *) xpm_menu; ! 1127: if (view_mode == SINGLE_VIEW) ! 1128: row[COL_PIXVIS] = GINT_TO_POINTER(TRUE); ! 1129: row[COL_BTNVIS] = GINT_TO_POINTER(FALSE); ! 1130: break; ! 1131: case P_COMMENT: ! 1132: row[COL_PIXBUF] = (gchar *) xpm_void; ! 1133: row[COL_PIXVIS] = GINT_TO_POINTER(FALSE); ! 1134: row[COL_BTNVIS] = GINT_TO_POINTER(FALSE); ! 1135: break; ! 1136: default: ! 1137: row[COL_PIXBUF] = (gchar *) xpm_void; ! 1138: row[COL_PIXVIS] = GINT_TO_POINTER(FALSE); ! 1139: row[COL_BTNVIS] = GINT_TO_POINTER(TRUE); ! 1140: break; ! 1141: } ! 1142: ! 1143: if (!sym) ! 1144: return row; ! 1145: row[COL_NAME] = g_strdup(sym->name); ! 1146: ! 1147: sym_calc_value(sym); ! 1148: sym->flags &= ~SYMBOL_CHANGED; ! 1149: ! 1150: if (sym_is_choice(sym)) { // parse childs for getting final value ! 1151: struct menu *child; ! 1152: struct symbol *def_sym = sym_get_choice_value(sym); ! 1153: struct menu *def_menu = NULL; ! 1154: ! 1155: row[COL_BTNVIS] = GINT_TO_POINTER(FALSE); ! 1156: ! 1157: for (child = menu->list; child; child = child->next) { ! 1158: if (menu_is_visible(child) ! 1159: && child->sym == def_sym) ! 1160: def_menu = child; ! 1161: } ! 1162: ! 1163: if (def_menu) ! 1164: row[COL_VALUE] = ! 1165: g_strdup(_(menu_get_prompt(def_menu))); ! 1166: } ! 1167: if (sym->flags & SYMBOL_CHOICEVAL) ! 1168: row[COL_BTNRAD] = GINT_TO_POINTER(TRUE); ! 1169: ! 1170: stype = sym_get_type(sym); ! 1171: switch (stype) { ! 1172: case S_BOOLEAN: ! 1173: if (GPOINTER_TO_INT(row[COL_PIXVIS]) == FALSE) ! 1174: row[COL_BTNVIS] = GINT_TO_POINTER(TRUE); ! 1175: if (sym_is_choice(sym)) ! 1176: break; ! 1177: case S_TRISTATE: ! 1178: val = sym_get_tristate_value(sym); ! 1179: switch (val) { ! 1180: case no: ! 1181: row[COL_NO] = g_strdup("N"); ! 1182: row[COL_VALUE] = g_strdup("N"); ! 1183: row[COL_BTNACT] = GINT_TO_POINTER(FALSE); ! 1184: row[COL_BTNINC] = GINT_TO_POINTER(FALSE); ! 1185: break; ! 1186: case mod: ! 1187: row[COL_MOD] = g_strdup("M"); ! 1188: row[COL_VALUE] = g_strdup("M"); ! 1189: row[COL_BTNINC] = GINT_TO_POINTER(TRUE); ! 1190: break; ! 1191: case yes: ! 1192: row[COL_YES] = g_strdup("Y"); ! 1193: row[COL_VALUE] = g_strdup("Y"); ! 1194: row[COL_BTNACT] = GINT_TO_POINTER(TRUE); ! 1195: row[COL_BTNINC] = GINT_TO_POINTER(FALSE); ! 1196: break; ! 1197: } ! 1198: ! 1199: if (val != no && sym_tristate_within_range(sym, no)) ! 1200: row[COL_NO] = g_strdup("_"); ! 1201: if (val != mod && sym_tristate_within_range(sym, mod)) ! 1202: row[COL_MOD] = g_strdup("_"); ! 1203: if (val != yes && sym_tristate_within_range(sym, yes)) ! 1204: row[COL_YES] = g_strdup("_"); ! 1205: break; ! 1206: case S_INT: ! 1207: case S_HEX: ! 1208: case S_STRING: ! 1209: def = sym_get_string_value(sym); ! 1210: row[COL_VALUE] = g_strdup(def); ! 1211: row[COL_EDIT] = GINT_TO_POINTER(TRUE); ! 1212: row[COL_BTNVIS] = GINT_TO_POINTER(FALSE); ! 1213: break; ! 1214: } ! 1215: ! 1216: return row; ! 1217: } ! 1218: ! 1219: ! 1220: /* Set the node content with a row of strings */ ! 1221: static void set_node(GtkTreeIter * node, struct menu *menu, gchar ** row) ! 1222: { ! 1223: GdkColor color; ! 1224: gboolean success; ! 1225: GdkPixbuf *pix; ! 1226: ! 1227: pix = gdk_pixbuf_new_from_xpm_data((const char **) ! 1228: row[COL_PIXBUF]); ! 1229: ! 1230: gdk_color_parse(row[COL_COLOR], &color); ! 1231: gdk_colormap_alloc_colors(gdk_colormap_get_system(), &color, 1, ! 1232: FALSE, FALSE, &success); ! 1233: ! 1234: gtk_tree_store_set(tree, node, ! 1235: COL_OPTION, row[COL_OPTION], ! 1236: COL_NAME, row[COL_NAME], ! 1237: COL_NO, row[COL_NO], ! 1238: COL_MOD, row[COL_MOD], ! 1239: COL_YES, row[COL_YES], ! 1240: COL_VALUE, row[COL_VALUE], ! 1241: COL_MENU, (gpointer) menu, ! 1242: COL_COLOR, &color, ! 1243: COL_EDIT, GPOINTER_TO_INT(row[COL_EDIT]), ! 1244: COL_PIXBUF, pix, ! 1245: COL_PIXVIS, GPOINTER_TO_INT(row[COL_PIXVIS]), ! 1246: COL_BTNVIS, GPOINTER_TO_INT(row[COL_BTNVIS]), ! 1247: COL_BTNACT, GPOINTER_TO_INT(row[COL_BTNACT]), ! 1248: COL_BTNINC, GPOINTER_TO_INT(row[COL_BTNINC]), ! 1249: COL_BTNRAD, GPOINTER_TO_INT(row[COL_BTNRAD]), ! 1250: -1); ! 1251: ! 1252: g_object_unref(pix); ! 1253: } ! 1254: ! 1255: ! 1256: /* Add a node to the tree */ ! 1257: static void place_node(struct menu *menu, char **row) ! 1258: { ! 1259: GtkTreeIter *parent = parents[indent - 1]; ! 1260: GtkTreeIter *node = parents[indent]; ! 1261: ! 1262: gtk_tree_store_append(tree, node, parent); ! 1263: set_node(node, menu, row); ! 1264: } ! 1265: ! 1266: ! 1267: /* Find a node in the GTK+ tree */ ! 1268: static GtkTreeIter found; ! 1269: ! 1270: /* ! 1271: * Find a menu in the GtkTree starting at parent. ! 1272: */ ! 1273: GtkTreeIter *gtktree_iter_find_node(GtkTreeIter * parent, ! 1274: struct menu *tofind) ! 1275: { ! 1276: GtkTreeIter iter; ! 1277: GtkTreeIter *child = &iter; ! 1278: gboolean valid; ! 1279: GtkTreeIter *ret; ! 1280: ! 1281: valid = gtk_tree_model_iter_children(model2, child, parent); ! 1282: while (valid) { ! 1283: struct menu *menu; ! 1284: ! 1285: gtk_tree_model_get(model2, child, 6, &menu, -1); ! 1286: ! 1287: if (menu == tofind) { ! 1288: memcpy(&found, child, sizeof(GtkTreeIter)); ! 1289: return &found; ! 1290: } ! 1291: ! 1292: ret = gtktree_iter_find_node(child, tofind); ! 1293: if (ret) ! 1294: return ret; ! 1295: ! 1296: valid = gtk_tree_model_iter_next(model2, child); ! 1297: } ! 1298: ! 1299: return NULL; ! 1300: } ! 1301: ! 1302: ! 1303: /* ! 1304: * Update the tree by adding/removing entries ! 1305: * Does not change other nodes ! 1306: */ ! 1307: static void update_tree(struct menu *src, GtkTreeIter * dst) ! 1308: { ! 1309: struct menu *child1; ! 1310: GtkTreeIter iter, tmp; ! 1311: GtkTreeIter *child2 = &iter; ! 1312: gboolean valid; ! 1313: GtkTreeIter *sibling; ! 1314: struct symbol *sym; ! 1315: struct property *prop; ! 1316: struct menu *menu1, *menu2; ! 1317: ! 1318: if (src == &rootmenu) ! 1319: indent = 1; ! 1320: ! 1321: valid = gtk_tree_model_iter_children(model2, child2, dst); ! 1322: for (child1 = src->list; child1; child1 = child1->next) { ! 1323: ! 1324: prop = child1->prompt; ! 1325: sym = child1->sym; ! 1326: ! 1327: reparse: ! 1328: menu1 = child1; ! 1329: if (valid) ! 1330: gtk_tree_model_get(model2, child2, COL_MENU, ! 1331: &menu2, -1); ! 1332: else ! 1333: menu2 = NULL; // force adding of a first child ! 1334: ! 1335: #ifdef DEBUG ! 1336: printf("%*c%s | %s\n", indent, ' ', ! 1337: menu1 ? menu_get_prompt(menu1) : "nil", ! 1338: menu2 ? menu_get_prompt(menu2) : "nil"); ! 1339: #endif ! 1340: ! 1341: if ((opt_mode == OPT_NORMAL && !menu_is_visible(child1)) || ! 1342: (opt_mode == OPT_PROMPT && !menu_has_prompt(child1)) || ! 1343: (opt_mode == OPT_ALL && !menu_get_prompt(child1))) { ! 1344: ! 1345: /* remove node */ ! 1346: if (gtktree_iter_find_node(dst, menu1) != NULL) { ! 1347: memcpy(&tmp, child2, sizeof(GtkTreeIter)); ! 1348: valid = gtk_tree_model_iter_next(model2, ! 1349: child2); ! 1350: gtk_tree_store_remove(tree2, &tmp); ! 1351: if (!valid) ! 1352: return; /* next parent */ ! 1353: else ! 1354: goto reparse; /* next child */ ! 1355: } else ! 1356: continue; ! 1357: } ! 1358: ! 1359: if (menu1 != menu2) { ! 1360: if (gtktree_iter_find_node(dst, menu1) == NULL) { // add node ! 1361: if (!valid && !menu2) ! 1362: sibling = NULL; ! 1363: else ! 1364: sibling = child2; ! 1365: gtk_tree_store_insert_before(tree2, ! 1366: child2, ! 1367: dst, sibling); ! 1368: set_node(child2, menu1, fill_row(menu1)); ! 1369: if (menu2 == NULL) ! 1370: valid = TRUE; ! 1371: } else { // remove node ! 1372: memcpy(&tmp, child2, sizeof(GtkTreeIter)); ! 1373: valid = gtk_tree_model_iter_next(model2, ! 1374: child2); ! 1375: gtk_tree_store_remove(tree2, &tmp); ! 1376: if (!valid) ! 1377: return; // next parent ! 1378: else ! 1379: goto reparse; // next child ! 1380: } ! 1381: } else if (sym && (sym->flags & SYMBOL_CHANGED)) { ! 1382: set_node(child2, menu1, fill_row(menu1)); ! 1383: } ! 1384: ! 1385: indent++; ! 1386: update_tree(child1, child2); ! 1387: indent--; ! 1388: ! 1389: valid = gtk_tree_model_iter_next(model2, child2); ! 1390: } ! 1391: } ! 1392: ! 1393: ! 1394: /* Display the whole tree (single/split/full view) */ ! 1395: static void display_tree(struct menu *menu) ! 1396: { ! 1397: struct symbol *sym; ! 1398: struct property *prop; ! 1399: struct menu *child; ! 1400: enum prop_type ptype; ! 1401: ! 1402: if (menu == &rootmenu) { ! 1403: indent = 1; ! 1404: current = &rootmenu; ! 1405: } ! 1406: ! 1407: for (child = menu->list; child; child = child->next) { ! 1408: prop = child->prompt; ! 1409: sym = child->sym; ! 1410: ptype = prop ? prop->type : P_UNKNOWN; ! 1411: ! 1412: if (sym) ! 1413: sym->flags &= ~SYMBOL_CHANGED; ! 1414: ! 1415: if ((view_mode == SPLIT_VIEW) ! 1416: && !(child->flags & MENU_ROOT) && (tree == tree1)) ! 1417: continue; ! 1418: ! 1419: if ((view_mode == SPLIT_VIEW) && (child->flags & MENU_ROOT) ! 1420: && (tree == tree2)) ! 1421: continue; ! 1422: ! 1423: if ((opt_mode == OPT_NORMAL && menu_is_visible(child)) || ! 1424: (opt_mode == OPT_PROMPT && menu_has_prompt(child)) || ! 1425: (opt_mode == OPT_ALL && menu_get_prompt(child))) ! 1426: place_node(child, fill_row(child)); ! 1427: #ifdef DEBUG ! 1428: printf("%*c%s: ", indent, ' ', menu_get_prompt(child)); ! 1429: printf("%s", child->flags & MENU_ROOT ? "rootmenu | " : ""); ! 1430: printf("%s", prop_get_type_name(ptype)); ! 1431: printf(" | "); ! 1432: if (sym) { ! 1433: printf("%s", sym_type_name(sym->type)); ! 1434: printf(" | "); ! 1435: printf("%s", dbg_sym_flags(sym->flags)); ! 1436: printf("\n"); ! 1437: } else ! 1438: printf("\n"); ! 1439: #endif ! 1440: if ((view_mode != FULL_VIEW) && (ptype == P_MENU) ! 1441: && (tree == tree2)) ! 1442: continue; ! 1443: /* ! 1444: if (((menu != &rootmenu) && !(menu->flags & MENU_ROOT)) ! 1445: || (view_mode == FULL_VIEW) ! 1446: || (view_mode == SPLIT_VIEW))*/ ! 1447: if (((view_mode == SINGLE_VIEW) && (menu->flags & MENU_ROOT)) ! 1448: || (view_mode == FULL_VIEW) ! 1449: || (view_mode == SPLIT_VIEW)) { ! 1450: indent++; ! 1451: display_tree(child); ! 1452: indent--; ! 1453: } ! 1454: } ! 1455: } ! 1456: ! 1457: /* Display a part of the tree starting at current node (single/split view) */ ! 1458: static void display_tree_part(void) ! 1459: { ! 1460: if (tree2) ! 1461: gtk_tree_store_clear(tree2); ! 1462: if (view_mode == SINGLE_VIEW) ! 1463: display_tree(current); ! 1464: else if (view_mode == SPLIT_VIEW) ! 1465: display_tree(browsed); ! 1466: gtk_tree_view_expand_all(GTK_TREE_VIEW(tree2_w)); ! 1467: } ! 1468: ! 1469: /* Display the list in the left frame (split view) */ ! 1470: static void display_list(void) ! 1471: { ! 1472: if (tree1) ! 1473: gtk_tree_store_clear(tree1); ! 1474: ! 1475: tree = tree1; ! 1476: display_tree(&rootmenu); ! 1477: gtk_tree_view_expand_all(GTK_TREE_VIEW(tree1_w)); ! 1478: tree = tree2; ! 1479: } ! 1480: ! 1481: void fixup_rootmenu(struct menu *menu) ! 1482: { ! 1483: struct menu *child; ! 1484: static int menu_cnt = 0; ! 1485: ! 1486: menu->flags |= MENU_ROOT; ! 1487: for (child = menu->list; child; child = child->next) { ! 1488: if (child->prompt && child->prompt->type == P_MENU) { ! 1489: menu_cnt++; ! 1490: fixup_rootmenu(child); ! 1491: menu_cnt--; ! 1492: } else if (!menu_cnt) ! 1493: fixup_rootmenu(child); ! 1494: } ! 1495: } ! 1496: ! 1497: ! 1498: /* Main */ ! 1499: int main(int ac, char *av[]) ! 1500: { ! 1501: const char *name; ! 1502: char *env; ! 1503: gchar *glade_file; ! 1504: ! 1505: #ifndef LKC_DIRECT_LINK ! 1506: kconfig_load(); ! 1507: #endif ! 1508: ! 1509: bindtextdomain(PACKAGE, LOCALEDIR); ! 1510: bind_textdomain_codeset(PACKAGE, "UTF-8"); ! 1511: textdomain(PACKAGE); ! 1512: ! 1513: /* GTK stuffs */ ! 1514: gtk_set_locale(); ! 1515: gtk_init(&ac, &av); ! 1516: glade_init(); ! 1517: ! 1518: //add_pixmap_directory (PACKAGE_DATA_DIR "/" PACKAGE "/pixmaps"); ! 1519: //add_pixmap_directory (PACKAGE_SOURCE_DIR "/pixmaps"); ! 1520: ! 1521: /* Determine GUI path */ ! 1522: env = getenv(SRCTREE); ! 1523: if (env) ! 1524: glade_file = g_strconcat(env, "/tools/kconfig/gconf.glade", NULL); ! 1525: else if (av[0][0] == '/') ! 1526: glade_file = g_strconcat(av[0], ".glade", NULL); ! 1527: else ! 1528: glade_file = g_strconcat(g_get_current_dir(), "/", av[0], ".glade", NULL); ! 1529: ! 1530: /* Conf stuffs */ ! 1531: if (ac > 1 && av[1][0] == '-') { ! 1532: switch (av[1][1]) { ! 1533: case 'a': ! 1534: //showAll = 1; ! 1535: break; ! 1536: case 'h': ! 1537: case '?': ! 1538: printf("%s <config>\n", av[0]); ! 1539: exit(0); ! 1540: } ! 1541: name = av[2]; ! 1542: } else ! 1543: name = av[1]; ! 1544: ! 1545: conf_parse(name); ! 1546: fixup_rootmenu(&rootmenu); ! 1547: conf_read(NULL); ! 1548: ! 1549: /* Load the interface and connect signals */ ! 1550: init_main_window(glade_file); ! 1551: init_tree_model(); ! 1552: init_left_tree(); ! 1553: init_right_tree(); ! 1554: ! 1555: switch (view_mode) { ! 1556: case SINGLE_VIEW: ! 1557: display_tree_part(); ! 1558: break; ! 1559: case SPLIT_VIEW: ! 1560: display_list(); ! 1561: break; ! 1562: case FULL_VIEW: ! 1563: display_tree(&rootmenu); ! 1564: break; ! 1565: } ! 1566: ! 1567: gtk_main(); ! 1568: ! 1569: return 0; ! 1570: } ! 1571: ! 1572: static void conf_changed(void) ! 1573: { ! 1574: bool changed = conf_get_changed(); ! 1575: gtk_widget_set_sensitive(save_btn, changed); ! 1576: gtk_widget_set_sensitive(save_menu_item, changed); ! 1577: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.