linux/scripts/kconfig/qconf.cc
<<
>>
Prefs
   1/*
   2 * Copyright (C) 2002 Roman Zippel <zippel@linux-m68k.org>
   3 * Released under the terms of the GNU GPL v2.0.
   4 */
   5
   6#include <qapplication.h>
   7#include <qmainwindow.h>
   8#include <qdesktopwidget.h>
   9#include <qtoolbar.h>
  10#include <qlayout.h>
  11#include <qvbox.h>
  12#include <qsplitter.h>
  13#include <qlistview.h>
  14#include <qtextbrowser.h>
  15#include <qlineedit.h>
  16#include <qlabel.h>
  17#include <qpushbutton.h>
  18#include <qmenubar.h>
  19#include <qmessagebox.h>
  20#include <qaction.h>
  21#include <qheader.h>
  22#include <qfiledialog.h>
  23#include <qdragobject.h>
  24#include <qregexp.h>
  25
  26#include <stdlib.h>
  27
  28#include "lkc.h"
  29#include "qconf.h"
  30
  31#include "qconf.moc"
  32#include "images.c"
  33
  34#ifdef _
  35# undef _
  36# define _ qgettext
  37#endif
  38
  39static QApplication *configApp;
  40static ConfigSettings *configSettings;
  41
  42QAction *ConfigMainWindow::saveAction;
  43
  44static inline QString qgettext(const char* str)
  45{
  46        return QString::fromLocal8Bit(gettext(str));
  47}
  48
  49static inline QString qgettext(const QString& str)
  50{
  51        return QString::fromLocal8Bit(gettext(str.latin1()));
  52}
  53
  54/**
  55 * Reads a list of integer values from the application settings.
  56 */
  57QValueList<int> ConfigSettings::readSizes(const QString& key, bool *ok)
  58{
  59        QValueList<int> result;
  60        QStringList entryList = readListEntry(key, ok);
  61        QStringList::Iterator it;
  62
  63        for (it = entryList.begin(); it != entryList.end(); ++it)
  64                result.push_back((*it).toInt());
  65
  66        return result;
  67}
  68
  69/**
  70 * Writes a list of integer values to the application settings.
  71 */
  72bool ConfigSettings::writeSizes(const QString& key, const QValueList<int>& value)
  73{
  74        QStringList stringList;
  75        QValueList<int>::ConstIterator it;
  76
  77        for (it = value.begin(); it != value.end(); ++it)
  78                stringList.push_back(QString::number(*it));
  79        return writeEntry(key, stringList);
  80}
  81
  82
  83#if QT_VERSION >= 300
  84/*
  85 * set the new data
  86 * TODO check the value
  87 */
  88void ConfigItem::okRename(int col)
  89{
  90        Parent::okRename(col);
  91        sym_set_string_value(menu->sym, text(dataColIdx).latin1());
  92        listView()->updateList(this);
  93}
  94#endif
  95
  96/*
  97 * update the displayed of a menu entry
  98 */
  99void ConfigItem::updateMenu(void)
 100{
 101        ConfigList* list;
 102        struct symbol* sym;
 103        struct property *prop;
 104        QString prompt;
 105        int type;
 106        tristate expr;
 107
 108        list = listView();
 109        if (goParent) {
 110                setPixmap(promptColIdx, list->menuBackPix);
 111                prompt = "..";
 112                goto set_prompt;
 113        }
 114
 115        sym = menu->sym;
 116        prop = menu->prompt;
 117        prompt = _(menu_get_prompt(menu));
 118
 119        if (prop) switch (prop->type) {
 120        case P_MENU:
 121                if (list->mode == singleMode || list->mode == symbolMode) {
 122                        /* a menuconfig entry is displayed differently
 123                         * depending whether it's at the view root or a child.
 124                         */
 125                        if (sym && list->rootEntry == menu)
 126                                break;
 127                        setPixmap(promptColIdx, list->menuPix);
 128                } else {
 129                        if (sym)
 130                                break;
 131                        setPixmap(promptColIdx, 0);
 132                }
 133                goto set_prompt;
 134        case P_COMMENT:
 135                setPixmap(promptColIdx, 0);
 136                goto set_prompt;
 137        default:
 138                ;
 139        }
 140        if (!sym)
 141                goto set_prompt;
 142
 143        setText(nameColIdx, QString::fromLocal8Bit(sym->name));
 144
 145        type = sym_get_type(sym);
 146        switch (type) {
 147        case S_BOOLEAN:
 148        case S_TRISTATE:
 149                char ch;
 150
 151                if (!sym_is_changable(sym) && list->optMode == normalOpt) {
 152                        setPixmap(promptColIdx, 0);
 153                        setText(noColIdx, QString::null);
 154                        setText(modColIdx, QString::null);
 155                        setText(yesColIdx, QString::null);
 156                        break;
 157                }
 158                expr = sym_get_tristate_value(sym);
 159                switch (expr) {
 160                case yes:
 161                        if (sym_is_choice_value(sym) && type == S_BOOLEAN)
 162                                setPixmap(promptColIdx, list->choiceYesPix);
 163                        else
 164                                setPixmap(promptColIdx, list->symbolYesPix);
 165                        setText(yesColIdx, "Y");
 166                        ch = 'Y';
 167                        break;
 168                case mod:
 169                        setPixmap(promptColIdx, list->symbolModPix);
 170                        setText(modColIdx, "M");
 171                        ch = 'M';
 172                        break;
 173                default:
 174                        if (sym_is_choice_value(sym) && type == S_BOOLEAN)
 175                                setPixmap(promptColIdx, list->choiceNoPix);
 176                        else
 177                                setPixmap(promptColIdx, list->symbolNoPix);
 178                        setText(noColIdx, "N");
 179                        ch = 'N';
 180                        break;
 181                }
 182                if (expr != no)
 183                        setText(noColIdx, sym_tristate_within_range(sym, no) ? "_" : 0);
 184                if (expr != mod)
 185                        setText(modColIdx, sym_tristate_within_range(sym, mod) ? "_" : 0);
 186                if (expr != yes)
 187                        setText(yesColIdx, sym_tristate_within_range(sym, yes) ? "_" : 0);
 188
 189                setText(dataColIdx, QChar(ch));
 190                break;
 191        case S_INT:
 192        case S_HEX:
 193        case S_STRING:
 194                const char* data;
 195
 196                data = sym_get_string_value(sym);
 197
 198#if QT_VERSION >= 300
 199                int i = list->mapIdx(dataColIdx);
 200                if (i >= 0)
 201                        setRenameEnabled(i, TRUE);
 202#endif
 203                setText(dataColIdx, data);
 204                if (type == S_STRING)
 205                        prompt = QString("%1: %2").arg(prompt).arg(data);
 206                else
 207                        prompt = QString("(%2) %1").arg(prompt).arg(data);
 208                break;
 209        }
 210        if (!sym_has_value(sym) && visible)
 211                prompt += _(" (NEW)");
 212set_prompt:
 213        setText(promptColIdx, prompt);
 214}
 215
 216void ConfigItem::testUpdateMenu(bool v)
 217{
 218        ConfigItem* i;
 219
 220        visible = v;
 221        if (!menu)
 222                return;
 223
 224        sym_calc_value(menu->sym);
 225        if (menu->flags & MENU_CHANGED) {
 226                /* the menu entry changed, so update all list items */
 227                menu->flags &= ~MENU_CHANGED;
 228                for (i = (ConfigItem*)menu->data; i; i = i->nextItem)
 229                        i->updateMenu();
 230        } else if (listView()->updateAll)
 231                updateMenu();
 232}
 233
 234void ConfigItem::paintCell(QPainter* p, const QColorGroup& cg, int column, int width, int align)
 235{
 236        ConfigList* list = listView();
 237
 238        if (visible) {
 239                if (isSelected() && !list->hasFocus() && list->mode == menuMode)
 240                        Parent::paintCell(p, list->inactivedColorGroup, column, width, align);
 241                else
 242                        Parent::paintCell(p, cg, column, width, align);
 243        } else
 244                Parent::paintCell(p, list->disabledColorGroup, column, width, align);
 245}
 246
 247/*
 248 * construct a menu entry
 249 */
 250void ConfigItem::init(void)
 251{
 252        if (menu) {
 253                ConfigList* list = listView();
 254                nextItem = (ConfigItem*)menu->data;
 255                menu->data = this;
 256
 257                if (list->mode != fullMode)
 258                        setOpen(TRUE);
 259                sym_calc_value(menu->sym);
 260        }
 261        updateMenu();
 262}
 263
 264/*
 265 * destruct a menu entry
 266 */
 267ConfigItem::~ConfigItem(void)
 268{
 269        if (menu) {
 270                ConfigItem** ip = (ConfigItem**)&menu->data;
 271                for (; *ip; ip = &(*ip)->nextItem) {
 272                        if (*ip == this) {
 273                                *ip = nextItem;
 274                                break;
 275                        }
 276                }
 277        }
 278}
 279
 280ConfigLineEdit::ConfigLineEdit(ConfigView* parent)
 281        : Parent(parent)
 282{
 283        connect(this, SIGNAL(lostFocus()), SLOT(hide()));
 284}
 285
 286void ConfigLineEdit::show(ConfigItem* i)
 287{
 288        item = i;
 289        if (sym_get_string_value(item->menu->sym))
 290                setText(QString::fromLocal8Bit(sym_get_string_value(item->menu->sym)));
 291        else
 292                setText(QString::null);
 293        Parent::show();
 294        setFocus();
 295}
 296
 297void ConfigLineEdit::keyPressEvent(QKeyEvent* e)
 298{
 299        switch (e->key()) {
 300        case Qt::Key_Escape:
 301                break;
 302        case Qt::Key_Return:
 303        case Qt::Key_Enter:
 304                sym_set_string_value(item->menu->sym, text().latin1());
 305                parent()->updateList(item);
 306                break;
 307        default:
 308                Parent::keyPressEvent(e);
 309                return;
 310        }
 311        e->accept();
 312        parent()->list->setFocus();
 313        hide();
 314}
 315
 316ConfigList::ConfigList(ConfigView* p, const char *name)
 317        : Parent(p, name),
 318          updateAll(false),
 319          symbolYesPix(xpm_symbol_yes), symbolModPix(xpm_symbol_mod), symbolNoPix(xpm_symbol_no),
 320          choiceYesPix(xpm_choice_yes), choiceNoPix(xpm_choice_no),
 321          menuPix(xpm_menu), menuInvPix(xpm_menu_inv), menuBackPix(xpm_menuback), voidPix(xpm_void),
 322          showName(false), showRange(false), showData(false), optMode(normalOpt),
 323          rootEntry(0), headerPopup(0)
 324{
 325        int i;
 326
 327        setSorting(-1);
 328        setRootIsDecorated(TRUE);
 329        disabledColorGroup = palette().active();
 330        disabledColorGroup.setColor(QColorGroup::Text, palette().disabled().text());
 331        inactivedColorGroup = palette().active();
 332        inactivedColorGroup.setColor(QColorGroup::Highlight, palette().disabled().highlight());
 333
 334        connect(this, SIGNAL(selectionChanged(void)),
 335                SLOT(updateSelection(void)));
 336
 337        if (name) {
 338                configSettings->beginGroup(name);
 339                showName = configSettings->readBoolEntry("/showName", false);
 340                showRange = configSettings->readBoolEntry("/showRange", false);
 341                showData = configSettings->readBoolEntry("/showData", false);
 342                optMode = (enum optionMode)configSettings->readNumEntry("/optionMode", false);
 343                configSettings->endGroup();
 344                connect(configApp, SIGNAL(aboutToQuit()), SLOT(saveSettings()));
 345        }
 346
 347        for (i = 0; i < colNr; i++)
 348                colMap[i] = colRevMap[i] = -1;
 349        addColumn(promptColIdx, _("Option"));
 350
 351        reinit();
 352}
 353
 354bool ConfigList::menuSkip(struct menu *menu)
 355{
 356        if (optMode == normalOpt && menu_is_visible(menu))
 357                return false;
 358        if (optMode == promptOpt && menu_has_prompt(menu))
 359                return false;
 360        if (optMode == allOpt)
 361                return false;
 362        return true;
 363}
 364
 365void ConfigList::reinit(void)
 366{
 367        removeColumn(dataColIdx);
 368        removeColumn(yesColIdx);
 369        removeColumn(modColIdx);
 370        removeColumn(noColIdx);
 371        removeColumn(nameColIdx);
 372
 373        if (showName)
 374                addColumn(nameColIdx, _("Name"));
 375        if (showRange) {
 376                addColumn(noColIdx, "N");
 377                addColumn(modColIdx, "M");
 378                addColumn(yesColIdx, "Y");
 379        }
 380        if (showData)
 381                addColumn(dataColIdx, _("Value"));
 382
 383        updateListAll();
 384}
 385
 386void ConfigList::saveSettings(void)
 387{
 388        if (name()) {
 389                configSettings->beginGroup(name());
 390                configSettings->writeEntry("/showName", showName);
 391                configSettings->writeEntry("/showRange", showRange);
 392                configSettings->writeEntry("/showData", showData);
 393                configSettings->writeEntry("/optionMode", (int)optMode);
 394                configSettings->endGroup();
 395        }
 396}
 397
 398ConfigItem* ConfigList::findConfigItem(struct menu *menu)
 399{
 400        ConfigItem* item = (ConfigItem*)menu->data;
 401
 402        for (; item; item = item->nextItem) {
 403                if (this == item->listView())
 404                        break;
 405        }
 406
 407        return item;
 408}
 409
 410void ConfigList::updateSelection(void)
 411{
 412        struct menu *menu;
 413        enum prop_type type;
 414
 415        ConfigItem* item = (ConfigItem*)selectedItem();
 416        if (!item)
 417                return;
 418
 419        menu = item->menu;
 420        emit menuChanged(menu);
 421        if (!menu)
 422                return;
 423        type = menu->prompt ? menu->prompt->type : P_UNKNOWN;
 424        if (mode == menuMode && type == P_MENU)
 425                emit menuSelected(menu);
 426}
 427
 428void ConfigList::updateList(ConfigItem* item)
 429{
 430        ConfigItem* last = 0;
 431
 432        if (!rootEntry) {
 433                if (mode != listMode)
 434                        goto update;
 435                QListViewItemIterator it(this);
 436                ConfigItem* item;
 437
 438                for (; it.current(); ++it) {
 439                        item = (ConfigItem*)it.current();
 440                        if (!item->menu)
 441                                continue;
 442                        item->testUpdateMenu(menu_is_visible(item->menu));
 443                }
 444                return;
 445        }
 446
 447        if (rootEntry != &rootmenu && (mode == singleMode ||
 448            (mode == symbolMode && rootEntry->parent != &rootmenu))) {
 449                item = firstChild();
 450                if (!item)
 451                        item = new ConfigItem(this, 0, true);
 452                last = item;
 453        }
 454        if ((mode == singleMode || (mode == symbolMode && !(rootEntry->flags & MENU_ROOT))) &&
 455            rootEntry->sym && rootEntry->prompt) {
 456                item = last ? last->nextSibling() : firstChild();
 457                if (!item)
 458                        item = new ConfigItem(this, last, rootEntry, true);
 459                else
 460                        item->testUpdateMenu(true);
 461
 462                updateMenuList(item, rootEntry);
 463                triggerUpdate();
 464                return;
 465        }
 466update:
 467        updateMenuList(this, rootEntry);
 468        triggerUpdate();
 469}
 470
 471void ConfigList::setValue(ConfigItem* item, tristate val)
 472{
 473        struct symbol* sym;
 474        int type;
 475        tristate oldval;
 476
 477        sym = item->menu ? item->menu->sym : 0;
 478        if (!sym)
 479                return;
 480
 481        type = sym_get_type(sym);
 482        switch (type) {
 483        case S_BOOLEAN:
 484        case S_TRISTATE:
 485                oldval = sym_get_tristate_value(sym);
 486
 487                if (!sym_set_tristate_value(sym, val))
 488                        return;
 489                if (oldval == no && item->menu->list)
 490                        item->setOpen(TRUE);
 491                parent()->updateList(item);
 492                break;
 493        }
 494}
 495
 496void ConfigList::changeValue(ConfigItem* item)
 497{
 498        struct symbol* sym;
 499        struct menu* menu;
 500        int type, oldexpr, newexpr;
 501
 502        menu = item->menu;
 503        if (!menu)
 504                return;
 505        sym = menu->sym;
 506        if (!sym) {
 507                if (item->menu->list)
 508                        item->setOpen(!item->isOpen());
 509                return;
 510        }
 511
 512        type = sym_get_type(sym);
 513        switch (type) {
 514        case S_BOOLEAN:
 515        case S_TRISTATE:
 516                oldexpr = sym_get_tristate_value(sym);
 517                newexpr = sym_toggle_tristate_value(sym);
 518                if (item->menu->list) {
 519                        if (oldexpr == newexpr)
 520                                item->setOpen(!item->isOpen());
 521                        else if (oldexpr == no)
 522                                item->setOpen(TRUE);
 523                }
 524                if (oldexpr != newexpr)
 525                        parent()->updateList(item);
 526                break;
 527        case S_INT:
 528        case S_HEX:
 529        case S_STRING:
 530#if QT_VERSION >= 300
 531                if (colMap[dataColIdx] >= 0)
 532                        item->startRename(colMap[dataColIdx]);
 533                else
 534#endif
 535                        parent()->lineEdit->show(item);
 536                break;
 537        }
 538}
 539
 540void ConfigList::setRootMenu(struct menu *menu)
 541{
 542        enum prop_type type;
 543
 544        if (rootEntry == menu)
 545                return;
 546        type = menu && menu->prompt ? menu->prompt->type : P_UNKNOWN;
 547        if (type != P_MENU)
 548                return;
 549        updateMenuList(this, 0);
 550        rootEntry = menu;
 551        updateListAll();
 552        setSelected(currentItem(), hasFocus());
 553        ensureItemVisible(currentItem());
 554}
 555
 556void ConfigList::setParentMenu(void)
 557{
 558        ConfigItem* item;
 559        struct menu *oldroot;
 560
 561        oldroot = rootEntry;
 562        if (rootEntry == &rootmenu)
 563                return;
 564        setRootMenu(menu_get_parent_menu(rootEntry->parent));
 565
 566        QListViewItemIterator it(this);
 567        for (; (item = (ConfigItem*)it.current()); it++) {
 568                if (item->menu == oldroot) {
 569                        setCurrentItem(item);
 570                        ensureItemVisible(item);
 571                        break;
 572                }
 573        }
 574}
 575
 576/*
 577 * update all the children of a menu entry
 578 *   removes/adds the entries from the parent widget as necessary
 579 *
 580 * parent: either the menu list widget or a menu entry widget
 581 * menu: entry to be updated
 582 */
 583template <class P>
 584void ConfigList::updateMenuList(P* parent, struct menu* menu)
 585{
 586        struct menu* child;
 587        ConfigItem* item;
 588        ConfigItem* last;
 589        bool visible;
 590        enum prop_type type;
 591
 592        if (!menu) {
 593                while ((item = parent->firstChild()))
 594                        delete item;
 595                return;
 596        }
 597
 598        last = parent->firstChild();
 599        if (last && !last->goParent)
 600                last = 0;
 601        for (child = menu->list; child; child = child->next) {
 602                item = last ? last->nextSibling() : parent->firstChild();
 603                type = child->prompt ? child->prompt->type : P_UNKNOWN;
 604
 605                switch (mode) {
 606                case menuMode:
 607                        if (!(child->flags & MENU_ROOT))
 608                                goto hide;
 609                        break;
 610                case symbolMode:
 611                        if (child->flags & MENU_ROOT)
 612                                goto hide;
 613                        break;
 614                default:
 615                        break;
 616                }
 617
 618                visible = menu_is_visible(child);
 619                if (!menuSkip(child)) {
 620                        if (!child->sym && !child->list && !child->prompt)
 621                                continue;
 622                        if (!item || item->menu != child)
 623                                item = new ConfigItem(parent, last, child, visible);
 624                        else
 625                                item->testUpdateMenu(visible);
 626
 627                        if (mode == fullMode || mode == menuMode || type != P_MENU)
 628                                updateMenuList(item, child);
 629                        else
 630                                updateMenuList(item, 0);
 631                        last = item;
 632                        continue;
 633                }
 634        hide:
 635                if (item && item->menu == child) {
 636                        last = parent->firstChild();
 637                        if (last == item)
 638                                last = 0;
 639                        else while (last->nextSibling() != item)
 640                                last = last->nextSibling();
 641                        delete item;
 642                }
 643        }
 644}
 645
 646void ConfigList::keyPressEvent(QKeyEvent* ev)
 647{
 648        QListViewItem* i = currentItem();
 649        ConfigItem* item;
 650        struct menu *menu;
 651        enum prop_type type;
 652
 653        if (ev->key() == Qt::Key_Escape && mode != fullMode && mode != listMode) {
 654                emit parentSelected();
 655                ev->accept();
 656                return;
 657        }
 658
 659        if (!i) {
 660                Parent::keyPressEvent(ev);
 661                return;
 662        }
 663        item = (ConfigItem*)i;
 664
 665        switch (ev->key()) {
 666        case Qt::Key_Return:
 667        case Qt::Key_Enter:
 668                if (item->goParent) {
 669                        emit parentSelected();
 670                        break;
 671                }
 672                menu = item->menu;
 673                if (!menu)
 674                        break;
 675                type = menu->prompt ? menu->prompt->type : P_UNKNOWN;
 676                if (type == P_MENU && rootEntry != menu &&
 677                    mode != fullMode && mode != menuMode) {
 678                        emit menuSelected(menu);
 679                        break;
 680                }
 681        case Qt::Key_Space:
 682                changeValue(item);
 683                break;
 684        case Qt::Key_N:
 685                setValue(item, no);
 686                break;
 687        case Qt::Key_M:
 688                setValue(item, mod);
 689                break;
 690        case Qt::Key_Y:
 691                setValue(item, yes);
 692                break;
 693        default:
 694                Parent::keyPressEvent(ev);
 695                return;
 696        }
 697        ev->accept();
 698}
 699
 700void ConfigList::contentsMousePressEvent(QMouseEvent* e)
 701{
 702        //QPoint p(contentsToViewport(e->pos()));
 703        //printf("contentsMousePressEvent: %d,%d\n", p.x(), p.y());
 704        Parent::contentsMousePressEvent(e);
 705}
 706
 707void ConfigList::contentsMouseReleaseEvent(QMouseEvent* e)
 708{
 709        QPoint p(contentsToViewport(e->pos()));
 710        ConfigItem* item = (ConfigItem*)itemAt(p);
 711        struct menu *menu;
 712        enum prop_type ptype;
 713        const QPixmap* pm;
 714        int idx, x;
 715
 716        if (!item)
 717                goto skip;
 718
 719        menu = item->menu;
 720        x = header()->offset() + p.x();
 721        idx = colRevMap[header()->sectionAt(x)];
 722        switch (idx) {
 723        case promptColIdx:
 724                pm = item->pixmap(promptColIdx);
 725                if (pm) {
 726                        int off = header()->sectionPos(0) + itemMargin() +
 727                                treeStepSize() * (item->depth() + (rootIsDecorated() ? 1 : 0));
 728                        if (x >= off && x < off + pm->width()) {
 729                                if (item->goParent) {
 730                                        emit parentSelected();
 731                                        break;
 732                                } else if (!menu)
 733                                        break;
 734                                ptype = menu->prompt ? menu->prompt->type : P_UNKNOWN;
 735                                if (ptype == P_MENU && rootEntry != menu &&
 736                                    mode != fullMode && mode != menuMode)
 737                                        emit menuSelected(menu);
 738                                else
 739                                        changeValue(item);
 740                        }
 741                }
 742                break;
 743        case noColIdx:
 744                setValue(item, no);
 745                break;
 746        case modColIdx:
 747                setValue(item, mod);
 748                break;
 749        case yesColIdx:
 750                setValue(item, yes);
 751                break;
 752        case dataColIdx:
 753                changeValue(item);
 754                break;
 755        }
 756
 757skip:
 758        //printf("contentsMouseReleaseEvent: %d,%d\n", p.x(), p.y());
 759        Parent::contentsMouseReleaseEvent(e);
 760}
 761
 762void ConfigList::contentsMouseMoveEvent(QMouseEvent* e)
 763{
 764        //QPoint p(contentsToViewport(e->pos()));
 765        //printf("contentsMouseMoveEvent: %d,%d\n", p.x(), p.y());
 766        Parent::contentsMouseMoveEvent(e);
 767}
 768
 769void ConfigList::contentsMouseDoubleClickEvent(QMouseEvent* e)
 770{
 771        QPoint p(contentsToViewport(e->pos()));
 772        ConfigItem* item = (ConfigItem*)itemAt(p);
 773        struct menu *menu;
 774        enum prop_type ptype;
 775
 776        if (!item)
 777                goto skip;
 778        if (item->goParent) {
 779                emit parentSelected();
 780                goto skip;
 781        }
 782        menu = item->menu;
 783        if (!menu)
 784                goto skip;
 785        ptype = menu->prompt ? menu->prompt->type : P_UNKNOWN;
 786        if (ptype == P_MENU && (mode == singleMode || mode == symbolMode))
 787                emit menuSelected(menu);
 788        else if (menu->sym)
 789                changeValue(item);
 790
 791skip:
 792        //printf("contentsMouseDoubleClickEvent: %d,%d\n", p.x(), p.y());
 793        Parent::contentsMouseDoubleClickEvent(e);
 794}
 795
 796void ConfigList::focusInEvent(QFocusEvent *e)
 797{
 798        struct menu *menu = NULL;
 799
 800        Parent::focusInEvent(e);
 801
 802        ConfigItem* item = (ConfigItem *)currentItem();
 803        if (item) {
 804                setSelected(item, TRUE);
 805                menu = item->menu;
 806        }
 807        emit gotFocus(menu);
 808}
 809
 810void ConfigList::contextMenuEvent(QContextMenuEvent *e)
 811{
 812        if (e->y() <= header()->geometry().bottom()) {
 813                if (!headerPopup) {
 814                        QAction *action;
 815
 816                        headerPopup = new QPopupMenu(this);
 817                        action = new QAction(NULL, _("Show Name"), 0, this);
 818                          action->setToggleAction(TRUE);
 819                          connect(action, SIGNAL(toggled(bool)),
 820                                  parent(), SLOT(setShowName(bool)));
 821                          connect(parent(), SIGNAL(showNameChanged(bool)),
 822                                  action, SLOT(setOn(bool)));
 823                          action->setOn(showName);
 824                          action->addTo(headerPopup);
 825                        action = new QAction(NULL, _("Show Range"), 0, this);
 826                          action->setToggleAction(TRUE);
 827                          connect(action, SIGNAL(toggled(bool)),
 828                                  parent(), SLOT(setShowRange(bool)));
 829                          connect(parent(), SIGNAL(showRangeChanged(bool)),
 830                                  action, SLOT(setOn(bool)));
 831                          action->setOn(showRange);
 832                          action->addTo(headerPopup);
 833                        action = new QAction(NULL, _("Show Data"), 0, this);
 834                          action->setToggleAction(TRUE);
 835                          connect(action, SIGNAL(toggled(bool)),
 836                                  parent(), SLOT(setShowData(bool)));
 837                          connect(parent(), SIGNAL(showDataChanged(bool)),
 838                                  action, SLOT(setOn(bool)));
 839                          action->setOn(showData);
 840                          action->addTo(headerPopup);
 841                }
 842                headerPopup->exec(e->globalPos());
 843                e->accept();
 844        } else
 845                e->ignore();
 846}
 847
 848ConfigView*ConfigView::viewList;
 849QAction *ConfigView::showNormalAction;
 850QAction *ConfigView::showAllAction;
 851QAction *ConfigView::showPromptAction;
 852
 853ConfigView::ConfigView(QWidget* parent, const char *name)
 854        : Parent(parent, name)
 855{
 856        list = new ConfigList(this, name);
 857        lineEdit = new ConfigLineEdit(this);
 858        lineEdit->hide();
 859
 860        this->nextView = viewList;
 861        viewList = this;
 862}
 863
 864ConfigView::~ConfigView(void)
 865{
 866        ConfigView** vp;
 867
 868        for (vp = &viewList; *vp; vp = &(*vp)->nextView) {
 869                if (*vp == this) {
 870                        *vp = nextView;
 871                        break;
 872                }
 873        }
 874}
 875
 876void ConfigView::setOptionMode(QAction *act)
 877{
 878        if (act == showNormalAction)
 879                list->optMode = normalOpt;
 880        else if (act == showAllAction)
 881                list->optMode = allOpt;
 882        else
 883                list->optMode = promptOpt;
 884
 885        list->updateListAll();
 886}
 887
 888void ConfigView::setShowName(bool b)
 889{
 890        if (list->showName != b) {
 891                list->showName = b;
 892                list->reinit();
 893                emit showNameChanged(b);
 894        }
 895}
 896
 897void ConfigView::setShowRange(bool b)
 898{
 899        if (list->showRange != b) {
 900                list->showRange = b;
 901                list->reinit();
 902                emit showRangeChanged(b);
 903        }
 904}
 905
 906void ConfigView::setShowData(bool b)
 907{
 908        if (list->showData != b) {
 909                list->showData = b;
 910                list->reinit();
 911                emit showDataChanged(b);
 912        }
 913}
 914
 915void ConfigList::setAllOpen(bool open)
 916{
 917        QListViewItemIterator it(this);
 918
 919        for (; it.current(); it++)
 920                it.current()->setOpen(open);
 921}
 922
 923void ConfigView::updateList(ConfigItem* item)
 924{
 925        ConfigView* v;
 926
 927        for (v = viewList; v; v = v->nextView)
 928                v->list->updateList(item);
 929}
 930
 931void ConfigView::updateListAll(void)
 932{
 933        ConfigView* v;
 934
 935        for (v = viewList; v; v = v->nextView)
 936                v->list->updateListAll();
 937}
 938
 939ConfigInfoView::ConfigInfoView(QWidget* parent, const char *name)
 940        : Parent(parent, name), sym(0), menu(0)
 941{
 942        if (name) {
 943                configSettings->beginGroup(name);
 944                _showDebug = configSettings->readBoolEntry("/showDebug", false);
 945                configSettings->endGroup();
 946                connect(configApp, SIGNAL(aboutToQuit()), SLOT(saveSettings()));
 947        }
 948}
 949
 950void ConfigInfoView::saveSettings(void)
 951{
 952        if (name()) {
 953                configSettings->beginGroup(name());
 954                configSettings->writeEntry("/showDebug", showDebug());
 955                configSettings->endGroup();
 956        }
 957}
 958
 959void ConfigInfoView::setShowDebug(bool b)
 960{
 961        if (_showDebug != b) {
 962                _showDebug = b;
 963                if (menu)
 964                        menuInfo();
 965                else if (sym)
 966                        symbolInfo();
 967                emit showDebugChanged(b);
 968        }
 969}
 970
 971void ConfigInfoView::setInfo(struct menu *m)
 972{
 973        if (menu == m)
 974                return;
 975        menu = m;
 976        sym = NULL;
 977        if (!menu)
 978                clear();
 979        else
 980                menuInfo();
 981}
 982
 983void ConfigInfoView::symbolInfo(void)
 984{
 985        QString str;
 986
 987        str += "<big>Symbol: <b>";
 988        str += print_filter(sym->name);
 989        str += "</b></big><br><br>value: ";
 990        str += print_filter(sym_get_string_value(sym));
 991        str += "<br>visibility: ";
 992        str += sym->visible == yes ? "y" : sym->visible == mod ? "m" : "n";
 993        str += "<br>";
 994        str += debug_info(sym);
 995
 996        setText(str);
 997}
 998
 999void ConfigInfoView::menuInfo(void)
1000{
1001        struct symbol* sym;
1002        QString head, debug, help;
1003
1004        sym = menu->sym;
1005        if (sym) {
1006                if (menu->prompt) {
1007                        head += "<big><b>";
1008                        head += print_filter(_(menu->prompt->text));
1009                        head += "</b></big>";
1010                        if (sym->name) {
1011                                head += " (";
1012                                if (showDebug())
1013                                        head += QString().sprintf("<a href=\"s%p\">", sym);
1014                                head += print_filter(sym->name);
1015                                if (showDebug())
1016                                        head += "</a>";
1017                                head += ")";
1018                        }
1019                } else if (sym->name) {
1020                        head += "<big><b>";
1021                        if (showDebug())
1022                                head += QString().sprintf("<a href=\"s%p\">", sym);
1023                        head += print_filter(sym->name);
1024                        if (showDebug())
1025                                head += "</a>";
1026                        head += "</b></big>";
1027                }
1028                head += "<br><br>";
1029
1030                if (showDebug())
1031                        debug = debug_info(sym);
1032
1033                struct gstr help_gstr = str_new();
1034                menu_get_ext_help(menu, &help_gstr);
1035                help = print_filter(str_get(&help_gstr));
1036                str_free(&help_gstr);
1037        } else if (menu->prompt) {
1038                head += "<big><b>";
1039                head += print_filter(_(menu->prompt->text));
1040                head += "</b></big><br><br>";
1041                if (showDebug()) {
1042                        if (menu->prompt->visible.expr) {
1043                                debug += "&nbsp;&nbsp;dep: ";
1044                                expr_print(menu->prompt->visible.expr, expr_print_help, &debug, E_NONE);
1045                                debug += "<br><br>";
1046                        }
1047                }
1048        }
1049        if (showDebug())
1050                debug += QString().sprintf("defined at %s:%d<br><br>", menu->file->name, menu->lineno);
1051
1052        setText(head + debug + help);
1053}
1054
1055QString ConfigInfoView::debug_info(struct symbol *sym)
1056{
1057        QString debug;
1058
1059        debug += "type: ";
1060        debug += print_filter(sym_type_name(sym->type));
1061        if (sym_is_choice(sym))
1062                debug += " (choice)";
1063        debug += "<br>";
1064        if (sym->rev_dep.expr) {
1065                debug += "reverse dep: ";
1066                expr_print(sym->rev_dep.expr, expr_print_help, &debug, E_NONE);
1067                debug += "<br>";
1068        }
1069        for (struct property *prop = sym->prop; prop; prop = prop->next) {
1070                switch (prop->type) {
1071                case P_PROMPT:
1072                case P_MENU:
1073                        debug += QString().sprintf("prompt: <a href=\"m%p\">", prop->menu);
1074                        debug += print_filter(_(prop->text));
1075                        debug += "</a><br>";
1076                        break;
1077                case P_DEFAULT:
1078                case P_SELECT:
1079                case P_RANGE:
1080                case P_ENV:
1081                        debug += prop_get_type_name(prop->type);
1082                        debug += ": ";
1083                        expr_print(prop->expr, expr_print_help, &debug, E_NONE);
1084                        debug += "<br>";
1085                        break;
1086                case P_CHOICE:
1087                        if (sym_is_choice(sym)) {
1088                                debug += "choice: ";
1089                                expr_print(prop->expr, expr_print_help, &debug, E_NONE);
1090                                debug += "<br>";
1091                        }
1092                        break;
1093                default:
1094                        debug += "unknown property: ";
1095                        debug += prop_get_type_name(prop->type);
1096                        debug += "<br>";
1097                }
1098                if (prop->visible.expr) {
1099                        debug += "&nbsp;&nbsp;&nbsp;&nbsp;dep: ";
1100                        expr_print(prop->visible.expr, expr_print_help, &debug, E_NONE);
1101                        debug += "<br>";
1102                }
1103        }
1104        debug += "<br>";
1105
1106        return debug;
1107}
1108
1109QString ConfigInfoView::print_filter(const QString &str)
1110{
1111        QRegExp re("[<>&\"\\n]");
1112        QString res = str;
1113        for (int i = 0; (i = res.find(re, i)) >= 0;) {
1114                switch (res[i].latin1()) {
1115                case '<':
1116                        res.replace(i, 1, "&lt;");
1117                        i += 4;
1118                        break;
1119                case '>':
1120                        res.replace(i, 1, "&gt;");
1121                        i += 4;
1122                        break;
1123                case '&':
1124                        res.replace(i, 1, "&amp;");
1125                        i += 5;
1126                        break;
1127                case '"':
1128                        res.replace(i, 1, "&quot;");
1129                        i += 6;
1130                        break;
1131                case '\n':
1132                        res.replace(i, 1, "<br>");
1133                        i += 4;
1134                        break;
1135                }
1136        }
1137        return res;
1138}
1139
1140void ConfigInfoView::expr_print_help(void *data, struct symbol *sym, const char *str)
1141{
1142        QString* text = reinterpret_cast<QString*>(data);
1143        QString str2 = print_filter(str);
1144
1145        if (sym && sym->name && !(sym->flags & SYMBOL_CONST)) {
1146                *text += QString().sprintf("<a href=\"s%p\">", sym);
1147                *text += str2;
1148                *text += "</a>";
1149        } else
1150                *text += str2;
1151}
1152
1153QPopupMenu* ConfigInfoView::createPopupMenu(const QPoint& pos)
1154{
1155        QPopupMenu* popup = Parent::createPopupMenu(pos);
1156        QAction* action = new QAction(NULL, _("Show Debug Info"), 0, popup);
1157          action->setToggleAction(TRUE);
1158          connect(action, SIGNAL(toggled(bool)), SLOT(setShowDebug(bool)));
1159          connect(this, SIGNAL(showDebugChanged(bool)), action, SLOT(setOn(bool)));
1160          action->setOn(showDebug());
1161        popup->insertSeparator();
1162        action->addTo(popup);
1163        return popup;
1164}
1165
1166void ConfigInfoView::contentsContextMenuEvent(QContextMenuEvent *e)
1167{
1168        Parent::contentsContextMenuEvent(e);
1169}
1170
1171ConfigSearchWindow::ConfigSearchWindow(ConfigMainWindow* parent, const char *name)
1172        : Parent(parent, name), result(NULL)
1173{
1174        setCaption("Search Config");
1175
1176        QVBoxLayout* layout1 = new QVBoxLayout(this, 11, 6);
1177        QHBoxLayout* layout2 = new QHBoxLayout(0, 0, 6);
1178        layout2->addWidget(new QLabel(_("Find:"), this));
1179        editField = new QLineEdit(this);
1180        connect(editField, SIGNAL(returnPressed()), SLOT(search()));
1181        layout2->addWidget(editField);
1182        searchButton = new QPushButton(_("Search"), this);
1183        searchButton->setAutoDefault(FALSE);
1184        connect(searchButton, SIGNAL(clicked()), SLOT(search()));
1185        layout2->addWidget(searchButton);
1186        layout1->addLayout(layout2);
1187
1188        split = new QSplitter(this);
1189        split->setOrientation(Qt::Vertical);
1190        list = new ConfigView(split, name);
1191        list->list->mode = listMode;
1192        info = new ConfigInfoView(split, name);
1193        connect(list->list, SIGNAL(menuChanged(struct menu *)),
1194                info, SLOT(setInfo(struct menu *)));
1195        connect(list->list, SIGNAL(menuChanged(struct menu *)),
1196                parent, SLOT(setMenuLink(struct menu *)));
1197
1198        layout1->addWidget(split);
1199
1200        if (name) {
1201                int x, y, width, height;
1202                bool ok;
1203
1204                configSettings->beginGroup(name);
1205                width = configSettings->readNumEntry("/window width", parent->width() / 2);
1206                height = configSettings->readNumEntry("/window height", parent->height() / 2);
1207                resize(width, height);
1208                x = configSettings->readNumEntry("/window x", 0, &ok);
1209                if (ok)
1210                        y = configSettings->readNumEntry("/window y", 0, &ok);
1211                if (ok)
1212                        move(x, y);
1213                QValueList<int> sizes = configSettings->readSizes("/split", &ok);
1214                if (ok)
1215                        split->setSizes(sizes);
1216                configSettings->endGroup();
1217                connect(configApp, SIGNAL(aboutToQuit()), SLOT(saveSettings()));
1218        }
1219}
1220
1221void ConfigSearchWindow::saveSettings(void)
1222{
1223        if (name()) {
1224                configSettings->beginGroup(name());
1225                configSettings->writeEntry("/window x", pos().x());
1226                configSettings->writeEntry("/window y", pos().y());
1227                configSettings->writeEntry("/window width", size().width());
1228                configSettings->writeEntry("/window height", size().height());
1229                configSettings->writeSizes("/split", split->sizes());
1230                configSettings->endGroup();
1231        }
1232}
1233
1234void ConfigSearchWindow::search(void)
1235{
1236        struct symbol **p;
1237        struct property *prop;
1238        ConfigItem *lastItem = NULL;
1239
1240        free(result);
1241        list->list->clear();
1242        info->clear();
1243
1244        result = sym_re_search(editField->text().latin1());
1245        if (!result)
1246                return;
1247        for (p = result; *p; p++) {
1248                for_all_prompts((*p), prop)
1249                        lastItem = new ConfigItem(list->list, lastItem, prop->menu,
1250                                                  menu_is_visible(prop->menu));
1251        }
1252}
1253
1254/*
1255 * Construct the complete config widget
1256 */
1257ConfigMainWindow::ConfigMainWindow(void)
1258        : searchWindow(0)
1259{
1260        QMenuBar* menu;
1261        bool ok;
1262        int x, y, width, height;
1263        char title[256];
1264
1265        QDesktopWidget *d = configApp->desktop();
1266        snprintf(title, sizeof(title), _("Linux Kernel v%s Configuration"),
1267                getenv("KERNELVERSION"));
1268        setCaption(title);
1269
1270        width = configSettings->readNumEntry("/window width", d->width() - 64);
1271        height = configSettings->readNumEntry("/window height", d->height() - 64);
1272        resize(width, height);
1273        x = configSettings->readNumEntry("/window x", 0, &ok);
1274        if (ok)
1275                y = configSettings->readNumEntry("/window y", 0, &ok);
1276        if (ok)
1277                move(x, y);
1278
1279        split1 = new QSplitter(this);
1280        split1->setOrientation(Qt::Horizontal);
1281        setCentralWidget(split1);
1282
1283        menuView = new ConfigView(split1, "menu");
1284        menuList = menuView->list;
1285
1286        split2 = new QSplitter(split1);
1287        split2->setOrientation(Qt::Vertical);
1288
1289        // create config tree
1290        configView = new ConfigView(split2, "config");
1291        configList = configView->list;
1292
1293        helpText = new ConfigInfoView(split2, "help");
1294        helpText->setTextFormat(Qt::RichText);
1295
1296        setTabOrder(configList, helpText);
1297        configList->setFocus();
1298
1299        menu = menuBar();
1300        toolBar = new QToolBar("Tools", this);
1301
1302        backAction = new QAction("Back", QPixmap(xpm_back), _("Back"), 0, this);
1303          connect(backAction, SIGNAL(activated()), SLOT(goBack()));
1304          backAction->setEnabled(FALSE);
1305        QAction *quitAction = new QAction("Quit", _("&Quit"), Qt::CTRL + Qt::Key_Q, this);
1306          connect(quitAction, SIGNAL(activated()), SLOT(close()));
1307        QAction *loadAction = new QAction("Load", QPixmap(xpm_load), _("&Load"), Qt::CTRL + Qt::Key_L, this);
1308          connect(loadAction, SIGNAL(activated()), SLOT(loadConfig()));
1309        saveAction = new QAction("Save", QPixmap(xpm_save), _("&Save"), Qt::CTRL + Qt::Key_S, this);
1310          connect(saveAction, SIGNAL(activated()), SLOT(saveConfig()));
1311        conf_set_changed_callback(conf_changed);
1312        // Set saveAction's initial state
1313        conf_changed();
1314        QAction *saveAsAction = new QAction("Save As...", _("Save &As..."), 0, this);
1315          connect(saveAsAction, SIGNAL(activated()), SLOT(saveConfigAs()));
1316        QAction *searchAction = new QAction("Find", _("&Find"), Qt::CTRL + Qt::Key_F, this);
1317          connect(searchAction, SIGNAL(activated()), SLOT(searchConfig()));
1318        QAction *singleViewAction = new QAction("Single View", QPixmap(xpm_single_view), _("Single View"), 0, this);
1319          connect(singleViewAction, SIGNAL(activated()), SLOT(showSingleView()));
1320        QAction *splitViewAction = new QAction("Split View", QPixmap(xpm_split_view), _("Split View"), 0, this);
1321          connect(splitViewAction, SIGNAL(activated()), SLOT(showSplitView()));
1322        QAction *fullViewAction = new QAction("Full View", QPixmap(xpm_tree_view), _("Full View"), 0, this);
1323          connect(fullViewAction, SIGNAL(activated()), SLOT(showFullView()));
1324
1325        QAction *showNameAction = new QAction(NULL, _("Show Name"), 0, this);
1326          showNameAction->setToggleAction(TRUE);
1327          connect(showNameAction, SIGNAL(toggled(bool)), configView, SLOT(setShowName(bool)));
1328          connect(configView, SIGNAL(showNameChanged(bool)), showNameAction, SLOT(setOn(bool)));
1329          showNameAction->setOn(configView->showName());
1330        QAction *showRangeAction = new QAction(NULL, _("Show Range"), 0, this);
1331          showRangeAction->setToggleAction(TRUE);
1332          connect(showRangeAction, SIGNAL(toggled(bool)), configView, SLOT(setShowRange(bool)));
1333          connect(configView, SIGNAL(showRangeChanged(bool)), showRangeAction, SLOT(setOn(bool)));
1334          showRangeAction->setOn(configList->showRange);
1335        QAction *showDataAction = new QAction(NULL, _("Show Data"), 0, this);
1336          showDataAction->setToggleAction(TRUE);
1337          connect(showDataAction, SIGNAL(toggled(bool)), configView, SLOT(setShowData(bool)));
1338          connect(configView, SIGNAL(showDataChanged(bool)), showDataAction, SLOT(setOn(bool)));
1339          showDataAction->setOn(configList->showData);
1340
1341        QActionGroup *optGroup = new QActionGroup(this);
1342        optGroup->setExclusive(TRUE);
1343        connect(optGroup, SIGNAL(selected(QAction *)), configView,
1344                SLOT(setOptionMode(QAction *)));
1345        connect(optGroup, SIGNAL(selected(QAction *)), menuView,
1346                SLOT(setOptionMode(QAction *)));
1347
1348        configView->showNormalAction = new QAction(NULL, _("Show Normal Options"), 0, optGroup);
1349        configView->showAllAction = new QAction(NULL, _("Show All Options"), 0, optGroup);
1350        configView->showPromptAction = new QAction(NULL, _("Show Prompt Options"), 0, optGroup);
1351        configView->showNormalAction->setToggleAction(TRUE);
1352        configView->showNormalAction->setOn(configList->optMode == normalOpt);
1353        configView->showAllAction->setToggleAction(TRUE);
1354        configView->showAllAction->setOn(configList->optMode == allOpt);
1355        configView->showPromptAction->setToggleAction(TRUE);
1356        configView->showPromptAction->setOn(configList->optMode == promptOpt);
1357
1358        QAction *showDebugAction = new QAction(NULL, _("Show Debug Info"), 0, this);
1359          showDebugAction->setToggleAction(TRUE);
1360          connect(showDebugAction, SIGNAL(toggled(bool)), helpText, SLOT(setShowDebug(bool)));
1361          connect(helpText, SIGNAL(showDebugChanged(bool)), showDebugAction, SLOT(setOn(bool)));
1362          showDebugAction->setOn(helpText->showDebug());
1363
1364        QAction *showIntroAction = new QAction(NULL, _("Introduction"), 0, this);
1365          connect(showIntroAction, SIGNAL(activated()), SLOT(showIntro()));
1366        QAction *showAboutAction = new QAction(NULL, _("About"), 0, this);
1367          connect(showAboutAction, SIGNAL(activated()), SLOT(showAbout()));
1368
1369        // init tool bar
1370        backAction->addTo(toolBar);
1371        toolBar->addSeparator();
1372        loadAction->addTo(toolBar);
1373        saveAction->addTo(toolBar);
1374        toolBar->addSeparator();
1375        singleViewAction->addTo(toolBar);
1376        splitViewAction->addTo(toolBar);
1377        fullViewAction->addTo(toolBar);
1378
1379        // create config menu
1380        QPopupMenu* config = new QPopupMenu(this);
1381        menu->insertItem(_("&File"), config);
1382        loadAction->addTo(config);
1383        saveAction->addTo(config);
1384        saveAsAction->addTo(config);
1385        config->insertSeparator();
1386        quitAction->addTo(config);
1387
1388        // create edit menu
1389        QPopupMenu* editMenu = new QPopupMenu(this);
1390        menu->insertItem(_("&Edit"), editMenu);
1391        searchAction->addTo(editMenu);
1392
1393        // create options menu
1394        QPopupMenu* optionMenu = new QPopupMenu(this);
1395        menu->insertItem(_("&Option"), optionMenu);
1396        showNameAction->addTo(optionMenu);
1397        showRangeAction->addTo(optionMenu);
1398        showDataAction->addTo(optionMenu);
1399        optionMenu->insertSeparator();
1400        optGroup->addTo(optionMenu);
1401        optionMenu->insertSeparator();
1402        showDebugAction->addTo(optionMenu);
1403
1404        // create help menu
1405        QPopupMenu* helpMenu = new QPopupMenu(this);
1406        menu->insertSeparator();
1407        menu->insertItem(_("&Help"), helpMenu);
1408        showIntroAction->addTo(helpMenu);
1409        showAboutAction->addTo(helpMenu);
1410
1411        connect(configList, SIGNAL(menuChanged(struct menu *)),
1412                helpText, SLOT(setInfo(struct menu *)));
1413        connect(configList, SIGNAL(menuSelected(struct menu *)),
1414                SLOT(changeMenu(struct menu *)));
1415        connect(configList, SIGNAL(parentSelected()),
1416                SLOT(goBack()));
1417        connect(menuList, SIGNAL(menuChanged(struct menu *)),
1418                helpText, SLOT(setInfo(struct menu *)));
1419        connect(menuList, SIGNAL(menuSelected(struct menu *)),
1420                SLOT(changeMenu(struct menu *)));
1421
1422        connect(configList, SIGNAL(gotFocus(struct menu *)),
1423                helpText, SLOT(setInfo(struct menu *)));
1424        connect(menuList, SIGNAL(gotFocus(struct menu *)),
1425                helpText, SLOT(setInfo(struct menu *)));
1426        connect(menuList, SIGNAL(gotFocus(struct menu *)),
1427                SLOT(listFocusChanged(void)));
1428        connect(helpText, SIGNAL(menuSelected(struct menu *)),
1429                SLOT(setMenuLink(struct menu *)));
1430
1431        QString listMode = configSettings->readEntry("/listMode", "symbol");
1432        if (listMode == "single")
1433                showSingleView();
1434        else if (listMode == "full")
1435                showFullView();
1436        else /*if (listMode == "split")*/
1437                showSplitView();
1438
1439        // UI setup done, restore splitter positions
1440        QValueList<int> sizes = configSettings->readSizes("/split1", &ok);
1441        if (ok)
1442                split1->setSizes(sizes);
1443
1444        sizes = configSettings->readSizes("/split2", &ok);
1445        if (ok)
1446                split2->setSizes(sizes);
1447}
1448
1449void ConfigMainWindow::loadConfig(void)
1450{
1451        QString s = QFileDialog::getOpenFileName(conf_get_configname(), NULL, this);
1452        if (s.isNull())
1453                return;
1454        if (conf_read(QFile::encodeName(s)))
1455                QMessageBox::information(this, "qconf", _("Unable to load configuration!"));
1456        ConfigView::updateListAll();
1457}
1458
1459void ConfigMainWindow::saveConfig(void)
1460{
1461        if (conf_write(NULL))
1462                QMessageBox::information(this, "qconf", _("Unable to save configuration!"));
1463}
1464
1465void ConfigMainWindow::saveConfigAs(void)
1466{
1467        QString s = QFileDialog::getSaveFileName(conf_get_configname(), NULL, this);
1468        if (s.isNull())
1469                return;
1470        if (conf_write(QFile::encodeName(s)))
1471                QMessageBox::information(this, "qconf", _("Unable to save configuration!"));
1472}
1473
1474void ConfigMainWindow::searchConfig(void)
1475{
1476        if (!searchWindow)
1477                searchWindow = new ConfigSearchWindow(this, "search");
1478        searchWindow->show();
1479}
1480
1481void ConfigMainWindow::changeMenu(struct menu *menu)
1482{
1483        configList->setRootMenu(menu);
1484        if (configList->rootEntry->parent == &rootmenu)
1485                backAction->setEnabled(FALSE);
1486        else
1487                backAction->setEnabled(TRUE);
1488}
1489
1490void ConfigMainWindow::setMenuLink(struct menu *menu)
1491{
1492        struct menu *parent;
1493        ConfigList* list = NULL;
1494        ConfigItem* item;
1495
1496        if (configList->menuSkip(menu))
1497                return;
1498
1499        switch (configList->mode) {
1500        case singleMode:
1501                list = configList;
1502                parent = menu_get_parent_menu(menu);
1503                if (!parent)
1504                        return;
1505                list->setRootMenu(parent);
1506                break;
1507        case symbolMode:
1508                if (menu->flags & MENU_ROOT) {
1509                        configList->setRootMenu(menu);
1510                        configList->clearSelection();
1511                        list = menuList;
1512                } else {
1513                        list = configList;
1514                        parent = menu_get_parent_menu(menu->parent);
1515                        if (!parent)
1516                                return;
1517                        item = menuList->findConfigItem(parent);
1518                        if (item) {
1519                                menuList->setSelected(item, TRUE);
1520                                menuList->ensureItemVisible(item);
1521                        }
1522                        list->setRootMenu(parent);
1523                }
1524                break;
1525        case fullMode:
1526                list = configList;
1527                break;
1528        default:
1529                break;
1530        }
1531
1532        if (list) {
1533                item = list->findConfigItem(menu);
1534                if (item) {
1535                        list->setSelected(item, TRUE);
1536                        list->ensureItemVisible(item);
1537                        list->setFocus();
1538                }
1539        }
1540}
1541
1542void ConfigMainWindow::listFocusChanged(void)
1543{
1544        if (menuList->mode == menuMode)
1545                configList->clearSelection();
1546}
1547
1548void ConfigMainWindow::goBack(void)
1549{
1550        ConfigItem* item;
1551
1552        configList->setParentMenu();
1553        if (configList->rootEntry == &rootmenu)
1554                backAction->setEnabled(FALSE);
1555        item = (ConfigItem*)menuList->selectedItem();
1556        while (item) {
1557                if (item->menu == configList->rootEntry) {
1558                        menuList->setSelected(item, TRUE);
1559                        break;
1560                }
1561                item = (ConfigItem*)item->parent();
1562        }
1563}
1564
1565void ConfigMainWindow::showSingleView(void)
1566{
1567        menuView->hide();
1568        menuList->setRootMenu(0);
1569        configList->mode = singleMode;
1570        if (configList->rootEntry == &rootmenu)
1571                configList->updateListAll();
1572        else
1573                configList->setRootMenu(&rootmenu);
1574        configList->setAllOpen(TRUE);
1575        configList->setFocus();
1576}
1577
1578void ConfigMainWindow::showSplitView(void)
1579{
1580        configList->mode = symbolMode;
1581        if (configList->rootEntry == &rootmenu)
1582                configList->updateListAll();
1583        else
1584                configList->setRootMenu(&rootmenu);
1585        configList->setAllOpen(TRUE);
1586        configApp->processEvents();
1587        menuList->mode = menuMode;
1588        menuList->setRootMenu(&rootmenu);
1589        menuList->setAllOpen(TRUE);
1590        menuView->show();
1591        menuList->setFocus();
1592}
1593
1594void ConfigMainWindow::showFullView(void)
1595{
1596        menuView->hide();
1597        menuList->setRootMenu(0);
1598        configList->mode = fullMode;
1599        if (configList->rootEntry == &rootmenu)
1600                configList->updateListAll();
1601        else
1602                configList->setRootMenu(&rootmenu);
1603        configList->setAllOpen(FALSE);
1604        configList->setFocus();
1605}
1606
1607/*
1608 * ask for saving configuration before quitting
1609 * TODO ask only when something changed
1610 */
1611void ConfigMainWindow::closeEvent(QCloseEvent* e)
1612{
1613        if (!conf_get_changed()) {
1614                e->accept();
1615                return;
1616        }
1617        QMessageBox mb("qconf", _("Save configuration?"), QMessageBox::Warning,
1618                        QMessageBox::Yes | QMessageBox::Default, QMessageBox::No, QMessageBox::Cancel | QMessageBox::Escape);
1619        mb.setButtonText(QMessageBox::Yes, _("&Save Changes"));
1620        mb.setButtonText(QMessageBox::No, _("&Discard Changes"));
1621        mb.setButtonText(QMessageBox::Cancel, _("Cancel Exit"));
1622        switch (mb.exec()) {
1623        case QMessageBox::Yes:
1624                conf_write(NULL);
1625        case QMessageBox::No:
1626                e->accept();
1627                break;
1628        case QMessageBox::Cancel:
1629                e->ignore();
1630                break;
1631        }
1632}
1633
1634void ConfigMainWindow::showIntro(void)
1635{
1636        static const QString str = _("Welcome to the qconf graphical kernel configuration tool for Linux.\n\n"
1637                "For each option, a blank box indicates the feature is disabled, a check\n"
1638                "indicates it is enabled, and a dot indicates that it is to be compiled\n"
1639                "as a module.  Clicking on the box will cycle through the three states.\n\n"
1640                "If you do not see an option (e.g., a device driver) that you believe\n"
1641                "should be present, try turning on Show All Options under the Options menu.\n"
1642                "Although there is no cross reference yet to help you figure out what other\n"
1643                "options must be enabled to support the option you are interested in, you can\n"
1644                "still view the help of a grayed-out option.\n\n"
1645                "Toggling Show Debug Info under the Options menu will show the dependencies,\n"
1646                "which you can then match by examining other options.\n\n");
1647
1648        QMessageBox::information(this, "qconf", str);
1649}
1650
1651void ConfigMainWindow::showAbout(void)
1652{
1653        static const QString str = _("qconf is Copyright (C) 2002 Roman Zippel <zippel@linux-m68k.org>.\n\n"
1654                "Bug reports and feature request can also be entered at http://bugzilla.kernel.org/\n");
1655
1656        QMessageBox::information(this, "qconf", str);
1657}
1658
1659void ConfigMainWindow::saveSettings(void)
1660{
1661        configSettings->writeEntry("/window x", pos().x());
1662        configSettings->writeEntry("/window y", pos().y());
1663        configSettings->writeEntry("/window width", size().width());
1664        configSettings->writeEntry("/window height", size().height());
1665
1666        QString entry;
1667        switch(configList->mode) {
1668        case singleMode :
1669                entry = "single";
1670                break;
1671
1672        case symbolMode :
1673                entry = "split";
1674                break;
1675
1676        case fullMode :
1677                entry = "full";
1678                break;
1679
1680        default:
1681                break;
1682        }
1683        configSettings->writeEntry("/listMode", entry);
1684
1685        configSettings->writeSizes("/split1", split1->sizes());
1686        configSettings->writeSizes("/split2", split2->sizes());
1687}
1688
1689void ConfigMainWindow::conf_changed(void)
1690{
1691        if (saveAction)
1692                saveAction->setEnabled(conf_get_changed());
1693}
1694
1695void fixup_rootmenu(struct menu *menu)
1696{
1697        struct menu *child;
1698        static int menu_cnt = 0;
1699
1700        menu->flags |= MENU_ROOT;
1701        for (child = menu->list; child; child = child->next) {
1702                if (child->prompt && child->prompt->type == P_MENU) {
1703                        menu_cnt++;
1704                        fixup_rootmenu(child);
1705                        menu_cnt--;
1706                } else if (!menu_cnt)
1707                        fixup_rootmenu(child);
1708        }
1709}
1710
1711static const char *progname;
1712
1713static void usage(void)
1714{
1715        printf(_("%s <config>\n"), progname);
1716        exit(0);
1717}
1718
1719int main(int ac, char** av)
1720{
1721        ConfigMainWindow* v;
1722        const char *name;
1723
1724        bindtextdomain(PACKAGE, LOCALEDIR);
1725        textdomain(PACKAGE);
1726
1727#ifndef LKC_DIRECT_LINK
1728        kconfig_load();
1729#endif
1730
1731        progname = av[0];
1732        configApp = new QApplication(ac, av);
1733        if (ac > 1 && av[1][0] == '-') {
1734                switch (av[1][1]) {
1735                case 'h':
1736                case '?':
1737                        usage();
1738                }
1739                name = av[2];
1740        } else
1741                name = av[1];
1742        if (!name)
1743                usage();
1744
1745        conf_parse(name);
1746        fixup_rootmenu(&rootmenu);
1747        conf_read(NULL);
1748        //zconfdump(stdout);
1749
1750        configSettings = new ConfigSettings();
1751        configSettings->beginGroup("/kconfig/qconf");
1752        v = new ConfigMainWindow();
1753
1754        //zconfdump(stdout);
1755        configApp->setMainWidget(v);
1756        configApp->connect(configApp, SIGNAL(lastWindowClosed()), SLOT(quit()));
1757        configApp->connect(configApp, SIGNAL(aboutToQuit()), v, SLOT(saveSettings()));
1758        v->show();
1759        configApp->exec();
1760
1761        configSettings->endGroup();
1762        delete configSettings;
1763
1764        return 0;
1765}
1766