source: MondoRescue/branches/stable/mindi-busybox/scripts/kconfig/qconf.cc @ 1770

Last change on this file since 1770 was 1765, checked in by Bruno Cornec, 12 years ago

Update to busybox 1.7.2

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