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