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 int kconfig_warnings
= 0;
44 static QApplication
*configApp
;
45 static ConfigSettings
*configSettings
;
47 QAction
*ConfigMainWindow::saveAction
;
49 static inline QString
qgettext(const char* str
)
51 return QString::fromLocal8Bit(gettext(str
));
54 static inline QString
qgettext(const QString
& str
)
56 return QString::fromLocal8Bit(gettext(str
.toLatin1()));
59 ConfigSettings::ConfigSettings()
60 : QSettings("kernel.org", "qconf")
65 * Reads a list of integer values from the application settings.
67 QList
<int> ConfigSettings::readSizes(const QString
& key
, bool *ok
)
70 QStringList entryList
= value(key
).toStringList();
71 QStringList::Iterator it
;
73 for (it
= entryList
.begin(); it
!= entryList
.end(); ++it
)
74 result
.push_back((*it
).toInt());
80 * Writes a list of integer values to the application settings.
82 bool ConfigSettings::writeSizes(const QString
& key
, const QList
<int>& value
)
84 QStringList stringList
;
85 QList
<int>::ConstIterator it
;
87 for (it
= value
.begin(); it
!= value
.end(); ++it
)
88 stringList
.push_back(QString::number(*it
));
89 setValue(key
, stringList
);
97 * TODO check the value
99 void ConfigItem::okRename(int col
)
104 * update the displayed of a menu entry
106 void ConfigItem::updateMenu(void)
110 struct property
*prop
;
117 setPixmap(promptColIdx
, list
->menuBackPix
);
124 prompt
= _(menu_get_prompt(menu
));
126 if (prop
) switch (prop
->type
) {
128 if (list
->mode
== singleMode
|| list
->mode
== symbolMode
) {
129 /* a menuconfig entry is displayed differently
130 * depending whether it's at the view root or a child.
132 if (sym
&& list
->rootEntry
== menu
)
134 setPixmap(promptColIdx
, list
->menuPix
);
138 setPixmap(promptColIdx
, QIcon());
142 setPixmap(promptColIdx
, QIcon());
150 setText(nameColIdx
, QString::fromLocal8Bit(sym
->name
));
152 type
= sym_get_type(sym
);
158 if (!sym_is_changable(sym
) && list
->optMode
== normalOpt
) {
159 setPixmap(promptColIdx
, QIcon());
160 setText(noColIdx
, QString::null
);
161 setText(modColIdx
, QString::null
);
162 setText(yesColIdx
, QString::null
);
165 expr
= sym_get_tristate_value(sym
);
168 if (sym_is_choice_value(sym
) && type
== S_BOOLEAN
)
169 setPixmap(promptColIdx
, list
->choiceYesPix
);
171 setPixmap(promptColIdx
, list
->symbolYesPix
);
172 setText(yesColIdx
, "Y");
176 setPixmap(promptColIdx
, list
->symbolModPix
);
177 setText(modColIdx
, "M");
181 if (sym_is_choice_value(sym
) && type
== S_BOOLEAN
)
182 setPixmap(promptColIdx
, list
->choiceNoPix
);
184 setPixmap(promptColIdx
, list
->symbolNoPix
);
185 setText(noColIdx
, "N");
190 setText(noColIdx
, sym_tristate_within_range(sym
, no
) ? "_" : 0);
192 setText(modColIdx
, sym_tristate_within_range(sym
, mod
) ? "_" : 0);
194 setText(yesColIdx
, sym_tristate_within_range(sym
, yes
) ? "_" : 0);
196 setText(dataColIdx
, QChar(ch
));
203 data
= sym_get_string_value(sym
);
205 setText(dataColIdx
, data
);
206 if (type
== S_STRING
)
207 prompt
= QString("%1: %2").arg(prompt
).arg(data
);
209 prompt
= QString("(%2) %1").arg(prompt
).arg(data
);
212 if (!sym_has_value(sym
) && visible
)
213 prompt
+= _(" (NEW)");
215 setText(promptColIdx
, prompt
);
218 void ConfigItem::testUpdateMenu(bool v
)
226 sym_calc_value(menu
->sym
);
227 if (menu
->flags
& MENU_CHANGED
) {
228 /* the menu entry changed, so update all list items */
229 menu
->flags
&= ~MENU_CHANGED
;
230 for (i
= (ConfigItem
*)menu
->data
; i
; i
= i
->nextItem
)
232 } else if (listView()->updateAll
)
238 * construct a menu entry
240 void ConfigItem::init(void)
243 ConfigList
* list
= listView();
244 nextItem
= (ConfigItem
*)menu
->data
;
247 if (list
->mode
!= fullMode
)
249 sym_calc_value(menu
->sym
);
255 * destruct a menu entry
257 ConfigItem::~ConfigItem(void)
260 ConfigItem
** ip
= (ConfigItem
**)&menu
->data
;
261 for (; *ip
; ip
= &(*ip
)->nextItem
) {
270 ConfigLineEdit::ConfigLineEdit(ConfigView
* parent
)
273 connect(this, SIGNAL(editingFinished()), SLOT(hide()));
276 void ConfigLineEdit::show(ConfigItem
* i
)
279 if (sym_get_string_value(item
->menu
->sym
))
280 setText(QString::fromLocal8Bit(sym_get_string_value(item
->menu
->sym
)));
282 setText(QString::null
);
287 void ConfigLineEdit::keyPressEvent(QKeyEvent
* e
)
294 sym_set_string_value(item
->menu
->sym
, text().toLatin1());
295 parent()->updateList(item
);
298 Parent::keyPressEvent(e
);
302 parent()->list
->setFocus();
306 ConfigList::ConfigList(ConfigView
* p
, const char *name
)
309 symbolYesPix(xpm_symbol_yes
), symbolModPix(xpm_symbol_mod
), symbolNoPix(xpm_symbol_no
),
310 choiceYesPix(xpm_choice_yes
), choiceNoPix(xpm_choice_no
),
311 menuPix(xpm_menu
), menuInvPix(xpm_menu_inv
), menuBackPix(xpm_menuback
), voidPix(xpm_void
),
312 showName(false), showRange(false), showData(false), mode(singleMode
), optMode(normalOpt
),
313 rootEntry(0), headerPopup(0)
318 setSortingEnabled(false);
319 setRootIsDecorated(true);
321 setVerticalScrollMode(ScrollPerPixel
);
322 setHorizontalScrollMode(ScrollPerPixel
);
324 setHeaderLabels(QStringList() << _("Option") << _("Name") << "N" << "M" << "Y" << _("Value"));
326 connect(this, SIGNAL(itemSelectionChanged(void)),
327 SLOT(updateSelection(void)));
330 configSettings
->beginGroup(name
);
331 showName
= configSettings
->value("/showName", false).toBool();
332 showRange
= configSettings
->value("/showRange", false).toBool();
333 showData
= configSettings
->value("/showData", false).toBool();
334 optMode
= (enum optionMode
)configSettings
->value("/optionMode", 0).toInt();
335 configSettings
->endGroup();
336 connect(configApp
, SIGNAL(aboutToQuit()), SLOT(saveSettings()));
339 addColumn(promptColIdx
);
344 bool ConfigList::menuSkip(struct menu
*menu
)
346 if (optMode
== normalOpt
&& menu_is_visible(menu
))
348 if (optMode
== promptOpt
&& menu_has_prompt(menu
))
350 if (optMode
== allOpt
)
355 void ConfigList::reinit(void)
357 removeColumn(dataColIdx
);
358 removeColumn(yesColIdx
);
359 removeColumn(modColIdx
);
360 removeColumn(noColIdx
);
361 removeColumn(nameColIdx
);
364 addColumn(nameColIdx
);
367 addColumn(modColIdx
);
368 addColumn(yesColIdx
);
371 addColumn(dataColIdx
);
376 void ConfigList::saveSettings(void)
378 if (!objectName().isEmpty()) {
379 configSettings
->beginGroup(objectName());
380 configSettings
->setValue("/showName", showName
);
381 configSettings
->setValue("/showRange", showRange
);
382 configSettings
->setValue("/showData", showData
);
383 configSettings
->setValue("/optionMode", (int)optMode
);
384 configSettings
->endGroup();
388 ConfigItem
* ConfigList::findConfigItem(struct menu
*menu
)
390 ConfigItem
* item
= (ConfigItem
*)menu
->data
;
392 for (; item
; item
= item
->nextItem
) {
393 if (this == item
->listView())
400 void ConfigList::updateSelection(void)
405 if (selectedItems().count() == 0)
408 ConfigItem
* item
= (ConfigItem
*)selectedItems().first();
413 emit
menuChanged(menu
);
416 type
= menu
->prompt
? menu
->prompt
->type
: P_UNKNOWN
;
417 if (mode
== menuMode
&& type
== P_MENU
)
418 emit
menuSelected(menu
);
421 void ConfigList::updateList(ConfigItem
* item
)
423 ConfigItem
* last
= 0;
426 if (mode
!= listMode
)
428 QTreeWidgetItemIterator
it(this);
432 item
= (ConfigItem
*)(*it
);
435 item
->testUpdateMenu(menu_is_visible(item
->menu
));
442 if (rootEntry
!= &rootmenu
&& (mode
== singleMode
||
443 (mode
== symbolMode
&& rootEntry
->parent
!= &rootmenu
))) {
444 item
= (ConfigItem
*)topLevelItem(0);
446 item
= new ConfigItem(this, 0, true);
449 if ((mode
== singleMode
|| (mode
== symbolMode
&& !(rootEntry
->flags
& MENU_ROOT
))) &&
450 rootEntry
->sym
&& rootEntry
->prompt
) {
451 item
= last
? last
->nextSibling() : firstChild();
453 item
= new ConfigItem(this, last
, rootEntry
, true);
455 item
->testUpdateMenu(true);
457 updateMenuList(item
, rootEntry
);
459 resizeColumnToContents(0);
463 updateMenuList(this, rootEntry
);
465 resizeColumnToContents(0);
468 void ConfigList::setValue(ConfigItem
* item
, tristate val
)
474 sym
= item
->menu
? item
->menu
->sym
: 0;
478 type
= sym_get_type(sym
);
482 oldval
= sym_get_tristate_value(sym
);
484 if (!sym_set_tristate_value(sym
, val
))
486 if (oldval
== no
&& item
->menu
->list
)
487 item
->setExpanded(true);
488 parent()->updateList(item
);
493 void ConfigList::changeValue(ConfigItem
* item
)
497 int type
, oldexpr
, newexpr
;
504 if (item
->menu
->list
)
505 item
->setExpanded(!item
->isExpanded());
509 type
= sym_get_type(sym
);
513 oldexpr
= sym_get_tristate_value(sym
);
514 newexpr
= sym_toggle_tristate_value(sym
);
515 if (item
->menu
->list
) {
516 if (oldexpr
== newexpr
)
517 item
->setExpanded(!item
->isExpanded());
518 else if (oldexpr
== no
)
519 item
->setExpanded(true);
521 if (oldexpr
!= newexpr
)
522 parent()->updateList(item
);
527 parent()->lineEdit
->show(item
);
532 void ConfigList::setRootMenu(struct menu
*menu
)
536 if (rootEntry
== menu
)
538 type
= menu
&& menu
->prompt
? menu
->prompt
->type
: P_UNKNOWN
;
541 updateMenuList(this, 0);
545 currentItem()->setSelected(hasFocus());
546 scrollToItem(currentItem());
550 void ConfigList::setParentMenu(void)
553 struct menu
*oldroot
;
556 if (rootEntry
== &rootmenu
)
558 setRootMenu(menu_get_parent_menu(rootEntry
->parent
));
560 QTreeWidgetItemIterator
it(this);
562 item
= (ConfigItem
*)(*it
);
563 if (item
->menu
== oldroot
) {
564 setCurrentItem(item
);
574 * update all the children of a menu entry
575 * removes/adds the entries from the parent widget as necessary
577 * parent: either the menu list widget or a menu entry widget
578 * menu: entry to be updated
580 void ConfigList::updateMenuList(ConfigItem
*parent
, struct menu
* menu
)
589 while (parent
->childCount() > 0)
591 delete parent
->takeChild(0);
597 last
= parent
->firstChild();
598 if (last
&& !last
->goParent
)
600 for (child
= menu
->list
; child
; child
= child
->next
) {
601 item
= last
? last
->nextSibling() : parent
->firstChild();
602 type
= child
->prompt
? child
->prompt
->type
: P_UNKNOWN
;
606 if (!(child
->flags
& MENU_ROOT
))
610 if (child
->flags
& MENU_ROOT
)
617 visible
= menu_is_visible(child
);
618 if (!menuSkip(child
)) {
619 if (!child
->sym
&& !child
->list
&& !child
->prompt
)
621 if (!item
|| item
->menu
!= child
)
622 item
= new ConfigItem(parent
, last
, child
, visible
);
624 item
->testUpdateMenu(visible
);
626 if (mode
== fullMode
|| mode
== menuMode
|| type
!= P_MENU
)
627 updateMenuList(item
, child
);
629 updateMenuList(item
, 0);
634 if (item
&& item
->menu
== child
) {
635 last
= parent
->firstChild();
638 else while (last
->nextSibling() != item
)
639 last
= last
->nextSibling();
645 void ConfigList::updateMenuList(ConfigList
*parent
, struct menu
* menu
)
654 while (parent
->topLevelItemCount() > 0)
656 delete parent
->takeTopLevelItem(0);
662 last
= (ConfigItem
*)parent
->topLevelItem(0);
663 if (last
&& !last
->goParent
)
665 for (child
= menu
->list
; child
; child
= child
->next
) {
666 item
= last
? last
->nextSibling() : (ConfigItem
*)parent
->topLevelItem(0);
667 type
= child
->prompt
? child
->prompt
->type
: P_UNKNOWN
;
671 if (!(child
->flags
& MENU_ROOT
))
675 if (child
->flags
& MENU_ROOT
)
682 visible
= menu_is_visible(child
);
683 if (!menuSkip(child
)) {
684 if (!child
->sym
&& !child
->list
&& !child
->prompt
)
686 if (!item
|| item
->menu
!= child
)
687 item
= new ConfigItem(parent
, last
, child
, visible
);
689 item
->testUpdateMenu(visible
);
691 if (mode
== fullMode
|| mode
== menuMode
|| type
!= P_MENU
)
692 updateMenuList(item
, child
);
694 updateMenuList(item
, 0);
699 if (item
&& item
->menu
== child
) {
700 last
= (ConfigItem
*)parent
->topLevelItem(0);
703 else while (last
->nextSibling() != item
)
704 last
= last
->nextSibling();
710 void ConfigList::keyPressEvent(QKeyEvent
* ev
)
712 QTreeWidgetItem
* i
= currentItem();
717 if (ev
->key() == Qt::Key_Escape
&& mode
!= fullMode
&& mode
!= listMode
) {
718 emit
parentSelected();
724 Parent::keyPressEvent(ev
);
727 item
= (ConfigItem
*)i
;
732 if (item
->goParent
) {
733 emit
parentSelected();
739 type
= menu
->prompt
? menu
->prompt
->type
: P_UNKNOWN
;
740 if (type
== P_MENU
&& rootEntry
!= menu
&&
741 mode
!= fullMode
&& mode
!= menuMode
) {
742 emit
menuSelected(menu
);
758 Parent::keyPressEvent(ev
);
764 void ConfigList::mousePressEvent(QMouseEvent
* e
)
766 //QPoint p(contentsToViewport(e->pos()));
767 //printf("contentsMousePressEvent: %d,%d\n", p.x(), p.y());
768 Parent::mousePressEvent(e
);
771 void ConfigList::mouseReleaseEvent(QMouseEvent
* e
)
774 ConfigItem
* item
= (ConfigItem
*)itemAt(p
);
776 enum prop_type ptype
;
784 x
= header()->offset() + p
.x();
785 idx
= header()->logicalIndexAt(x
);
788 icon
= item
->pixmap(promptColIdx
);
789 if (!icon
.isNull()) {
790 int off
= header()->sectionPosition(0) + visualRect(indexAt(p
)).x() + 4; // 4 is Hardcoded image offset. There might be a way to do it properly.
791 if (x
>= off
&& x
< off
+ icon
.availableSizes().first().width()) {
792 if (item
->goParent
) {
793 emit
parentSelected();
797 ptype
= menu
->prompt
? menu
->prompt
->type
: P_UNKNOWN
;
798 if (ptype
== P_MENU
&& rootEntry
!= menu
&&
799 mode
!= fullMode
&& mode
!= menuMode
)
800 emit
menuSelected(menu
);
821 //printf("contentsMouseReleaseEvent: %d,%d\n", p.x(), p.y());
822 Parent::mouseReleaseEvent(e
);
825 void ConfigList::mouseMoveEvent(QMouseEvent
* e
)
827 //QPoint p(contentsToViewport(e->pos()));
828 //printf("contentsMouseMoveEvent: %d,%d\n", p.x(), p.y());
829 Parent::mouseMoveEvent(e
);
832 void ConfigList::mouseDoubleClickEvent(QMouseEvent
* e
)
834 QPoint p
= e
->pos(); // TODO: Check if this works(was contentsToViewport).
835 ConfigItem
* item
= (ConfigItem
*)itemAt(p
);
837 enum prop_type ptype
;
841 if (item
->goParent
) {
842 emit
parentSelected();
848 ptype
= menu
->prompt
? menu
->prompt
->type
: P_UNKNOWN
;
849 if (ptype
== P_MENU
&& (mode
== singleMode
|| mode
== symbolMode
))
850 emit
menuSelected(menu
);
855 //printf("contentsMouseDoubleClickEvent: %d,%d\n", p.x(), p.y());
856 Parent::mouseDoubleClickEvent(e
);
859 void ConfigList::focusInEvent(QFocusEvent
*e
)
861 struct menu
*menu
= NULL
;
863 Parent::focusInEvent(e
);
865 ConfigItem
* item
= (ConfigItem
*)currentItem();
867 item
->setSelected(true);
873 void ConfigList::contextMenuEvent(QContextMenuEvent
*e
)
875 if (e
->y() <= header()->geometry().bottom()) {
879 headerPopup
= new QMenu(this);
880 action
= new QAction(_("Show Name"), this);
881 action
->setCheckable(true);
882 connect(action
, SIGNAL(toggled(bool)),
883 parent(), SLOT(setShowName(bool)));
884 connect(parent(), SIGNAL(showNameChanged(bool)),
885 action
, SLOT(setOn(bool)));
886 action
->setChecked(showName
);
887 headerPopup
->addAction(action
);
888 action
= new QAction(_("Show Range"), this);
889 action
->setCheckable(true);
890 connect(action
, SIGNAL(toggled(bool)),
891 parent(), SLOT(setShowRange(bool)));
892 connect(parent(), SIGNAL(showRangeChanged(bool)),
893 action
, SLOT(setOn(bool)));
894 action
->setChecked(showRange
);
895 headerPopup
->addAction(action
);
896 action
= new QAction(_("Show Data"), this);
897 action
->setCheckable(true);
898 connect(action
, SIGNAL(toggled(bool)),
899 parent(), SLOT(setShowData(bool)));
900 connect(parent(), SIGNAL(showDataChanged(bool)),
901 action
, SLOT(setOn(bool)));
902 action
->setChecked(showData
);
903 headerPopup
->addAction(action
);
905 headerPopup
->exec(e
->globalPos());
911 ConfigView
*ConfigView::viewList
;
912 QAction
*ConfigView::showNormalAction
;
913 QAction
*ConfigView::showAllAction
;
914 QAction
*ConfigView::showPromptAction
;
916 ConfigView::ConfigView(QWidget
* parent
, const char *name
)
920 QVBoxLayout
*verticalLayout
= new QVBoxLayout(this);
921 verticalLayout
->setContentsMargins(0, 0, 0, 0);
923 list
= new ConfigList(this);
924 verticalLayout
->addWidget(list
);
925 lineEdit
= new ConfigLineEdit(this);
927 verticalLayout
->addWidget(lineEdit
);
929 this->nextView
= viewList
;
933 ConfigView::~ConfigView(void)
937 for (vp
= &viewList
; *vp
; vp
= &(*vp
)->nextView
) {
945 void ConfigView::setOptionMode(QAction
*act
)
947 if (act
== showNormalAction
)
948 list
->optMode
= normalOpt
;
949 else if (act
== showAllAction
)
950 list
->optMode
= allOpt
;
952 list
->optMode
= promptOpt
;
954 list
->updateListAll();
957 void ConfigView::setShowName(bool b
)
959 if (list
->showName
!= b
) {
962 emit
showNameChanged(b
);
966 void ConfigView::setShowRange(bool b
)
968 if (list
->showRange
!= b
) {
971 emit
showRangeChanged(b
);
975 void ConfigView::setShowData(bool b
)
977 if (list
->showData
!= b
) {
980 emit
showDataChanged(b
);
984 void ConfigList::setAllOpen(bool open
)
986 QTreeWidgetItemIterator
it(this);
989 (*it
)->setExpanded(open
);
995 void ConfigView::updateList(ConfigItem
* item
)
999 for (v
= viewList
; v
; v
= v
->nextView
)
1000 v
->list
->updateList(item
);
1003 void ConfigView::updateListAll(void)
1007 for (v
= viewList
; v
; v
= v
->nextView
)
1008 v
->list
->updateListAll();
1011 ConfigInfoView::ConfigInfoView(QWidget
* parent
, const char *name
)
1012 : Parent(parent
), sym(0), _menu(0)
1014 setObjectName(name
);
1017 if (!objectName().isEmpty()) {
1018 configSettings
->beginGroup(objectName());
1019 _showDebug
= configSettings
->value("/showDebug", false).toBool();
1020 configSettings
->endGroup();
1021 connect(configApp
, SIGNAL(aboutToQuit()), SLOT(saveSettings()));
1025 void ConfigInfoView::saveSettings(void)
1027 if (!objectName().isEmpty()) {
1028 configSettings
->beginGroup(objectName());
1029 configSettings
->setValue("/showDebug", showDebug());
1030 configSettings
->endGroup();
1034 void ConfigInfoView::setShowDebug(bool b
)
1036 if (_showDebug
!= b
) {
1042 emit
showDebugChanged(b
);
1046 void ConfigInfoView::setInfo(struct menu
*m
)
1058 void ConfigInfoView::symbolInfo(void)
1062 str
+= "<big>Symbol: <b>";
1063 str
+= print_filter(sym
->name
);
1064 str
+= "</b></big><br><br>value: ";
1065 str
+= print_filter(sym_get_string_value(sym
));
1066 str
+= "<br>visibility: ";
1067 str
+= sym
->visible
== yes
? "y" : sym
->visible
== mod
? "m" : "n";
1069 str
+= debug_info(sym
);
1074 void ConfigInfoView::menuInfo(void)
1077 QString head
, debug
, help
;
1081 if (_menu
->prompt
) {
1083 head
+= print_filter(_(_menu
->prompt
->text
));
1084 head
+= "</b></big>";
1088 head
+= QString().sprintf("<a href=\"s%p\">", sym
);
1089 head
+= print_filter(sym
->name
);
1094 } else if (sym
->name
) {
1097 head
+= QString().sprintf("<a href=\"s%p\">", sym
);
1098 head
+= print_filter(sym
->name
);
1101 head
+= "</b></big>";
1106 debug
= debug_info(sym
);
1108 struct gstr help_gstr
= str_new();
1109 menu_get_ext_help(_menu
, &help_gstr
);
1110 help
= print_filter(str_get(&help_gstr
));
1111 str_free(&help_gstr
);
1112 } else if (_menu
->prompt
) {
1114 head
+= print_filter(_(_menu
->prompt
->text
));
1115 head
+= "</b></big><br><br>";
1117 if (_menu
->prompt
->visible
.expr
) {
1118 debug
+= " dep: ";
1119 expr_print(_menu
->prompt
->visible
.expr
, expr_print_help
, &debug
, E_NONE
);
1120 debug
+= "<br><br>";
1125 debug
+= QString().sprintf("defined at %s:%d<br><br>", _menu
->file
->name
, _menu
->lineno
);
1127 setText(head
+ debug
+ help
);
1130 QString
ConfigInfoView::debug_info(struct symbol
*sym
)
1135 debug
+= print_filter(sym_type_name(sym
->type
));
1136 if (sym_is_choice(sym
))
1137 debug
+= " (choice)";
1139 if (sym
->rev_dep
.expr
) {
1140 debug
+= "reverse dep: ";
1141 expr_print(sym
->rev_dep
.expr
, expr_print_help
, &debug
, E_NONE
);
1144 for (struct property
*prop
= sym
->prop
; prop
; prop
= prop
->next
) {
1145 switch (prop
->type
) {
1148 debug
+= QString().sprintf("prompt: <a href=\"m%p\">", prop
->menu
);
1149 debug
+= print_filter(_(prop
->text
));
1150 debug
+= "</a><br>";
1156 debug
+= prop_get_type_name(prop
->type
);
1158 expr_print(prop
->expr
, expr_print_help
, &debug
, E_NONE
);
1162 if (sym_is_choice(sym
)) {
1163 debug
+= "choice: ";
1164 expr_print(prop
->expr
, expr_print_help
, &debug
, E_NONE
);
1169 debug
+= "unknown property: ";
1170 debug
+= prop_get_type_name(prop
->type
);
1173 if (prop
->visible
.expr
) {
1174 debug
+= " dep: ";
1175 expr_print(prop
->visible
.expr
, expr_print_help
, &debug
, E_NONE
);
1184 QString
ConfigInfoView::print_filter(const QString
&str
)
1186 QRegExp
re("[<>&\"\\n]");
1188 for (int i
= 0; (i
= res
.indexOf(re
, i
)) >= 0;) {
1189 switch (res
[i
].toLatin1()) {
1191 res
.replace(i
, 1, "<");
1195 res
.replace(i
, 1, ">");
1199 res
.replace(i
, 1, "&");
1203 res
.replace(i
, 1, """);
1207 res
.replace(i
, 1, "<br>");
1215 void ConfigInfoView::expr_print_help(void *data
, struct symbol
*sym
, const char *str
)
1217 QString
* text
= reinterpret_cast<QString
*>(data
);
1218 QString str2
= print_filter(str
);
1220 if (sym
&& sym
->name
&& !(sym
->flags
& SYMBOL_CONST
)) {
1221 *text
+= QString().sprintf("<a href=\"s%p\">", sym
);
1228 QMenu
* ConfigInfoView::createStandardContextMenu(const QPoint
& pos
)
1230 QMenu
* popup
= Parent::createStandardContextMenu(pos
);
1231 QAction
* action
= new QAction(_("Show Debug Info"), popup
);
1232 action
->setCheckable(true);
1233 connect(action
, SIGNAL(toggled(bool)), SLOT(setShowDebug(bool)));
1234 connect(this, SIGNAL(showDebugChanged(bool)), action
, SLOT(setOn(bool)));
1235 action
->setChecked(showDebug());
1236 popup
->addSeparator();
1237 popup
->addAction(action
);
1241 void ConfigInfoView::contextMenuEvent(QContextMenuEvent
*e
)
1243 Parent::contextMenuEvent(e
);
1246 ConfigSearchWindow::ConfigSearchWindow(ConfigMainWindow
* parent
, const char *name
)
1247 : Parent(parent
), result(NULL
)
1249 setObjectName(name
);
1250 setWindowTitle("Search Config");
1252 QVBoxLayout
* layout1
= new QVBoxLayout(this);
1253 layout1
->setContentsMargins(11, 11, 11, 11);
1254 layout1
->setSpacing(6);
1255 QHBoxLayout
* layout2
= new QHBoxLayout(0);
1256 layout2
->setContentsMargins(0, 0, 0, 0);
1257 layout2
->setSpacing(6);
1258 layout2
->addWidget(new QLabel(_("Find:"), this));
1259 editField
= new QLineEdit(this);
1260 connect(editField
, SIGNAL(returnPressed()), SLOT(search()));
1261 layout2
->addWidget(editField
);
1262 searchButton
= new QPushButton(_("Search"), this);
1263 searchButton
->setAutoDefault(false);
1264 connect(searchButton
, SIGNAL(clicked()), SLOT(search()));
1265 layout2
->addWidget(searchButton
);
1266 layout1
->addLayout(layout2
);
1268 split
= new QSplitter(this);
1269 split
->setOrientation(Qt::Vertical
);
1270 list
= new ConfigView(split
, name
);
1271 list
->list
->mode
= listMode
;
1272 info
= new ConfigInfoView(split
, name
);
1273 connect(list
->list
, SIGNAL(menuChanged(struct menu
*)),
1274 info
, SLOT(setInfo(struct menu
*)));
1275 connect(list
->list
, SIGNAL(menuChanged(struct menu
*)),
1276 parent
, SLOT(setMenuLink(struct menu
*)));
1278 layout1
->addWidget(split
);
1285 configSettings
->beginGroup(name
);
1286 width
= configSettings
->value("/window width", parent
->width() / 2).toInt();
1287 height
= configSettings
->value("/window height", parent
->height() / 2).toInt();
1288 resize(width
, height
);
1289 x
= configSettings
->value("/window x");
1290 y
= configSettings
->value("/window y");
1291 if ((x
.isValid())&&(y
.isValid()))
1292 move(x
.toInt(), y
.toInt());
1293 QList
<int> sizes
= configSettings
->readSizes("/split", &ok
);
1295 split
->setSizes(sizes
);
1296 configSettings
->endGroup();
1297 connect(configApp
, SIGNAL(aboutToQuit()), SLOT(saveSettings()));
1301 void ConfigSearchWindow::saveSettings(void)
1303 if (!objectName().isEmpty()) {
1304 configSettings
->beginGroup(objectName());
1305 configSettings
->setValue("/window x", pos().x());
1306 configSettings
->setValue("/window y", pos().y());
1307 configSettings
->setValue("/window width", size().width());
1308 configSettings
->setValue("/window height", size().height());
1309 configSettings
->writeSizes("/split", split
->sizes());
1310 configSettings
->endGroup();
1314 void ConfigSearchWindow::search(void)
1317 struct property
*prop
;
1318 ConfigItem
*lastItem
= NULL
;
1321 list
->list
->clear();
1324 result
= sym_re_search(editField
->text().toLatin1());
1327 for (p
= result
; *p
; p
++) {
1328 for_all_prompts((*p
), prop
)
1329 lastItem
= new ConfigItem(list
->list
, lastItem
, prop
->menu
,
1330 menu_is_visible(prop
->menu
));
1335 * Construct the complete config widget
1337 ConfigMainWindow::ConfigMainWindow(void)
1346 QDesktopWidget
*d
= configApp
->desktop();
1347 snprintf(title
, sizeof(title
), "%s%s",
1348 rootmenu
.prompt
->text
,
1351 setWindowTitle(title
);
1353 width
= configSettings
->value("/window width", d
->width() - 64).toInt();
1354 height
= configSettings
->value("/window height", d
->height() - 64).toInt();
1355 resize(width
, height
);
1356 x
= configSettings
->value("/window x");
1357 y
= configSettings
->value("/window y");
1358 if ((x
.isValid())&&(y
.isValid()))
1359 move(x
.toInt(), y
.toInt());
1361 split1
= new QSplitter(this);
1362 split1
->setOrientation(Qt::Horizontal
);
1363 setCentralWidget(split1
);
1365 menuView
= new ConfigView(split1
, "menu");
1366 menuList
= menuView
->list
;
1368 split2
= new QSplitter(split1
);
1369 split2
->setOrientation(Qt::Vertical
);
1371 // create config tree
1372 configView
= new ConfigView(split2
, "config");
1373 configList
= configView
->list
;
1375 helpText
= new ConfigInfoView(split2
, "help");
1377 setTabOrder(configList
, helpText
);
1378 configList
->setFocus();
1381 toolBar
= new QToolBar("Tools", this);
1382 addToolBar(toolBar
);
1384 backAction
= new QAction(QPixmap(xpm_back
), _("Back"), this);
1385 connect(backAction
, SIGNAL(triggered(bool)), SLOT(goBack()));
1386 backAction
->setEnabled(false);
1387 QAction
*quitAction
= new QAction(_("&Quit"), this);
1388 quitAction
->setShortcut(Qt::CTRL
+ Qt::Key_Q
);
1389 connect(quitAction
, SIGNAL(triggered(bool)), SLOT(close()));
1390 QAction
*loadAction
= new QAction(QPixmap(xpm_load
), _("&Load"), this);
1391 loadAction
->setShortcut(Qt::CTRL
+ Qt::Key_L
);
1392 connect(loadAction
, SIGNAL(triggered(bool)), SLOT(loadConfig()));
1393 saveAction
= new QAction(QPixmap(xpm_save
), _("&Save"), this);
1394 saveAction
->setShortcut(Qt::CTRL
+ Qt::Key_S
);
1395 connect(saveAction
, SIGNAL(triggered(bool)), SLOT(saveConfig()));
1396 conf_set_changed_callback(conf_changed
);
1397 // Set saveAction's initial state
1399 QAction
*saveAsAction
= new QAction(_("Save &As..."), this);
1400 connect(saveAsAction
, SIGNAL(triggered(bool)), SLOT(saveConfigAs()));
1401 QAction
*searchAction
= new QAction(_("&Find"), this);
1402 searchAction
->setShortcut(Qt::CTRL
+ Qt::Key_F
);
1403 connect(searchAction
, SIGNAL(triggered(bool)), SLOT(searchConfig()));
1404 singleViewAction
= new QAction(QPixmap(xpm_single_view
), _("Single View"), this);
1405 singleViewAction
->setCheckable(true);
1406 connect(singleViewAction
, SIGNAL(triggered(bool)), SLOT(showSingleView()));
1407 splitViewAction
= new QAction(QPixmap(xpm_split_view
), _("Split View"), this);
1408 splitViewAction
->setCheckable(true);
1409 connect(splitViewAction
, SIGNAL(triggered(bool)), SLOT(showSplitView()));
1410 fullViewAction
= new QAction(QPixmap(xpm_tree_view
), _("Full View"), this);
1411 fullViewAction
->setCheckable(true);
1412 connect(fullViewAction
, SIGNAL(triggered(bool)), SLOT(showFullView()));
1414 QAction
*showNameAction
= new QAction(_("Show Name"), this);
1415 showNameAction
->setCheckable(true);
1416 connect(showNameAction
, SIGNAL(toggled(bool)), configView
, SLOT(setShowName(bool)));
1417 showNameAction
->setChecked(configView
->showName());
1418 QAction
*showRangeAction
= new QAction(_("Show Range"), this);
1419 showRangeAction
->setCheckable(true);
1420 connect(showRangeAction
, SIGNAL(toggled(bool)), configView
, SLOT(setShowRange(bool)));
1421 QAction
*showDataAction
= new QAction(_("Show Data"), this);
1422 showDataAction
->setCheckable(true);
1423 connect(showDataAction
, SIGNAL(toggled(bool)), configView
, SLOT(setShowData(bool)));
1425 QActionGroup
*optGroup
= new QActionGroup(this);
1426 optGroup
->setExclusive(true);
1427 connect(optGroup
, SIGNAL(triggered(QAction
*)), configView
,
1428 SLOT(setOptionMode(QAction
*)));
1429 connect(optGroup
, SIGNAL(triggered(QAction
*)), menuView
,
1430 SLOT(setOptionMode(QAction
*)));
1432 configView
->showNormalAction
= new QAction(_("Show Normal Options"), optGroup
);
1433 configView
->showAllAction
= new QAction(_("Show All Options"), optGroup
);
1434 configView
->showPromptAction
= new QAction(_("Show Prompt Options"), optGroup
);
1435 configView
->showNormalAction
->setCheckable(true);
1436 configView
->showAllAction
->setCheckable(true);
1437 configView
->showPromptAction
->setCheckable(true);
1439 QAction
*showDebugAction
= new QAction( _("Show Debug Info"), this);
1440 showDebugAction
->setCheckable(true);
1441 connect(showDebugAction
, SIGNAL(toggled(bool)), helpText
, SLOT(setShowDebug(bool)));
1442 showDebugAction
->setChecked(helpText
->showDebug());
1444 QAction
*showIntroAction
= new QAction( _("Introduction"), this);
1445 connect(showIntroAction
, SIGNAL(triggered(bool)), SLOT(showIntro()));
1446 QAction
*showAboutAction
= new QAction( _("About"), this);
1447 connect(showAboutAction
, SIGNAL(triggered(bool)), SLOT(showAbout()));
1450 toolBar
->addAction(backAction
);
1451 toolBar
->addSeparator();
1452 toolBar
->addAction(loadAction
);
1453 toolBar
->addAction(saveAction
);
1454 toolBar
->addSeparator();
1455 toolBar
->addAction(singleViewAction
);
1456 toolBar
->addAction(splitViewAction
);
1457 toolBar
->addAction(fullViewAction
);
1459 // create config menu
1460 QMenu
* config
= menu
->addMenu(_("&File"));
1461 config
->addAction(loadAction
);
1462 config
->addAction(saveAction
);
1463 config
->addAction(saveAsAction
);
1464 config
->addSeparator();
1465 config
->addAction(quitAction
);
1468 QMenu
* editMenu
= menu
->addMenu(_("&Edit"));
1469 editMenu
->addAction(searchAction
);
1471 // create options menu
1472 QMenu
* optionMenu
= menu
->addMenu(_("&Option"));
1473 optionMenu
->addAction(showNameAction
);
1474 optionMenu
->addAction(showRangeAction
);
1475 optionMenu
->addAction(showDataAction
);
1476 optionMenu
->addSeparator();
1477 optionMenu
->addActions(optGroup
->actions());
1478 optionMenu
->addSeparator();
1481 menu
->addSeparator();
1482 QMenu
* helpMenu
= menu
->addMenu(_("&Help"));
1483 helpMenu
->addAction(showIntroAction
);
1484 helpMenu
->addAction(showAboutAction
);
1486 connect(configList
, SIGNAL(menuChanged(struct menu
*)),
1487 helpText
, SLOT(setInfo(struct menu
*)));
1488 connect(configList
, SIGNAL(menuSelected(struct menu
*)),
1489 SLOT(changeMenu(struct menu
*)));
1490 connect(configList
, SIGNAL(parentSelected()),
1492 connect(menuList
, SIGNAL(menuChanged(struct menu
*)),
1493 helpText
, SLOT(setInfo(struct menu
*)));
1494 connect(menuList
, SIGNAL(menuSelected(struct menu
*)),
1495 SLOT(changeMenu(struct menu
*)));
1497 connect(configList
, SIGNAL(gotFocus(struct menu
*)),
1498 helpText
, SLOT(setInfo(struct menu
*)));
1499 connect(menuList
, SIGNAL(gotFocus(struct menu
*)),
1500 helpText
, SLOT(setInfo(struct menu
*)));
1501 connect(menuList
, SIGNAL(gotFocus(struct menu
*)),
1502 SLOT(listFocusChanged(void)));
1503 connect(helpText
, SIGNAL(menuSelected(struct menu
*)),
1504 SLOT(setMenuLink(struct menu
*)));
1506 QString listMode
= configSettings
->value("/listMode", "symbol").toString();
1507 if (listMode
== "single")
1509 else if (listMode
== "full")
1511 else /*if (listMode == "split")*/
1514 // UI setup done, restore splitter positions
1515 QList
<int> sizes
= configSettings
->readSizes("/split1", &ok
);
1517 split1
->setSizes(sizes
);
1519 sizes
= configSettings
->readSizes("/split2", &ok
);
1521 split2
->setSizes(sizes
);
1524 void ConfigMainWindow::loadConfig(void)
1526 QString s
= QFileDialog::getOpenFileName(this, "", conf_get_configname());
1529 if (conf_read(QFile::encodeName(s
)))
1530 QMessageBox::information(this, "qconf", _("Unable to load configuration!"));
1531 ConfigView::updateListAll();
1534 bool ConfigMainWindow::saveConfig(void)
1536 if (conf_write(NULL
)) {
1537 QMessageBox::information(this, "qconf", _("Unable to save configuration!"));
1543 void ConfigMainWindow::saveConfigAs(void)
1545 QString s
= QFileDialog::getSaveFileName(this, "", conf_get_configname());
1551 void ConfigMainWindow::searchConfig(void)
1554 searchWindow
= new ConfigSearchWindow(this, "search");
1555 searchWindow
->show();
1558 void ConfigMainWindow::changeMenu(struct menu
*menu
)
1560 configList
->setRootMenu(menu
);
1561 if (configList
->rootEntry
->parent
== &rootmenu
)
1562 backAction
->setEnabled(false);
1564 backAction
->setEnabled(true);
1567 void ConfigMainWindow::setMenuLink(struct menu
*menu
)
1569 struct menu
*parent
;
1570 ConfigList
* list
= NULL
;
1573 if (configList
->menuSkip(menu
))
1576 switch (configList
->mode
) {
1579 parent
= menu_get_parent_menu(menu
);
1582 list
->setRootMenu(parent
);
1585 if (menu
->flags
& MENU_ROOT
) {
1586 configList
->setRootMenu(menu
);
1587 configList
->clearSelection();
1591 parent
= menu_get_parent_menu(menu
->parent
);
1594 item
= menuList
->findConfigItem(parent
);
1596 item
->setSelected(true);
1597 menuList
->scrollToItem(item
);
1599 list
->setRootMenu(parent
);
1610 item
= list
->findConfigItem(menu
);
1612 item
->setSelected(true);
1613 list
->scrollToItem(item
);
1619 void ConfigMainWindow::listFocusChanged(void)
1621 if (menuList
->mode
== menuMode
)
1622 configList
->clearSelection();
1625 void ConfigMainWindow::goBack(void)
1627 ConfigItem
* item
, *oldSelection
;
1629 configList
->setParentMenu();
1630 if (configList
->rootEntry
== &rootmenu
)
1631 backAction
->setEnabled(false);
1633 if (menuList
->selectedItems().count() == 0)
1636 item
= (ConfigItem
*)menuList
->selectedItems().first();
1637 oldSelection
= item
;
1639 if (item
->menu
== configList
->rootEntry
) {
1640 oldSelection
->setSelected(false);
1641 item
->setSelected(true);
1644 item
= (ConfigItem
*)item
->parent();
1648 void ConfigMainWindow::showSingleView(void)
1650 singleViewAction
->setEnabled(false);
1651 singleViewAction
->setChecked(true);
1652 splitViewAction
->setEnabled(true);
1653 splitViewAction
->setChecked(false);
1654 fullViewAction
->setEnabled(true);
1655 fullViewAction
->setChecked(false);
1658 menuList
->setRootMenu(0);
1659 configList
->mode
= singleMode
;
1660 if (configList
->rootEntry
== &rootmenu
)
1661 configList
->updateListAll();
1663 configList
->setRootMenu(&rootmenu
);
1664 configList
->setFocus();
1667 void ConfigMainWindow::showSplitView(void)
1669 singleViewAction
->setEnabled(true);
1670 singleViewAction
->setChecked(false);
1671 splitViewAction
->setEnabled(false);
1672 splitViewAction
->setChecked(true);
1673 fullViewAction
->setEnabled(true);
1674 fullViewAction
->setChecked(false);
1676 configList
->mode
= symbolMode
;
1677 if (configList
->rootEntry
== &rootmenu
)
1678 configList
->updateListAll();
1680 configList
->setRootMenu(&rootmenu
);
1681 configList
->setAllOpen(true);
1682 configApp
->processEvents();
1683 menuList
->mode
= menuMode
;
1684 menuList
->setRootMenu(&rootmenu
);
1685 menuList
->setAllOpen(true);
1687 menuList
->setFocus();
1690 void ConfigMainWindow::showFullView(void)
1692 singleViewAction
->setEnabled(true);
1693 singleViewAction
->setChecked(false);
1694 splitViewAction
->setEnabled(true);
1695 splitViewAction
->setChecked(false);
1696 fullViewAction
->setEnabled(false);
1697 fullViewAction
->setChecked(true);
1700 menuList
->setRootMenu(0);
1701 configList
->mode
= fullMode
;
1702 if (configList
->rootEntry
== &rootmenu
)
1703 configList
->updateListAll();
1705 configList
->setRootMenu(&rootmenu
);
1706 configList
->setFocus();
1710 * ask for saving configuration before quitting
1711 * TODO ask only when something changed
1713 void ConfigMainWindow::closeEvent(QCloseEvent
* e
)
1715 if (!conf_get_changed()) {
1719 QMessageBox
mb("qconf", _("Save configuration?"), QMessageBox::Warning
,
1720 QMessageBox::Yes
| QMessageBox::Default
, QMessageBox::No
, QMessageBox::Cancel
| QMessageBox::Escape
);
1721 mb
.setButtonText(QMessageBox::Yes
, _("&Save Changes"));
1722 mb
.setButtonText(QMessageBox::No
, _("&Discard Changes"));
1723 mb
.setButtonText(QMessageBox::Cancel
, _("Cancel Exit"));
1724 switch (mb
.exec()) {
1725 case QMessageBox::Yes
:
1731 case QMessageBox::No
:
1734 case QMessageBox::Cancel
:
1740 void ConfigMainWindow::showIntro(void)
1742 static const QString str
= _("Welcome to the qconf graphical configuration tool.\n\n"
1743 "For each option, a blank box indicates the feature is disabled, a check\n"
1744 "indicates it is enabled, and a dot indicates that it is to be compiled\n"
1745 "as a module. Clicking on the box will cycle through the three states.\n\n"
1746 "If you do not see an option (e.g., a device driver) that you believe\n"
1747 "should be present, try turning on Show All Options under the Options menu.\n"
1748 "Although there is no cross reference yet to help you figure out what other\n"
1749 "options must be enabled to support the option you are interested in, you can\n"
1750 "still view the help of a grayed-out option.\n\n"
1751 "Toggling Show Debug Info under the Options menu will show the dependencies,\n"
1752 "which you can then match by examining other options.\n\n");
1754 QMessageBox::information(this, "qconf", str
);
1757 void ConfigMainWindow::showAbout(void)
1759 static const QString str
= _("qconf is Copyright (C) 2002 Roman Zippel <zippel@linux-m68k.org>.\n"
1760 "Copyright (C) 2015 Boris Barbulovski <bbarbulovski@gmail.com>.\n\n"
1761 "Bug reports and feature request can also be entered at http://bugzilla.kernel.org/\n");
1763 QMessageBox::information(this, "qconf", str
);
1766 void ConfigMainWindow::saveSettings(void)
1768 configSettings
->setValue("/window x", pos().x());
1769 configSettings
->setValue("/window y", pos().y());
1770 configSettings
->setValue("/window width", size().width());
1771 configSettings
->setValue("/window height", size().height());
1774 switch(configList
->mode
) {
1790 configSettings
->setValue("/listMode", entry
);
1792 configSettings
->writeSizes("/split1", split1
->sizes());
1793 configSettings
->writeSizes("/split2", split2
->sizes());
1796 void ConfigMainWindow::conf_changed(void)
1799 saveAction
->setEnabled(conf_get_changed());
1802 void fixup_rootmenu(struct menu
*menu
)
1805 static int menu_cnt
= 0;
1807 menu
->flags
|= MENU_ROOT
;
1808 for (child
= menu
->list
; child
; child
= child
->next
) {
1809 if (child
->prompt
&& child
->prompt
->type
== P_MENU
) {
1811 fixup_rootmenu(child
);
1813 } else if (!menu_cnt
)
1814 fixup_rootmenu(child
);
1818 static const char *progname
;
1820 static void usage(void)
1822 printf(_("%s [-s] <config>\n").toLatin1().constData(), progname
);
1826 int main(int ac
, char** av
)
1828 ConfigMainWindow
* v
;
1831 bindtextdomain(PACKAGE
, LOCALEDIR
);
1832 textdomain(PACKAGE
);
1835 configApp
= new QApplication(ac
, av
);
1836 if (ac
> 1 && av
[1][0] == '-') {
1839 conf_set_message_callback(NULL
);
1852 fixup_rootmenu(&rootmenu
);
1854 //zconfdump(stdout);
1856 configSettings
= new ConfigSettings();
1857 configSettings
->beginGroup("/kconfig/qconf");
1858 v
= new ConfigMainWindow();
1860 //zconfdump(stdout);
1861 configApp
->connect(configApp
, SIGNAL(lastWindowClosed()), SLOT(quit()));
1862 configApp
->connect(configApp
, SIGNAL(aboutToQuit()), v
, SLOT(saveSettings()));
1866 configSettings
->endGroup();
1867 delete configSettings
;