00001
00002
00003
00004
00005
00006 #include <qapplication.h>
00007 #include <qmainwindow.h>
00008 #include <qtoolbar.h>
00009 #include <qvbox.h>
00010 #include <qsplitter.h>
00011 #include <qlistview.h>
00012 #include <qtextview.h>
00013 #include <qlineedit.h>
00014 #include <qmenubar.h>
00015 #include <qmessagebox.h>
00016 #include <qaction.h>
00017 #include <qheader.h>
00018 #include <qfiledialog.h>
00019 #include <qregexp.h>
00020 #if QT_VERSION >= 0x030000
00021 #include <qsettings.h>
00022 #endif
00023
00024 #include <stdlib.h>
00025
00026 #include "lkc.h"
00027 #include "qconf.h"
00028
00029 #include "qconf.moc"
00030 #include "images.c"
00031
00032 static QApplication *configApp;
00033 #if QT_VERSION >= 0x030000
00034 static QSettings *configSettings;
00035 #endif
00036
00037
00038
00039
00040
00041
00042
00043
00044 template <class P>
00045 void ConfigList::updateMenuList(P* parent, struct menu* menu)
00046 {
00047 struct menu* child;
00048 ConfigItem* item;
00049 ConfigItem* last;
00050 bool visible;
00051 enum prop_type type;
00052
00053 if (!menu) {
00054 while ((item = parent->firstChild()))
00055 delete item;
00056 return;
00057 }
00058
00059 last = parent->firstChild();
00060 if (last && !last->goParent)
00061 last = 0;
00062 for (child = menu->list; child; child = child->next) {
00063 item = last ? last->nextSibling() : parent->firstChild();
00064 type = child->prompt ? child->prompt->type : P_UNKNOWN;
00065
00066 switch (mode) {
00067 case menuMode:
00068 if (!(child->flags & MENU_ROOT))
00069 goto hide;
00070 break;
00071 case symbolMode:
00072 if (child->flags & MENU_ROOT)
00073 goto hide;
00074 break;
00075 default:
00076 break;
00077 }
00078
00079 visible = menu_is_visible(child);
00080 if (showAll || visible) {
00081 if (!item || item->menu != child)
00082 item = new ConfigItem(parent, last, child, visible);
00083 else
00084 item->testUpdateMenu(visible);
00085
00086 if (mode == fullMode || mode == menuMode || type != P_MENU)
00087 updateMenuList(item, child);
00088 else
00089 updateMenuList(item, 0);
00090 last = item;
00091 continue;
00092 }
00093 hide:
00094 if (item && item->menu == child) {
00095 last = parent->firstChild();
00096 if (last == item)
00097 last = 0;
00098 else while (last->nextSibling() != item)
00099 last = last->nextSibling();
00100 delete item;
00101 }
00102 }
00103 }
00104
00105 #if QT_VERSION >= 0x030000
00106
00107
00108
00109
00110 void ConfigItem::okRename(int col)
00111 {
00112 Parent::okRename(col);
00113 sym_set_string_value(menu->sym, text(dataColIdx).latin1());
00114 }
00115 #endif
00116
00117
00118
00119
00120 void ConfigItem::updateMenu(void)
00121 {
00122 ConfigList* list;
00123 struct symbol* sym;
00124 struct property *prop;
00125 QString prompt;
00126 int type;
00127 tristate expr;
00128
00129 list = listView();
00130 if (goParent) {
00131 setPixmap(promptColIdx, list->menuBackPix);
00132 prompt = "..";
00133 goto set_prompt;
00134 }
00135
00136 sym = menu->sym;
00137 prop = menu->prompt;
00138 prompt = menu_get_prompt(menu);
00139
00140 if (prop) switch (prop->type) {
00141 case P_MENU:
00142 if (list->mode == singleMode || list->mode == symbolMode) {
00143
00144
00145
00146 if (sym && list->rootEntry == menu)
00147 break;
00148 setPixmap(promptColIdx, list->menuPix);
00149 } else {
00150 if (sym)
00151 break;
00152 setPixmap(promptColIdx, 0);
00153 }
00154 goto set_prompt;
00155 case P_COMMENT:
00156 setPixmap(promptColIdx, 0);
00157 goto set_prompt;
00158 default:
00159 ;
00160 }
00161 if (!sym)
00162 goto set_prompt;
00163
00164 setText(nameColIdx, sym->name);
00165
00166 type = sym_get_type(sym);
00167 switch (type) {
00168 case S_BOOLEAN:
00169 case S_TRISTATE:
00170 char ch;
00171
00172 if (!sym_is_changable(sym) && !list->showAll) {
00173 setPixmap(promptColIdx, 0);
00174 setText(noColIdx, 0);
00175 setText(modColIdx, 0);
00176 setText(yesColIdx, 0);
00177 break;
00178 }
00179 expr = sym_get_tristate_value(sym);
00180 switch (expr) {
00181 case yes:
00182 if (sym_is_choice_value(sym) && type == S_BOOLEAN)
00183 setPixmap(promptColIdx, list->choiceYesPix);
00184 else
00185 setPixmap(promptColIdx, list->symbolYesPix);
00186 setText(yesColIdx, "Y");
00187 ch = 'Y';
00188 break;
00189 case mod:
00190 setPixmap(promptColIdx, list->symbolModPix);
00191 setText(modColIdx, "M");
00192 ch = 'M';
00193 break;
00194 default:
00195 if (sym_is_choice_value(sym) && type == S_BOOLEAN)
00196 setPixmap(promptColIdx, list->choiceNoPix);
00197 else
00198 setPixmap(promptColIdx, list->symbolNoPix);
00199 setText(noColIdx, "N");
00200 ch = 'N';
00201 break;
00202 }
00203 if (expr != no)
00204 setText(noColIdx, sym_tristate_within_range(sym, no) ? "_" : 0);
00205 if (expr != mod)
00206 setText(modColIdx, sym_tristate_within_range(sym, mod) ? "_" : 0);
00207 if (expr != yes)
00208 setText(yesColIdx, sym_tristate_within_range(sym, yes) ? "_" : 0);
00209
00210 setText(dataColIdx, QChar(ch));
00211 break;
00212 case S_INT:
00213 case S_HEX:
00214 case S_STRING:
00215 const char* data;
00216
00217 data = sym_get_string_value(sym);
00218 #if QT_VERSION >= 0x030000
00219 int i = list->mapIdx(dataColIdx);
00220 if (i >= 0)
00221 setRenameEnabled(i, TRUE);
00222 #endif
00223 setText(dataColIdx, data);
00224 if (type == S_STRING)
00225 prompt.sprintf("%s: %s", prompt.latin1(), data);
00226 else
00227 prompt.sprintf("(%s) %s", data, prompt.latin1());
00228 break;
00229 }
00230 if (!sym_has_value(sym) && visible)
00231 prompt += " (NEW)";
00232 set_prompt:
00233 setText(promptColIdx, prompt);
00234 }
00235
00236 void ConfigItem::testUpdateMenu(bool v)
00237 {
00238 ConfigItem* i;
00239
00240 visible = v;
00241 if (!menu)
00242 return;
00243
00244 sym_calc_value(menu->sym);
00245 if (menu->flags & MENU_CHANGED) {
00246
00247 menu->flags &= ~MENU_CHANGED;
00248 for (i = (ConfigItem*)menu->data; i; i = i->nextItem)
00249 i->updateMenu();
00250 } else if (listView()->updateAll)
00251 updateMenu();
00252 }
00253
00254 void ConfigItem::paintCell(QPainter* p, const QColorGroup& cg, int column, int width, int align)
00255 {
00256 ConfigList* list = listView();
00257
00258 if (visible) {
00259 if (isSelected() && !list->hasFocus() && list->mode == menuMode)
00260 Parent::paintCell(p, list->inactivedColorGroup, column, width, align);
00261 else
00262 Parent::paintCell(p, cg, column, width, align);
00263 } else
00264 Parent::paintCell(p, list->disabledColorGroup, column, width, align);
00265 }
00266
00267
00268
00269
00270 void ConfigItem::init(void)
00271 {
00272 if (menu) {
00273 ConfigList* list = listView();
00274 nextItem = (ConfigItem*)menu->data;
00275 menu->data = this;
00276
00277 if (list->mode != fullMode)
00278 setOpen(TRUE);
00279 sym_calc_value(menu->sym);
00280 }
00281 updateMenu();
00282 }
00283
00284
00285
00286
00287 ConfigItem::~ConfigItem(void)
00288 {
00289 if (menu) {
00290 ConfigItem** ip = (ConfigItem**)&menu->data;
00291 for (; *ip; ip = &(*ip)->nextItem) {
00292 if (*ip == this) {
00293 *ip = nextItem;
00294 break;
00295 }
00296 }
00297 }
00298 }
00299
00300 void ConfigLineEdit::show(ConfigItem* i)
00301 {
00302 item = i;
00303 if (sym_get_string_value(item->menu->sym))
00304 setText(sym_get_string_value(item->menu->sym));
00305 else
00306 setText(0);
00307 Parent::show();
00308 setFocus();
00309 }
00310
00311 void ConfigLineEdit::keyPressEvent(QKeyEvent* e)
00312 {
00313 switch (e->key()) {
00314 case Key_Escape:
00315 break;
00316 case Key_Return:
00317 case Key_Enter:
00318 sym_set_string_value(item->menu->sym, text().latin1());
00319 parent()->updateList(item);
00320 break;
00321 default:
00322 Parent::keyPressEvent(e);
00323 return;
00324 }
00325 e->accept();
00326 parent()->list->setFocus();
00327 hide();
00328 }
00329
00330 ConfigList::ConfigList(ConfigView* p, ConfigMainWindow* cv)
00331 : Parent(p), cview(cv),
00332 updateAll(false),
00333 symbolYesPix(xpm_symbol_yes), symbolModPix(xpm_symbol_mod), symbolNoPix(xpm_symbol_no),
00334 choiceYesPix(xpm_choice_yes), choiceNoPix(xpm_choice_no),
00335 menuPix(xpm_menu), menuInvPix(xpm_menu_inv), menuBackPix(xpm_menuback), voidPix(xpm_void),
00336 showAll(false), showName(false), showRange(false), showData(false),
00337 rootEntry(0)
00338 {
00339 int i;
00340
00341 setSorting(-1);
00342 setRootIsDecorated(TRUE);
00343 disabledColorGroup = palette().active();
00344 disabledColorGroup.setColor(QColorGroup::Text, palette().disabled().text());
00345 inactivedColorGroup = palette().active();
00346 inactivedColorGroup.setColor(QColorGroup::Highlight, palette().disabled().highlight());
00347
00348 connect(this, SIGNAL(selectionChanged(void)),
00349 SLOT(updateSelection(void)));
00350
00351 for (i = 0; i < colNr; i++)
00352 colMap[i] = colRevMap[i] = -1;
00353 addColumn(promptColIdx, "Option");
00354
00355 reinit();
00356 }
00357
00358 void ConfigList::reinit(void)
00359 {
00360 removeColumn(dataColIdx);
00361 removeColumn(yesColIdx);
00362 removeColumn(modColIdx);
00363 removeColumn(noColIdx);
00364 removeColumn(nameColIdx);
00365
00366 if (showName)
00367 addColumn(nameColIdx, "Name");
00368 if (showRange) {
00369 addColumn(noColIdx, "N");
00370 addColumn(modColIdx, "M");
00371 addColumn(yesColIdx, "Y");
00372 }
00373 if (showData)
00374 addColumn(dataColIdx, "Value");
00375
00376 updateListAll();
00377 }
00378
00379 void ConfigList::updateSelection(void)
00380 {
00381 struct menu *menu;
00382 enum prop_type type;
00383
00384 ConfigItem* item = (ConfigItem*)selectedItem();
00385 if (!item)
00386 return;
00387
00388 cview->setHelp(item);
00389
00390 menu = item->menu;
00391 if (!menu)
00392 return;
00393 type = menu->prompt ? menu->prompt->type : P_UNKNOWN;
00394 if (mode == menuMode && type == P_MENU)
00395 emit menuSelected(menu);
00396 }
00397
00398 void ConfigList::updateList(ConfigItem* item)
00399 {
00400 ConfigItem* last = 0;
00401
00402 if (!rootEntry)
00403 goto update;
00404
00405 if (rootEntry != &rootmenu && (mode == singleMode ||
00406 (mode == symbolMode && rootEntry->parent != &rootmenu))) {
00407 item = firstChild();
00408 if (!item)
00409 item = new ConfigItem(this, 0, true);
00410 last = item;
00411 }
00412 if (mode == singleMode && rootEntry->sym && rootEntry->prompt) {
00413 item = last ? last->nextSibling() : firstChild();
00414 if (!item)
00415 item = new ConfigItem(this, last, rootEntry, true);
00416
00417 updateMenuList(item, rootEntry);
00418 triggerUpdate();
00419 return;
00420 }
00421 update:
00422 updateMenuList(this, rootEntry);
00423 triggerUpdate();
00424 }
00425
00426 void ConfigList::setAllOpen(bool open)
00427 {
00428 QListViewItemIterator it(this);
00429
00430 for (; it.current(); it++)
00431 it.current()->setOpen(open);
00432 }
00433
00434 void ConfigList::setValue(ConfigItem* item, tristate val)
00435 {
00436 struct symbol* sym;
00437 int type;
00438 tristate oldval;
00439
00440 sym = item->menu ? item->menu->sym : 0;
00441 if (!sym)
00442 return;
00443
00444 type = sym_get_type(sym);
00445 switch (type) {
00446 case S_BOOLEAN:
00447 case S_TRISTATE:
00448 oldval = sym_get_tristate_value(sym);
00449
00450 if (!sym_set_tristate_value(sym, val))
00451 return;
00452 if (oldval == no && item->menu->list)
00453 item->setOpen(TRUE);
00454 parent()->updateList(item);
00455 break;
00456 }
00457 }
00458
00459 void ConfigList::changeValue(ConfigItem* item)
00460 {
00461 struct symbol* sym;
00462 struct menu* menu;
00463 int type, oldexpr, newexpr;
00464
00465 menu = item->menu;
00466 if (!menu)
00467 return;
00468 sym = menu->sym;
00469 if (!sym) {
00470 if (item->menu->list)
00471 item->setOpen(!item->isOpen());
00472 return;
00473 }
00474
00475 type = sym_get_type(sym);
00476 switch (type) {
00477 case S_BOOLEAN:
00478 case S_TRISTATE:
00479 oldexpr = sym_get_tristate_value(sym);
00480 newexpr = sym_toggle_tristate_value(sym);
00481 if (item->menu->list) {
00482 if (oldexpr == newexpr)
00483 item->setOpen(!item->isOpen());
00484 else if (oldexpr == no)
00485 item->setOpen(TRUE);
00486 }
00487 if (oldexpr != newexpr)
00488 parent()->updateList(item);
00489 break;
00490 case S_INT:
00491 case S_HEX:
00492 case S_STRING:
00493 #if QT_VERSION >= 0x030000
00494 if (colMap[dataColIdx] >= 0)
00495 item->startRename(colMap[dataColIdx]);
00496 else
00497 #endif
00498 parent()->lineEdit->show(item);
00499 break;
00500 }
00501 }
00502
00503 void ConfigList::setRootMenu(struct menu *menu)
00504 {
00505 enum prop_type type;
00506
00507 if (rootEntry == menu)
00508 return;
00509 type = menu && menu->prompt ? menu->prompt->type : P_UNKNOWN;
00510 if (type != P_MENU)
00511 return;
00512 updateMenuList(this, 0);
00513 rootEntry = menu;
00514 updateListAll();
00515 setSelected(currentItem(), hasFocus());
00516 }
00517
00518 void ConfigList::setParentMenu(void)
00519 {
00520 ConfigItem* item;
00521 struct menu *oldroot;
00522
00523 oldroot = rootEntry;
00524 if (rootEntry == &rootmenu)
00525 return;
00526 setRootMenu(menu_get_parent_menu(rootEntry->parent));
00527
00528 QListViewItemIterator it(this);
00529 for (; (item = (ConfigItem*)it.current()); it++) {
00530 if (item->menu == oldroot) {
00531 setCurrentItem(item);
00532 ensureItemVisible(item);
00533 break;
00534 }
00535 }
00536 }
00537
00538 void ConfigList::keyPressEvent(QKeyEvent* ev)
00539 {
00540 QListViewItem* i = currentItem();
00541 ConfigItem* item;
00542 struct menu *menu;
00543 enum prop_type type;
00544
00545 if (ev->key() == Key_Escape && mode != fullMode) {
00546 emit parentSelected();
00547 ev->accept();
00548 return;
00549 }
00550
00551 if (!i) {
00552 Parent::keyPressEvent(ev);
00553 return;
00554 }
00555 item = (ConfigItem*)i;
00556
00557 switch (ev->key()) {
00558 case Key_Return:
00559 case Key_Enter:
00560 if (item->goParent) {
00561 emit parentSelected();
00562 break;
00563 }
00564 menu = item->menu;
00565 if (!menu)
00566 break;
00567 type = menu->prompt ? menu->prompt->type : P_UNKNOWN;
00568 if (type == P_MENU && rootEntry != menu &&
00569 mode != fullMode && mode != menuMode) {
00570 emit menuSelected(menu);
00571 break;
00572 }
00573 case Key_Space:
00574 changeValue(item);
00575 break;
00576 case Key_N:
00577 setValue(item, no);
00578 break;
00579 case Key_M:
00580 setValue(item, mod);
00581 break;
00582 case Key_Y:
00583 setValue(item, yes);
00584 break;
00585 default:
00586 Parent::keyPressEvent(ev);
00587 return;
00588 }
00589 ev->accept();
00590 }
00591
00592 void ConfigList::contentsMousePressEvent(QMouseEvent* e)
00593 {
00594
00595
00596 Parent::contentsMousePressEvent(e);
00597 }
00598
00599 void ConfigList::contentsMouseReleaseEvent(QMouseEvent* e)
00600 {
00601 QPoint p(contentsToViewport(e->pos()));
00602 ConfigItem* item = (ConfigItem*)itemAt(p);
00603 struct menu *menu;
00604 enum prop_type ptype;
00605 const QPixmap* pm;
00606 int idx, x;
00607
00608 if (!item)
00609 goto skip;
00610
00611 menu = item->menu;
00612 x = header()->offset() + p.x();
00613 idx = colRevMap[header()->sectionAt(x)];
00614 switch (idx) {
00615 case promptColIdx:
00616 pm = item->pixmap(promptColIdx);
00617 if (pm) {
00618 int off = header()->sectionPos(0) + itemMargin() +
00619 treeStepSize() * (item->depth() + (rootIsDecorated() ? 1 : 0));
00620 if (x >= off && x < off + pm->width()) {
00621 if (item->goParent) {
00622 emit parentSelected();
00623 break;
00624 } else if (!menu)
00625 break;
00626 ptype = menu->prompt ? menu->prompt->type : P_UNKNOWN;
00627 if (ptype == P_MENU && rootEntry != menu &&
00628 mode != fullMode && mode != menuMode)
00629 emit menuSelected(menu);
00630 else
00631 changeValue(item);
00632 }
00633 }
00634 break;
00635 case noColIdx:
00636 setValue(item, no);
00637 break;
00638 case modColIdx:
00639 setValue(item, mod);
00640 break;
00641 case yesColIdx:
00642 setValue(item, yes);
00643 break;
00644 case dataColIdx:
00645 changeValue(item);
00646 break;
00647 }
00648
00649 skip:
00650
00651 Parent::contentsMouseReleaseEvent(e);
00652 }
00653
00654 void ConfigList::contentsMouseMoveEvent(QMouseEvent* e)
00655 {
00656
00657
00658 Parent::contentsMouseMoveEvent(e);
00659 }
00660
00661 void ConfigList::contentsMouseDoubleClickEvent(QMouseEvent* e)
00662 {
00663 QPoint p(contentsToViewport(e->pos()));
00664 ConfigItem* item = (ConfigItem*)itemAt(p);
00665 struct menu *menu;
00666 enum prop_type ptype;
00667
00668 if (!item)
00669 goto skip;
00670 if (item->goParent) {
00671 emit parentSelected();
00672 goto skip;
00673 }
00674 menu = item->menu;
00675 if (!menu)
00676 goto skip;
00677 ptype = menu->prompt ? menu->prompt->type : P_UNKNOWN;
00678 if (ptype == P_MENU && (mode == singleMode || mode == symbolMode))
00679 emit menuSelected(menu);
00680 else if (menu->sym)
00681 changeValue(item);
00682
00683 skip:
00684
00685 Parent::contentsMouseDoubleClickEvent(e);
00686 }
00687
00688 void ConfigList::focusInEvent(QFocusEvent *e)
00689 {
00690 Parent::focusInEvent(e);
00691
00692 QListViewItem* item = currentItem();
00693 if (!item)
00694 return;
00695
00696 setSelected(item, TRUE);
00697 emit gotFocus();
00698 }
00699
00700 ConfigView* ConfigView::viewList;
00701
00702 ConfigView::ConfigView(QWidget* parent, ConfigMainWindow* cview)
00703 : Parent(parent)
00704 {
00705 list = new ConfigList(this, cview);
00706 lineEdit = new ConfigLineEdit(this);
00707 lineEdit->hide();
00708
00709 this->nextView = viewList;
00710 viewList = this;
00711 }
00712
00713 ConfigView::~ConfigView(void)
00714 {
00715 ConfigView** vp;
00716
00717 for (vp = &viewList; *vp; vp = &(*vp)->nextView) {
00718 if (*vp == this) {
00719 *vp = nextView;
00720 break;
00721 }
00722 }
00723 }
00724
00725 void ConfigView::updateList(ConfigItem* item)
00726 {
00727 ConfigView* v;
00728
00729 for (v = viewList; v; v = v->nextView)
00730 v->list->updateList(item);
00731 }
00732
00733 void ConfigView::updateListAll(void)
00734 {
00735 ConfigView* v;
00736
00737 for (v = viewList; v; v = v->nextView)
00738 v->list->updateListAll();
00739 }
00740
00741
00742
00743
00744 ConfigMainWindow::ConfigMainWindow(void)
00745 {
00746 QMenuBar* menu;
00747 QSplitter* split1;
00748 QSplitter* split2;
00749 bool ok;
00750 int x, y, width, height;
00751
00752 QWidget *d = configApp->desktop();
00753
00754 #if QT_VERSION >= 0x030000
00755 width = configSettings->readNumEntry("/kconfig/qconf/window width", d->width() - 64);
00756 height = configSettings->readNumEntry("/kconfig/qconf/window height", d->height() - 64);
00757 resize(width, height);
00758 x = configSettings->readNumEntry("/kconfig/qconf/window x", 0, &ok);
00759 if (ok)
00760 y = configSettings->readNumEntry("/kconfig/qconf/window y", 0, &ok);
00761 if (ok)
00762 move(x, y);
00763 #else
00764 width = d->width() - 64;
00765 height = d->height() - 64;
00766 resize(width, height);
00767 #endif
00768
00769 showDebug = false;
00770
00771 split1 = new QSplitter(this);
00772 split1->setOrientation(QSplitter::Horizontal);
00773 setCentralWidget(split1);
00774
00775 menuView = new ConfigView(split1, this);
00776 menuList = menuView->list;
00777
00778 split2 = new QSplitter(split1);
00779 split2->setOrientation(QSplitter::Vertical);
00780
00781
00782 configView = new ConfigView(split2, this);
00783 configList = configView->list;
00784
00785 helpText = new QTextView(split2);
00786 helpText->setTextFormat(Qt::RichText);
00787
00788 setTabOrder(configList, helpText);
00789 configList->setFocus();
00790
00791 menu = menuBar();
00792 toolBar = new QToolBar("Tools", this);
00793
00794 backAction = new QAction("Back", QPixmap(xpm_back), "Back", 0, this);
00795 connect(backAction, SIGNAL(activated()), SLOT(goBack()));
00796 backAction->setEnabled(FALSE);
00797 QAction *quitAction = new QAction("Quit", "&Quit", CTRL+Key_Q, this);
00798 connect(quitAction, SIGNAL(activated()), SLOT(close()));
00799 QAction *loadAction = new QAction("Load", QPixmap(xpm_load), "&Load", CTRL+Key_L, this);
00800 connect(loadAction, SIGNAL(activated()), SLOT(loadConfig()));
00801 QAction *saveAction = new QAction("Save", QPixmap(xpm_save), "&Save", CTRL+Key_S, this);
00802 connect(saveAction, SIGNAL(activated()), SLOT(saveConfig()));
00803 QAction *saveAsAction = new QAction("Save As...", "Save &As...", 0, this);
00804 connect(saveAsAction, SIGNAL(activated()), SLOT(saveConfigAs()));
00805 QAction *singleViewAction = new QAction("Single View", QPixmap(xpm_single_view), "Split View", 0, this);
00806 connect(singleViewAction, SIGNAL(activated()), SLOT(showSingleView()));
00807 QAction *splitViewAction = new QAction("Split View", QPixmap(xpm_split_view), "Split View", 0, this);
00808 connect(splitViewAction, SIGNAL(activated()), SLOT(showSplitView()));
00809 QAction *fullViewAction = new QAction("Full View", QPixmap(xpm_tree_view), "Full View", 0, this);
00810 connect(fullViewAction, SIGNAL(activated()), SLOT(showFullView()));
00811
00812 QAction *showNameAction = new QAction(NULL, "Show Name", 0, this);
00813 showNameAction->setToggleAction(TRUE);
00814 showNameAction->setOn(configList->showName);
00815 connect(showNameAction, SIGNAL(toggled(bool)), SLOT(setShowName(bool)));
00816 QAction *showRangeAction = new QAction(NULL, "Show Range", 0, this);
00817 showRangeAction->setToggleAction(TRUE);
00818 showRangeAction->setOn(configList->showRange);
00819 connect(showRangeAction, SIGNAL(toggled(bool)), SLOT(setShowRange(bool)));
00820 QAction *showDataAction = new QAction(NULL, "Show Data", 0, this);
00821 showDataAction->setToggleAction(TRUE);
00822 showDataAction->setOn(configList->showData);
00823 connect(showDataAction, SIGNAL(toggled(bool)), SLOT(setShowData(bool)));
00824 QAction *showAllAction = new QAction(NULL, "Show All Options", 0, this);
00825 showAllAction->setToggleAction(TRUE);
00826 showAllAction->setOn(configList->showAll);
00827 connect(showAllAction, SIGNAL(toggled(bool)), SLOT(setShowAll(bool)));
00828 QAction *showDebugAction = new QAction(NULL, "Show Debug Info", 0, this);
00829 showDebugAction->setToggleAction(TRUE);
00830 showDebugAction->setOn(showDebug);
00831 connect(showDebugAction, SIGNAL(toggled(bool)), SLOT(setShowDebug(bool)));
00832
00833 QAction *showIntroAction = new QAction(NULL, "Introduction", 0, this);
00834 connect(showIntroAction, SIGNAL(activated()), SLOT(showIntro()));
00835 QAction *showAboutAction = new QAction(NULL, "About", 0, this);
00836 connect(showAboutAction, SIGNAL(activated()), SLOT(showAbout()));
00837
00838
00839 backAction->addTo(toolBar);
00840 toolBar->addSeparator();
00841 loadAction->addTo(toolBar);
00842 saveAction->addTo(toolBar);
00843 toolBar->addSeparator();
00844 singleViewAction->addTo(toolBar);
00845 splitViewAction->addTo(toolBar);
00846 fullViewAction->addTo(toolBar);
00847
00848
00849 QPopupMenu* config = new QPopupMenu(this);
00850 menu->insertItem("&File", config);
00851 loadAction->addTo(config);
00852 saveAction->addTo(config);
00853 saveAsAction->addTo(config);
00854 config->insertSeparator();
00855 quitAction->addTo(config);
00856
00857
00858 QPopupMenu* optionMenu = new QPopupMenu(this);
00859 menu->insertItem("&Option", optionMenu);
00860 showNameAction->addTo(optionMenu);
00861 showRangeAction->addTo(optionMenu);
00862 showDataAction->addTo(optionMenu);
00863 optionMenu->insertSeparator();
00864 showAllAction->addTo(optionMenu);
00865 showDebugAction->addTo(optionMenu);
00866
00867
00868 QPopupMenu* helpMenu = new QPopupMenu(this);
00869 menu->insertSeparator();
00870 menu->insertItem("&Help", helpMenu);
00871 showIntroAction->addTo(helpMenu);
00872 showAboutAction->addTo(helpMenu);
00873
00874 connect(configList, SIGNAL(menuSelected(struct menu *)),
00875 SLOT(changeMenu(struct menu *)));
00876 connect(configList, SIGNAL(parentSelected()),
00877 SLOT(goBack()));
00878 connect(menuList, SIGNAL(menuSelected(struct menu *)),
00879 SLOT(changeMenu(struct menu *)));
00880
00881 connect(configList, SIGNAL(gotFocus(void)),
00882 SLOT(listFocusChanged(void)));
00883 connect(menuList, SIGNAL(gotFocus(void)),
00884 SLOT(listFocusChanged(void)));
00885
00886 showSplitView();
00887 }
00888
00889 static QString print_filter(const char *str)
00890 {
00891 QRegExp re("[<>&\"\\n]");
00892 QString res = str;
00893 for (int i = 0; (i = res.find(re, i)) >= 0;) {
00894 switch (res[i].latin1()) {
00895 case '<':
00896 res.replace(i, 1, "<");
00897 i += 4;
00898 break;
00899 case '>':
00900 res.replace(i, 1, ">");
00901 i += 4;
00902 break;
00903 case '&':
00904 res.replace(i, 1, "&");
00905 i += 5;
00906 break;
00907 case '"':
00908 res.replace(i, 1, """);
00909 i += 6;
00910 break;
00911 case '\n':
00912 res.replace(i, 1, "<br>");
00913 i += 4;
00914 break;
00915 }
00916 }
00917 return res;
00918 }
00919
00920 static void expr_print_help(void *data, const char *str)
00921 {
00922 ((QString*)data)->append(print_filter(str));
00923 }
00924
00925
00926
00927
00928 void ConfigMainWindow::setHelp(QListViewItem* item)
00929 {
00930 struct symbol* sym;
00931 struct menu* menu = 0;
00932
00933 configList->parent()->lineEdit->hide();
00934 if (item)
00935 menu = ((ConfigItem*)item)->menu;
00936 if (!menu) {
00937 helpText->setText(NULL);
00938 return;
00939 }
00940
00941 QString head, debug, help;
00942 menu = ((ConfigItem*)item)->menu;
00943 sym = menu->sym;
00944 if (sym) {
00945 if (menu->prompt) {
00946 head += "<big><b>";
00947 head += print_filter(menu->prompt->text);
00948 head += "</b></big>";
00949 if (sym->name) {
00950 head += " (";
00951 head += print_filter(sym->name);
00952 head += ")";
00953 }
00954 } else if (sym->name) {
00955 head += "<big><b>";
00956 head += print_filter(sym->name);
00957 head += "</b></big>";
00958 }
00959 head += "<br><br>";
00960
00961 if (showDebug) {
00962 debug += "type: ";
00963 debug += print_filter(sym_type_name(sym->type));
00964 if (sym_is_choice(sym))
00965 debug += " (choice)";
00966 debug += "<br>";
00967 if (sym->rev_dep.expr) {
00968 debug += "reverse dep: ";
00969 expr_print(sym->rev_dep.expr, expr_print_help, &debug, E_NONE);
00970 debug += "<br>";
00971 }
00972 for (struct property *prop = sym->prop; prop; prop = prop->next) {
00973 switch (prop->type) {
00974 case P_PROMPT:
00975 case P_MENU:
00976 debug += "prompt: ";
00977 debug += print_filter(prop->text);
00978 debug += "<br>";
00979 break;
00980 case P_DEFAULT:
00981 debug += "default: ";
00982 expr_print(prop->expr, expr_print_help, &debug, E_NONE);
00983 debug += "<br>";
00984 break;
00985 case P_CHOICE:
00986 if (sym_is_choice(sym)) {
00987 debug += "choice: ";
00988 expr_print(prop->expr, expr_print_help, &debug, E_NONE);
00989 debug += "<br>";
00990 }
00991 break;
00992 case P_SELECT:
00993 debug += "select: ";
00994 expr_print(prop->expr, expr_print_help, &debug, E_NONE);
00995 debug += "<br>";
00996 break;
00997 case P_RANGE:
00998 debug += "range: ";
00999 expr_print(prop->expr, expr_print_help, &debug, E_NONE);
01000 debug += "<br>";
01001 break;
01002 default:
01003 debug += "unknown property: ";
01004 debug += prop_get_type_name(prop->type);
01005 debug += "<br>";
01006 }
01007 if (prop->visible.expr) {
01008 debug += " dep: ";
01009 expr_print(prop->visible.expr, expr_print_help, &debug, E_NONE);
01010 debug += "<br>";
01011 }
01012 }
01013 debug += "<br>";
01014 }
01015
01016 help = print_filter(sym->help);
01017 } else if (menu->prompt) {
01018 head += "<big><b>";
01019 head += print_filter(menu->prompt->text);
01020 head += "</b></big><br><br>";
01021 if (showDebug) {
01022 if (menu->prompt->visible.expr) {
01023 debug += " dep: ";
01024 expr_print(menu->prompt->visible.expr, expr_print_help, &debug, E_NONE);
01025 debug += "<br><br>";
01026 }
01027 }
01028 }
01029 if (showDebug)
01030 debug += QString().sprintf("defined at %s:%d<br><br>", menu->file->name, menu->lineno);
01031 helpText->setText(head + debug + help);
01032 }
01033
01034 void ConfigMainWindow::loadConfig(void)
01035 {
01036 QString s = QFileDialog::getOpenFileName(".config", NULL, this);
01037 if (s.isNull())
01038 return;
01039 if (conf_read(s.latin1()))
01040 QMessageBox::information(this, "qconf", "Unable to load configuration!");
01041 ConfigView::updateListAll();
01042 }
01043
01044 void ConfigMainWindow::saveConfig(void)
01045 {
01046 if (conf_write(NULL))
01047 QMessageBox::information(this, "qconf", "Unable to save configuration!");
01048 }
01049
01050 void ConfigMainWindow::saveConfigAs(void)
01051 {
01052 QString s = QFileDialog::getSaveFileName(".config", NULL, this);
01053 if (s.isNull())
01054 return;
01055 if (conf_write(s.latin1()))
01056 QMessageBox::information(this, "qconf", "Unable to save configuration!");
01057 }
01058
01059 void ConfigMainWindow::changeMenu(struct menu *menu)
01060 {
01061 configList->setRootMenu(menu);
01062 backAction->setEnabled(TRUE);
01063 }
01064
01065 void ConfigMainWindow::listFocusChanged(void)
01066 {
01067 if (menuList->hasFocus()) {
01068 if (menuList->mode == menuMode)
01069 configList->clearSelection();
01070 setHelp(menuList->selectedItem());
01071 } else if (configList->hasFocus()) {
01072 setHelp(configList->selectedItem());
01073 }
01074 }
01075
01076 void ConfigMainWindow::goBack(void)
01077 {
01078 ConfigItem* item;
01079
01080 configList->setParentMenu();
01081 if (configList->rootEntry == &rootmenu)
01082 backAction->setEnabled(FALSE);
01083 item = (ConfigItem*)menuList->selectedItem();
01084 while (item) {
01085 if (item->menu == configList->rootEntry) {
01086 menuList->setSelected(item, TRUE);
01087 break;
01088 }
01089 item = (ConfigItem*)item->parent();
01090 }
01091 }
01092
01093 void ConfigMainWindow::showSingleView(void)
01094 {
01095 menuView->hide();
01096 menuList->setRootMenu(0);
01097 configList->mode = singleMode;
01098 if (configList->rootEntry == &rootmenu)
01099 configList->updateListAll();
01100 else
01101 configList->setRootMenu(&rootmenu);
01102 configList->setAllOpen(TRUE);
01103 configList->setFocus();
01104 }
01105
01106 void ConfigMainWindow::showSplitView(void)
01107 {
01108 configList->mode = symbolMode;
01109 if (configList->rootEntry == &rootmenu)
01110 configList->updateListAll();
01111 else
01112 configList->setRootMenu(&rootmenu);
01113 configList->setAllOpen(TRUE);
01114 configApp->processEvents();
01115 menuList->mode = menuMode;
01116 menuList->setRootMenu(&rootmenu);
01117 menuList->setAllOpen(TRUE);
01118 menuView->show();
01119 menuList->setFocus();
01120 }
01121
01122 void ConfigMainWindow::showFullView(void)
01123 {
01124 menuView->hide();
01125 menuList->setRootMenu(0);
01126 configList->mode = fullMode;
01127 if (configList->rootEntry == &rootmenu)
01128 configList->updateListAll();
01129 else
01130 configList->setRootMenu(&rootmenu);
01131 configList->setAllOpen(FALSE);
01132 configList->setFocus();
01133 }
01134
01135 void ConfigMainWindow::setShowAll(bool b)
01136 {
01137 if (configList->showAll == b)
01138 return;
01139 configList->showAll = b;
01140 configList->updateListAll();
01141 menuList->showAll = b;
01142 menuList->updateListAll();
01143 }
01144
01145 void ConfigMainWindow::setShowDebug(bool b)
01146 {
01147 if (showDebug == b)
01148 return;
01149 showDebug = b;
01150 }
01151
01152 void ConfigMainWindow::setShowName(bool b)
01153 {
01154 if (configList->showName == b)
01155 return;
01156 configList->showName = b;
01157 configList->reinit();
01158 menuList->showName = b;
01159 menuList->reinit();
01160 }
01161
01162 void ConfigMainWindow::setShowRange(bool b)
01163 {
01164 if (configList->showRange == b)
01165 return;
01166 configList->showRange = b;
01167 configList->reinit();
01168 menuList->showRange = b;
01169 menuList->reinit();
01170 }
01171
01172 void ConfigMainWindow::setShowData(bool b)
01173 {
01174 if (configList->showData == b)
01175 return;
01176 configList->showData = b;
01177 configList->reinit();
01178 menuList->showData = b;
01179 menuList->reinit();
01180 }
01181
01182
01183
01184
01185
01186 void ConfigMainWindow::closeEvent(QCloseEvent* e)
01187 {
01188 if (!sym_change_count) {
01189 e->accept();
01190 return;
01191 }
01192 QMessageBox mb("qconf", "Save configuration?", QMessageBox::Warning,
01193 QMessageBox::Yes | QMessageBox::Default, QMessageBox::No, QMessageBox::Cancel | QMessageBox::Escape);
01194 mb.setButtonText(QMessageBox::Yes, "&Save Changes");
01195 mb.setButtonText(QMessageBox::No, "&Discard Changes");
01196 mb.setButtonText(QMessageBox::Cancel, "Cancel Exit");
01197 switch (mb.exec()) {
01198 case QMessageBox::Yes:
01199 conf_write(NULL);
01200 case QMessageBox::No:
01201 e->accept();
01202 break;
01203 case QMessageBox::Cancel:
01204 e->ignore();
01205 break;
01206 }
01207 }
01208
01209 void ConfigMainWindow::showIntro(void)
01210 {
01211 static char str[] = "Welcome to the qconf graphical kernel configuration tool for Linux.\n\n"
01212 "For each option, a blank box indicates the feature is disabled, a check\n"
01213 "indicates it is enabled, and a dot indicates that it is to be compiled\n"
01214 "as a module. Clicking on the box will cycle through the three states.\n\n"
01215 "If you do not see an option (e.g., a device driver) that you believe\n"
01216 "should be present, try turning on Show All Options under the Options menu.\n"
01217 "Although there is no cross reference yet to help you figure out what other\n"
01218 "options must be enabled to support the option you are interested in, you can\n"
01219 "still view the help of a grayed-out option.\n\n"
01220 "Toggling Show Debug Info under the Options menu will show the dependencies,\n"
01221 "which you can then match by examining other options.\n\n";
01222
01223 QMessageBox::information(this, "qconf", str);
01224 }
01225
01226 void ConfigMainWindow::showAbout(void)
01227 {
01228 static char str[] = "qconf is Copyright (C) 2002 Roman Zippel <zippel@linux-m68k.org>.\n\n"
01229 "Bug reports and feature request can also be entered at http://bugzilla.kernel.org/\n";
01230
01231 QMessageBox::information(this, "qconf", str);
01232 }
01233
01234 void fixup_rootmenu(struct menu *menu)
01235 {
01236 struct menu *child;
01237 static int menu_cnt = 0;
01238
01239 menu->flags |= MENU_ROOT;
01240 for (child = menu->list; child; child = child->next) {
01241 if (child->prompt && child->prompt->type == P_MENU) {
01242 menu_cnt++;
01243 fixup_rootmenu(child);
01244 menu_cnt--;
01245 } else if (!menu_cnt)
01246 fixup_rootmenu(child);
01247 }
01248 }
01249
01250 static const char *progname;
01251
01252 static void usage(void)
01253 {
01254 printf("%s <config>\n", progname);
01255 exit(0);
01256 }
01257
01258 int main(int ac, char** av)
01259 {
01260 ConfigMainWindow* v;
01261 const char *name;
01262
01263 #ifndef LKC_DIRECT_LINK
01264 kconfig_load();
01265 #endif
01266
01267 progname = av[0];
01268 configApp = new QApplication(ac, av);
01269 #if QT_VERSION >= 0x030000
01270 configSettings = new QSettings;
01271 #endif
01272 if (ac > 1 && av[1][0] == '-') {
01273 switch (av[1][1]) {
01274 case 'h':
01275 case '?':
01276 usage();
01277 }
01278 name = av[2];
01279 } else
01280 name = av[1];
01281 if (!name)
01282 usage();
01283
01284 conf_parse(name);
01285 fixup_rootmenu(&rootmenu);
01286 conf_read(NULL);
01287
01288
01289 v = new ConfigMainWindow();
01290
01291
01292 v->show();
01293 configApp->connect(configApp, SIGNAL(lastWindowClosed()), SLOT(quit()));
01294 configApp->exec();
01295
01296 #if QT_VERSION >= 0x030000
01297 configSettings->writeEntry("/kconfig/qconf/window x", v->pos().x());
01298 configSettings->writeEntry("/kconfig/qconf/window y", v->pos().y());
01299 configSettings->writeEntry("/kconfig/qconf/window width", v->size().width());
01300 configSettings->writeEntry("/kconfig/qconf/window height", v->size().height());
01301 delete configSettings;
01302 #endif
01303 return 0;
01304 }