Root/scripts/kconfig/qconf.cc

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
1481void ConfigMainWindow::saveConfig(void)
1482{
1483    if (conf_write(NULL))
1484        QMessageBox::information(this, "qconf", _("Unable to save configuration!"));
1485}
1486
1487void ConfigMainWindow::saveConfigAs(void)
1488{
1489    QString s = Q3FileDialog::getSaveFileName(conf_get_configname(), NULL, this);
1490    if (s.isNull())
1491        return;
1492    saveConfig();
1493}
1494
1495void ConfigMainWindow::searchConfig(void)
1496{
1497    if (!searchWindow)
1498        searchWindow = new ConfigSearchWindow(this, "search");
1499    searchWindow->show();
1500}
1501
1502void ConfigMainWindow::changeMenu(struct menu *menu)
1503{
1504    configList->setRootMenu(menu);
1505    if (configList->rootEntry->parent == &rootmenu)
1506        backAction->setEnabled(FALSE);
1507    else
1508        backAction->setEnabled(TRUE);
1509}
1510
1511void ConfigMainWindow::setMenuLink(struct menu *menu)
1512{
1513    struct menu *parent;
1514    ConfigList* list = NULL;
1515    ConfigItem* item;
1516
1517    if (configList->menuSkip(menu))
1518        return;
1519
1520    switch (configList->mode) {
1521    case singleMode:
1522        list = configList;
1523        parent = menu_get_parent_menu(menu);
1524        if (!parent)
1525            return;
1526        list->setRootMenu(parent);
1527        break;
1528    case symbolMode:
1529        if (menu->flags & MENU_ROOT) {
1530            configList->setRootMenu(menu);
1531            configList->clearSelection();
1532            list = menuList;
1533        } else {
1534            list = configList;
1535            parent = menu_get_parent_menu(menu->parent);
1536            if (!parent)
1537                return;
1538            item = menuList->findConfigItem(parent);
1539            if (item) {
1540                menuList->setSelected(item, TRUE);
1541                menuList->ensureItemVisible(item);
1542            }
1543            list->setRootMenu(parent);
1544        }
1545        break;
1546    case fullMode:
1547        list = configList;
1548        break;
1549    default:
1550        break;
1551    }
1552
1553    if (list) {
1554        item = list->findConfigItem(menu);
1555        if (item) {
1556            list->setSelected(item, TRUE);
1557            list->ensureItemVisible(item);
1558            list->setFocus();
1559        }
1560    }
1561}
1562
1563void ConfigMainWindow::listFocusChanged(void)
1564{
1565    if (menuList->mode == menuMode)
1566        configList->clearSelection();
1567}
1568
1569void ConfigMainWindow::goBack(void)
1570{
1571    ConfigItem* item;
1572
1573    configList->setParentMenu();
1574    if (configList->rootEntry == &rootmenu)
1575        backAction->setEnabled(FALSE);
1576    item = (ConfigItem*)menuList->selectedItem();
1577    while (item) {
1578        if (item->menu == configList->rootEntry) {
1579            menuList->setSelected(item, TRUE);
1580            break;
1581        }
1582        item = (ConfigItem*)item->parent();
1583    }
1584}
1585
1586void ConfigMainWindow::showSingleView(void)
1587{
1588    menuView->hide();
1589    menuList->setRootMenu(0);
1590    configList->mode = singleMode;
1591    if (configList->rootEntry == &rootmenu)
1592        configList->updateListAll();
1593    else
1594        configList->setRootMenu(&rootmenu);
1595    configList->setAllOpen(TRUE);
1596    configList->setFocus();
1597}
1598
1599void ConfigMainWindow::showSplitView(void)
1600{
1601    configList->mode = symbolMode;
1602    if (configList->rootEntry == &rootmenu)
1603        configList->updateListAll();
1604    else
1605        configList->setRootMenu(&rootmenu);
1606    configList->setAllOpen(TRUE);
1607    configApp->processEvents();
1608    menuList->mode = menuMode;
1609    menuList->setRootMenu(&rootmenu);
1610    menuList->setAllOpen(TRUE);
1611    menuView->show();
1612    menuList->setFocus();
1613}
1614
1615void ConfigMainWindow::showFullView(void)
1616{
1617    menuView->hide();
1618    menuList->setRootMenu(0);
1619    configList->mode = fullMode;
1620    if (configList->rootEntry == &rootmenu)
1621        configList->updateListAll();
1622    else
1623        configList->setRootMenu(&rootmenu);
1624    configList->setAllOpen(FALSE);
1625    configList->setFocus();
1626}
1627
1628/*
1629 * ask for saving configuration before quitting
1630 * TODO ask only when something changed
1631 */
1632void ConfigMainWindow::closeEvent(QCloseEvent* e)
1633{
1634    if (!conf_get_changed()) {
1635        e->accept();
1636        return;
1637    }
1638    QMessageBox mb("qconf", _("Save configuration?"), QMessageBox::Warning,
1639            QMessageBox::Yes | QMessageBox::Default, QMessageBox::No, QMessageBox::Cancel | QMessageBox::Escape);
1640    mb.setButtonText(QMessageBox::Yes, _("&Save Changes"));
1641    mb.setButtonText(QMessageBox::No, _("&Discard Changes"));
1642    mb.setButtonText(QMessageBox::Cancel, _("Cancel Exit"));
1643    switch (mb.exec()) {
1644    case QMessageBox::Yes:
1645        saveConfig();
1646    case QMessageBox::No:
1647        e->accept();
1648        break;
1649    case QMessageBox::Cancel:
1650        e->ignore();
1651        break;
1652    }
1653}
1654
1655void ConfigMainWindow::showIntro(void)
1656{
1657    static const QString str = _("Welcome to the qconf graphical configuration tool.\n\n"
1658        "For each option, a blank box indicates the feature is disabled, a check\n"
1659        "indicates it is enabled, and a dot indicates that it is to be compiled\n"
1660        "as a module. Clicking on the box will cycle through the three states.\n\n"
1661        "If you do not see an option (e.g., a device driver) that you believe\n"
1662        "should be present, try turning on Show All Options under the Options menu.\n"
1663        "Although there is no cross reference yet to help you figure out what other\n"
1664        "options must be enabled to support the option you are interested in, you can\n"
1665        "still view the help of a grayed-out option.\n\n"
1666        "Toggling Show Debug Info under the Options menu will show the dependencies,\n"
1667        "which you can then match by examining other options.\n\n");
1668
1669    QMessageBox::information(this, "qconf", str);
1670}
1671
1672void ConfigMainWindow::showAbout(void)
1673{
1674    static const QString str = _("qconf is Copyright (C) 2002 Roman Zippel <zippel@linux-m68k.org>.\n\n"
1675        "Bug reports and feature request can also be entered at http://bugzilla.kernel.org/\n");
1676
1677    QMessageBox::information(this, "qconf", str);
1678}
1679
1680void ConfigMainWindow::saveSettings(void)
1681{
1682    configSettings->writeEntry("/window x", pos().x());
1683    configSettings->writeEntry("/window y", pos().y());
1684    configSettings->writeEntry("/window width", size().width());
1685    configSettings->writeEntry("/window height", size().height());
1686
1687    QString entry;
1688    switch(configList->mode) {
1689    case singleMode :
1690        entry = "single";
1691        break;
1692
1693    case symbolMode :
1694        entry = "split";
1695        break;
1696
1697    case fullMode :
1698        entry = "full";
1699        break;
1700
1701    default:
1702        break;
1703    }
1704    configSettings->writeEntry("/listMode", entry);
1705
1706    configSettings->writeSizes("/split1", split1->sizes());
1707    configSettings->writeSizes("/split2", split2->sizes());
1708}
1709
1710void ConfigMainWindow::conf_changed(void)
1711{
1712    if (saveAction)
1713        saveAction->setEnabled(conf_get_changed());
1714}
1715
1716void fixup_rootmenu(struct menu *menu)
1717{
1718    struct menu *child;
1719    static int menu_cnt = 0;
1720
1721    menu->flags |= MENU_ROOT;
1722    for (child = menu->list; child; child = child->next) {
1723        if (child->prompt && child->prompt->type == P_MENU) {
1724            menu_cnt++;
1725            fixup_rootmenu(child);
1726            menu_cnt--;
1727        } else if (!menu_cnt)
1728            fixup_rootmenu(child);
1729    }
1730}
1731
1732static const char *progname;
1733
1734static void usage(void)
1735{
1736    printf(_("%s <config>\n"), progname);
1737    exit(0);
1738}
1739
1740int main(int ac, char** av)
1741{
1742    ConfigMainWindow* v;
1743    const char *name;
1744
1745    bindtextdomain(PACKAGE, LOCALEDIR);
1746    textdomain(PACKAGE);
1747
1748#ifndef LKC_DIRECT_LINK
1749    kconfig_load();
1750#endif
1751
1752    progname = av[0];
1753    configApp = new QApplication(ac, av);
1754    if (ac > 1 && av[1][0] == '-') {
1755        switch (av[1][1]) {
1756        case 'h':
1757        case '?':
1758            usage();
1759        }
1760        name = av[2];
1761    } else
1762        name = av[1];
1763    if (!name)
1764        usage();
1765
1766    conf_parse(name);
1767    fixup_rootmenu(&rootmenu);
1768    conf_read(NULL);
1769    //zconfdump(stdout);
1770
1771    configSettings = new ConfigSettings();
1772    configSettings->beginGroup("/kconfig/qconf");
1773    v = new ConfigMainWindow();
1774
1775    //zconfdump(stdout);
1776    configApp->setMainWidget(v);
1777    configApp->connect(configApp, SIGNAL(lastWindowClosed()), SLOT(quit()));
1778    configApp->connect(configApp, SIGNAL(aboutToQuit()), v, SLOT(saveSettings()));
1779    v->show();
1780    configApp->exec();
1781
1782    configSettings->endGroup();
1783    delete configSettings;
1784
1785    return 0;
1786}
1787

Archive Download this file



interactive