]>
git.proxmox.com Git - mirror_ubuntu-jammy-kernel.git/blob - scripts/kconfig/qconf.cc
1 // SPDX-License-Identifier: GPL-2.0
3 * Copyright (C) 2002 Roman Zippel <zippel@linux-m68k.org>
4 * Copyright (C) 2015 Boris Barbulovski <bbarbulovski@gmail.com>
8 #include <QApplication>
11 #include <QDesktopWidget>
12 #include <QFileDialog>
18 #include <QMessageBox>
29 static QApplication
*configApp
;
30 static ConfigSettings
*configSettings
;
32 QAction
*ConfigMainWindow::saveAction
;
34 ConfigSettings::ConfigSettings()
35 : QSettings("kernel.org", "qconf")
40 * Reads a list of integer values from the application settings.
42 QList
<int> ConfigSettings::readSizes(const QString
& key
, bool *ok
)
48 QStringList entryList
= value(key
).toStringList();
49 QStringList::Iterator it
;
51 for (it
= entryList
.begin(); it
!= entryList
.end(); ++it
)
52 result
.push_back((*it
).toInt());
63 * Writes a list of integer values to the application settings.
65 bool ConfigSettings::writeSizes(const QString
& key
, const QList
<int>& value
)
67 QStringList stringList
;
68 QList
<int>::ConstIterator it
;
70 for (it
= value
.begin(); it
!= value
.end(); ++it
)
71 stringList
.push_back(QString::number(*it
));
72 setValue(key
, stringList
);
77 QIcon
ConfigItem::symbolYesIcon
;
78 QIcon
ConfigItem::symbolModIcon
;
79 QIcon
ConfigItem::symbolNoIcon
;
80 QIcon
ConfigItem::choiceYesIcon
;
81 QIcon
ConfigItem::choiceNoIcon
;
82 QIcon
ConfigItem::menuIcon
;
83 QIcon
ConfigItem::menubackIcon
;
86 * update the displayed of a menu entry
88 void ConfigItem::updateMenu(void)
92 struct property
*prop
;
99 setIcon(promptColIdx
, menubackIcon
);
106 prompt
= menu_get_prompt(menu
);
108 if (prop
) switch (prop
->type
) {
110 if (list
->mode
== singleMode
|| list
->mode
== symbolMode
) {
111 /* a menuconfig entry is displayed differently
112 * depending whether it's at the view root or a child.
114 if (sym
&& list
->rootEntry
== menu
)
116 setIcon(promptColIdx
, menuIcon
);
120 setIcon(promptColIdx
, QIcon());
124 setIcon(promptColIdx
, QIcon());
125 prompt
= "*** " + prompt
+ " ***";
133 setText(nameColIdx
, sym
->name
);
135 type
= sym_get_type(sym
);
141 if (!sym_is_changeable(sym
) && list
->optMode
== normalOpt
) {
142 setIcon(promptColIdx
, QIcon());
145 expr
= sym_get_tristate_value(sym
);
148 if (sym_is_choice_value(sym
) && type
== S_BOOLEAN
)
149 setIcon(promptColIdx
, choiceYesIcon
);
151 setIcon(promptColIdx
, symbolYesIcon
);
155 setIcon(promptColIdx
, symbolModIcon
);
159 if (sym_is_choice_value(sym
) && type
== S_BOOLEAN
)
160 setIcon(promptColIdx
, choiceNoIcon
);
162 setIcon(promptColIdx
, symbolNoIcon
);
167 setText(dataColIdx
, QChar(ch
));
172 setText(dataColIdx
, sym_get_string_value(sym
));
175 if (!sym_has_value(sym
) && visible
)
178 setText(promptColIdx
, prompt
);
181 void ConfigItem::testUpdateMenu(bool v
)
189 sym_calc_value(menu
->sym
);
190 if (menu
->flags
& MENU_CHANGED
) {
191 /* the menu entry changed, so update all list items */
192 menu
->flags
&= ~MENU_CHANGED
;
193 for (i
= (ConfigItem
*)menu
->data
; i
; i
= i
->nextItem
)
195 } else if (listView()->updateAll
)
201 * construct a menu entry
203 void ConfigItem::init(void)
206 ConfigList
* list
= listView();
207 nextItem
= (ConfigItem
*)menu
->data
;
210 if (list
->mode
!= fullMode
)
212 sym_calc_value(menu
->sym
);
215 enum symbol_type type
= menu
->sym
->type
;
217 // Allow to edit "int", "hex", and "string" in-place in
218 // the data column. Unfortunately, you cannot specify
219 // the flags per column. Set ItemIsEditable for all
220 // columns here, and check the column in createEditor().
221 if (type
== S_INT
|| type
== S_HEX
|| type
== S_STRING
)
222 setFlags(flags() | Qt::ItemIsEditable
);
229 * destruct a menu entry
231 ConfigItem::~ConfigItem(void)
234 ConfigItem
** ip
= (ConfigItem
**)&menu
->data
;
235 for (; *ip
; ip
= &(*ip
)->nextItem
) {
244 QWidget
*ConfigItemDelegate::createEditor(QWidget
*parent
,
245 const QStyleOptionViewItem
&option
,
246 const QModelIndex
&index
) const
250 // Only the data column is editable
251 if (index
.column() != dataColIdx
)
254 // You cannot edit invisible menus
255 item
= static_cast<ConfigItem
*>(index
.internalPointer());
256 if (!item
|| !item
->menu
|| !menu_is_visible(item
->menu
))
259 return QStyledItemDelegate::createEditor(parent
, option
, index
);
262 void ConfigItemDelegate::setModelData(QWidget
*editor
,
263 QAbstractItemModel
*model
,
264 const QModelIndex
&index
) const
271 lineEdit
= qobject_cast
<QLineEdit
*>(editor
);
272 // If this is not a QLineEdit, use the parent's default.
273 // (does this happen?)
277 item
= static_cast<ConfigItem
*>(index
.internalPointer());
278 if (!item
|| !item
->menu
)
281 sym
= item
->menu
->sym
;
285 success
= sym_set_string_value(sym
, lineEdit
->text().toUtf8().data());
287 ConfigList::updateListForAll();
289 QMessageBox::information(editor
, "qconf",
290 "Cannot set the data (maybe due to out of range).\n"
291 "Setting the old value.");
292 lineEdit
->setText(sym_get_string_value(sym
));
296 QStyledItemDelegate::setModelData(editor
, model
, index
);
299 ConfigList::ConfigList(QWidget
*parent
, const char *name
)
300 : QTreeWidget(parent
),
302 showName(false), mode(singleMode
), optMode(normalOpt
),
303 rootEntry(0), headerPopup(0)
306 setSortingEnabled(false);
307 setRootIsDecorated(true);
309 setVerticalScrollMode(ScrollPerPixel
);
310 setHorizontalScrollMode(ScrollPerPixel
);
312 setHeaderLabels(QStringList() << "Option" << "Name" << "Value");
314 connect(this, &ConfigList::itemSelectionChanged
,
315 this, &ConfigList::updateSelection
);
318 configSettings
->beginGroup(name
);
319 showName
= configSettings
->value("/showName", false).toBool();
320 optMode
= (enum optionMode
)configSettings
->value("/optionMode", 0).toInt();
321 configSettings
->endGroup();
322 connect(configApp
, &QApplication::aboutToQuit
,
323 this, &ConfigList::saveSettings
);
326 showColumn(promptColIdx
);
328 setItemDelegate(new ConfigItemDelegate(this));
330 allLists
.append(this);
335 ConfigList::~ConfigList()
337 allLists
.removeOne(this);
340 bool ConfigList::menuSkip(struct menu
*menu
)
342 if (optMode
== normalOpt
&& menu_is_visible(menu
))
344 if (optMode
== promptOpt
&& menu_has_prompt(menu
))
346 if (optMode
== allOpt
)
351 void ConfigList::reinit(void)
353 hideColumn(nameColIdx
);
356 showColumn(nameColIdx
);
361 void ConfigList::setOptionMode(QAction
*action
)
363 if (action
== showNormalAction
)
365 else if (action
== showAllAction
)
373 void ConfigList::saveSettings(void)
375 if (!objectName().isEmpty()) {
376 configSettings
->beginGroup(objectName());
377 configSettings
->setValue("/showName", showName
);
378 configSettings
->setValue("/optionMode", (int)optMode
);
379 configSettings
->endGroup();
383 ConfigItem
* ConfigList::findConfigItem(struct menu
*menu
)
385 ConfigItem
* item
= (ConfigItem
*)menu
->data
;
387 for (; item
; item
= item
->nextItem
) {
388 if (this == item
->listView())
395 void ConfigList::updateSelection(void)
400 if (selectedItems().count() == 0)
403 ConfigItem
* item
= (ConfigItem
*)selectedItems().first();
408 emit
menuChanged(menu
);
411 type
= menu
->prompt
? menu
->prompt
->type
: P_UNKNOWN
;
412 if (mode
== menuMode
&& type
== P_MENU
)
413 emit
menuSelected(menu
);
416 void ConfigList::updateList()
418 ConfigItem
* last
= 0;
422 if (mode
!= listMode
)
424 QTreeWidgetItemIterator
it(this);
427 item
= (ConfigItem
*)(*it
);
430 item
->testUpdateMenu(menu_is_visible(item
->menu
));
437 if (rootEntry
!= &rootmenu
&& (mode
== singleMode
||
438 (mode
== symbolMode
&& rootEntry
->parent
!= &rootmenu
))) {
439 item
= (ConfigItem
*)topLevelItem(0);
441 item
= new ConfigItem(this, 0, true);
444 if ((mode
== singleMode
|| (mode
== symbolMode
&& !(rootEntry
->flags
& MENU_ROOT
))) &&
445 rootEntry
->sym
&& rootEntry
->prompt
) {
446 item
= last
? last
->nextSibling() : nullptr;
448 item
= new ConfigItem(this, last
, rootEntry
, true);
450 item
->testUpdateMenu(true);
452 updateMenuList(item
, rootEntry
);
454 resizeColumnToContents(0);
458 updateMenuList(rootEntry
);
460 resizeColumnToContents(0);
463 void ConfigList::updateListForAll()
465 QListIterator
<ConfigList
*> it(allLists
);
467 while (it
.hasNext()) {
468 ConfigList
*list
= it
.next();
474 void ConfigList::updateListAllForAll()
476 QListIterator
<ConfigList
*> it(allLists
);
478 while (it
.hasNext()) {
479 ConfigList
*list
= it
.next();
485 void ConfigList::setValue(ConfigItem
* item
, tristate val
)
491 sym
= item
->menu
? item
->menu
->sym
: 0;
495 type
= sym_get_type(sym
);
499 oldval
= sym_get_tristate_value(sym
);
501 if (!sym_set_tristate_value(sym
, val
))
503 if (oldval
== no
&& item
->menu
->list
)
504 item
->setExpanded(true);
505 ConfigList::updateListForAll();
510 void ConfigList::changeValue(ConfigItem
* item
)
514 int type
, oldexpr
, newexpr
;
521 if (item
->menu
->list
)
522 item
->setExpanded(!item
->isExpanded());
526 type
= sym_get_type(sym
);
530 oldexpr
= sym_get_tristate_value(sym
);
531 newexpr
= sym_toggle_tristate_value(sym
);
532 if (item
->menu
->list
) {
533 if (oldexpr
== newexpr
)
534 item
->setExpanded(!item
->isExpanded());
535 else if (oldexpr
== no
)
536 item
->setExpanded(true);
538 if (oldexpr
!= newexpr
)
539 ConfigList::updateListForAll();
546 void ConfigList::setRootMenu(struct menu
*menu
)
550 if (rootEntry
== menu
)
552 type
= menu
&& menu
->prompt
? menu
->prompt
->type
: P_UNKNOWN
;
559 setSelected(currentItem(), hasFocus());
560 scrollToItem(currentItem());
564 void ConfigList::setParentMenu(void)
567 struct menu
*oldroot
;
570 if (rootEntry
== &rootmenu
)
572 setRootMenu(menu_get_parent_menu(rootEntry
->parent
));
574 QTreeWidgetItemIterator
it(this);
576 item
= (ConfigItem
*)(*it
);
577 if (item
->menu
== oldroot
) {
578 setCurrentItem(item
);
588 * update all the children of a menu entry
589 * removes/adds the entries from the parent widget as necessary
591 * parent: either the menu list widget or a menu entry widget
592 * menu: entry to be updated
594 void ConfigList::updateMenuList(ConfigItem
*parent
, struct menu
* menu
)
603 while (parent
->childCount() > 0)
605 delete parent
->takeChild(0);
611 last
= parent
->firstChild();
612 if (last
&& !last
->goParent
)
614 for (child
= menu
->list
; child
; child
= child
->next
) {
615 item
= last
? last
->nextSibling() : parent
->firstChild();
616 type
= child
->prompt
? child
->prompt
->type
: P_UNKNOWN
;
620 if (!(child
->flags
& MENU_ROOT
))
624 if (child
->flags
& MENU_ROOT
)
631 visible
= menu_is_visible(child
);
632 if (!menuSkip(child
)) {
633 if (!child
->sym
&& !child
->list
&& !child
->prompt
)
635 if (!item
|| item
->menu
!= child
)
636 item
= new ConfigItem(parent
, last
, child
, visible
);
638 item
->testUpdateMenu(visible
);
640 if (mode
== fullMode
|| mode
== menuMode
|| type
!= P_MENU
)
641 updateMenuList(item
, child
);
643 updateMenuList(item
, 0);
648 if (item
&& item
->menu
== child
) {
649 last
= parent
->firstChild();
652 else while (last
->nextSibling() != item
)
653 last
= last
->nextSibling();
659 void ConfigList::updateMenuList(struct menu
*menu
)
668 while (topLevelItemCount() > 0)
670 delete takeTopLevelItem(0);
676 last
= (ConfigItem
*)topLevelItem(0);
677 if (last
&& !last
->goParent
)
679 for (child
= menu
->list
; child
; child
= child
->next
) {
680 item
= last
? last
->nextSibling() : (ConfigItem
*)topLevelItem(0);
681 type
= child
->prompt
? child
->prompt
->type
: P_UNKNOWN
;
685 if (!(child
->flags
& MENU_ROOT
))
689 if (child
->flags
& MENU_ROOT
)
696 visible
= menu_is_visible(child
);
697 if (!menuSkip(child
)) {
698 if (!child
->sym
&& !child
->list
&& !child
->prompt
)
700 if (!item
|| item
->menu
!= child
)
701 item
= new ConfigItem(this, last
, child
, visible
);
703 item
->testUpdateMenu(visible
);
705 if (mode
== fullMode
|| mode
== menuMode
|| type
!= P_MENU
)
706 updateMenuList(item
, child
);
708 updateMenuList(item
, 0);
713 if (item
&& item
->menu
== child
) {
714 last
= (ConfigItem
*)topLevelItem(0);
717 else while (last
->nextSibling() != item
)
718 last
= last
->nextSibling();
724 void ConfigList::keyPressEvent(QKeyEvent
* ev
)
726 QTreeWidgetItem
* i
= currentItem();
731 if (ev
->key() == Qt::Key_Escape
&& mode
!= fullMode
&& mode
!= listMode
) {
732 emit
parentSelected();
738 Parent::keyPressEvent(ev
);
741 item
= (ConfigItem
*)i
;
746 if (item
->goParent
) {
747 emit
parentSelected();
753 type
= menu
->prompt
? menu
->prompt
->type
: P_UNKNOWN
;
754 if (type
== P_MENU
&& rootEntry
!= menu
&&
755 mode
!= fullMode
&& mode
!= menuMode
) {
756 if (mode
== menuMode
)
757 emit
menuSelected(menu
);
759 emit
itemSelected(menu
);
775 Parent::keyPressEvent(ev
);
781 void ConfigList::mousePressEvent(QMouseEvent
* e
)
783 //QPoint p(contentsToViewport(e->pos()));
784 //printf("contentsMousePressEvent: %d,%d\n", p.x(), p.y());
785 Parent::mousePressEvent(e
);
788 void ConfigList::mouseReleaseEvent(QMouseEvent
* e
)
791 ConfigItem
* item
= (ConfigItem
*)itemAt(p
);
793 enum prop_type ptype
;
801 x
= header()->offset() + p
.x();
802 idx
= header()->logicalIndexAt(x
);
805 icon
= item
->icon(promptColIdx
);
806 if (!icon
.isNull()) {
807 int off
= header()->sectionPosition(0) + visualRect(indexAt(p
)).x() + 4; // 4 is Hardcoded image offset. There might be a way to do it properly.
808 if (x
>= off
&& x
< off
+ icon
.availableSizes().first().width()) {
809 if (item
->goParent
) {
810 emit
parentSelected();
814 ptype
= menu
->prompt
? menu
->prompt
->type
: P_UNKNOWN
;
815 if (ptype
== P_MENU
&& rootEntry
!= menu
&&
816 mode
!= fullMode
&& mode
!= menuMode
&&
818 emit
menuSelected(menu
);
830 //printf("contentsMouseReleaseEvent: %d,%d\n", p.x(), p.y());
831 Parent::mouseReleaseEvent(e
);
834 void ConfigList::mouseMoveEvent(QMouseEvent
* e
)
836 //QPoint p(contentsToViewport(e->pos()));
837 //printf("contentsMouseMoveEvent: %d,%d\n", p.x(), p.y());
838 Parent::mouseMoveEvent(e
);
841 void ConfigList::mouseDoubleClickEvent(QMouseEvent
* e
)
844 ConfigItem
* item
= (ConfigItem
*)itemAt(p
);
846 enum prop_type ptype
;
850 if (item
->goParent
) {
851 emit
parentSelected();
857 ptype
= menu
->prompt
? menu
->prompt
->type
: P_UNKNOWN
;
858 if (ptype
== P_MENU
&& mode
!= listMode
) {
859 if (mode
== singleMode
)
860 emit
itemSelected(menu
);
861 else if (mode
== symbolMode
)
862 emit
menuSelected(menu
);
863 } else if (menu
->sym
)
867 //printf("contentsMouseDoubleClickEvent: %d,%d\n", p.x(), p.y());
868 Parent::mouseDoubleClickEvent(e
);
871 void ConfigList::focusInEvent(QFocusEvent
*e
)
873 struct menu
*menu
= NULL
;
875 Parent::focusInEvent(e
);
877 ConfigItem
* item
= (ConfigItem
*)currentItem();
879 setSelected(item
, true);
885 void ConfigList::contextMenuEvent(QContextMenuEvent
*e
)
890 headerPopup
= new QMenu(this);
891 action
= new QAction("Show Name", this);
892 action
->setCheckable(true);
893 connect(action
, &QAction::toggled
,
894 this, &ConfigList::setShowName
);
895 connect(this, &ConfigList::showNameChanged
,
896 action
, &QAction::setChecked
);
897 action
->setChecked(showName
);
898 headerPopup
->addAction(action
);
901 headerPopup
->exec(e
->globalPos());
905 void ConfigList::setShowName(bool on
)
912 emit
showNameChanged(on
);
915 QList
<ConfigList
*> ConfigList::allLists
;
916 QAction
*ConfigList::showNormalAction
;
917 QAction
*ConfigList::showAllAction
;
918 QAction
*ConfigList::showPromptAction
;
920 void ConfigList::setAllOpen(bool open
)
922 QTreeWidgetItemIterator
it(this);
925 (*it
)->setExpanded(open
);
931 ConfigInfoView::ConfigInfoView(QWidget
* parent
, const char *name
)
932 : Parent(parent
), sym(0), _menu(0)
937 if (!objectName().isEmpty()) {
938 configSettings
->beginGroup(objectName());
939 setShowDebug(configSettings
->value("/showDebug", false).toBool());
940 configSettings
->endGroup();
941 connect(configApp
, &QApplication::aboutToQuit
,
942 this, &ConfigInfoView::saveSettings
);
945 contextMenu
= createStandardContextMenu();
946 QAction
*action
= new QAction("Show Debug Info", contextMenu
);
948 action
->setCheckable(true);
949 connect(action
, &QAction::toggled
,
950 this, &ConfigInfoView::setShowDebug
);
951 connect(this, &ConfigInfoView::showDebugChanged
,
952 action
, &QAction::setChecked
);
953 action
->setChecked(showDebug());
954 contextMenu
->addSeparator();
955 contextMenu
->addAction(action
);
958 void ConfigInfoView::saveSettings(void)
960 if (!objectName().isEmpty()) {
961 configSettings
->beginGroup(objectName());
962 configSettings
->setValue("/showDebug", showDebug());
963 configSettings
->endGroup();
967 void ConfigInfoView::setShowDebug(bool b
)
969 if (_showDebug
!= b
) {
975 emit
showDebugChanged(b
);
979 void ConfigInfoView::setInfo(struct menu
*m
)
991 void ConfigInfoView::symbolInfo(void)
995 str
+= "<big>Symbol: <b>";
996 str
+= print_filter(sym
->name
);
997 str
+= "</b></big><br><br>value: ";
998 str
+= print_filter(sym_get_string_value(sym
));
999 str
+= "<br>visibility: ";
1000 str
+= sym
->visible
== yes
? "y" : sym
->visible
== mod
? "m" : "n";
1002 str
+= debug_info(sym
);
1007 void ConfigInfoView::menuInfo(void)
1011 QTextStream
stream(&info
);
1015 if (_menu
->prompt
) {
1016 stream
<< "<big><b>";
1017 stream
<< print_filter(_menu
->prompt
->text
);
1018 stream
<< "</b></big>";
1022 stream
<< "<a href=\"s" << sym
->name
<< "\">";
1023 stream
<< print_filter(sym
->name
);
1028 } else if (sym
->name
) {
1029 stream
<< "<big><b>";
1031 stream
<< "<a href=\"s" << sym
->name
<< "\">";
1032 stream
<< print_filter(sym
->name
);
1035 stream
<< "</b></big>";
1037 stream
<< "<br><br>";
1040 stream
<< debug_info(sym
);
1042 struct gstr help_gstr
= str_new();
1044 menu_get_ext_help(_menu
, &help_gstr
);
1045 stream
<< print_filter(str_get(&help_gstr
));
1046 str_free(&help_gstr
);
1047 } else if (_menu
->prompt
) {
1048 stream
<< "<big><b>";
1049 stream
<< print_filter(_menu
->prompt
->text
);
1050 stream
<< "</b></big><br><br>";
1052 if (_menu
->prompt
->visible
.expr
) {
1053 stream
<< " dep: ";
1054 expr_print(_menu
->prompt
->visible
.expr
,
1055 expr_print_help
, &stream
, E_NONE
);
1056 stream
<< "<br><br>";
1059 stream
<< "defined at " << _menu
->file
->name
<< ":"
1060 << _menu
->lineno
<< "<br><br>";
1067 QString
ConfigInfoView::debug_info(struct symbol
*sym
)
1070 QTextStream
stream(&debug
);
1073 stream
<< print_filter(sym_type_name(sym
->type
));
1074 if (sym_is_choice(sym
))
1075 stream
<< " (choice)";
1077 if (sym
->rev_dep
.expr
) {
1078 stream
<< "reverse dep: ";
1079 expr_print(sym
->rev_dep
.expr
, expr_print_help
, &stream
, E_NONE
);
1082 for (struct property
*prop
= sym
->prop
; prop
; prop
= prop
->next
) {
1083 switch (prop
->type
) {
1086 stream
<< "prompt: <a href=\"m" << sym
->name
<< "\">";
1087 stream
<< print_filter(prop
->text
);
1088 stream
<< "</a><br>";
1096 stream
<< prop_get_type_name(prop
->type
);
1098 expr_print(prop
->expr
, expr_print_help
,
1103 if (sym_is_choice(sym
)) {
1104 stream
<< "choice: ";
1105 expr_print(prop
->expr
, expr_print_help
,
1111 stream
<< "unknown property: ";
1112 stream
<< prop_get_type_name(prop
->type
);
1115 if (prop
->visible
.expr
) {
1116 stream
<< " dep: ";
1117 expr_print(prop
->visible
.expr
, expr_print_help
,
1127 QString
ConfigInfoView::print_filter(const QString
&str
)
1129 QRegExp
re("[<>&\"\\n]");
1131 for (int i
= 0; (i
= res
.indexOf(re
, i
)) >= 0;) {
1132 switch (res
[i
].toLatin1()) {
1134 res
.replace(i
, 1, "<");
1138 res
.replace(i
, 1, ">");
1142 res
.replace(i
, 1, "&");
1146 res
.replace(i
, 1, """);
1150 res
.replace(i
, 1, "<br>");
1158 void ConfigInfoView::expr_print_help(void *data
, struct symbol
*sym
, const char *str
)
1160 QTextStream
*stream
= reinterpret_cast<QTextStream
*>(data
);
1162 if (sym
&& sym
->name
&& !(sym
->flags
& SYMBOL_CONST
)) {
1163 *stream
<< "<a href=\"s" << sym
->name
<< "\">";
1164 *stream
<< print_filter(str
);
1167 *stream
<< print_filter(str
);
1171 void ConfigInfoView::clicked(const QUrl
&url
)
1173 QByteArray str
= url
.toEncoded();
1174 const std::size_t count
= str
.size();
1175 char *data
= new char[count
+ 1];
1176 struct symbol
**result
;
1177 struct menu
*m
= NULL
;
1184 memcpy(data
, str
.constData(), count
);
1187 /* Seek for exact match */
1190 result
= sym_re_search(data
);
1198 /* Seek for the menu which holds the symbol */
1199 for (struct property
*prop
= sym
->prop
; prop
; prop
= prop
->next
) {
1200 if (prop
->type
!= P_PROMPT
&& prop
->type
!= P_MENU
)
1207 /* Symbol is not visible as a menu */
1209 emit
showDebugChanged(true);
1211 emit
menuSelected(m
);
1218 void ConfigInfoView::contextMenuEvent(QContextMenuEvent
*event
)
1220 contextMenu
->popup(event
->globalPos());
1224 ConfigSearchWindow::ConfigSearchWindow(ConfigMainWindow
*parent
)
1225 : Parent(parent
), result(NULL
)
1227 setObjectName("search");
1228 setWindowTitle("Search Config");
1230 QVBoxLayout
* layout1
= new QVBoxLayout(this);
1231 layout1
->setContentsMargins(11, 11, 11, 11);
1232 layout1
->setSpacing(6);
1234 QHBoxLayout
* layout2
= new QHBoxLayout();
1235 layout2
->setContentsMargins(0, 0, 0, 0);
1236 layout2
->setSpacing(6);
1237 layout2
->addWidget(new QLabel("Find:", this));
1238 editField
= new QLineEdit(this);
1239 connect(editField
, &QLineEdit::returnPressed
,
1240 this, &ConfigSearchWindow::search
);
1241 layout2
->addWidget(editField
);
1242 searchButton
= new QPushButton("Search", this);
1243 searchButton
->setAutoDefault(false);
1244 connect(searchButton
, &QPushButton::clicked
,
1245 this, &ConfigSearchWindow::search
);
1246 layout2
->addWidget(searchButton
);
1247 layout1
->addLayout(layout2
);
1249 split
= new QSplitter(this);
1250 split
->setOrientation(Qt::Vertical
);
1251 list
= new ConfigList(split
, "search");
1252 list
->mode
= listMode
;
1253 info
= new ConfigInfoView(split
, "search");
1254 connect(list
, &ConfigList::menuChanged
,
1255 info
, &ConfigInfoView::setInfo
);
1256 connect(list
, &ConfigList::menuChanged
,
1257 parent
, &ConfigMainWindow::setMenuLink
);
1259 layout1
->addWidget(split
);
1265 configSettings
->beginGroup("search");
1266 width
= configSettings
->value("/window width", parent
->width() / 2).toInt();
1267 height
= configSettings
->value("/window height", parent
->height() / 2).toInt();
1268 resize(width
, height
);
1269 x
= configSettings
->value("/window x");
1270 y
= configSettings
->value("/window y");
1271 if (x
.isValid() && y
.isValid())
1272 move(x
.toInt(), y
.toInt());
1273 QList
<int> sizes
= configSettings
->readSizes("/split", &ok
);
1275 split
->setSizes(sizes
);
1276 configSettings
->endGroup();
1277 connect(configApp
, &QApplication::aboutToQuit
,
1278 this, &ConfigSearchWindow::saveSettings
);
1281 void ConfigSearchWindow::saveSettings(void)
1283 if (!objectName().isEmpty()) {
1284 configSettings
->beginGroup(objectName());
1285 configSettings
->setValue("/window x", pos().x());
1286 configSettings
->setValue("/window y", pos().y());
1287 configSettings
->setValue("/window width", size().width());
1288 configSettings
->setValue("/window height", size().height());
1289 configSettings
->writeSizes("/split", split
->sizes());
1290 configSettings
->endGroup();
1294 void ConfigSearchWindow::search(void)
1297 struct property
*prop
;
1298 ConfigItem
*lastItem
= NULL
;
1304 result
= sym_re_search(editField
->text().toLatin1());
1307 for (p
= result
; *p
; p
++) {
1308 for_all_prompts((*p
), prop
)
1309 lastItem
= new ConfigItem(list
, lastItem
, prop
->menu
,
1310 menu_is_visible(prop
->menu
));
1315 * Construct the complete config widget
1317 ConfigMainWindow::ConfigMainWindow(void)
1325 QDesktopWidget
*d
= configApp
->desktop();
1326 snprintf(title
, sizeof(title
), "%s%s",
1327 rootmenu
.prompt
->text
,
1330 setWindowTitle(title
);
1332 width
= configSettings
->value("/window width", d
->width() - 64).toInt();
1333 height
= configSettings
->value("/window height", d
->height() - 64).toInt();
1334 resize(width
, height
);
1335 x
= configSettings
->value("/window x");
1336 y
= configSettings
->value("/window y");
1337 if ((x
.isValid())&&(y
.isValid()))
1338 move(x
.toInt(), y
.toInt());
1341 ConfigItem::symbolYesIcon
= QIcon(QPixmap(xpm_symbol_yes
));
1342 ConfigItem::symbolModIcon
= QIcon(QPixmap(xpm_symbol_mod
));
1343 ConfigItem::symbolNoIcon
= QIcon(QPixmap(xpm_symbol_no
));
1344 ConfigItem::choiceYesIcon
= QIcon(QPixmap(xpm_choice_yes
));
1345 ConfigItem::choiceNoIcon
= QIcon(QPixmap(xpm_choice_no
));
1346 ConfigItem::menuIcon
= QIcon(QPixmap(xpm_menu
));
1347 ConfigItem::menubackIcon
= QIcon(QPixmap(xpm_menuback
));
1349 QWidget
*widget
= new QWidget(this);
1350 QVBoxLayout
*layout
= new QVBoxLayout(widget
);
1351 setCentralWidget(widget
);
1353 split1
= new QSplitter(widget
);
1354 split1
->setOrientation(Qt::Horizontal
);
1355 split1
->setChildrenCollapsible(false);
1357 menuList
= new ConfigList(widget
, "menu");
1359 split2
= new QSplitter(widget
);
1360 split2
->setChildrenCollapsible(false);
1361 split2
->setOrientation(Qt::Vertical
);
1363 // create config tree
1364 configList
= new ConfigList(widget
, "config");
1366 helpText
= new ConfigInfoView(widget
, "help");
1368 layout
->addWidget(split2
);
1369 split2
->addWidget(split1
);
1370 split1
->addWidget(configList
);
1371 split1
->addWidget(menuList
);
1372 split2
->addWidget(helpText
);
1374 setTabOrder(configList
, helpText
);
1375 configList
->setFocus();
1377 backAction
= new QAction(QPixmap(xpm_back
), "Back", this);
1378 connect(backAction
, &QAction::triggered
,
1379 this, &ConfigMainWindow::goBack
);
1381 QAction
*quitAction
= new QAction("&Quit", this);
1382 quitAction
->setShortcut(Qt::CTRL
+ Qt::Key_Q
);
1383 connect(quitAction
, &QAction::triggered
,
1384 this, &ConfigMainWindow::close
);
1386 QAction
*loadAction
= new QAction(QPixmap(xpm_load
), "&Load", this);
1387 loadAction
->setShortcut(Qt::CTRL
+ Qt::Key_L
);
1388 connect(loadAction
, &QAction::triggered
,
1389 this, &ConfigMainWindow::loadConfig
);
1391 saveAction
= new QAction(QPixmap(xpm_save
), "&Save", this);
1392 saveAction
->setShortcut(Qt::CTRL
+ Qt::Key_S
);
1393 connect(saveAction
, &QAction::triggered
,
1394 this, &ConfigMainWindow::saveConfig
);
1396 conf_set_changed_callback(conf_changed
);
1398 // Set saveAction's initial state
1400 configname
= xstrdup(conf_get_configname());
1402 QAction
*saveAsAction
= new QAction("Save &As...", this);
1403 connect(saveAsAction
, &QAction::triggered
,
1404 this, &ConfigMainWindow::saveConfigAs
);
1405 QAction
*searchAction
= new QAction("&Find", this);
1406 searchAction
->setShortcut(Qt::CTRL
+ Qt::Key_F
);
1407 connect(searchAction
, &QAction::triggered
,
1408 this, &ConfigMainWindow::searchConfig
);
1409 singleViewAction
= new QAction(QPixmap(xpm_single_view
), "Single View", this);
1410 singleViewAction
->setCheckable(true);
1411 connect(singleViewAction
, &QAction::triggered
,
1412 this, &ConfigMainWindow::showSingleView
);
1413 splitViewAction
= new QAction(QPixmap(xpm_split_view
), "Split View", this);
1414 splitViewAction
->setCheckable(true);
1415 connect(splitViewAction
, &QAction::triggered
,
1416 this, &ConfigMainWindow::showSplitView
);
1417 fullViewAction
= new QAction(QPixmap(xpm_tree_view
), "Full View", this);
1418 fullViewAction
->setCheckable(true);
1419 connect(fullViewAction
, &QAction::triggered
,
1420 this, &ConfigMainWindow::showFullView
);
1422 QAction
*showNameAction
= new QAction("Show Name", this);
1423 showNameAction
->setCheckable(true);
1424 connect(showNameAction
, &QAction::toggled
,
1425 configList
, &ConfigList::setShowName
);
1426 showNameAction
->setChecked(configList
->showName
);
1428 QActionGroup
*optGroup
= new QActionGroup(this);
1429 optGroup
->setExclusive(true);
1430 connect(optGroup
, &QActionGroup::triggered
,
1431 configList
, &ConfigList::setOptionMode
);
1432 connect(optGroup
, &QActionGroup::triggered
,
1433 menuList
, &ConfigList::setOptionMode
);
1435 ConfigList::showNormalAction
= new QAction("Show Normal Options", optGroup
);
1436 ConfigList::showNormalAction
->setCheckable(true);
1437 ConfigList::showAllAction
= new QAction("Show All Options", optGroup
);
1438 ConfigList::showAllAction
->setCheckable(true);
1439 ConfigList::showPromptAction
= new QAction("Show Prompt Options", optGroup
);
1440 ConfigList::showPromptAction
->setCheckable(true);
1442 QAction
*showDebugAction
= new QAction("Show Debug Info", this);
1443 showDebugAction
->setCheckable(true);
1444 connect(showDebugAction
, &QAction::toggled
,
1445 helpText
, &ConfigInfoView::setShowDebug
);
1446 showDebugAction
->setChecked(helpText
->showDebug());
1448 QAction
*showIntroAction
= new QAction("Introduction", this);
1449 connect(showIntroAction
, &QAction::triggered
,
1450 this, &ConfigMainWindow::showIntro
);
1451 QAction
*showAboutAction
= new QAction("About", this);
1452 connect(showAboutAction
, &QAction::triggered
,
1453 this, &ConfigMainWindow::showAbout
);
1456 QToolBar
*toolBar
= addToolBar("Tools");
1457 toolBar
->addAction(backAction
);
1458 toolBar
->addSeparator();
1459 toolBar
->addAction(loadAction
);
1460 toolBar
->addAction(saveAction
);
1461 toolBar
->addSeparator();
1462 toolBar
->addAction(singleViewAction
);
1463 toolBar
->addAction(splitViewAction
);
1464 toolBar
->addAction(fullViewAction
);
1467 QMenu
*menu
= menuBar()->addMenu("&File");
1468 menu
->addAction(loadAction
);
1469 menu
->addAction(saveAction
);
1470 menu
->addAction(saveAsAction
);
1471 menu
->addSeparator();
1472 menu
->addAction(quitAction
);
1475 menu
= menuBar()->addMenu("&Edit");
1476 menu
->addAction(searchAction
);
1478 // create options menu
1479 menu
= menuBar()->addMenu("&Option");
1480 menu
->addAction(showNameAction
);
1481 menu
->addSeparator();
1482 menu
->addActions(optGroup
->actions());
1483 menu
->addSeparator();
1484 menu
->addAction(showDebugAction
);
1487 menu
= menuBar()->addMenu("&Help");
1488 menu
->addAction(showIntroAction
);
1489 menu
->addAction(showAboutAction
);
1491 connect(helpText
, &ConfigInfoView::anchorClicked
,
1492 helpText
, &ConfigInfoView::clicked
);
1494 connect(configList
, &ConfigList::menuChanged
,
1495 helpText
, &ConfigInfoView::setInfo
);
1496 connect(configList
, &ConfigList::menuSelected
,
1497 this, &ConfigMainWindow::changeMenu
);
1498 connect(configList
, &ConfigList::itemSelected
,
1499 this, &ConfigMainWindow::changeItens
);
1500 connect(configList
, &ConfigList::parentSelected
,
1501 this, &ConfigMainWindow::goBack
);
1502 connect(menuList
, &ConfigList::menuChanged
,
1503 helpText
, &ConfigInfoView::setInfo
);
1504 connect(menuList
, &ConfigList::menuSelected
,
1505 this, &ConfigMainWindow::changeMenu
);
1507 connect(configList
, &ConfigList::gotFocus
,
1508 helpText
, &ConfigInfoView::setInfo
);
1509 connect(menuList
, &ConfigList::gotFocus
,
1510 helpText
, &ConfigInfoView::setInfo
);
1511 connect(menuList
, &ConfigList::gotFocus
,
1512 this, &ConfigMainWindow::listFocusChanged
);
1513 connect(helpText
, &ConfigInfoView::menuSelected
,
1514 this, &ConfigMainWindow::setMenuLink
);
1516 QString listMode
= configSettings
->value("/listMode", "symbol").toString();
1517 if (listMode
== "single")
1519 else if (listMode
== "full")
1521 else /*if (listMode == "split")*/
1524 // UI setup done, restore splitter positions
1525 QList
<int> sizes
= configSettings
->readSizes("/split1", &ok
);
1527 split1
->setSizes(sizes
);
1529 sizes
= configSettings
->readSizes("/split2", &ok
);
1531 split2
->setSizes(sizes
);
1534 void ConfigMainWindow::loadConfig(void)
1540 str
= QFileDialog::getOpenFileName(this, "", configname
);
1544 ba
= str
.toLocal8Bit();
1547 if (conf_read(name
))
1548 QMessageBox::information(this, "qconf", "Unable to load configuration!");
1551 configname
= xstrdup(name
);
1553 ConfigList::updateListAllForAll();
1556 bool ConfigMainWindow::saveConfig(void)
1558 if (conf_write(configname
)) {
1559 QMessageBox::information(this, "qconf", "Unable to save configuration!");
1562 conf_write_autoconf(0);
1567 void ConfigMainWindow::saveConfigAs(void)
1573 str
= QFileDialog::getSaveFileName(this, "", configname
);
1577 ba
= str
.toLocal8Bit();
1580 if (conf_write(name
)) {
1581 QMessageBox::information(this, "qconf", "Unable to save configuration!");
1583 conf_write_autoconf(0);
1586 configname
= xstrdup(name
);
1589 void ConfigMainWindow::searchConfig(void)
1592 searchWindow
= new ConfigSearchWindow(this);
1593 searchWindow
->show();
1596 void ConfigMainWindow::changeItens(struct menu
*menu
)
1598 configList
->setRootMenu(menu
);
1601 void ConfigMainWindow::changeMenu(struct menu
*menu
)
1603 menuList
->setRootMenu(menu
);
1606 void ConfigMainWindow::setMenuLink(struct menu
*menu
)
1608 struct menu
*parent
;
1609 ConfigList
* list
= NULL
;
1612 if (configList
->menuSkip(menu
))
1615 switch (configList
->mode
) {
1618 parent
= menu_get_parent_menu(menu
);
1621 list
->setRootMenu(parent
);
1624 if (menu
->flags
& MENU_ROOT
) {
1625 menuList
->setRootMenu(menu
);
1626 configList
->clearSelection();
1629 parent
= menu_get_parent_menu(menu
->parent
);
1633 /* Select the config view */
1634 item
= configList
->findConfigItem(parent
);
1636 configList
->setSelected(item
, true);
1637 configList
->scrollToItem(item
);
1640 menuList
->setRootMenu(parent
);
1641 menuList
->clearSelection();
1653 item
= list
->findConfigItem(menu
);
1655 list
->setSelected(item
, true);
1656 list
->scrollToItem(item
);
1658 helpText
->setInfo(menu
);
1663 void ConfigMainWindow::listFocusChanged(void)
1665 if (menuList
->mode
== menuMode
)
1666 configList
->clearSelection();
1669 void ConfigMainWindow::goBack(void)
1671 if (configList
->rootEntry
== &rootmenu
)
1674 configList
->setParentMenu();
1677 void ConfigMainWindow::showSingleView(void)
1679 singleViewAction
->setEnabled(false);
1680 singleViewAction
->setChecked(true);
1681 splitViewAction
->setEnabled(true);
1682 splitViewAction
->setChecked(false);
1683 fullViewAction
->setEnabled(true);
1684 fullViewAction
->setChecked(false);
1686 backAction
->setEnabled(true);
1689 menuList
->setRootMenu(0);
1690 configList
->mode
= singleMode
;
1691 if (configList
->rootEntry
== &rootmenu
)
1692 configList
->updateListAll();
1694 configList
->setRootMenu(&rootmenu
);
1695 configList
->setFocus();
1698 void ConfigMainWindow::showSplitView(void)
1700 singleViewAction
->setEnabled(true);
1701 singleViewAction
->setChecked(false);
1702 splitViewAction
->setEnabled(false);
1703 splitViewAction
->setChecked(true);
1704 fullViewAction
->setEnabled(true);
1705 fullViewAction
->setChecked(false);
1707 backAction
->setEnabled(false);
1709 configList
->mode
= menuMode
;
1710 if (configList
->rootEntry
== &rootmenu
)
1711 configList
->updateListAll();
1713 configList
->setRootMenu(&rootmenu
);
1714 configList
->setAllOpen(true);
1715 configApp
->processEvents();
1716 menuList
->mode
= symbolMode
;
1717 menuList
->setRootMenu(&rootmenu
);
1718 menuList
->setAllOpen(true);
1720 menuList
->setFocus();
1723 void ConfigMainWindow::showFullView(void)
1725 singleViewAction
->setEnabled(true);
1726 singleViewAction
->setChecked(false);
1727 splitViewAction
->setEnabled(true);
1728 splitViewAction
->setChecked(false);
1729 fullViewAction
->setEnabled(false);
1730 fullViewAction
->setChecked(true);
1732 backAction
->setEnabled(false);
1735 menuList
->setRootMenu(0);
1736 configList
->mode
= fullMode
;
1737 if (configList
->rootEntry
== &rootmenu
)
1738 configList
->updateListAll();
1740 configList
->setRootMenu(&rootmenu
);
1741 configList
->setFocus();
1745 * ask for saving configuration before quitting
1747 void ConfigMainWindow::closeEvent(QCloseEvent
* e
)
1749 if (!conf_get_changed()) {
1753 QMessageBox
mb("qconf", "Save configuration?", QMessageBox::Warning
,
1754 QMessageBox::Yes
| QMessageBox::Default
, QMessageBox::No
, QMessageBox::Cancel
| QMessageBox::Escape
);
1755 mb
.setButtonText(QMessageBox::Yes
, "&Save Changes");
1756 mb
.setButtonText(QMessageBox::No
, "&Discard Changes");
1757 mb
.setButtonText(QMessageBox::Cancel
, "Cancel Exit");
1758 switch (mb
.exec()) {
1759 case QMessageBox::Yes
:
1765 case QMessageBox::No
:
1768 case QMessageBox::Cancel
:
1774 void ConfigMainWindow::showIntro(void)
1776 static const QString str
=
1777 "Welcome to the qconf graphical configuration tool.\n"
1779 "For bool and tristate options, a blank box indicates the "
1780 "feature is disabled, a check indicates it is enabled, and a "
1781 "dot indicates that it is to be compiled as a module. Clicking "
1782 "on the box will cycle through the three states. For int, hex, "
1783 "and string options, double-clicking or pressing F2 on the "
1784 "Value cell will allow you to edit the value.\n"
1786 "If you do not see an option (e.g., a device driver) that you "
1787 "believe should be present, try turning on Show All Options "
1788 "under the Options menu. Enabling Show Debug Info will help you"
1789 "figure out what other options must be enabled to support the "
1790 "option you are interested in, and hyperlinks will navigate to "
1793 "Toggling Show Debug Info under the Options menu will show the "
1794 "dependencies, which you can then match by examining other "
1797 QMessageBox::information(this, "qconf", str
);
1800 void ConfigMainWindow::showAbout(void)
1802 static const QString str
= "qconf is Copyright (C) 2002 Roman Zippel <zippel@linux-m68k.org>.\n"
1803 "Copyright (C) 2015 Boris Barbulovski <bbarbulovski@gmail.com>.\n"
1805 "Bug reports and feature request can also be entered at http://bugzilla.kernel.org/\n"
1809 QMessageBox::information(this, "qconf", str
+ qVersion());
1812 void ConfigMainWindow::saveSettings(void)
1814 configSettings
->setValue("/window x", pos().x());
1815 configSettings
->setValue("/window y", pos().y());
1816 configSettings
->setValue("/window width", size().width());
1817 configSettings
->setValue("/window height", size().height());
1820 switch(configList
->mode
) {
1836 configSettings
->setValue("/listMode", entry
);
1838 configSettings
->writeSizes("/split1", split1
->sizes());
1839 configSettings
->writeSizes("/split2", split2
->sizes());
1842 void ConfigMainWindow::conf_changed(void)
1845 saveAction
->setEnabled(conf_get_changed());
1848 void fixup_rootmenu(struct menu
*menu
)
1851 static int menu_cnt
= 0;
1853 menu
->flags
|= MENU_ROOT
;
1854 for (child
= menu
->list
; child
; child
= child
->next
) {
1855 if (child
->prompt
&& child
->prompt
->type
== P_MENU
) {
1857 fixup_rootmenu(child
);
1859 } else if (!menu_cnt
)
1860 fixup_rootmenu(child
);
1864 static const char *progname
;
1866 static void usage(void)
1868 printf("%s [-s] <config>\n", progname
);
1872 int main(int ac
, char** av
)
1874 ConfigMainWindow
* v
;
1878 if (ac
> 1 && av
[1][0] == '-') {
1881 conf_set_message_callback(NULL
);
1894 fixup_rootmenu(&rootmenu
);
1896 //zconfdump(stdout);
1898 configApp
= new QApplication(ac
, av
);
1900 configSettings
= new ConfigSettings();
1901 configSettings
->beginGroup("/kconfig/qconf");
1902 v
= new ConfigMainWindow();
1904 //zconfdump(stdout);
1905 configApp
->connect(configApp
, SIGNAL(lastWindowClosed()), SLOT(quit()));
1906 configApp
->connect(configApp
, SIGNAL(aboutToQuit()), v
, SLOT(saveSettings()));
1910 configSettings
->endGroup();
1911 delete configSettings
;