1 // SPDX-License-Identifier: GPL-2.0
2 /*
3 * Copyright (C) 2002-2003 Romain Lievin <roms@tilp.info>
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; // left frame
33 static GtkWidget *tree2_w; // right frame
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; // browsed menu for SINGLE/SPLIT view
46 static struct menu *selected; // selected entry
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
conf_changed(bool dirty)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 /* Utility Functions */
65
text_insert_msg(const char * title,const char * msg)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
text_insert_help(struct menu * menu)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
_select_menu(GtkTreeView * view,GtkTreeModel * model,GtkTreeIter * parent,struct menu * match)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
select_menu(GtkTreeView * view,struct menu * match)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
_update_row_visibility(GtkTreeView * view)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
update_row_visibility(void)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
set_node(GtkTreeStore * tree,GtkTreeIter * node,struct menu * menu)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) { // parse children to get a final value
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
_update_tree(GtkTreeStore * store,GtkTreeIter * parent)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
update_tree(GtkTreeStore * store)270 static void update_tree(GtkTreeStore *store)
271 {
272 _update_tree(store, NULL);
273 update_row_visibility();
274 }
275
update_trees(void)276 static void update_trees(void)
277 {
278 if (view_mode == SPLIT_VIEW)
279 update_tree(tree1);
280 update_tree(tree2);
281 }
282
set_view_mode(enum view_mode mode)283 static void set_view_mode(enum view_mode mode)
284 {
285 view_mode = mode;
286
287 if (mode == SPLIT_VIEW) { // two panes
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 /* Menu & Toolbar Callbacks */
342
on_load1_activate(GtkMenuItem * menuitem,gpointer user_data)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
on_save_activate(GtkMenuItem * menuitem,gpointer user_data)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
on_save_as1_activate(GtkMenuItem * menuitem,gpointer user_data)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
on_show_name1_activate(GtkMenuItem * menuitem,gpointer user_data)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
on_show_range1_activate(GtkMenuItem * menuitem,gpointer user_data)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
on_show_data1_activate(GtkMenuItem * menuitem,gpointer user_data)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
on_set_option_mode1_activate(GtkMenuItem * menuitem,gpointer user_data)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
on_set_option_mode2_activate(GtkMenuItem * menuitem,gpointer user_data)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
on_set_option_mode3_activate(GtkMenuItem * menuitem,gpointer user_data)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
on_introduction1_activate(GtkMenuItem * menuitem,gpointer user_data)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
on_about1_activate(GtkMenuItem * menuitem,gpointer user_data)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 <roms@lpg.ticalc.org>.\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
on_license1_activate(GtkMenuItem * menuitem,gpointer user_data)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 /* toolbar handlers */
on_back_clicked(GtkButton * button,gpointer user_data)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
on_load_clicked(GtkButton * button,gpointer user_data)545 static void on_load_clicked(GtkButton *button, gpointer user_data)
546 {
547 on_load1_activate(NULL, user_data);
548 }
549
on_save_clicked(GtkButton * button,gpointer user_data)550 static void on_save_clicked(GtkButton *button, gpointer user_data)
551 {
552 on_save_activate(NULL, user_data);
553 }
554
on_single_clicked(GtkButton * button,gpointer user_data)555 static void on_single_clicked(GtkButton *button, gpointer user_data)
556 {
557 set_view_mode(SINGLE_VIEW);
558 }
559
on_split_clicked(GtkButton * button,gpointer user_data)560 static void on_split_clicked(GtkButton *button, gpointer user_data)
561 {
562 set_view_mode(SPLIT_VIEW);
563 }
564
on_full_clicked(GtkButton * button,gpointer user_data)565 static void on_full_clicked(GtkButton *button, gpointer user_data)
566 {
567 set_view_mode(FULL_VIEW);
568 }
569
on_collapse_clicked(GtkButton * button,gpointer user_data)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
on_expand_clicked(GtkButton * button,gpointer user_data)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 /* Main Windows Callbacks */
581
on_window1_destroy(GtkWidget * widget,gpointer user_data)582 static void on_window1_destroy(GtkWidget *widget, gpointer user_data)
583 {
584 gtk_main_quit();
585 }
586
on_window1_configure(GtkWidget * self,GdkEventConfigure * event,gpointer user_data)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
on_window1_delete_event(GtkWidget * widget,GdkEvent * event,gpointer user_data)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
on_quit1_activate(GtkMenuItem * menuitem,gpointer user_data)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 /* CTree Callbacks */
653
654 /* Change hex/int/string value in the cell */
renderer_edited(GtkCellRendererText * cell,const gchar * path_string,const gchar * new_text,gpointer user_data)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 /* Change the value of a symbol and update the tree */
change_sym_value(struct menu * menu,gint col)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
toggle_sym_value(struct menu * menu)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
column2index(GtkTreeViewColumn * column)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 /* User click: update choice (full) or goes down (single) */
on_treeview2_button_press_event(GtkWidget * widget,GdkEventButton * event,gpointer user_data)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 // goes down into menu
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 /* Key pressed: update choice */
on_treeview2_key_press_event(GtkWidget * widget,GdkEventKey * event,gpointer user_data)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 /* Row selection changed: update help */
on_treeview2_cursor_changed(GtkTreeView * treeview,gpointer user_data)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 /* User click: display sub-tree in the right frame. */
on_treeview1_button_press_event(GtkWidget * widget,GdkEventButton * event,gpointer user_data)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 /* Display the whole tree (single/split/full view) */
_display_tree(GtkTreeStore * tree,struct menu * menu,GtkTreeIter * parent)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
display_tree(GtkTreeStore * store,struct menu * menu)923 static void display_tree(GtkTreeStore *store, struct menu *menu)
924 {
925 _display_tree(store, menu, NULL);
926 }
927
928 /* Recreate the tree store starting at 'browsed' node */
recreate_tree(void)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
fixup_rootmenu(struct menu * menu)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 /* Main Window Initialization */
replace_button_icon(GtkWidget * widget,const char * filename)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
init_main_window(const gchar * glade_file)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 /* menubar */
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 /* toolbar */
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 /*"style", PANGO_STYLE_OBLIQUE, */
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
visible_func(GtkTreeModel * model,GtkTreeIter * iter,gpointer data)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
init_left_tree(void)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
init_right_tree(void)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 /* Main */
main(int ac,char * av[])1305 int main(int ac, char *av[])
1306 {
1307 const char *name;
1308 char *env;
1309 gchar *glade_file;
1310
1311 /* GTK stuffs */
1312 gtk_init(&ac, &av);
1313
1314 /* Determine GUI path */
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 /* Conf stuffs */
1324 if (ac > 1 && av[1][0] == '-') {
1325 switch (av[1][1]) {
1326 case 'a':
1327 //showAll = 1;
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 /* Load the interface and connect signals */
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 }
1357