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