2 * Copyright (C) 2002 Roman Zippel <zippel@linux-m68k.org>
3 * Copyright (C) 2015 Boris Barbulovski <bbarbulovski@gmail.com>
4 * Released under the terms of the GNU GPL v2.0.
11 #include <qtextbrowser.h>
13 #include <QFileDialog>
16 #include <qapplication.h>
17 #include <qdesktopwidget.h>
20 #include <qsplitter.h>
21 #include <qlineedit.h>
23 #include <qpushbutton.h>
25 #include <qmessagebox.h>
42 static QApplication
*configApp
;
43 static ConfigSettings
*configSettings
;
45 QAction
*ConfigMainWindow::saveAction
;
47 static inline QString
qgettext(const char* str
)
49 return QString::fromLocal8Bit(gettext(str
));
52 static inline QString
qgettext(const QString
& str
)
54 return QString::fromLocal8Bit(gettext(str
.toLatin1()));
57 ConfigSettings::ConfigSettings()
58 : QSettings("kernel.org", "qconf")
63 * Reads a list of integer values from the application settings.
65 QList
<int> ConfigSettings::readSizes(const QString
& key
, bool *ok
)
71 QStringList entryList
= value(key
).toStringList();
72 QStringList::Iterator it
;
74 for (it
= entryList
.begin(); it
!= entryList
.end(); ++it
)
75 result
.push_back((*it
).toInt());
86 * Writes a list of integer values to the application settings.
88 bool ConfigSettings::writeSizes(const QString
& key
, const QList
<int>& value
)
90 QStringList stringList
;
91 QList
<int>::ConstIterator it
;
93 for (it
= value
.begin(); it
!= value
.end(); ++it
)
94 stringList
.push_back(QString::number(*it
));
95 setValue(key
, stringList
);
103 * TODO check the value
105 void ConfigItem::okRename(int col
)
110 * update the displayed of a menu entry
112 void ConfigItem::updateMenu(void)
116 struct property
*prop
;
123 setPixmap(promptColIdx
, list
->menuBackPix
);
130 prompt
= _(menu_get_prompt(menu
));
132 if (prop
) switch (prop
->type
) {
134 if (list
->mode
== singleMode
|| list
->mode
== symbolMode
) {
135 /* a menuconfig entry is displayed differently
136 * depending whether it's at the view root or a child.
138 if (sym
&& list
->rootEntry
== menu
)
140 setPixmap(promptColIdx
, list
->menuPix
);
144 setPixmap(promptColIdx
, QIcon());
148 setPixmap(promptColIdx
, QIcon());
156 setText(nameColIdx
, QString::fromLocal8Bit(sym
->name
));
158 type
= sym_get_type(sym
);
164 if (!sym_is_changable(sym
) && list
->optMode
== normalOpt
) {
165 setPixmap(promptColIdx
, QIcon());
166 setText(noColIdx
, QString::null
);
167 setText(modColIdx
, QString::null
);
168 setText(yesColIdx
, QString::null
);
171 expr
= sym_get_tristate_value(sym
);
174 if (sym_is_choice_value(sym
) && type
== S_BOOLEAN
)
175 setPixmap(promptColIdx
, list
->choiceYesPix
);
177 setPixmap(promptColIdx
, list
->symbolYesPix
);
178 setText(yesColIdx
, "Y");
182 setPixmap(promptColIdx
, list
->symbolModPix
);
183 setText(modColIdx
, "M");
187 if (sym_is_choice_value(sym
) && type
== S_BOOLEAN
)
188 setPixmap(promptColIdx
, list
->choiceNoPix
);
190 setPixmap(promptColIdx
, list
->symbolNoPix
);
191 setText(noColIdx
, "N");
196 setText(noColIdx
, sym_tristate_within_range(sym
, no
) ? "_" : 0);
198 setText(modColIdx
, sym_tristate_within_range(sym
, mod
) ? "_" : 0);
200 setText(yesColIdx
, sym_tristate_within_range(sym
, yes
) ? "_" : 0);
202 setText(dataColIdx
, QChar(ch
));
209 data
= sym_get_string_value(sym
);
211 setText(dataColIdx
, data
);
212 if (type
== S_STRING
)
213 prompt
= QString("%1: %2").arg(prompt
).arg(data
);
215 prompt
= QString("(%2) %1").arg(prompt
).arg(data
);
218 if (!sym_has_value(sym
) && visible
)
219 prompt
+= _(" (NEW)");
221 setText(promptColIdx
, prompt
);
224 void ConfigItem::testUpdateMenu(bool v
)
232 sym_calc_value(menu
->sym
);
233 if (menu
->flags
& MENU_CHANGED
) {
234 /* the menu entry changed, so update all list items */
235 menu
->flags
&= ~MENU_CHANGED
;
236 for (i
= (ConfigItem
*)menu
->data
; i
; i
= i
->nextItem
)
238 } else if (listView()->updateAll
)
244 * construct a menu entry
246 void ConfigItem::init(void)
249 ConfigList
* list
= listView();
250 nextItem
= (ConfigItem
*)menu
->data
;
253 if (list
->mode
!= fullMode
)
255 sym_calc_value(menu
->sym
);
261 * destruct a menu entry
263 ConfigItem::~ConfigItem(void)
266 ConfigItem
** ip
= (ConfigItem
**)&menu
->data
;
267 for (; *ip
; ip
= &(*ip
)->nextItem
) {
276 ConfigLineEdit::ConfigLineEdit(ConfigView
* parent
)
279 connect(this, SIGNAL(editingFinished()), SLOT(hide()));
282 void ConfigLineEdit::show(ConfigItem
* i
)
285 if (sym_get_string_value(item
->menu
->sym
))
286 setText(QString::fromLocal8Bit(sym_get_string_value(item
->menu
->sym
)));
288 setText(QString::null
);
293 void ConfigLineEdit::keyPressEvent(QKeyEvent
* e
)
300 sym_set_string_value(item
->menu
->sym
, text().toLatin1());
301 parent()->updateList(item
);
304 Parent::keyPressEvent(e
);
308 parent()->list
->setFocus();
312 ConfigList::ConfigList(ConfigView
* p
, const char *name
)
315 symbolYesPix(xpm_symbol_yes
), symbolModPix(xpm_symbol_mod
), symbolNoPix(xpm_symbol_no
),
316 choiceYesPix(xpm_choice_yes
), choiceNoPix(xpm_choice_no
),
317 menuPix(xpm_menu
), menuInvPix(xpm_menu_inv
), menuBackPix(xpm_menuback
), voidPix(xpm_void
),
318 showName(false), showRange(false), showData(false), mode(singleMode
), optMode(normalOpt
),
319 rootEntry(0), headerPopup(0)
324 setSortingEnabled(false);
325 setRootIsDecorated(true);
327 setVerticalScrollMode(ScrollPerPixel
);
328 setHorizontalScrollMode(ScrollPerPixel
);
330 setHeaderLabels(QStringList() << _("Option") << _("Name") << "N" << "M" << "Y" << _("Value"));
332 connect(this, SIGNAL(itemSelectionChanged(void)),
333 SLOT(updateSelection(void)));
336 configSettings
->beginGroup(name
);
337 showName
= configSettings
->value("/showName", false).toBool();
338 showRange
= configSettings
->value("/showRange", false).toBool();
339 showData
= configSettings
->value("/showData", false).toBool();
340 optMode
= (enum optionMode
)configSettings
->value("/optionMode", 0).toInt();
341 configSettings
->endGroup();
342 connect(configApp
, SIGNAL(aboutToQuit()), SLOT(saveSettings()));
345 addColumn(promptColIdx
);
350 bool ConfigList::menuSkip(struct menu
*menu
)
352 if (optMode
== normalOpt
&& menu_is_visible(menu
))
354 if (optMode
== promptOpt
&& menu_has_prompt(menu
))
356 if (optMode
== allOpt
)
361 void ConfigList::reinit(void)
363 removeColumn(dataColIdx
);
364 removeColumn(yesColIdx
);
365 removeColumn(modColIdx
);
366 removeColumn(noColIdx
);
367 removeColumn(nameColIdx
);
370 addColumn(nameColIdx
);
373 addColumn(modColIdx
);
374 addColumn(yesColIdx
);
377 addColumn(dataColIdx
);
382 void ConfigList::saveSettings(void)
384 if (!objectName().isEmpty()) {
385 configSettings
->beginGroup(objectName());
386 configSettings
->setValue("/showName", showName
);
387 configSettings
->setValue("/showRange", showRange
);
388 configSettings
->setValue("/showData", showData
);
389 configSettings
->setValue("/optionMode", (int)optMode
);
390 configSettings
->endGroup();
394 ConfigItem
* ConfigList::findConfigItem(struct menu
*menu
)
396 ConfigItem
* item
= (ConfigItem
*)menu
->data
;
398 for (; item
; item
= item
->nextItem
) {
399 if (this == item
->listView())
406 void ConfigList::updateSelection(void)
411 if (selectedItems().count() == 0)
414 ConfigItem
* item
= (ConfigItem
*)selectedItems().first();
419 emit
menuChanged(menu
);
422 type
= menu
->prompt
? menu
->prompt
->type
: P_UNKNOWN
;
423 if (mode
== menuMode
&& type
== P_MENU
)
424 emit
menuSelected(menu
);
427 void ConfigList::updateList(ConfigItem
* item
)
429 ConfigItem
* last
= 0;
432 if (mode
!= listMode
)
434 QTreeWidgetItemIterator
it(this);
438 item
= (ConfigItem
*)(*it
);
441 item
->testUpdateMenu(menu_is_visible(item
->menu
));
448 if (rootEntry
!= &rootmenu
&& (mode
== singleMode
||
449 (mode
== symbolMode
&& rootEntry
->parent
!= &rootmenu
))) {
450 item
= (ConfigItem
*)topLevelItem(0);
452 item
= new ConfigItem(this, 0, true);
455 if ((mode
== singleMode
|| (mode
== symbolMode
&& !(rootEntry
->flags
& MENU_ROOT
))) &&
456 rootEntry
->sym
&& rootEntry
->prompt
) {
457 item
= last
? last
->nextSibling() : firstChild();
459 item
= new ConfigItem(this, last
, rootEntry
, true);
461 item
->testUpdateMenu(true);
463 updateMenuList(item
, rootEntry
);
465 resizeColumnToContents(0);
469 updateMenuList(this, rootEntry
);
471 resizeColumnToContents(0);
474 void ConfigList::setValue(ConfigItem
* item
, tristate val
)
480 sym
= item
->menu
? item
->menu
->sym
: 0;
484 type
= sym_get_type(sym
);
488 oldval
= sym_get_tristate_value(sym
);
490 if (!sym_set_tristate_value(sym
, val
))
492 if (oldval
== no
&& item
->menu
->list
)
493 item
->setExpanded(true);
494 parent()->updateList(item
);
499 void ConfigList::changeValue(ConfigItem
* item
)
503 int type
, oldexpr
, newexpr
;
510 if (item
->menu
->list
)
511 item
->setExpanded(!item
->isExpanded());
515 type
= sym_get_type(sym
);
519 oldexpr
= sym_get_tristate_value(sym
);
520 newexpr
= sym_toggle_tristate_value(sym
);
521 if (item
->menu
->list
) {
522 if (oldexpr
== newexpr
)
523 item
->setExpanded(!item
->isExpanded());
524 else if (oldexpr
== no
)
525 item
->setExpanded(true);
527 if (oldexpr
!= newexpr
)
528 parent()->updateList(item
);
533 parent()->lineEdit
->show(item
);
538 void ConfigList::setRootMenu(struct menu
*menu
)
542 if (rootEntry
== menu
)
544 type
= menu
&& menu
->prompt
? menu
->prompt
->type
: P_UNKNOWN
;
547 updateMenuList(this, 0);
551 currentItem()->setSelected(hasFocus());
552 scrollToItem(currentItem());
556 void ConfigList::setParentMenu(void)
559 struct menu
*oldroot
;
562 if (rootEntry
== &rootmenu
)
564 setRootMenu(menu_get_parent_menu(rootEntry
->parent
));
566 QTreeWidgetItemIterator
it(this);
568 item
= (ConfigItem
*)(*it
);
569 if (item
->menu
== oldroot
) {
570 setCurrentItem(item
);
580 * update all the children of a menu entry
581 * removes/adds the entries from the parent widget as necessary
583 * parent: either the menu list widget or a menu entry widget
584 * menu: entry to be updated
586 void ConfigList::updateMenuList(ConfigItem
*parent
, struct menu
* menu
)
595 while (parent
->childCount() > 0)
597 delete parent
->takeChild(0);
603 last
= parent
->firstChild();
604 if (last
&& !last
->goParent
)
606 for (child
= menu
->list
; child
; child
= child
->next
) {
607 item
= last
? last
->nextSibling() : parent
->firstChild();
608 type
= child
->prompt
? child
->prompt
->type
: P_UNKNOWN
;
612 if (!(child
->flags
& MENU_ROOT
))
616 if (child
->flags
& MENU_ROOT
)
623 visible
= menu_is_visible(child
);
624 if (!menuSkip(child
)) {
625 if (!child
->sym
&& !child
->list
&& !child
->prompt
)
627 if (!item
|| item
->menu
!= child
)
628 item
= new ConfigItem(parent
, last
, child
, visible
);
630 item
->testUpdateMenu(visible
);
632 if (mode
== fullMode
|| mode
== menuMode
|| type
!= P_MENU
)
633 updateMenuList(item
, child
);
635 updateMenuList(item
, 0);
640 if (item
&& item
->menu
== child
) {
641 last
= parent
->firstChild();
644 else while (last
->nextSibling() != item
)
645 last
= last
->nextSibling();
651 void ConfigList::updateMenuList(ConfigList
*parent
, struct menu
* menu
)
660 while (parent
->topLevelItemCount() > 0)
662 delete parent
->takeTopLevelItem(0);
668 last
= (ConfigItem
*)parent
->topLevelItem(0);
669 if (last
&& !last
->goParent
)
671 for (child
= menu
->list
; child
; child
= child
->next
) {
672 item
= last
? last
->nextSibling() : (ConfigItem
*)parent
->topLevelItem(0);
673 type
= child
->prompt
? child
->prompt
->type
: P_UNKNOWN
;
677 if (!(child
->flags
& MENU_ROOT
))
681 if (child
->flags
& MENU_ROOT
)
688 visible
= menu_is_visible(child
);
689 if (!menuSkip(child
)) {
690 if (!child
->sym
&& !child
->list
&& !child
->prompt
)
692 if (!item
|| item
->menu
!= child
)
693 item
= new ConfigItem(parent
, last
, child
, visible
);
695 item
->testUpdateMenu(visible
);
697 if (mode
== fullMode
|| mode
== menuMode
|| type
!= P_MENU
)
698 updateMenuList(item
, child
);
700 updateMenuList(item
, 0);
705 if (item
&& item
->menu
== child
) {
706 last
= (ConfigItem
*)parent
->topLevelItem(0);
709 else while (last
->nextSibling() != item
)
710 last
= last
->nextSibling();
716 void ConfigList::keyPressEvent(QKeyEvent
* ev
)
718 QTreeWidgetItem
* i
= currentItem();
723 if (ev
->key() == Qt::Key_Escape
&& mode
!= fullMode
&& mode
!= listMode
) {
724 emit
parentSelected();
730 Parent::keyPressEvent(ev
);
733 item
= (ConfigItem
*)i
;
738 if (item
->goParent
) {
739 emit
parentSelected();
745 type
= menu
->prompt
? menu
->prompt
->type
: P_UNKNOWN
;
746 if (type
== P_MENU
&& rootEntry
!= menu
&&
747 mode
!= fullMode
&& mode
!= menuMode
) {
748 emit
menuSelected(menu
);
764 Parent::keyPressEvent(ev
);
770 void ConfigList::mousePressEvent(QMouseEvent
* e
)
772 //QPoint p(contentsToViewport(e->pos()));
773 //printf("contentsMousePressEvent: %d,%d\n", p.x(), p.y());
774 Parent::mousePressEvent(e
);
777 void ConfigList::mouseReleaseEvent(QMouseEvent
* e
)
780 ConfigItem
* item
= (ConfigItem
*)itemAt(p
);
782 enum prop_type ptype
;
790 x
= header()->offset() + p
.x();
791 idx
= header()->logicalIndexAt(x
);
794 icon
= item
->pixmap(promptColIdx
);
795 if (!icon
.isNull()) {
796 int off
= header()->sectionPosition(0) + visualRect(indexAt(p
)).x() + 4; // 4 is Hardcoded image offset. There might be a way to do it properly.
797 if (x
>= off
&& x
< off
+ icon
.availableSizes().first().width()) {
798 if (item
->goParent
) {
799 emit
parentSelected();
803 ptype
= menu
->prompt
? menu
->prompt
->type
: P_UNKNOWN
;
804 if (ptype
== P_MENU
&& rootEntry
!= menu
&&
805 mode
!= fullMode
&& mode
!= menuMode
)
806 emit
menuSelected(menu
);
827 //printf("contentsMouseReleaseEvent: %d,%d\n", p.x(), p.y());
828 Parent::mouseReleaseEvent(e
);
831 void ConfigList::mouseMoveEvent(QMouseEvent
* e
)
833 //QPoint p(contentsToViewport(e->pos()));
834 //printf("contentsMouseMoveEvent: %d,%d\n", p.x(), p.y());
835 Parent::mouseMoveEvent(e
);
838 void ConfigList::mouseDoubleClickEvent(QMouseEvent
* e
)
840 QPoint p
= e
->pos(); // TODO: Check if this works(was contentsToViewport).
841 ConfigItem
* item
= (ConfigItem
*)itemAt(p
);
843 enum prop_type ptype
;
847 if (item
->goParent
) {
848 emit
parentSelected();
854 ptype
= menu
->prompt
? menu
->prompt
->type
: P_UNKNOWN
;
855 if (ptype
== P_MENU
&& (mode
== singleMode
|| mode
== symbolMode
))
856 emit
menuSelected(menu
);
861 //printf("contentsMouseDoubleClickEvent: %d,%d\n", p.x(), p.y());
862 Parent::mouseDoubleClickEvent(e
);
865 void ConfigList::focusInEvent(QFocusEvent
*e
)
867 struct menu
*menu
= NULL
;
869 Parent::focusInEvent(e
);
871 ConfigItem
* item
= (ConfigItem
*)currentItem();
873 item
->setSelected(true);
879 void ConfigList::contextMenuEvent(QContextMenuEvent
*e
)
881 if (e
->y() <= header()->geometry().bottom()) {
885 headerPopup
= new QMenu(this);
886 action
= new QAction(_("Show Name"), this);
887 action
->setCheckable(true);
888 connect(action
, SIGNAL(toggled(bool)),
889 parent(), SLOT(setShowName(bool)));
890 connect(parent(), SIGNAL(showNameChanged(bool)),
891 action
, SLOT(setOn(bool)));
892 action
->setChecked(showName
);
893 headerPopup
->addAction(action
);
894 action
= new QAction(_("Show Range"), this);
895 action
->setCheckable(true);
896 connect(action
, SIGNAL(toggled(bool)),
897 parent(), SLOT(setShowRange(bool)));
898 connect(parent(), SIGNAL(showRangeChanged(bool)),
899 action
, SLOT(setOn(bool)));
900 action
->setChecked(showRange
);
901 headerPopup
->addAction(action
);
902 action
= new QAction(_("Show Data"), this);
903 action
->setCheckable(true);
904 connect(action
, SIGNAL(toggled(bool)),
905 parent(), SLOT(setShowData(bool)));
906 connect(parent(), SIGNAL(showDataChanged(bool)),
907 action
, SLOT(setOn(bool)));
908 action
->setChecked(showData
);
909 headerPopup
->addAction(action
);
911 headerPopup
->exec(e
->globalPos());
917 ConfigView
*ConfigView::viewList
;
918 QAction
*ConfigView::showNormalAction
;
919 QAction
*ConfigView::showAllAction
;
920 QAction
*ConfigView::showPromptAction
;
922 ConfigView::ConfigView(QWidget
* parent
, const char *name
)
926 QVBoxLayout
*verticalLayout
= new QVBoxLayout(this);
927 verticalLayout
->setContentsMargins(0, 0, 0, 0);
929 list
= new ConfigList(this);
930 verticalLayout
->addWidget(list
);
931 lineEdit
= new ConfigLineEdit(this);
933 verticalLayout
->addWidget(lineEdit
);
935 this->nextView
= viewList
;
939 ConfigView::~ConfigView(void)
943 for (vp
= &viewList
; *vp
; vp
= &(*vp
)->nextView
) {
951 void ConfigView::setOptionMode(QAction
*act
)
953 if (act
== showNormalAction
)
954 list
->optMode
= normalOpt
;
955 else if (act
== showAllAction
)
956 list
->optMode
= allOpt
;
958 list
->optMode
= promptOpt
;
960 list
->updateListAll();
963 void ConfigView::setShowName(bool b
)
965 if (list
->showName
!= b
) {
968 emit
showNameChanged(b
);
972 void ConfigView::setShowRange(bool b
)
974 if (list
->showRange
!= b
) {
977 emit
showRangeChanged(b
);
981 void ConfigView::setShowData(bool b
)
983 if (list
->showData
!= b
) {
986 emit
showDataChanged(b
);
990 void ConfigList::setAllOpen(bool open
)
992 QTreeWidgetItemIterator
it(this);
995 (*it
)->setExpanded(open
);
1001 void ConfigView::updateList(ConfigItem
* item
)
1005 for (v
= viewList
; v
; v
= v
->nextView
)
1006 v
->list
->updateList(item
);
1009 void ConfigView::updateListAll(void)
1013 for (v
= viewList
; v
; v
= v
->nextView
)
1014 v
->list
->updateListAll();
1017 ConfigInfoView::ConfigInfoView(QWidget
* parent
, const char *name
)
1018 : Parent(parent
), sym(0), _menu(0)
1020 setObjectName(name
);
1023 if (!objectName().isEmpty()) {
1024 configSettings
->beginGroup(objectName());
1025 setShowDebug(configSettings
->value("/showDebug", false).toBool());
1026 configSettings
->endGroup();
1027 connect(configApp
, SIGNAL(aboutToQuit()), SLOT(saveSettings()));
1031 void ConfigInfoView::saveSettings(void)
1033 if (!objectName().isEmpty()) {
1034 configSettings
->beginGroup(objectName());
1035 configSettings
->setValue("/showDebug", showDebug());
1036 configSettings
->endGroup();
1040 void ConfigInfoView::setShowDebug(bool b
)
1042 if (_showDebug
!= b
) {
1048 emit
showDebugChanged(b
);
1052 void ConfigInfoView::setInfo(struct menu
*m
)
1064 void ConfigInfoView::symbolInfo(void)
1068 str
+= "<big>Symbol: <b>";
1069 str
+= print_filter(sym
->name
);
1070 str
+= "</b></big><br><br>value: ";
1071 str
+= print_filter(sym_get_string_value(sym
));
1072 str
+= "<br>visibility: ";
1073 str
+= sym
->visible
== yes
? "y" : sym
->visible
== mod
? "m" : "n";
1075 str
+= debug_info(sym
);
1080 void ConfigInfoView::menuInfo(void)
1083 QString head
, debug
, help
;
1087 if (_menu
->prompt
) {
1089 head
+= print_filter(_(_menu
->prompt
->text
));
1090 head
+= "</b></big>";
1094 head
+= QString().sprintf("<a href=\"s%p\">", sym
);
1095 head
+= print_filter(sym
->name
);
1100 } else if (sym
->name
) {
1103 head
+= QString().sprintf("<a href=\"s%p\">", sym
);
1104 head
+= print_filter(sym
->name
);
1107 head
+= "</b></big>";
1112 debug
= debug_info(sym
);
1114 struct gstr help_gstr
= str_new();
1115 menu_get_ext_help(_menu
, &help_gstr
);
1116 help
= print_filter(str_get(&help_gstr
));
1117 str_free(&help_gstr
);
1118 } else if (_menu
->prompt
) {
1120 head
+= print_filter(_(_menu
->prompt
->text
));
1121 head
+= "</b></big><br><br>";
1123 if (_menu
->prompt
->visible
.expr
) {
1124 debug
+= " dep: ";
1125 expr_print(_menu
->prompt
->visible
.expr
, expr_print_help
, &debug
, E_NONE
);
1126 debug
+= "<br><br>";
1131 debug
+= QString().sprintf("defined at %s:%d<br><br>", _menu
->file
->name
, _menu
->lineno
);
1133 setText(head
+ debug
+ help
);
1136 QString
ConfigInfoView::debug_info(struct symbol
*sym
)
1141 debug
+= print_filter(sym_type_name(sym
->type
));
1142 if (sym_is_choice(sym
))
1143 debug
+= " (choice)";
1145 if (sym
->rev_dep
.expr
) {
1146 debug
+= "reverse dep: ";
1147 expr_print(sym
->rev_dep
.expr
, expr_print_help
, &debug
, E_NONE
);
1150 for (struct property
*prop
= sym
->prop
; prop
; prop
= prop
->next
) {
1151 switch (prop
->type
) {
1154 debug
+= QString().sprintf("prompt: <a href=\"m%p\">", prop
->menu
);
1155 debug
+= print_filter(_(prop
->text
));
1156 debug
+= "</a><br>";
1162 debug
+= prop_get_type_name(prop
->type
);
1164 expr_print(prop
->expr
, expr_print_help
, &debug
, E_NONE
);
1168 if (sym_is_choice(sym
)) {
1169 debug
+= "choice: ";
1170 expr_print(prop
->expr
, expr_print_help
, &debug
, E_NONE
);
1175 debug
+= "unknown property: ";
1176 debug
+= prop_get_type_name(prop
->type
);
1179 if (prop
->visible
.expr
) {
1180 debug
+= " dep: ";
1181 expr_print(prop
->visible
.expr
, expr_print_help
, &debug
, E_NONE
);
1190 QString
ConfigInfoView::print_filter(const QString
&str
)
1192 QRegExp
re("[<>&\"\\n]");
1194 for (int i
= 0; (i
= res
.indexOf(re
, i
)) >= 0;) {
1195 switch (res
[i
].toLatin1()) {
1197 res
.replace(i
, 1, "<");
1201 res
.replace(i
, 1, ">");
1205 res
.replace(i
, 1, "&");
1209 res
.replace(i
, 1, """);
1213 res
.replace(i
, 1, "<br>");
1221 void ConfigInfoView::expr_print_help(void *data
, struct symbol
*sym
, const char *str
)
1223 QString
* text
= reinterpret_cast<QString
*>(data
);
1224 QString str2
= print_filter(str
);
1226 if (sym
&& sym
->name
&& !(sym
->flags
& SYMBOL_CONST
)) {
1227 *text
+= QString().sprintf("<a href=\"s%p\">", sym
);
1234 QMenu
* ConfigInfoView::createStandardContextMenu(const QPoint
& pos
)
1236 QMenu
* popup
= Parent::createStandardContextMenu(pos
);
1237 QAction
* action
= new QAction(_("Show Debug Info"), popup
);
1238 action
->setCheckable(true);
1239 connect(action
, SIGNAL(toggled(bool)), SLOT(setShowDebug(bool)));
1240 connect(this, SIGNAL(showDebugChanged(bool)), action
, SLOT(setOn(bool)));
1241 action
->setChecked(showDebug());
1242 popup
->addSeparator();
1243 popup
->addAction(action
);
1247 void ConfigInfoView::contextMenuEvent(QContextMenuEvent
*e
)
1249 Parent::contextMenuEvent(e
);
1252 ConfigSearchWindow::ConfigSearchWindow(ConfigMainWindow
* parent
, const char *name
)
1253 : Parent(parent
), result(NULL
)
1255 setObjectName(name
);
1256 setWindowTitle("Search Config");
1258 QVBoxLayout
* layout1
= new QVBoxLayout(this);
1259 layout1
->setContentsMargins(11, 11, 11, 11);
1260 layout1
->setSpacing(6);
1261 QHBoxLayout
* layout2
= new QHBoxLayout(0);
1262 layout2
->setContentsMargins(0, 0, 0, 0);
1263 layout2
->setSpacing(6);
1264 layout2
->addWidget(new QLabel(_("Find:"), this));
1265 editField
= new QLineEdit(this);
1266 connect(editField
, SIGNAL(returnPressed()), SLOT(search()));
1267 layout2
->addWidget(editField
);
1268 searchButton
= new QPushButton(_("Search"), this);
1269 searchButton
->setAutoDefault(false);
1270 connect(searchButton
, SIGNAL(clicked()), SLOT(search()));
1271 layout2
->addWidget(searchButton
);
1272 layout1
->addLayout(layout2
);
1274 split
= new QSplitter(this);
1275 split
->setOrientation(Qt::Vertical
);
1276 list
= new ConfigView(split
, name
);
1277 list
->list
->mode
= listMode
;
1278 info
= new ConfigInfoView(split
, name
);
1279 connect(list
->list
, SIGNAL(menuChanged(struct menu
*)),
1280 info
, SLOT(setInfo(struct menu
*)));
1281 connect(list
->list
, SIGNAL(menuChanged(struct menu
*)),
1282 parent
, SLOT(setMenuLink(struct menu
*)));
1284 layout1
->addWidget(split
);
1291 configSettings
->beginGroup(name
);
1292 width
= configSettings
->value("/window width", parent
->width() / 2).toInt();
1293 height
= configSettings
->value("/window height", parent
->height() / 2).toInt();
1294 resize(width
, height
);
1295 x
= configSettings
->value("/window x");
1296 y
= configSettings
->value("/window y");
1297 if ((x
.isValid())&&(y
.isValid()))
1298 move(x
.toInt(), y
.toInt());
1299 QList
<int> sizes
= configSettings
->readSizes("/split", &ok
);
1301 split
->setSizes(sizes
);
1302 configSettings
->endGroup();
1303 connect(configApp
, SIGNAL(aboutToQuit()), SLOT(saveSettings()));
1307 void ConfigSearchWindow::saveSettings(void)
1309 if (!objectName().isEmpty()) {
1310 configSettings
->beginGroup(objectName());
1311 configSettings
->setValue("/window x", pos().x());
1312 configSettings
->setValue("/window y", pos().y());
1313 configSettings
->setValue("/window width", size().width());
1314 configSettings
->setValue("/window height", size().height());
1315 configSettings
->writeSizes("/split", split
->sizes());
1316 configSettings
->endGroup();
1320 void ConfigSearchWindow::search(void)
1323 struct property
*prop
;
1324 ConfigItem
*lastItem
= NULL
;
1327 list
->list
->clear();
1330 result
= sym_re_search(editField
->text().toLatin1());
1333 for (p
= result
; *p
; p
++) {
1334 for_all_prompts((*p
), prop
)
1335 lastItem
= new ConfigItem(list
->list
, lastItem
, prop
->menu
,
1336 menu_is_visible(prop
->menu
));
1341 * Construct the complete config widget
1343 ConfigMainWindow::ConfigMainWindow(void)
1352 QDesktopWidget
*d
= configApp
->desktop();
1353 snprintf(title
, sizeof(title
), "%s%s",
1354 rootmenu
.prompt
->text
,
1357 setWindowTitle(title
);
1359 width
= configSettings
->value("/window width", d
->width() - 64).toInt();
1360 height
= configSettings
->value("/window height", d
->height() - 64).toInt();
1361 resize(width
, height
);
1362 x
= configSettings
->value("/window x");
1363 y
= configSettings
->value("/window y");
1364 if ((x
.isValid())&&(y
.isValid()))
1365 move(x
.toInt(), y
.toInt());
1367 split1
= new QSplitter(this);
1368 split1
->setOrientation(Qt::Horizontal
);
1369 setCentralWidget(split1
);
1371 menuView
= new ConfigView(split1
, "menu");
1372 menuList
= menuView
->list
;
1374 split2
= new QSplitter(split1
);
1375 split2
->setOrientation(Qt::Vertical
);
1377 // create config tree
1378 configView
= new ConfigView(split2
, "config");
1379 configList
= configView
->list
;
1381 helpText
= new ConfigInfoView(split2
, "help");
1383 setTabOrder(configList
, helpText
);
1384 configList
->setFocus();
1387 toolBar
= new QToolBar("Tools", this);
1388 addToolBar(toolBar
);
1390 backAction
= new QAction(QPixmap(xpm_back
), _("Back"), this);
1391 connect(backAction
, SIGNAL(triggered(bool)), SLOT(goBack()));
1392 backAction
->setEnabled(false);
1393 QAction
*quitAction
= new QAction(_("&Quit"), this);
1394 quitAction
->setShortcut(Qt::CTRL
+ Qt::Key_Q
);
1395 connect(quitAction
, SIGNAL(triggered(bool)), SLOT(close()));
1396 QAction
*loadAction
= new QAction(QPixmap(xpm_load
), _("&Load"), this);
1397 loadAction
->setShortcut(Qt::CTRL
+ Qt::Key_L
);
1398 connect(loadAction
, SIGNAL(triggered(bool)), SLOT(loadConfig()));
1399 saveAction
= new QAction(QPixmap(xpm_save
), _("&Save"), this);
1400 saveAction
->setShortcut(Qt::CTRL
+ Qt::Key_S
);
1401 connect(saveAction
, SIGNAL(triggered(bool)), SLOT(saveConfig()));
1402 conf_set_changed_callback(conf_changed
);
1403 // Set saveAction's initial state
1405 QAction
*saveAsAction
= new QAction(_("Save &As..."), this);
1406 connect(saveAsAction
, SIGNAL(triggered(bool)), SLOT(saveConfigAs()));
1407 QAction
*searchAction
= new QAction(_("&Find"), this);
1408 searchAction
->setShortcut(Qt::CTRL
+ Qt::Key_F
);
1409 connect(searchAction
, SIGNAL(triggered(bool)), SLOT(searchConfig()));
1410 singleViewAction
= new QAction(QPixmap(xpm_single_view
), _("Single View"), this);
1411 singleViewAction
->setCheckable(true);
1412 connect(singleViewAction
, SIGNAL(triggered(bool)), SLOT(showSingleView()));
1413 splitViewAction
= new QAction(QPixmap(xpm_split_view
), _("Split View"), this);
1414 splitViewAction
->setCheckable(true);
1415 connect(splitViewAction
, SIGNAL(triggered(bool)), SLOT(showSplitView()));
1416 fullViewAction
= new QAction(QPixmap(xpm_tree_view
), _("Full View"), this);
1417 fullViewAction
->setCheckable(true);
1418 connect(fullViewAction
, SIGNAL(triggered(bool)), SLOT(showFullView()));
1420 QAction
*showNameAction
= new QAction(_("Show Name"), this);
1421 showNameAction
->setCheckable(true);
1422 connect(showNameAction
, SIGNAL(toggled(bool)), configView
, SLOT(setShowName(bool)));
1423 showNameAction
->setChecked(configView
->showName());
1424 QAction
*showRangeAction
= new QAction(_("Show Range"), this);
1425 showRangeAction
->setCheckable(true);
1426 connect(showRangeAction
, SIGNAL(toggled(bool)), configView
, SLOT(setShowRange(bool)));
1427 QAction
*showDataAction
= new QAction(_("Show Data"), this);
1428 showDataAction
->setCheckable(true);
1429 connect(showDataAction
, SIGNAL(toggled(bool)), configView
, SLOT(setShowData(bool)));
1431 QActionGroup
*optGroup
= new QActionGroup(this);
1432 optGroup
->setExclusive(true);
1433 connect(optGroup
, SIGNAL(triggered(QAction
*)), configView
,
1434 SLOT(setOptionMode(QAction
*)));
1435 connect(optGroup
, SIGNAL(triggered(QAction
*)), menuView
,
1436 SLOT(setOptionMode(QAction
*)));
1438 configView
->showNormalAction
= new QAction(_("Show Normal Options"), optGroup
);
1439 configView
->showAllAction
= new QAction(_("Show All Options"), optGroup
);
1440 configView
->showPromptAction
= new QAction(_("Show Prompt Options"), optGroup
);
1441 configView
->showNormalAction
->setCheckable(true);
1442 configView
->showAllAction
->setCheckable(true);
1443 configView
->showPromptAction
->setCheckable(true);
1445 QAction
*showDebugAction
= new QAction( _("Show Debug Info"), this);
1446 showDebugAction
->setCheckable(true);
1447 connect(showDebugAction
, SIGNAL(toggled(bool)), helpText
, SLOT(setShowDebug(bool)));
1448 showDebugAction
->setChecked(helpText
->showDebug());
1450 QAction
*showIntroAction
= new QAction( _("Introduction"), this);
1451 connect(showIntroAction
, SIGNAL(triggered(bool)), SLOT(showIntro()));
1452 QAction
*showAboutAction
= new QAction( _("About"), this);
1453 connect(showAboutAction
, SIGNAL(triggered(bool)), SLOT(showAbout()));
1456 toolBar
->addAction(backAction
);
1457 toolBar
->addSeparator();
1458 toolBar
->addAction(loadAction
);
1459 toolBar
->addAction(saveAction
);
1460 toolBar
->addSeparator();
1461 toolBar
->addAction(singleViewAction
);
1462 toolBar
->addAction(splitViewAction
);
1463 toolBar
->addAction(fullViewAction
);
1465 // create config menu
1466 QMenu
* config
= menu
->addMenu(_("&File"));
1467 config
->addAction(loadAction
);
1468 config
->addAction(saveAction
);
1469 config
->addAction(saveAsAction
);
1470 config
->addSeparator();
1471 config
->addAction(quitAction
);
1474 QMenu
* editMenu
= menu
->addMenu(_("&Edit"));
1475 editMenu
->addAction(searchAction
);
1477 // create options menu
1478 QMenu
* optionMenu
= menu
->addMenu(_("&Option"));
1479 optionMenu
->addAction(showNameAction
);
1480 optionMenu
->addAction(showRangeAction
);
1481 optionMenu
->addAction(showDataAction
);
1482 optionMenu
->addSeparator();
1483 optionMenu
->addActions(optGroup
->actions());
1484 optionMenu
->addSeparator();
1485 optionMenu
->addAction(showDebugAction
);
1488 menu
->addSeparator();
1489 QMenu
* helpMenu
= menu
->addMenu(_("&Help"));
1490 helpMenu
->addAction(showIntroAction
);
1491 helpMenu
->addAction(showAboutAction
);
1493 connect(configList
, SIGNAL(menuChanged(struct menu
*)),
1494 helpText
, SLOT(setInfo(struct menu
*)));
1495 connect(configList
, SIGNAL(menuSelected(struct menu
*)),
1496 SLOT(changeMenu(struct menu
*)));
1497 connect(configList
, SIGNAL(parentSelected()),
1499 connect(menuList
, SIGNAL(menuChanged(struct menu
*)),
1500 helpText
, SLOT(setInfo(struct menu
*)));
1501 connect(menuList
, SIGNAL(menuSelected(struct menu
*)),
1502 SLOT(changeMenu(struct menu
*)));
1504 connect(configList
, SIGNAL(gotFocus(struct menu
*)),
1505 helpText
, SLOT(setInfo(struct menu
*)));
1506 connect(menuList
, SIGNAL(gotFocus(struct menu
*)),
1507 helpText
, SLOT(setInfo(struct menu
*)));
1508 connect(menuList
, SIGNAL(gotFocus(struct menu
*)),
1509 SLOT(listFocusChanged(void)));
1510 connect(helpText
, SIGNAL(menuSelected(struct menu
*)),
1511 SLOT(setMenuLink(struct menu
*)));
1513 QString listMode
= configSettings
->value("/listMode", "symbol").toString();
1514 if (listMode
== "single")
1516 else if (listMode
== "full")
1518 else /*if (listMode == "split")*/
1521 // UI setup done, restore splitter positions
1522 QList
<int> sizes
= configSettings
->readSizes("/split1", &ok
);
1524 split1
->setSizes(sizes
);
1526 sizes
= configSettings
->readSizes("/split2", &ok
);
1528 split2
->setSizes(sizes
);
1531 void ConfigMainWindow::loadConfig(void)
1533 QString s
= QFileDialog::getOpenFileName(this, "", conf_get_configname());
1536 if (conf_read(QFile::encodeName(s
)))
1537 QMessageBox::information(this, "qconf", _("Unable to load configuration!"));
1538 ConfigView::updateListAll();
1541 bool ConfigMainWindow::saveConfig(void)
1543 if (conf_write(NULL
)) {
1544 QMessageBox::information(this, "qconf", _("Unable to save configuration!"));
1550 void ConfigMainWindow::saveConfigAs(void)
1552 QString s
= QFileDialog::getSaveFileName(this, "", conf_get_configname());
1558 void ConfigMainWindow::searchConfig(void)
1561 searchWindow
= new ConfigSearchWindow(this, "search");
1562 searchWindow
->show();
1565 void ConfigMainWindow::changeMenu(struct menu
*menu
)
1567 configList
->setRootMenu(menu
);
1568 if (configList
->rootEntry
->parent
== &rootmenu
)
1569 backAction
->setEnabled(false);
1571 backAction
->setEnabled(true);
1574 void ConfigMainWindow::setMenuLink(struct menu
*menu
)
1576 struct menu
*parent
;
1577 ConfigList
* list
= NULL
;
1580 if (configList
->menuSkip(menu
))
1583 switch (configList
->mode
) {
1586 parent
= menu_get_parent_menu(menu
);
1589 list
->setRootMenu(parent
);
1592 if (menu
->flags
& MENU_ROOT
) {
1593 configList
->setRootMenu(menu
);
1594 configList
->clearSelection();
1598 parent
= menu_get_parent_menu(menu
->parent
);
1601 item
= menuList
->findConfigItem(parent
);
1603 item
->setSelected(true);
1604 menuList
->scrollToItem(item
);
1606 list
->setRootMenu(parent
);
1617 item
= list
->findConfigItem(menu
);
1619 item
->setSelected(true);
1620 list
->scrollToItem(item
);
1626 void ConfigMainWindow::listFocusChanged(void)
1628 if (menuList
->mode
== menuMode
)
1629 configList
->clearSelection();
1632 void ConfigMainWindow::goBack(void)
1634 ConfigItem
* item
, *oldSelection
;
1636 configList
->setParentMenu();
1637 if (configList
->rootEntry
== &rootmenu
)
1638 backAction
->setEnabled(false);
1640 if (menuList
->selectedItems().count() == 0)
1643 item
= (ConfigItem
*)menuList
->selectedItems().first();
1644 oldSelection
= item
;
1646 if (item
->menu
== configList
->rootEntry
) {
1647 oldSelection
->setSelected(false);
1648 item
->setSelected(true);
1651 item
= (ConfigItem
*)item
->parent();
1655 void ConfigMainWindow::showSingleView(void)
1657 singleViewAction
->setEnabled(false);
1658 singleViewAction
->setChecked(true);
1659 splitViewAction
->setEnabled(true);
1660 splitViewAction
->setChecked(false);
1661 fullViewAction
->setEnabled(true);
1662 fullViewAction
->setChecked(false);
1665 menuList
->setRootMenu(0);
1666 configList
->mode
= singleMode
;
1667 if (configList
->rootEntry
== &rootmenu
)
1668 configList
->updateListAll();
1670 configList
->setRootMenu(&rootmenu
);
1671 configList
->setFocus();
1674 void ConfigMainWindow::showSplitView(void)
1676 singleViewAction
->setEnabled(true);
1677 singleViewAction
->setChecked(false);
1678 splitViewAction
->setEnabled(false);
1679 splitViewAction
->setChecked(true);
1680 fullViewAction
->setEnabled(true);
1681 fullViewAction
->setChecked(false);
1683 configList
->mode
= symbolMode
;
1684 if (configList
->rootEntry
== &rootmenu
)
1685 configList
->updateListAll();
1687 configList
->setRootMenu(&rootmenu
);
1688 configList
->setAllOpen(true);
1689 configApp
->processEvents();
1690 menuList
->mode
= menuMode
;
1691 menuList
->setRootMenu(&rootmenu
);
1692 menuList
->setAllOpen(true);
1694 menuList
->setFocus();
1697 void ConfigMainWindow::showFullView(void)
1699 singleViewAction
->setEnabled(true);
1700 singleViewAction
->setChecked(false);
1701 splitViewAction
->setEnabled(true);
1702 splitViewAction
->setChecked(false);
1703 fullViewAction
->setEnabled(false);
1704 fullViewAction
->setChecked(true);
1707 menuList
->setRootMenu(0);
1708 configList
->mode
= fullMode
;
1709 if (configList
->rootEntry
== &rootmenu
)
1710 configList
->updateListAll();
1712 configList
->setRootMenu(&rootmenu
);
1713 configList
->setFocus();
1717 * ask for saving configuration before quitting
1718 * TODO ask only when something changed
1720 void ConfigMainWindow::closeEvent(QCloseEvent
* e
)
1722 if (!conf_get_changed()) {
1726 QMessageBox
mb("qconf", _("Save configuration?"), QMessageBox::Warning
,
1727 QMessageBox::Yes
| QMessageBox::Default
, QMessageBox::No
, QMessageBox::Cancel
| QMessageBox::Escape
);
1728 mb
.setButtonText(QMessageBox::Yes
, _("&Save Changes"));
1729 mb
.setButtonText(QMessageBox::No
, _("&Discard Changes"));
1730 mb
.setButtonText(QMessageBox::Cancel
, _("Cancel Exit"));
1731 switch (mb
.exec()) {
1732 case QMessageBox::Yes
:
1738 case QMessageBox::No
:
1741 case QMessageBox::Cancel
:
1747 void ConfigMainWindow::showIntro(void)
1749 static const QString str
= _("Welcome to the qconf graphical configuration tool.\n\n"
1750 "For each option, a blank box indicates the feature is disabled, a check\n"
1751 "indicates it is enabled, and a dot indicates that it is to be compiled\n"
1752 "as a module. Clicking on the box will cycle through the three states.\n\n"
1753 "If you do not see an option (e.g., a device driver) that you believe\n"
1754 "should be present, try turning on Show All Options under the Options menu.\n"
1755 "Although there is no cross reference yet to help you figure out what other\n"
1756 "options must be enabled to support the option you are interested in, you can\n"
1757 "still view the help of a grayed-out option.\n\n"
1758 "Toggling Show Debug Info under the Options menu will show the dependencies,\n"
1759 "which you can then match by examining other options.\n\n");
1761 QMessageBox::information(this, "qconf", str
);
1764 void ConfigMainWindow::showAbout(void)
1766 static const QString str
= _("qconf is Copyright (C) 2002 Roman Zippel <zippel@linux-m68k.org>.\n"
1767 "Copyright (C) 2015 Boris Barbulovski <bbarbulovski@gmail.com>.\n\n"
1768 "Bug reports and feature request can also be entered at http://bugzilla.kernel.org/\n");
1770 QMessageBox::information(this, "qconf", str
);
1773 void ConfigMainWindow::saveSettings(void)
1775 configSettings
->setValue("/window x", pos().x());
1776 configSettings
->setValue("/window y", pos().y());
1777 configSettings
->setValue("/window width", size().width());
1778 configSettings
->setValue("/window height", size().height());
1781 switch(configList
->mode
) {
1797 configSettings
->setValue("/listMode", entry
);
1799 configSettings
->writeSizes("/split1", split1
->sizes());
1800 configSettings
->writeSizes("/split2", split2
->sizes());
1803 void ConfigMainWindow::conf_changed(void)
1806 saveAction
->setEnabled(conf_get_changed());
1809 void fixup_rootmenu(struct menu
*menu
)
1812 static int menu_cnt
= 0;
1814 menu
->flags
|= MENU_ROOT
;
1815 for (child
= menu
->list
; child
; child
= child
->next
) {
1816 if (child
->prompt
&& child
->prompt
->type
== P_MENU
) {
1818 fixup_rootmenu(child
);
1820 } else if (!menu_cnt
)
1821 fixup_rootmenu(child
);
1825 static const char *progname
;
1827 static void usage(void)
1829 printf(_("%s [-s] <config>\n").toLatin1().constData(), progname
);
1833 int main(int ac
, char** av
)
1835 ConfigMainWindow
* v
;
1838 bindtextdomain(PACKAGE
, LOCALEDIR
);
1839 textdomain(PACKAGE
);
1842 configApp
= new QApplication(ac
, av
);
1843 if (ac
> 1 && av
[1][0] == '-') {
1846 conf_set_message_callback(NULL
);
1859 fixup_rootmenu(&rootmenu
);
1861 //zconfdump(stdout);
1863 configSettings
= new ConfigSettings();
1864 configSettings
->beginGroup("/kconfig/qconf");
1865 v
= new ConfigMainWindow();
1867 //zconfdump(stdout);
1868 configApp
->connect(configApp
, SIGNAL(lastWindowClosed()), SLOT(quit()));
1869 configApp
->connect(configApp
, SIGNAL(aboutToQuit()), v
, SLOT(saveSettings()));
1873 configSettings
->endGroup();
1874 delete configSettings
;