source: drbl_ui/backup/test_busybox/busybox-1.7.2/scripts/kconfig/qconf.cc @ 200

Last change on this file since 200 was 20, checked in by chris, 17 years ago
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.