| 1 | |
| 2 | |
| 3 | * Copyright (C) 2002-2003 Romain Lievin <[email protected]>
|
| 4 |
|
| 5 |
|
| 6 | #include <stdlib.h>
|
| 7 | #include "lkc.h"
|
| 8 |
|
| 9 | #include <gtk/gtk.h>
|
| 10 |
|
| 11 | #include <stdio.h>
|
| 12 | #include <string.h>
|
| 13 | #include <strings.h>
|
| 14 | #include <unistd.h>
|
| 15 | #include <time.h>
|
| 16 |
|
| 17 | enum view_mode {
|
| 18 | SINGLE_VIEW, SPLIT_VIEW, FULL_VIEW
|
| 19 | };
|
| 20 |
|
| 21 | enum {
|
| 22 | OPT_NORMAL, OPT_ALL, OPT_PROMPT
|
| 23 | };
|
| 24 |
|
| 25 | static gint view_mode = FULL_VIEW;
|
| 26 | static gboolean show_name = TRUE;
|
| 27 | static gboolean show_range = TRUE;
|
| 28 | static gboolean show_value = TRUE;
|
| 29 | static int opt_mode = OPT_NORMAL;
|
| 30 |
|
| 31 | static GtkWidget *main_wnd;
|
| 32 | static GtkWidget *tree1_w; |
| 33 | static GtkWidget *tree2_w; |
| 34 | static GtkWidget *text_w;
|
| 35 | static GtkWidget *hpaned;
|
| 36 | static GtkWidget *vpaned;
|
| 37 | static GtkWidget *back_btn, *save_btn, *single_btn, *split_btn, *full_btn;
|
| 38 | static GtkWidget *save_menu_item;
|
| 39 |
|
| 40 | static GtkTextTag *tag1, *tag2;
|
| 41 |
|
| 42 | static GtkTreeStore *tree1, *tree2;
|
| 43 | static GdkPixbuf *pix_menu;
|
| 44 |
|
| 45 | static struct menu *browsed; |
| 46 | static struct menu *selected; |
| 47 |
|
| 48 | enum {
|
| 49 | COL_OPTION, COL_NAME, COL_NO, COL_MOD, COL_YES, COL_VALUE,
|
| 50 | COL_MENU, COL_COLOR, COL_EDIT, COL_PIXBUF,
|
| 51 | COL_PIXVIS, COL_BTNVIS, COL_BTNACT, COL_BTNINC, COL_BTNRAD,
|
| 52 | COL_NUMBER
|
| 53 | };
|
| 54 |
|
| 55 | static void display_tree(GtkTreeStore *store, struct menu *menu);
|
| 56 | static void recreate_tree(void);
|
| 57 |
|
| 58 | static void conf_changed(bool dirty)
|
| 59 | {
|
| 60 | gtk_widget_set_sensitive(save_btn, dirty);
|
| 61 | gtk_widget_set_sensitive(save_menu_item, dirty);
|
| 62 | }
|
| 63 |
|
| 64 |
|
| 65 |
|
| 66 | static void text_insert_msg(const char *title, const char *msg)
|
| 67 | {
|
| 68 | GtkTextBuffer *buffer;
|
| 69 | GtkTextIter start, end;
|
| 70 |
|
| 71 | buffer = gtk_text_view_get_buffer(GTK_TEXT_VIEW(text_w));
|
| 72 | gtk_text_buffer_get_bounds(buffer, &start, &end);
|
| 73 | gtk_text_buffer_delete(buffer, &start, &end);
|
| 74 | gtk_text_view_set_left_margin(GTK_TEXT_VIEW(text_w), 15);
|
| 75 |
|
| 76 | gtk_text_buffer_get_end_iter(buffer, &end);
|
| 77 | gtk_text_buffer_insert_with_tags(buffer, &end, title, -1, tag1,
|
| 78 | NULL);
|
| 79 | gtk_text_buffer_insert_at_cursor(buffer, "\n\n", 2);
|
| 80 | gtk_text_buffer_get_end_iter(buffer, &end);
|
| 81 | gtk_text_buffer_insert_with_tags(buffer, &end, msg, -1, tag2,
|
| 82 | NULL);
|
| 83 | }
|
| 84 |
|
| 85 | static void text_insert_help(struct menu *menu)
|
| 86 | {
|
| 87 | struct gstr help = str_new();
|
| 88 |
|
| 89 | menu_get_ext_help(menu, &help);
|
| 90 | text_insert_msg(menu_get_prompt(menu), str_get(&help));
|
| 91 | str_free(&help);
|
| 92 | }
|
| 93 |
|
| 94 | static void _select_menu(GtkTreeView *view, GtkTreeModel *model,
|
| 95 | GtkTreeIter *parent, struct menu *match)
|
| 96 | {
|
| 97 | GtkTreeIter iter;
|
| 98 | gboolean valid;
|
| 99 |
|
| 100 | valid = gtk_tree_model_iter_children(model, &iter, parent);
|
| 101 | while (valid) {
|
| 102 | struct menu *menu;
|
| 103 |
|
| 104 | gtk_tree_model_get(model, &iter, COL_MENU, &menu, -1);
|
| 105 |
|
| 106 | if (menu == match) {
|
| 107 | GtkTreeSelection *selection;
|
| 108 | GtkTreePath *path;
|
| 109 |
|
| 110 | |
| 111 | * Expand parents to reflect the selection, and
|
| 112 | * scroll down to it.
|
| 113 |
|
| 114 | path = gtk_tree_model_get_path(model, &iter);
|
| 115 | gtk_tree_view_expand_to_path(view, path);
|
| 116 | gtk_tree_view_scroll_to_cell(view, path, NULL, TRUE,
|
| 117 | 0.5, 0.0);
|
| 118 | gtk_tree_path_free(path);
|
| 119 |
|
| 120 | selection = gtk_tree_view_get_selection(view);
|
| 121 | gtk_tree_selection_select_iter(selection, &iter);
|
| 122 |
|
| 123 | text_insert_help(menu);
|
| 124 | }
|
| 125 |
|
| 126 | _select_menu(view, model, &iter, match);
|
| 127 |
|
| 128 | valid = gtk_tree_model_iter_next(model, &iter);
|
| 129 | }
|
| 130 | }
|
| 131 |
|
| 132 | static void select_menu(GtkTreeView *view, struct menu *match)
|
| 133 | {
|
| 134 | _select_menu(view, gtk_tree_view_get_model(view), NULL, match);
|
| 135 | }
|
| 136 |
|
| 137 | static void _update_row_visibility(GtkTreeView *view)
|
| 138 | {
|
| 139 | GtkTreeModelFilter *filter = GTK_TREE_MODEL_FILTER(gtk_tree_view_get_model(view));
|
| 140 |
|
| 141 | gtk_tree_model_filter_refilter(filter);
|
| 142 | }
|
| 143 |
|
| 144 | static void update_row_visibility(void)
|
| 145 | {
|
| 146 | if (view_mode == SPLIT_VIEW)
|
| 147 | _update_row_visibility(GTK_TREE_VIEW(tree1_w));
|
| 148 | _update_row_visibility(GTK_TREE_VIEW(tree2_w));
|
| 149 | }
|
| 150 |
|
| 151 | static void set_node(GtkTreeStore *tree, GtkTreeIter *node, struct menu *menu)
|
| 152 | {
|
| 153 | struct symbol *sym = menu->sym;
|
| 154 | tristate val;
|
| 155 | gchar *option;
|
| 156 | const gchar *_no = "";
|
| 157 | const gchar *_mod = "";
|
| 158 | const gchar *_yes = "";
|
| 159 | const gchar *value = "";
|
| 160 | GdkRGBA color;
|
| 161 | gboolean editable = FALSE;
|
| 162 | gboolean btnvis = FALSE;
|
| 163 |
|
| 164 | option = g_strdup_printf("%s %s %s %s",
|
| 165 | menu->type == M_COMMENT ? "***" : "",
|
| 166 | menu_get_prompt(menu),
|
| 167 | menu->type == M_COMMENT ? "***" : "",
|
| 168 | sym && !sym_has_value(sym) ? "(NEW)" : "");
|
| 169 |
|
| 170 | gdk_rgba_parse(&color, menu_is_visible(menu) ? "Black" : "DarkGray");
|
| 171 |
|
| 172 | if (!sym)
|
| 173 | goto set;
|
| 174 |
|
| 175 | sym_calc_value(sym);
|
| 176 |
|
| 177 | if (menu->type == M_CHOICE) { |
| 178 | struct symbol *def_sym = sym_calc_choice(menu);
|
| 179 | struct menu *def_menu = NULL;
|
| 180 |
|
| 181 | for (struct menu *child = menu->list; child; child = child->next) {
|
| 182 | if (menu_is_visible(child) && child->sym == def_sym)
|
| 183 | def_menu = child;
|
| 184 | }
|
| 185 |
|
| 186 | if (def_menu)
|
| 187 | value = menu_get_prompt(def_menu);
|
| 188 |
|
| 189 | goto set;
|
| 190 | }
|
| 191 |
|
| 192 | switch (sym_get_type(sym)) {
|
| 193 | case S_BOOLEAN:
|
| 194 | case S_TRISTATE:
|
| 195 |
|
| 196 | btnvis = TRUE;
|
| 197 |
|
| 198 | val = sym_get_tristate_value(sym);
|
| 199 | switch (val) {
|
| 200 | case no:
|
| 201 | _no = "N";
|
| 202 | value = "N";
|
| 203 | break;
|
| 204 | case mod:
|
| 205 | _mod = "M";
|
| 206 | value = "M";
|
| 207 | break;
|
| 208 | case yes:
|
| 209 | _yes = "Y";
|
| 210 | value = "Y";
|
| 211 | break;
|
| 212 | }
|
| 213 |
|
| 214 | if (val != no && sym_tristate_within_range(sym, no))
|
| 215 | _no = "_";
|
| 216 | if (val != mod && sym_tristate_within_range(sym, mod))
|
| 217 | _mod = "_";
|
| 218 | if (val != yes && sym_tristate_within_range(sym, yes))
|
| 219 | _yes = "_";
|
| 220 | break;
|
| 221 | default:
|
| 222 | value = sym_get_string_value(sym);
|
| 223 | editable = TRUE;
|
| 224 | break;
|
| 225 | }
|
| 226 |
|
| 227 | set:
|
| 228 | gtk_tree_store_set(tree, node,
|
| 229 | COL_OPTION, option,
|
| 230 | COL_NAME, sym ? sym->name : "",
|
| 231 | COL_NO, _no,
|
| 232 | COL_MOD, _mod,
|
| 233 | COL_YES, _yes,
|
| 234 | COL_VALUE, value,
|
| 235 | COL_MENU, (gpointer) menu,
|
| 236 | COL_COLOR, &color,
|
| 237 | COL_EDIT, editable,
|
| 238 | COL_PIXBUF, pix_menu,
|
| 239 | COL_PIXVIS, view_mode == SINGLE_VIEW && menu->type == M_MENU,
|
| 240 | COL_BTNVIS, btnvis,
|
| 241 | COL_BTNACT, _yes[0] == 'Y',
|
| 242 | COL_BTNINC, _mod[0] == 'M',
|
| 243 | COL_BTNRAD, sym && sym_is_choice_value(sym),
|
| 244 | -1);
|
| 245 |
|
| 246 | g_free(option);
|
| 247 | }
|
| 248 |
|
| 249 | static void _update_tree(GtkTreeStore *store, GtkTreeIter *parent)
|
| 250 | {
|
| 251 | GtkTreeModel *model = GTK_TREE_MODEL(store);
|
| 252 | GtkTreeIter iter;
|
| 253 | gboolean valid;
|
| 254 |
|
| 255 | valid = gtk_tree_model_iter_children(model, &iter, parent);
|
| 256 | while (valid) {
|
| 257 | struct menu *menu;
|
| 258 |
|
| 259 | gtk_tree_model_get(model, &iter, COL_MENU, &menu, -1);
|
| 260 |
|
| 261 | if (menu)
|
| 262 | set_node(store, &iter, menu);
|
| 263 |
|
| 264 | _update_tree(store, &iter);
|
| 265 |
|
| 266 | valid = gtk_tree_model_iter_next(model, &iter);
|
| 267 | }
|
| 268 | }
|
| 269 |
|
| 270 | static void update_tree(GtkTreeStore *store)
|
| 271 | {
|
| 272 | _update_tree(store, NULL);
|
| 273 | update_row_visibility();
|
| 274 | }
|
| 275 |
|
| 276 | static void update_trees(void)
|
| 277 | {
|
| 278 | if (view_mode == SPLIT_VIEW)
|
| 279 | update_tree(tree1);
|
| 280 | update_tree(tree2);
|
| 281 | }
|
| 282 |
|
| 283 | static void set_view_mode(enum view_mode mode)
|
| 284 | {
|
| 285 | view_mode = mode;
|
| 286 |
|
| 287 | if (mode == SPLIT_VIEW) { |
| 288 | gint w;
|
| 289 |
|
| 290 | gtk_widget_show(tree1_w);
|
| 291 | gtk_window_get_default_size(GTK_WINDOW(main_wnd), &w, NULL);
|
| 292 | gtk_paned_set_position(GTK_PANED(hpaned), w / 2);
|
| 293 | } else {
|
| 294 | gtk_widget_hide(tree1_w);
|
| 295 | gtk_paned_set_position(GTK_PANED(hpaned), 0);
|
| 296 | }
|
| 297 |
|
| 298 | gtk_widget_set_sensitive(single_btn, TRUE);
|
| 299 | gtk_widget_set_sensitive(split_btn, TRUE);
|
| 300 | gtk_widget_set_sensitive(full_btn, TRUE);
|
| 301 |
|
| 302 | switch (mode) {
|
| 303 | case SINGLE_VIEW:
|
| 304 | if (selected)
|
| 305 | browsed = menu_get_parent_menu(selected) ?: &rootmenu;
|
| 306 | else
|
| 307 | browsed = &rootmenu;
|
| 308 | recreate_tree();
|
| 309 | text_insert_msg("", "");
|
| 310 | select_menu(GTK_TREE_VIEW(tree2_w), selected);
|
| 311 | gtk_widget_set_sensitive(single_btn, FALSE);
|
| 312 | break;
|
| 313 | case SPLIT_VIEW:
|
| 314 | browsed = selected;
|
| 315 | while (browsed && !(browsed->flags & MENU_ROOT))
|
| 316 | browsed = browsed->parent;
|
| 317 | gtk_tree_store_clear(tree1);
|
| 318 | display_tree(tree1, &rootmenu);
|
| 319 | gtk_tree_view_expand_all(GTK_TREE_VIEW(tree1_w));
|
| 320 | gtk_tree_store_clear(tree2);
|
| 321 | if (browsed)
|
| 322 | display_tree(tree2, browsed);
|
| 323 | text_insert_msg("", "");
|
| 324 | select_menu(GTK_TREE_VIEW(tree1_w), browsed);
|
| 325 | select_menu(GTK_TREE_VIEW(tree2_w), selected);
|
| 326 | gtk_widget_set_sensitive(split_btn, FALSE);
|
| 327 | break;
|
| 328 | case FULL_VIEW:
|
| 329 | gtk_tree_store_clear(tree2);
|
| 330 | display_tree(tree2, &rootmenu);
|
| 331 | text_insert_msg("", "");
|
| 332 | select_menu(GTK_TREE_VIEW(tree2_w), selected);
|
| 333 | gtk_widget_set_sensitive(full_btn, FALSE);
|
| 334 | break;
|
| 335 | }
|
| 336 |
|
| 337 | gtk_widget_set_sensitive(back_btn,
|
| 338 | mode == SINGLE_VIEW && browsed != &rootmenu);
|
| 339 | }
|
| 340 |
|
| 341 |
|
| 342 |
|
| 343 | static void on_load1_activate(GtkMenuItem *menuitem, gpointer user_data)
|
| 344 | {
|
| 345 | GtkWidget *dialog;
|
| 346 | GtkFileChooser *chooser;
|
| 347 | gint res;
|
| 348 |
|
| 349 | dialog = gtk_file_chooser_dialog_new("Load file...",
|
| 350 | GTK_WINDOW(user_data),
|
| 351 | GTK_FILE_CHOOSER_ACTION_OPEN,
|
| 352 | "_Cancel", GTK_RESPONSE_CANCEL,
|
| 353 | "_Open", GTK_RESPONSE_ACCEPT,
|
| 354 | NULL);
|
| 355 |
|
| 356 | chooser = GTK_FILE_CHOOSER(dialog);
|
| 357 | gtk_file_chooser_set_filename(chooser, conf_get_configname());
|
| 358 |
|
| 359 | res = gtk_dialog_run(GTK_DIALOG(dialog));
|
| 360 | if (res == GTK_RESPONSE_ACCEPT) {
|
| 361 | char *filename;
|
| 362 |
|
| 363 | filename = gtk_file_chooser_get_filename(chooser);
|
| 364 |
|
| 365 | if (conf_read(filename))
|
| 366 | text_insert_msg("Error",
|
| 367 | "Unable to load configuration!");
|
| 368 | else
|
| 369 | update_trees();
|
| 370 |
|
| 371 | g_free(filename);
|
| 372 | }
|
| 373 |
|
| 374 | gtk_widget_destroy(GTK_WIDGET(dialog));
|
| 375 | }
|
| 376 |
|
| 377 | static void on_save_activate(GtkMenuItem *menuitem, gpointer user_data)
|
| 378 | {
|
| 379 | if (conf_write(NULL))
|
| 380 | text_insert_msg("Error", "Unable to save configuration !");
|
| 381 | conf_write_autoconf(0);
|
| 382 | }
|
| 383 |
|
| 384 | static void on_save_as1_activate(GtkMenuItem *menuitem, gpointer user_data)
|
| 385 | {
|
| 386 | GtkWidget *dialog;
|
| 387 | GtkFileChooser *chooser;
|
| 388 | gint res;
|
| 389 |
|
| 390 | dialog = gtk_file_chooser_dialog_new("Save file as...",
|
| 391 | GTK_WINDOW(user_data),
|
| 392 | GTK_FILE_CHOOSER_ACTION_SAVE,
|
| 393 | "_Cancel", GTK_RESPONSE_CANCEL,
|
| 394 | "_Save", GTK_RESPONSE_ACCEPT,
|
| 395 | NULL);
|
| 396 |
|
| 397 | chooser = GTK_FILE_CHOOSER(dialog);
|
| 398 | gtk_file_chooser_set_filename(chooser, conf_get_configname());
|
| 399 |
|
| 400 | res = gtk_dialog_run(GTK_DIALOG(dialog));
|
| 401 | if (res == GTK_RESPONSE_ACCEPT) {
|
| 402 | char *filename;
|
| 403 |
|
| 404 | filename = gtk_file_chooser_get_filename(chooser);
|
| 405 |
|
| 406 | if (conf_write(filename))
|
| 407 | text_insert_msg("Error",
|
| 408 | "Unable to save configuration !");
|
| 409 |
|
| 410 | g_free(filename);
|
| 411 | }
|
| 412 |
|
| 413 | gtk_widget_destroy(dialog);
|
| 414 | }
|
| 415 |
|
| 416 | static void on_show_name1_activate(GtkMenuItem *menuitem, gpointer user_data)
|
| 417 | {
|
| 418 | GtkTreeViewColumn *col;
|
| 419 |
|
| 420 | show_name = gtk_check_menu_item_get_active(GTK_CHECK_MENU_ITEM(menuitem));
|
| 421 | col = gtk_tree_view_get_column(GTK_TREE_VIEW(tree2_w), COL_NAME);
|
| 422 | if (col)
|
| 423 | gtk_tree_view_column_set_visible(col, show_name);
|
| 424 | }
|
| 425 |
|
| 426 | static void on_show_range1_activate(GtkMenuItem *menuitem, gpointer user_data)
|
| 427 | {
|
| 428 | GtkTreeViewColumn *col;
|
| 429 |
|
| 430 | show_range = gtk_check_menu_item_get_active(GTK_CHECK_MENU_ITEM(menuitem));
|
| 431 | col = gtk_tree_view_get_column(GTK_TREE_VIEW(tree2_w), COL_NO);
|
| 432 | if (col)
|
| 433 | gtk_tree_view_column_set_visible(col, show_range);
|
| 434 | col = gtk_tree_view_get_column(GTK_TREE_VIEW(tree2_w), COL_MOD);
|
| 435 | if (col)
|
| 436 | gtk_tree_view_column_set_visible(col, show_range);
|
| 437 | col = gtk_tree_view_get_column(GTK_TREE_VIEW(tree2_w), COL_YES);
|
| 438 | if (col)
|
| 439 | gtk_tree_view_column_set_visible(col, show_range);
|
| 440 |
|
| 441 | }
|
| 442 |
|
| 443 | static void on_show_data1_activate(GtkMenuItem *menuitem, gpointer user_data)
|
| 444 | {
|
| 445 | GtkTreeViewColumn *col;
|
| 446 |
|
| 447 | show_value = gtk_check_menu_item_get_active(GTK_CHECK_MENU_ITEM(menuitem));
|
| 448 | col = gtk_tree_view_get_column(GTK_TREE_VIEW(tree2_w), COL_VALUE);
|
| 449 | if (col)
|
| 450 | gtk_tree_view_column_set_visible(col, show_value);
|
| 451 | }
|
| 452 |
|
| 453 | static void on_set_option_mode1_activate(GtkMenuItem *menuitem,
|
| 454 | gpointer user_data)
|
| 455 | {
|
| 456 | opt_mode = OPT_NORMAL;
|
| 457 | update_row_visibility();
|
| 458 | }
|
| 459 |
|
| 460 | static void on_set_option_mode2_activate(GtkMenuItem *menuitem,
|
| 461 | gpointer user_data)
|
| 462 | {
|
| 463 | opt_mode = OPT_ALL;
|
| 464 | update_row_visibility();
|
| 465 | }
|
| 466 |
|
| 467 | static void on_set_option_mode3_activate(GtkMenuItem *menuitem,
|
| 468 | gpointer user_data)
|
| 469 | {
|
| 470 | opt_mode = OPT_PROMPT;
|
| 471 | update_row_visibility();
|
| 472 | }
|
| 473 |
|
| 474 | static void on_introduction1_activate(GtkMenuItem *menuitem, gpointer user_data)
|
| 475 | {
|
| 476 | GtkWidget *dialog;
|
| 477 | const gchar *intro_text =
|
| 478 | "Welcome to gconfig, the GTK+ graphical configuration tool.\n"
|
| 479 | "For each option, a blank box indicates the feature is disabled, a\n"
|
| 480 | "check indicates it is enabled, and a dot indicates that it is to\n"
|
| 481 | "be compiled as a module. Clicking on the box will cycle through the three states.\n"
|
| 482 | "\n"
|
| 483 | "If you do not see an option (e.g., a device driver) that you\n"
|
| 484 | "believe should be present, try turning on Show All Options\n"
|
| 485 | "under the Options menu.\n"
|
| 486 | "Although there is no cross reference yet to help you figure out\n"
|
| 487 | "what other options must be enabled to support the option you\n"
|
| 488 | "are interested in, you can still view the help of a grayed-out\n"
|
| 489 | "option.";
|
| 490 |
|
| 491 | dialog = gtk_message_dialog_new(GTK_WINDOW(main_wnd),
|
| 492 | GTK_DIALOG_DESTROY_WITH_PARENT,
|
| 493 | GTK_MESSAGE_INFO,
|
| 494 | GTK_BUTTONS_CLOSE, "%s", intro_text);
|
| 495 | gtk_dialog_run(GTK_DIALOG(dialog));
|
| 496 | gtk_widget_destroy(dialog);
|
| 497 | }
|
| 498 |
|
| 499 | static void on_about1_activate(GtkMenuItem *menuitem, gpointer user_data)
|
| 500 | {
|
| 501 | GtkWidget *dialog;
|
| 502 | const gchar *about_text =
|
| 503 | "gconfig is copyright (c) 2002 Romain Lievin <[email protected]>.\n"
|
| 504 | "Based on the source code from Roman Zippel.\n";
|
| 505 |
|
| 506 | dialog = gtk_message_dialog_new(GTK_WINDOW(main_wnd),
|
| 507 | GTK_DIALOG_DESTROY_WITH_PARENT,
|
| 508 | GTK_MESSAGE_INFO,
|
| 509 | GTK_BUTTONS_CLOSE, "%s\nGTK version: %d.%d.%d",
|
| 510 | about_text,
|
| 511 | gtk_get_major_version(),
|
| 512 | gtk_get_minor_version(),
|
| 513 | gtk_get_micro_version());
|
| 514 | gtk_dialog_run(GTK_DIALOG(dialog));
|
| 515 | gtk_widget_destroy(dialog);
|
| 516 | }
|
| 517 |
|
| 518 | static void on_license1_activate(GtkMenuItem *menuitem, gpointer user_data)
|
| 519 | {
|
| 520 | GtkWidget *dialog;
|
| 521 | const gchar *license_text =
|
| 522 | "gconfig is released under the terms of the GNU GPL v2.\n"
|
| 523 | "For more information, please see the source code or\n"
|
| 524 | "visit http://www.fsf.org/licenses/licenses.html\n";
|
| 525 |
|
| 526 | dialog = gtk_message_dialog_new(GTK_WINDOW(main_wnd),
|
| 527 | GTK_DIALOG_DESTROY_WITH_PARENT,
|
| 528 | GTK_MESSAGE_INFO,
|
| 529 | GTK_BUTTONS_CLOSE, "%s", license_text);
|
| 530 | gtk_dialog_run(GTK_DIALOG(dialog));
|
| 531 | gtk_widget_destroy(dialog);
|
| 532 | }
|
| 533 |
|
| 534 |
|
| 535 | static void on_back_clicked(GtkButton *button, gpointer user_data)
|
| 536 | {
|
| 537 | browsed = menu_get_parent_menu(browsed) ?: &rootmenu;
|
| 538 |
|
| 539 | recreate_tree();
|
| 540 |
|
| 541 | if (browsed == &rootmenu)
|
| 542 | gtk_widget_set_sensitive(back_btn, FALSE);
|
| 543 | }
|
| 544 |
|
| 545 | static void on_load_clicked(GtkButton *button, gpointer user_data)
|
| 546 | {
|
| 547 | on_load1_activate(NULL, user_data);
|
| 548 | }
|
| 549 |
|
| 550 | static void on_save_clicked(GtkButton *button, gpointer user_data)
|
| 551 | {
|
| 552 | on_save_activate(NULL, user_data);
|
| 553 | }
|
| 554 |
|
| 555 | static void on_single_clicked(GtkButton *button, gpointer user_data)
|
| 556 | {
|
| 557 | set_view_mode(SINGLE_VIEW);
|
| 558 | }
|
| 559 |
|
| 560 | static void on_split_clicked(GtkButton *button, gpointer user_data)
|
| 561 | {
|
| 562 | set_view_mode(SPLIT_VIEW);
|
| 563 | }
|
| 564 |
|
| 565 | static void on_full_clicked(GtkButton *button, gpointer user_data)
|
| 566 | {
|
| 567 | set_view_mode(FULL_VIEW);
|
| 568 | }
|
| 569 |
|
| 570 | static void on_collapse_clicked(GtkButton *button, gpointer user_data)
|
| 571 | {
|
| 572 | gtk_tree_view_collapse_all(GTK_TREE_VIEW(tree2_w));
|
| 573 | }
|
| 574 |
|
| 575 | static void on_expand_clicked(GtkButton *button, gpointer user_data)
|
| 576 | {
|
| 577 | gtk_tree_view_expand_all(GTK_TREE_VIEW(tree2_w));
|
| 578 | }
|
| 579 |
|
| 580 |
|
| 581 |
|
| 582 | static void on_window1_destroy(GtkWidget *widget, gpointer user_data)
|
| 583 | {
|
| 584 | gtk_main_quit();
|
| 585 | }
|
| 586 |
|
| 587 | static gboolean on_window1_configure(GtkWidget *self,
|
| 588 | GdkEventConfigure *event,
|
| 589 | gpointer user_data)
|
| 590 | {
|
| 591 | gtk_paned_set_position(GTK_PANED(vpaned), 2 * event->height / 3);
|
| 592 | return FALSE;
|
| 593 | }
|
| 594 |
|
| 595 | static gboolean on_window1_delete_event(GtkWidget *widget, GdkEvent *event,
|
| 596 | gpointer user_data)
|
| 597 | {
|
| 598 | GtkWidget *dialog, *label, *content_area;
|
| 599 | gint result;
|
| 600 | gint ret = FALSE;
|
| 601 |
|
| 602 | if (!conf_get_changed())
|
| 603 | return FALSE;
|
| 604 |
|
| 605 | dialog = gtk_dialog_new_with_buttons("Warning !",
|
| 606 | GTK_WINDOW(main_wnd),
|
| 607 | (GtkDialogFlags)
|
| 608 | (GTK_DIALOG_MODAL |
|
| 609 | GTK_DIALOG_DESTROY_WITH_PARENT),
|
| 610 | "_OK",
|
| 611 | GTK_RESPONSE_YES,
|
| 612 | "_No",
|
| 613 | GTK_RESPONSE_NO,
|
| 614 | "_Cancel",
|
| 615 | GTK_RESPONSE_CANCEL, NULL);
|
| 616 | gtk_dialog_set_default_response(GTK_DIALOG(dialog),
|
| 617 | GTK_RESPONSE_CANCEL);
|
| 618 |
|
| 619 | label = gtk_label_new("\nSave configuration ?\n");
|
| 620 | content_area = gtk_dialog_get_content_area(GTK_DIALOG(dialog));
|
| 621 | gtk_container_add(GTK_CONTAINER(content_area), label);
|
| 622 | gtk_widget_show(label);
|
| 623 |
|
| 624 | result = gtk_dialog_run(GTK_DIALOG(dialog));
|
| 625 | switch (result) {
|
| 626 | case GTK_RESPONSE_YES:
|
| 627 | on_save_activate(NULL, NULL);
|
| 628 | break;
|
| 629 | case GTK_RESPONSE_NO:
|
| 630 | break;
|
| 631 | case GTK_RESPONSE_CANCEL:
|
| 632 | case GTK_RESPONSE_DELETE_EVENT:
|
| 633 | default:
|
| 634 | ret = TRUE;
|
| 635 | break;
|
| 636 | }
|
| 637 |
|
| 638 | gtk_widget_destroy(dialog);
|
| 639 |
|
| 640 | if (!ret)
|
| 641 | g_object_unref(pix_menu);
|
| 642 |
|
| 643 | return ret;
|
| 644 | }
|
| 645 |
|
| 646 | static void on_quit1_activate(GtkMenuItem *menuitem, gpointer user_data)
|
| 647 | {
|
| 648 | if (!on_window1_delete_event(NULL, NULL, NULL))
|
| 649 | gtk_widget_destroy(GTK_WIDGET(main_wnd));
|
| 650 | }
|
| 651 |
|
| 652 |
|
| 653 |
|
| 654 |
|
| 655 | static void renderer_edited(GtkCellRendererText * cell,
|
| 656 | const gchar * path_string,
|
| 657 | const gchar * new_text, gpointer user_data)
|
| 658 | {
|
| 659 | GtkTreeView *view = GTK_TREE_VIEW(user_data);
|
| 660 | GtkTreeModel *model = gtk_tree_view_get_model(view);
|
| 661 | GtkTreePath *path = gtk_tree_path_new_from_string(path_string);
|
| 662 | GtkTreeIter iter;
|
| 663 | const char *old_def, *new_def;
|
| 664 | struct menu *menu;
|
| 665 | struct symbol *sym;
|
| 666 |
|
| 667 | if (!gtk_tree_model_get_iter(model, &iter, path))
|
| 668 | goto free;
|
| 669 |
|
| 670 | gtk_tree_model_get(model, &iter, COL_MENU, &menu, -1);
|
| 671 | sym = menu->sym;
|
| 672 |
|
| 673 | gtk_tree_model_get(model, &iter, COL_VALUE, &old_def, -1);
|
| 674 | new_def = new_text;
|
| 675 |
|
| 676 | sym_set_string_value(sym, new_def);
|
| 677 |
|
| 678 | update_trees();
|
| 679 |
|
| 680 | free:
|
| 681 | gtk_tree_path_free(path);
|
| 682 | }
|
| 683 |
|
| 684 |
|
| 685 | static void change_sym_value(struct menu *menu, gint col)
|
| 686 | {
|
| 687 | struct symbol *sym = menu->sym;
|
| 688 | tristate newval;
|
| 689 |
|
| 690 | if (!sym)
|
| 691 | return;
|
| 692 |
|
| 693 | if (col == COL_NO)
|
| 694 | newval = no;
|
| 695 | else if (col == COL_MOD)
|
| 696 | newval = mod;
|
| 697 | else if (col == COL_YES)
|
| 698 | newval = yes;
|
| 699 | else
|
| 700 | return;
|
| 701 |
|
| 702 | switch (sym_get_type(sym)) {
|
| 703 | case S_BOOLEAN:
|
| 704 | case S_TRISTATE:
|
| 705 | if (!sym_tristate_within_range(sym, newval))
|
| 706 | newval = yes;
|
| 707 | sym_set_tristate_value(sym, newval);
|
| 708 | update_trees();
|
| 709 | break;
|
| 710 | case S_INT:
|
| 711 | case S_HEX:
|
| 712 | case S_STRING:
|
| 713 | default:
|
| 714 | break;
|
| 715 | }
|
| 716 | }
|
| 717 |
|
| 718 | static void toggle_sym_value(struct menu *menu)
|
| 719 | {
|
| 720 | if (!menu->sym)
|
| 721 | return;
|
| 722 |
|
| 723 | sym_toggle_tristate_value(menu->sym);
|
| 724 | update_trees();
|
| 725 | }
|
| 726 |
|
| 727 | static gint column2index(GtkTreeViewColumn * column)
|
| 728 | {
|
| 729 | gint i;
|
| 730 |
|
| 731 | for (i = 0; i < COL_NUMBER; i++) {
|
| 732 | GtkTreeViewColumn *col;
|
| 733 |
|
| 734 | col = gtk_tree_view_get_column(GTK_TREE_VIEW(tree2_w), i);
|
| 735 | if (col == column)
|
| 736 | return i;
|
| 737 | }
|
| 738 |
|
| 739 | return -1;
|
| 740 | }
|
| 741 |
|
| 742 |
|
| 743 |
|
| 744 | static gboolean on_treeview2_button_press_event(GtkWidget *widget,
|
| 745 | GdkEventButton *event,
|
| 746 | gpointer user_data)
|
| 747 | {
|
| 748 | GtkTreeView *view = GTK_TREE_VIEW(widget);
|
| 749 | GtkTreeModel *model = gtk_tree_view_get_model(view);
|
| 750 | GtkTreePath *path;
|
| 751 | GtkTreeViewColumn *column;
|
| 752 | GtkTreeIter iter;
|
| 753 | struct menu *menu;
|
| 754 | gint col;
|
| 755 | gint tx = (gint) event->x;
|
| 756 | gint ty = (gint) event->y;
|
| 757 |
|
| 758 | gtk_tree_view_get_path_at_pos(view, tx, ty, &path, &column, NULL, NULL);
|
| 759 | if (path == NULL)
|
| 760 | return FALSE;
|
| 761 |
|
| 762 | if (!gtk_tree_model_get_iter(model, &iter, path))
|
| 763 | return FALSE;
|
| 764 | gtk_tree_model_get(model, &iter, COL_MENU, &menu, -1);
|
| 765 |
|
| 766 | selected = menu;
|
| 767 |
|
| 768 | col = column2index(column);
|
| 769 | if (event->type == GDK_2BUTTON_PRESS) {
|
| 770 | enum prop_type ptype;
|
| 771 | ptype = menu->prompt ? menu->prompt->type : P_UNKNOWN;
|
| 772 |
|
| 773 | if (ptype == P_MENU && view_mode == SINGLE_VIEW && col == COL_OPTION) {
|
| 774 | |
| 775 | browsed = menu;
|
| 776 | recreate_tree();
|
| 777 | gtk_widget_set_sensitive(back_btn, TRUE);
|
| 778 | } else if (col == COL_OPTION) {
|
| 779 | toggle_sym_value(menu);
|
| 780 | gtk_tree_view_expand_row(view, path, TRUE);
|
| 781 | }
|
| 782 | } else {
|
| 783 | if (col == COL_VALUE) {
|
| 784 | toggle_sym_value(menu);
|
| 785 | gtk_tree_view_expand_row(view, path, TRUE);
|
| 786 | } else if (col == COL_NO || col == COL_MOD
|
| 787 | || col == COL_YES) {
|
| 788 | change_sym_value(menu, col);
|
| 789 | gtk_tree_view_expand_row(view, path, TRUE);
|
| 790 | }
|
| 791 | }
|
| 792 |
|
| 793 | return FALSE;
|
| 794 | }
|
| 795 |
|
| 796 |
|
| 797 | static gboolean on_treeview2_key_press_event(GtkWidget *widget,
|
| 798 | GdkEventKey *event,
|
| 799 | gpointer user_data)
|
| 800 | {
|
| 801 | GtkTreeView *view = GTK_TREE_VIEW(widget);
|
| 802 | GtkTreeModel *model = gtk_tree_view_get_model(view);
|
| 803 | GtkTreePath *path;
|
| 804 | GtkTreeIter iter;
|
| 805 | struct menu *menu;
|
| 806 | gint col;
|
| 807 |
|
| 808 | gtk_tree_view_get_cursor(view, &path, NULL);
|
| 809 | if (path == NULL)
|
| 810 | return FALSE;
|
| 811 |
|
| 812 | if (event->keyval == GDK_KEY_space) {
|
| 813 | if (gtk_tree_view_row_expanded(view, path))
|
| 814 | gtk_tree_view_collapse_row(view, path);
|
| 815 | else
|
| 816 | gtk_tree_view_expand_row(view, path, FALSE);
|
| 817 | return TRUE;
|
| 818 | }
|
| 819 |
|
| 820 | gtk_tree_model_get_iter(model, &iter, path);
|
| 821 | gtk_tree_model_get(model, &iter, COL_MENU, &menu, -1);
|
| 822 |
|
| 823 | if (!strcasecmp(event->string, "n"))
|
| 824 | col = COL_NO;
|
| 825 | else if (!strcasecmp(event->string, "m"))
|
| 826 | col = COL_MOD;
|
| 827 | else if (!strcasecmp(event->string, "y"))
|
| 828 | col = COL_YES;
|
| 829 | else
|
| 830 | col = -1;
|
| 831 | change_sym_value(menu, col);
|
| 832 |
|
| 833 | return FALSE;
|
| 834 | }
|
| 835 |
|
| 836 |
|
| 837 |
|
| 838 | static void on_treeview2_cursor_changed(GtkTreeView *treeview,
|
| 839 | gpointer user_data)
|
| 840 | {
|
| 841 | GtkTreeModel *model = gtk_tree_view_get_model(treeview);
|
| 842 | GtkTreeSelection *selection;
|
| 843 | GtkTreeIter iter;
|
| 844 | struct menu *menu;
|
| 845 |
|
| 846 | selection = gtk_tree_view_get_selection(treeview);
|
| 847 | if (gtk_tree_selection_get_selected(selection, &model, &iter)) {
|
| 848 | gtk_tree_model_get(model, &iter, COL_MENU, &menu, -1);
|
| 849 | text_insert_help(menu);
|
| 850 | }
|
| 851 | }
|
| 852 |
|
| 853 |
|
| 854 |
|
| 855 | static gboolean on_treeview1_button_press_event(GtkWidget *widget,
|
| 856 | GdkEventButton *event,
|
| 857 | gpointer user_data)
|
| 858 | {
|
| 859 | GtkTreeView *view = GTK_TREE_VIEW(widget);
|
| 860 | GtkTreeModel *model = gtk_tree_view_get_model(view);
|
| 861 | GtkTreePath *path;
|
| 862 | GtkTreeIter iter;
|
| 863 | struct menu *menu;
|
| 864 | gint tx = (gint) event->x;
|
| 865 | gint ty = (gint) event->y;
|
| 866 |
|
| 867 | gtk_tree_view_get_path_at_pos(view, tx, ty, &path, NULL, NULL, NULL);
|
| 868 | if (path == NULL)
|
| 869 | return FALSE;
|
| 870 |
|
| 871 | gtk_tree_model_get_iter(model, &iter, path);
|
| 872 | gtk_tree_model_get(model, &iter, COL_MENU, &menu, -1);
|
| 873 |
|
| 874 | if (event->type == GDK_2BUTTON_PRESS)
|
| 875 | toggle_sym_value(menu);
|
| 876 |
|
| 877 | selected = menu;
|
| 878 |
|
| 879 | if (menu->type == M_MENU) {
|
| 880 | browsed = menu;
|
| 881 | recreate_tree();
|
| 882 | }
|
| 883 |
|
| 884 | gtk_tree_view_set_cursor(view, path, NULL, FALSE);
|
| 885 | gtk_widget_grab_focus(tree2_w);
|
| 886 |
|
| 887 | return FALSE;
|
| 888 | }
|
| 889 |
|
| 890 |
|
| 891 | static void _display_tree(GtkTreeStore *tree, struct menu *menu,
|
| 892 | GtkTreeIter *parent)
|
| 893 | {
|
| 894 | struct menu *child;
|
| 895 | GtkTreeIter iter;
|
| 896 |
|
| 897 | for (child = menu->list; child; child = child->next) {
|
| 898 | |
| 899 | * REVISIT:
|
| 900 | * menu_finalize() creates empty "if" entries.
|
| 901 | * Do not confuse gtk_tree_model_get(), which would otherwise
|
| 902 | * return "if" menu entry.
|
| 903 |
|
| 904 | if (child->type == M_IF)
|
| 905 | continue;
|
| 906 |
|
| 907 | if ((view_mode == SPLIT_VIEW)
|
| 908 | && !(child->flags & MENU_ROOT) && (tree == tree1))
|
| 909 | continue;
|
| 910 |
|
| 911 | if ((view_mode == SPLIT_VIEW) && (child->flags & MENU_ROOT)
|
| 912 | && (tree == tree2))
|
| 913 | continue;
|
| 914 |
|
| 915 | gtk_tree_store_append(tree, &iter, parent);
|
| 916 | set_node(tree, &iter, child);
|
| 917 |
|
| 918 | if (view_mode != SINGLE_VIEW || child->type != M_MENU)
|
| 919 | _display_tree(tree, child, &iter);
|
| 920 | }
|
| 921 | }
|
| 922 |
|
| 923 | static void display_tree(GtkTreeStore *store, struct menu *menu)
|
| 924 | {
|
| 925 | _display_tree(store, menu, NULL);
|
| 926 | }
|
| 927 |
|
| 928 |
|
| 929 | static void recreate_tree(void)
|
| 930 | {
|
| 931 | gtk_tree_store_clear(tree2);
|
| 932 | display_tree(tree2, browsed);
|
| 933 | gtk_tree_view_expand_all(GTK_TREE_VIEW(tree2_w));
|
| 934 | }
|
| 935 |
|
| 936 | static void fixup_rootmenu(struct menu *menu)
|
| 937 | {
|
| 938 | struct menu *child;
|
| 939 | static int menu_cnt = 0;
|
| 940 |
|
| 941 | menu->flags |= MENU_ROOT;
|
| 942 | for (child = menu->list; child; child = child->next) {
|
| 943 | if (child->prompt && child->prompt->type == P_MENU) {
|
| 944 | menu_cnt++;
|
| 945 | fixup_rootmenu(child);
|
| 946 | menu_cnt--;
|
| 947 | } else if (!menu_cnt)
|
| 948 | fixup_rootmenu(child);
|
| 949 | }
|
| 950 | }
|
| 951 |
|
| 952 |
|
| 953 | static void replace_button_icon(GtkWidget *widget, const char *filename)
|
| 954 | {
|
| 955 | GdkPixbuf *pixbuf;
|
| 956 | GtkWidget *image;
|
| 957 | GError *err = NULL;
|
| 958 |
|
| 959 | char *env = getenv(SRCTREE);
|
| 960 | gchar *path = g_strconcat(env ? env : g_get_current_dir(), "/scripts/kconfig/icons/", filename, NULL);
|
| 961 |
|
| 962 | pixbuf = gdk_pixbuf_new_from_file(path, &err);
|
| 963 | g_free(path);
|
| 964 |
|
| 965 | if (err) {
|
| 966 | g_warning("Failed to load icon %s: %s", filename, err->message);
|
| 967 | g_error_free(err);
|
| 968 | return;
|
| 969 | }
|
| 970 |
|
| 971 | image = gtk_image_new_from_pixbuf(pixbuf);
|
| 972 | g_object_unref(pixbuf);
|
| 973 |
|
| 974 | gtk_widget_show(image);
|
| 975 | gtk_tool_button_set_icon_widget(GTK_TOOL_BUTTON(widget), image);
|
| 976 | }
|
| 977 |
|
| 978 | static void init_main_window(const gchar *glade_file)
|
| 979 | {
|
| 980 | GtkBuilder *builder;
|
| 981 | GtkWidget *widget;
|
| 982 | GtkTextBuffer *txtbuf;
|
| 983 |
|
| 984 | builder = gtk_builder_new_from_file(glade_file);
|
| 985 | if (!builder)
|
| 986 | g_error("GUI loading failed !\n");
|
| 987 |
|
| 988 | main_wnd = GTK_WIDGET(gtk_builder_get_object(builder, "window1"));
|
| 989 | g_signal_connect(main_wnd, "destroy",
|
| 990 | G_CALLBACK(on_window1_destroy), NULL);
|
| 991 | g_signal_connect(main_wnd, "configure-event",
|
| 992 | G_CALLBACK(on_window1_configure), NULL);
|
| 993 | g_signal_connect(main_wnd, "delete-event",
|
| 994 | G_CALLBACK(on_window1_delete_event), NULL);
|
| 995 |
|
| 996 | hpaned = GTK_WIDGET(gtk_builder_get_object(builder, "hpaned1"));
|
| 997 | vpaned = GTK_WIDGET(gtk_builder_get_object(builder, "vpaned1"));
|
| 998 | tree1_w = GTK_WIDGET(gtk_builder_get_object(builder, "treeview1"));
|
| 999 | g_signal_connect(tree1_w, "cursor-changed",
|
| 1000 | G_CALLBACK(on_treeview2_cursor_changed), NULL);
|
| 1001 | g_signal_connect(tree1_w, "button-press-event",
|
| 1002 | G_CALLBACK(on_treeview1_button_press_event), NULL);
|
| 1003 | g_signal_connect(tree1_w, "key-press-event",
|
| 1004 | G_CALLBACK(on_treeview2_key_press_event), NULL);
|
| 1005 |
|
| 1006 | tree2_w = GTK_WIDGET(gtk_builder_get_object(builder, "treeview2"));
|
| 1007 | g_signal_connect(tree2_w, "cursor-changed",
|
| 1008 | G_CALLBACK(on_treeview2_cursor_changed), NULL);
|
| 1009 | g_signal_connect(tree2_w, "button-press-event",
|
| 1010 | G_CALLBACK(on_treeview2_button_press_event), NULL);
|
| 1011 | g_signal_connect(tree2_w, "key-press-event",
|
| 1012 | G_CALLBACK(on_treeview2_key_press_event), NULL);
|
| 1013 |
|
| 1014 | text_w = GTK_WIDGET(gtk_builder_get_object(builder, "textview3"));
|
| 1015 |
|
| 1016 |
|
| 1017 | widget = GTK_WIDGET(gtk_builder_get_object(builder, "load1"));
|
| 1018 | g_signal_connect(widget, "activate",
|
| 1019 | G_CALLBACK(on_load1_activate), NULL);
|
| 1020 |
|
| 1021 | save_menu_item = GTK_WIDGET(gtk_builder_get_object(builder, "save1"));
|
| 1022 | g_signal_connect(save_menu_item, "activate",
|
| 1023 | G_CALLBACK(on_save_activate), NULL);
|
| 1024 |
|
| 1025 | widget = GTK_WIDGET(gtk_builder_get_object(builder, "save_as1"));
|
| 1026 | g_signal_connect(widget, "activate",
|
| 1027 | G_CALLBACK(on_save_as1_activate), NULL);
|
| 1028 |
|
| 1029 | widget = GTK_WIDGET(gtk_builder_get_object(builder, "quit1"));
|
| 1030 | g_signal_connect(widget, "activate",
|
| 1031 | G_CALLBACK(on_quit1_activate), NULL);
|
| 1032 |
|
| 1033 | widget = GTK_WIDGET(gtk_builder_get_object(builder, "show_name1"));
|
| 1034 | g_signal_connect(widget, "activate",
|
| 1035 | G_CALLBACK(on_show_name1_activate), NULL);
|
| 1036 | gtk_check_menu_item_set_active((GtkCheckMenuItem *) widget,
|
| 1037 | show_name);
|
| 1038 |
|
| 1039 | widget = GTK_WIDGET(gtk_builder_get_object(builder, "show_range1"));
|
| 1040 | g_signal_connect(widget, "activate",
|
| 1041 | G_CALLBACK(on_show_range1_activate), NULL);
|
| 1042 | gtk_check_menu_item_set_active((GtkCheckMenuItem *) widget,
|
| 1043 | show_range);
|
| 1044 |
|
| 1045 | widget = GTK_WIDGET(gtk_builder_get_object(builder, "show_data1"));
|
| 1046 | g_signal_connect(widget, "activate",
|
| 1047 | G_CALLBACK(on_show_data1_activate), NULL);
|
| 1048 | gtk_check_menu_item_set_active((GtkCheckMenuItem *) widget,
|
| 1049 | show_value);
|
| 1050 |
|
| 1051 | widget = GTK_WIDGET(gtk_builder_get_object(builder, "set_option_mode1"));
|
| 1052 | g_signal_connect(widget, "activate",
|
| 1053 | G_CALLBACK(on_set_option_mode1_activate), NULL);
|
| 1054 |
|
| 1055 | widget = GTK_WIDGET(gtk_builder_get_object(builder, "set_option_mode2"));
|
| 1056 | g_signal_connect(widget, "activate",
|
| 1057 | G_CALLBACK(on_set_option_mode2_activate), NULL);
|
| 1058 |
|
| 1059 | widget = GTK_WIDGET(gtk_builder_get_object(builder, "set_option_mode3"));
|
| 1060 | g_signal_connect(widget, "activate",
|
| 1061 | G_CALLBACK(on_set_option_mode3_activate), NULL);
|
| 1062 |
|
| 1063 | widget = GTK_WIDGET(gtk_builder_get_object(builder, "introduction1"));
|
| 1064 | g_signal_connect(widget, "activate",
|
| 1065 | G_CALLBACK(on_introduction1_activate), NULL);
|
| 1066 |
|
| 1067 | widget = GTK_WIDGET(gtk_builder_get_object(builder, "about1"));
|
| 1068 | g_signal_connect(widget, "activate",
|
| 1069 | G_CALLBACK(on_about1_activate), NULL);
|
| 1070 |
|
| 1071 | widget = GTK_WIDGET(gtk_builder_get_object(builder, "license1"));
|
| 1072 | g_signal_connect(widget, "activate",
|
| 1073 | G_CALLBACK(on_license1_activate), NULL);
|
| 1074 |
|
| 1075 |
|
| 1076 | back_btn = GTK_WIDGET(gtk_builder_get_object(builder, "button1"));
|
| 1077 | g_signal_connect(back_btn, "clicked",
|
| 1078 | G_CALLBACK(on_back_clicked), NULL);
|
| 1079 | gtk_widget_set_sensitive(back_btn, FALSE);
|
| 1080 |
|
| 1081 | widget = GTK_WIDGET(gtk_builder_get_object(builder, "button2"));
|
| 1082 | g_signal_connect(widget, "clicked",
|
| 1083 | G_CALLBACK(on_load_clicked), NULL);
|
| 1084 |
|
| 1085 | save_btn = GTK_WIDGET(gtk_builder_get_object(builder, "button3"));
|
| 1086 | g_signal_connect(save_btn, "clicked",
|
| 1087 | G_CALLBACK(on_save_clicked), NULL);
|
| 1088 |
|
| 1089 | single_btn = GTK_WIDGET(gtk_builder_get_object(builder, "button4"));
|
| 1090 | g_signal_connect(single_btn, "clicked",
|
| 1091 | G_CALLBACK(on_single_clicked), NULL);
|
| 1092 | replace_button_icon(single_btn, "single_view.xpm");
|
| 1093 |
|
| 1094 | split_btn = GTK_WIDGET(gtk_builder_get_object(builder, "button5"));
|
| 1095 | g_signal_connect(split_btn, "clicked",
|
| 1096 | G_CALLBACK(on_split_clicked), NULL);
|
| 1097 | replace_button_icon(split_btn, "split_view.xpm");
|
| 1098 |
|
| 1099 | full_btn = GTK_WIDGET(gtk_builder_get_object(builder, "button6"));
|
| 1100 | g_signal_connect(full_btn, "clicked",
|
| 1101 | G_CALLBACK(on_full_clicked), NULL);
|
| 1102 | replace_button_icon(full_btn, "tree_view.xpm");
|
| 1103 |
|
| 1104 | widget = GTK_WIDGET(gtk_builder_get_object(builder, "button7"));
|
| 1105 | g_signal_connect(widget, "clicked",
|
| 1106 | G_CALLBACK(on_collapse_clicked), NULL);
|
| 1107 |
|
| 1108 | widget = GTK_WIDGET(gtk_builder_get_object(builder, "button8"));
|
| 1109 | g_signal_connect(widget, "clicked",
|
| 1110 | G_CALLBACK(on_expand_clicked), NULL);
|
| 1111 |
|
| 1112 | txtbuf = gtk_text_view_get_buffer(GTK_TEXT_VIEW(text_w));
|
| 1113 | tag1 = gtk_text_buffer_create_tag(txtbuf, "mytag1",
|
| 1114 | "foreground", "red",
|
| 1115 | "weight", PANGO_WEIGHT_BOLD,
|
| 1116 | NULL);
|
| 1117 | tag2 = gtk_text_buffer_create_tag(txtbuf, "mytag2",
|
| 1118 |
|
| 1119 | NULL);
|
| 1120 |
|
| 1121 | gtk_window_set_title(GTK_WINDOW(main_wnd), rootmenu.prompt->text);
|
| 1122 |
|
| 1123 | gtk_widget_show_all(main_wnd);
|
| 1124 |
|
| 1125 | g_object_unref(builder);
|
| 1126 |
|
| 1127 | conf_set_changed_callback(conf_changed);
|
| 1128 | }
|
| 1129 |
|
| 1130 | static gboolean visible_func(GtkTreeModel *model, GtkTreeIter *iter,
|
| 1131 | gpointer data)
|
| 1132 | {
|
| 1133 | struct menu *menu;
|
| 1134 |
|
| 1135 | gtk_tree_model_get(model, iter, COL_MENU, &menu, -1);
|
| 1136 |
|
| 1137 | if (!menu)
|
| 1138 | return FALSE;
|
| 1139 |
|
| 1140 | return menu_is_visible(menu) || opt_mode == OPT_ALL ||
|
| 1141 | (opt_mode == OPT_PROMPT && menu_has_prompt(menu));
|
| 1142 | }
|
| 1143 |
|
| 1144 | static void init_left_tree(void)
|
| 1145 | {
|
| 1146 | GtkTreeView *view = GTK_TREE_VIEW(tree1_w);
|
| 1147 | GtkCellRenderer *renderer;
|
| 1148 | GtkTreeSelection *sel;
|
| 1149 | GtkTreeViewColumn *column;
|
| 1150 | GtkTreeModel *filter;
|
| 1151 |
|
| 1152 | tree1 = gtk_tree_store_new(COL_NUMBER,
|
| 1153 | G_TYPE_STRING, G_TYPE_STRING,
|
| 1154 | G_TYPE_STRING, G_TYPE_STRING,
|
| 1155 | G_TYPE_STRING, G_TYPE_STRING,
|
| 1156 | G_TYPE_POINTER, GDK_TYPE_RGBA,
|
| 1157 | G_TYPE_BOOLEAN, GDK_TYPE_PIXBUF,
|
| 1158 | G_TYPE_BOOLEAN, G_TYPE_BOOLEAN,
|
| 1159 | G_TYPE_BOOLEAN, G_TYPE_BOOLEAN,
|
| 1160 | G_TYPE_BOOLEAN);
|
| 1161 |
|
| 1162 | filter = gtk_tree_model_filter_new(GTK_TREE_MODEL(tree1), NULL);
|
| 1163 |
|
| 1164 | gtk_tree_model_filter_set_visible_func(GTK_TREE_MODEL_FILTER(filter),
|
| 1165 | visible_func, NULL, NULL);
|
| 1166 | gtk_tree_view_set_model(view, filter);
|
| 1167 |
|
| 1168 | column = gtk_tree_view_column_new();
|
| 1169 | gtk_tree_view_append_column(view, column);
|
| 1170 | gtk_tree_view_column_set_title(column, "Options");
|
| 1171 |
|
| 1172 | renderer = gtk_cell_renderer_toggle_new();
|
| 1173 | gtk_tree_view_column_pack_start(GTK_TREE_VIEW_COLUMN(column),
|
| 1174 | renderer, FALSE);
|
| 1175 | gtk_tree_view_column_set_attributes(GTK_TREE_VIEW_COLUMN(column),
|
| 1176 | renderer,
|
| 1177 | "active", COL_BTNACT,
|
| 1178 | "inconsistent", COL_BTNINC,
|
| 1179 | "visible", COL_BTNVIS,
|
| 1180 | "radio", COL_BTNRAD, NULL);
|
| 1181 | renderer = gtk_cell_renderer_text_new();
|
| 1182 | gtk_tree_view_column_pack_start(GTK_TREE_VIEW_COLUMN(column),
|
| 1183 | renderer, FALSE);
|
| 1184 | gtk_tree_view_column_set_attributes(GTK_TREE_VIEW_COLUMN(column),
|
| 1185 | renderer,
|
| 1186 | "text", COL_OPTION,
|
| 1187 | "foreground-rgba",
|
| 1188 | COL_COLOR, NULL);
|
| 1189 |
|
| 1190 | sel = gtk_tree_view_get_selection(view);
|
| 1191 | gtk_tree_selection_set_mode(sel, GTK_SELECTION_SINGLE);
|
| 1192 | }
|
| 1193 |
|
| 1194 | static void init_right_tree(void)
|
| 1195 | {
|
| 1196 | GtkTreeView *view = GTK_TREE_VIEW(tree2_w);
|
| 1197 | GtkCellRenderer *renderer;
|
| 1198 | GtkTreeSelection *sel;
|
| 1199 | GtkTreeViewColumn *column;
|
| 1200 | GtkTreeModel *filter;
|
| 1201 | gint i;
|
| 1202 |
|
| 1203 | tree2 = gtk_tree_store_new(COL_NUMBER,
|
| 1204 | G_TYPE_STRING, G_TYPE_STRING,
|
| 1205 | G_TYPE_STRING, G_TYPE_STRING,
|
| 1206 | G_TYPE_STRING, G_TYPE_STRING,
|
| 1207 | G_TYPE_POINTER, GDK_TYPE_RGBA,
|
| 1208 | G_TYPE_BOOLEAN, GDK_TYPE_PIXBUF,
|
| 1209 | G_TYPE_BOOLEAN, G_TYPE_BOOLEAN,
|
| 1210 | G_TYPE_BOOLEAN, G_TYPE_BOOLEAN,
|
| 1211 | G_TYPE_BOOLEAN);
|
| 1212 |
|
| 1213 | filter = gtk_tree_model_filter_new(GTK_TREE_MODEL(tree2), NULL);
|
| 1214 |
|
| 1215 | gtk_tree_model_filter_set_visible_func(GTK_TREE_MODEL_FILTER(filter),
|
| 1216 | visible_func, NULL, NULL);
|
| 1217 | gtk_tree_view_set_model(view, filter);
|
| 1218 |
|
| 1219 | column = gtk_tree_view_column_new();
|
| 1220 | gtk_tree_view_append_column(view, column);
|
| 1221 | gtk_tree_view_column_set_title(column, "Options");
|
| 1222 |
|
| 1223 | renderer = gtk_cell_renderer_pixbuf_new();
|
| 1224 | gtk_tree_view_column_pack_start(GTK_TREE_VIEW_COLUMN(column),
|
| 1225 | renderer, FALSE);
|
| 1226 | gtk_tree_view_column_set_attributes(GTK_TREE_VIEW_COLUMN(column),
|
| 1227 | renderer,
|
| 1228 | "pixbuf", COL_PIXBUF,
|
| 1229 | "visible", COL_PIXVIS, NULL);
|
| 1230 | renderer = gtk_cell_renderer_toggle_new();
|
| 1231 | gtk_tree_view_column_pack_start(GTK_TREE_VIEW_COLUMN(column),
|
| 1232 | renderer, FALSE);
|
| 1233 | gtk_tree_view_column_set_attributes(GTK_TREE_VIEW_COLUMN(column),
|
| 1234 | renderer,
|
| 1235 | "active", COL_BTNACT,
|
| 1236 | "inconsistent", COL_BTNINC,
|
| 1237 | "visible", COL_BTNVIS,
|
| 1238 | "radio", COL_BTNRAD, NULL);
|
| 1239 | renderer = gtk_cell_renderer_text_new();
|
| 1240 | gtk_tree_view_column_pack_start(GTK_TREE_VIEW_COLUMN(column),
|
| 1241 | renderer, FALSE);
|
| 1242 | gtk_tree_view_column_set_attributes(GTK_TREE_VIEW_COLUMN(column),
|
| 1243 | renderer,
|
| 1244 | "text", COL_OPTION,
|
| 1245 | "foreground-rgba",
|
| 1246 | COL_COLOR, NULL);
|
| 1247 |
|
| 1248 | renderer = gtk_cell_renderer_text_new();
|
| 1249 | gtk_tree_view_insert_column_with_attributes(view, -1,
|
| 1250 | "Name", renderer,
|
| 1251 | "text", COL_NAME,
|
| 1252 | "foreground-rgba",
|
| 1253 | COL_COLOR, NULL);
|
| 1254 | renderer = gtk_cell_renderer_text_new();
|
| 1255 | gtk_tree_view_insert_column_with_attributes(view, -1,
|
| 1256 | "N", renderer,
|
| 1257 | "text", COL_NO,
|
| 1258 | "foreground-rgba",
|
| 1259 | COL_COLOR, NULL);
|
| 1260 | renderer = gtk_cell_renderer_text_new();
|
| 1261 | gtk_tree_view_insert_column_with_attributes(view, -1,
|
| 1262 | "M", renderer,
|
| 1263 | "text", COL_MOD,
|
| 1264 | "foreground-rgba",
|
| 1265 | COL_COLOR, NULL);
|
| 1266 | renderer = gtk_cell_renderer_text_new();
|
| 1267 | gtk_tree_view_insert_column_with_attributes(view, -1,
|
| 1268 | "Y", renderer,
|
| 1269 | "text", COL_YES,
|
| 1270 | "foreground-rgba",
|
| 1271 | COL_COLOR, NULL);
|
| 1272 | renderer = gtk_cell_renderer_text_new();
|
| 1273 | gtk_tree_view_insert_column_with_attributes(view, -1,
|
| 1274 | "Value", renderer,
|
| 1275 | "text", COL_VALUE,
|
| 1276 | "editable",
|
| 1277 | COL_EDIT,
|
| 1278 | "foreground-rgba",
|
| 1279 | COL_COLOR, NULL);
|
| 1280 | g_signal_connect(G_OBJECT(renderer), "edited",
|
| 1281 | G_CALLBACK(renderer_edited), tree2_w);
|
| 1282 |
|
| 1283 | char *env = getenv(SRCTREE);
|
| 1284 | gchar *path = g_strconcat(env ? env : g_get_current_dir(), "/scripts/kconfig/icons/menu.xpm", NULL);
|
| 1285 | GError *err = NULL;
|
| 1286 |
|
| 1287 | pix_menu = gdk_pixbuf_new_from_file(path, &err);
|
| 1288 | g_free(path);
|
| 1289 |
|
| 1290 | if (err) {
|
| 1291 | g_warning("Failed to load menu icon: %s", err->message);
|
| 1292 | g_error_free(err);
|
| 1293 | }
|
| 1294 |
|
| 1295 | for (i = 0; i < COL_VALUE; i++) {
|
| 1296 | column = gtk_tree_view_get_column(view, i);
|
| 1297 | gtk_tree_view_column_set_resizable(column, TRUE);
|
| 1298 | }
|
| 1299 |
|
| 1300 | sel = gtk_tree_view_get_selection(view);
|
| 1301 | gtk_tree_selection_set_mode(sel, GTK_SELECTION_SINGLE);
|
| 1302 | }
|
| 1303 |
|
| 1304 |
|
| 1305 | int main(int ac, char *av[])
|
| 1306 | {
|
| 1307 | const char *name;
|
| 1308 | char *env;
|
| 1309 | gchar *glade_file;
|
| 1310 |
|
| 1311 |
|
| 1312 | gtk_init(&ac, &av);
|
| 1313 |
|
| 1314 |
|
| 1315 | env = getenv(SRCTREE);
|
| 1316 | if (env)
|
| 1317 | glade_file = g_strconcat(env, "/scripts/kconfig/gconf.ui", NULL);
|
| 1318 | else if (av[0][0] == '/')
|
| 1319 | glade_file = g_strconcat(av[0], ".ui", NULL);
|
| 1320 | else
|
| 1321 | glade_file = g_strconcat(g_get_current_dir(), "/", av[0], ".ui", NULL);
|
| 1322 |
|
| 1323 |
|
| 1324 | if (ac > 1 && av[1][0] == '-') {
|
| 1325 | switch (av[1][1]) {
|
| 1326 | case 'a':
|
| 1327 | |
| 1328 | break;
|
| 1329 | case 's':
|
| 1330 | conf_set_message_callback(NULL);
|
| 1331 | break;
|
| 1332 | case 'h':
|
| 1333 | case '?':
|
| 1334 | printf("%s [-s] <config>\n", av[0]);
|
| 1335 | exit(0);
|
| 1336 | }
|
| 1337 | name = av[2];
|
| 1338 | } else
|
| 1339 | name = av[1];
|
| 1340 |
|
| 1341 | conf_parse(name);
|
| 1342 | fixup_rootmenu(&rootmenu);
|
| 1343 |
|
| 1344 |
|
| 1345 | init_main_window(glade_file);
|
| 1346 | init_left_tree();
|
| 1347 | init_right_tree();
|
| 1348 |
|
| 1349 | conf_read(NULL);
|
| 1350 |
|
| 1351 | set_view_mode(view_mode);
|
| 1352 |
|
| 1353 | gtk_main();
|
| 1354 |
|
| 1355 | return 0;
|
| 1356 | }
|