Main Page | Namespace List | Class Hierarchy | Alphabetical List | Class List | Directories | File List | Namespace Members | Class Members | File Members | Related Pages

qconf.cc

Go to the documentation of this file.
00001 /*
00002  * Copyright (C) 2002 Roman Zippel <zippel@linux-m68k.org>
00003  * Released under the terms of the GNU GPL v2.0.
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  * update all the children of a menu entry
00039  *   removes/adds the entries from the parent widget as necessary
00040  *
00041  * parent: either the menu list widget or a menu entry widget
00042  * menu: entry to be updated
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  * set the new data
00108  * TODO check the value
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  * update the displayed of a menu entry
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                         /* a menuconfig entry is displayed differently
00144                          * depending whether it's at the view root or a child.
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                 /* the menu entry changed, so update all list items */
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  * construct a menu entry
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  * destruct a menu entry
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         //QPoint p(contentsToViewport(e->pos()));
00595         //printf("contentsMousePressEvent: %d,%d\n", p.x(), p.y());
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         //printf("contentsMouseReleaseEvent: %d,%d\n", p.x(), p.y());
00651         Parent::contentsMouseReleaseEvent(e);
00652 }
00653 
00654 void ConfigList::contentsMouseMoveEvent(QMouseEvent* e)
00655 {
00656         //QPoint p(contentsToViewport(e->pos()));
00657         //printf("contentsMouseMoveEvent: %d,%d\n", p.x(), p.y());
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         //printf("contentsMouseDoubleClickEvent: %d,%d\n", p.x(), p.y());
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  * Construct the complete config widget
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         // create config tree
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         // init tool bar
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         // create config menu
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         // create options menu
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         // create help menu
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, "&lt;");
00897                         i += 4;
00898                         break;
00899                 case '>':
00900                         res.replace(i, 1, "&gt;");
00901                         i += 4;
00902                         break;
00903                 case '&':
00904                         res.replace(i, 1, "&amp;");
00905                         i += 5;
00906                         break;
00907                 case '"':
00908                         res.replace(i, 1, "&quot;");
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  * display a new help entry as soon as a new menu entry is selected
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 += "&nbsp;&nbsp;&nbsp;&nbsp;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 += "&nbsp;&nbsp;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  * ask for saving configuration before quitting
01184  * TODO ask only when something changed
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         //zconfdump(stdout);
01288 
01289         v = new ConfigMainWindow();
01290 
01291         //zconfdump(stdout);
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 }

Generated on Sat Nov 5 16:18:35 2005 for OPIE by  doxygen 1.4.2