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