Something went wrong. Try again.
Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
Something went wrong. Try again.
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470147114721473147414751476147714781479148014811482148314841485148614871488148914901491149214931494149514961497149814991500150115021503150415051506150715081509151015111512151315141515151615171518151915201521152215231524152515261527152815291530153115321533153415351536153715381539154015411542154315441545154615471548154915501551155215531554155515561557155815591560156115621563156415651566156715681569157015711572157315741575157615771578157915801581158215831584158515861587158815891590159115921593159415951596159715981599160016011602160316041605160616071608160916101611161216131614161516161617161816191620162116221623162416251626162716281629163016311632163316341635163616371638163916401641164216431644164516461647164816491650165116521653165416551656165716581659166016611662166316641665166616671668166916701671167216731674167516761677167816791680168116821683168416851686168716881689169016911692169316941695169616971698169917001701170217031704170517061707170817091710171117121713171417151716171717181719172017211722172317241725172617271728172917301731173217331734173517361737173817391740174117421743174417451746174717481749175017511752175317541755175617571758175917601761176217631764176517661767176817691770177117721773177417751776177717781779178017811782178317841785178617871788178917901791179217931794179517961797179817991800180118021803180418051806180718081809181018111812181318141815181618171818181918201821182218231824182518261827182818291830183118321833183418351836183718381839184018411842184318441845184618471848184918501851185218531854185518561857185818591860186118621863// SPDX-License-Identifier: GPL-2.0/* * Copyright (C) 2002 Roman Zippel <zippel@linux-m68k.org> * Copyright (C) 2015 Boris Barbulovski <bbarbulovski@gmail.com> */
#include <QAction>#include <QActionGroup>#include <QApplication>#include <QCloseEvent>#include <QDebug>#include <QFileDialog>#include <QLabel>#include <QLayout>#include <QList>#include <QMenu>#include <QMenuBar>#include <QMessageBox>#include <QRegularExpression>#include <QScreen>#include <QToolBar>
#include <stdlib.h>
#include <xalloc.h>#include "lkc.h"#include "qconf.h"
static QApplication *configApp;static ConfigSettings *configSettings;
QAction *ConfigMainWindow::saveAction;
ConfigSettings::ConfigSettings() : QSettings("kernel.org", "qconf"){ beginGroup("/kconfig/qconf");}
ConfigSettings::~ConfigSettings(){ endGroup();}
/** * Reads a list of integer values from the application settings. */QList<int> ConfigSettings::readSizes(const QString& key, bool *ok){ QList<int> result;
if (contains(key)) { QStringList entryList = value(key).toStringList(); QStringList::Iterator it;
for (it = entryList.begin(); it != entryList.end(); ++it) result.push_back((*it).toInt());
*ok = true; } else *ok = false;
return result;}
/** * Writes a list of integer values to the application settings. */bool ConfigSettings::writeSizes(const QString& key, const QList<int>& value){ QStringList stringList; QList<int>::ConstIterator it;
for (it = value.begin(); it != value.end(); ++it) stringList.push_back(QString::number(*it)); setValue(key, stringList);
return true;}
QIcon ConfigItem::symbolYesIcon;QIcon ConfigItem::symbolModIcon;QIcon ConfigItem::symbolNoIcon;QIcon ConfigItem::choiceYesIcon;QIcon ConfigItem::choiceNoIcon;QIcon ConfigItem::menuIcon;QIcon ConfigItem::menubackIcon;
/* * update the displayed of a menu entry */void ConfigItem::updateMenu(void){ ConfigList* list; struct symbol* sym; QString prompt; int type; tristate expr;
list = listView(); if (goParent) { setIcon(promptColIdx, menubackIcon); prompt = ".."; goto set_prompt; }
sym = menu->sym; prompt = menu_get_prompt(menu);
switch (menu->type) { case M_MENU: if (list->mode == singleMode) { /* a menuconfig entry is displayed differently * depending whether it's at the view root or a child. */ if (sym && list->rootEntry == menu) break; setIcon(promptColIdx, menuIcon); } else { if (sym) break; setIcon(promptColIdx, QIcon()); } goto set_prompt; case M_COMMENT: setIcon(promptColIdx, QIcon()); prompt = "*** " + prompt + " ***"; goto set_prompt; case M_CHOICE: setIcon(promptColIdx, QIcon()); sym = sym_calc_choice(menu); if (sym) setText(dataColIdx, sym->name); goto set_prompt; default: ; } if (!sym) goto set_prompt;
setText(nameColIdx, sym->name);
type = sym_get_type(sym); switch (type) { case S_BOOLEAN: case S_TRISTATE: char ch;
if (!sym_is_changeable(sym) && list->optMode == normalOpt) { setIcon(promptColIdx, QIcon()); break; } expr = sym_get_tristate_value(sym); switch (expr) { case yes: if (sym_is_choice_value(sym)) setIcon(promptColIdx, choiceYesIcon); else setIcon(promptColIdx, symbolYesIcon); ch = 'Y'; break; case mod: setIcon(promptColIdx, symbolModIcon); ch = 'M'; break; default: if (sym_is_choice_value(sym)) setIcon(promptColIdx, choiceNoIcon); else setIcon(promptColIdx, symbolNoIcon); ch = 'N'; break; }
setText(dataColIdx, QChar(ch)); break; case S_INT: case S_HEX: case S_STRING: setText(dataColIdx, sym_get_string_value(sym)); break; } if (!sym_has_value(sym)) prompt += " (NEW)";set_prompt: setText(promptColIdx, prompt);}
void ConfigItem::testUpdateMenu(void){ ConfigItem* i;
if (!menu) return;
if (menu->type == M_CHOICE) sym_calc_choice(menu); else sym_calc_value(menu->sym);
if (menu->flags & MENU_CHANGED) { /* the menu entry changed, so update all list items */ menu->flags &= ~MENU_CHANGED; for (i = (ConfigItem*)menu->data; i; i = i->nextItem) i->updateMenu(); } else if (listView()->updateAll) updateMenu();}
/* * construct a menu entry */void ConfigItem::init(void){ if (menu) { ConfigList* list = listView(); nextItem = (ConfigItem*)menu->data; menu->data = this;
if (list->mode != fullMode) setExpanded(true); sym_calc_value(menu->sym);
if (menu->sym) { enum symbol_type type = menu->sym->type;
// Allow to edit "int", "hex", and "string" in-place in // the data column. Unfortunately, you cannot specify // the flags per column. Set ItemIsEditable for all // columns here, and check the column in createEditor(). if (type == S_INT || type == S_HEX || type == S_STRING) setFlags(flags() | Qt::ItemIsEditable); } } updateMenu();}
/* * destruct a menu entry */ConfigItem::~ConfigItem(void){ if (menu) { ConfigItem** ip = (ConfigItem**)&menu->data; for (; *ip; ip = &(*ip)->nextItem) { if (*ip == this) { *ip = nextItem; break; } } }}
QWidget *ConfigItemDelegate::createEditor(QWidget *parent, const QStyleOptionViewItem &option, const QModelIndex &index) const{ ConfigItem *item;
// Only the data column is editable if (index.column() != dataColIdx) return nullptr;
// You cannot edit invisible menus item = static_cast<ConfigItem *>(index.internalPointer()); if (!item || !item->menu || !menu_is_visible(item->menu)) return nullptr;
return QStyledItemDelegate::createEditor(parent, option, index);}
void ConfigItemDelegate::setModelData(QWidget *editor, QAbstractItemModel *model, const QModelIndex &index) const{ QLineEdit *lineEdit; ConfigItem *item; struct symbol *sym; bool success;
lineEdit = qobject_cast<QLineEdit *>(editor); // If this is not a QLineEdit, use the parent's default. // (does this happen?) if (!lineEdit) goto parent;
item = static_cast<ConfigItem *>(index.internalPointer()); if (!item || !item->menu) goto parent;
sym = item->menu->sym; if (!sym) goto parent;
success = sym_set_string_value(sym, lineEdit->text().toUtf8().data()); if (success) { ConfigList::updateListForAll(); } else { QMessageBox::information(editor, "qconf", "Cannot set the data (maybe due to out of range).\n" "Setting the old value."); lineEdit->setText(sym_get_string_value(sym)); }
parent: QStyledItemDelegate::setModelData(editor, model, index);}
ConfigList::ConfigList(QWidget *parent, const char *name) : QTreeWidget(parent), updateAll(false), showName(false), mode(singleMode), optMode(normalOpt), rootEntry(0), headerPopup(0){ setObjectName(name); setSortingEnabled(false);
setVerticalScrollMode(ScrollPerPixel); setHorizontalScrollMode(ScrollPerPixel);
setHeaderLabels(QStringList() << "Option" << "Name" << "Value");
connect(this, &ConfigList::itemSelectionChanged, this, &ConfigList::updateSelection);
if (name) { configSettings->beginGroup(name); showName = configSettings->value("/showName", false).toBool(); optMode = (enum optionMode)configSettings->value("/optionMode", 0).toInt(); configSettings->endGroup(); connect(configApp, &QApplication::aboutToQuit, this, &ConfigList::saveSettings); }
showColumn(promptColIdx);
setItemDelegate(new ConfigItemDelegate(this));
allLists.append(this);
reinit();}
ConfigList::~ConfigList(){ allLists.removeOne(this);}
bool ConfigList::menuSkip(struct menu *menu){ if (optMode == normalOpt && menu_is_visible(menu)) return false; if (optMode == promptOpt && menu_has_prompt(menu)) return false; if (optMode == allOpt) return false; return true;}
void ConfigList::reinit(void){ hideColumn(nameColIdx);
if (showName) showColumn(nameColIdx);
updateListAll();}
void ConfigList::setOptionMode(QAction *action){ if (action == showNormalAction) optMode = normalOpt; else if (action == showAllAction) optMode = allOpt; else optMode = promptOpt;
updateListAll();}
void ConfigList::saveSettings(void){ if (!objectName().isEmpty()) { configSettings->beginGroup(objectName()); configSettings->setValue("/showName", showName); configSettings->setValue("/optionMode", (int)optMode); configSettings->endGroup(); }}
ConfigItem* ConfigList::findConfigItem(struct menu *menu){ ConfigItem* item = (ConfigItem*)menu->data;
for (; item; item = item->nextItem) { if (this == item->listView()) break; }
return item;}
void ConfigList::updateSelection(void){ struct menu *menu; enum prop_type type;
if (selectedItems().count() == 0) return;
ConfigItem* item = (ConfigItem*)selectedItems().first(); if (!item) return;
menu = item->menu; emit menuChanged(menu); if (!menu) return; type = menu->prompt ? menu->prompt->type : P_UNKNOWN; if (mode == menuMode && type == P_MENU) emit menuSelected(menu);}
void ConfigList::updateList(){ ConfigItem* last = 0; ConfigItem *item;
if (!rootEntry) { if (mode != listMode) goto update; QTreeWidgetItemIterator it(this);
while (*it) { item = (ConfigItem*)(*it); if (!item->menu) continue; item->testUpdateMenu();
++it; } return; }
if (rootEntry != &rootmenu && mode == singleMode) { item = (ConfigItem *)topLevelItem(0); if (!item) item = new ConfigItem(this, 0); last = item; } if ((mode == singleMode || (mode == symbolMode && !(rootEntry->flags & MENU_ROOT))) && rootEntry->sym && rootEntry->prompt) { item = last ? last->nextSibling() : nullptr; if (!item) item = new ConfigItem(this, last, rootEntry); else item->testUpdateMenu();
updateMenuList(item, rootEntry); update(); resizeColumnToContents(0); return; }update: updateMenuList(rootEntry); update(); resizeColumnToContents(0);}
void ConfigList::updateListForAll(){ QListIterator<ConfigList *> it(allLists);
while (it.hasNext()) { ConfigList *list = it.next();
list->updateList(); }}
void ConfigList::updateListAllForAll(){ QListIterator<ConfigList *> it(allLists);
while (it.hasNext()) { ConfigList *list = it.next();
list->updateListAll(); }}
void ConfigList::setValue(ConfigItem* item, tristate val){ struct symbol* sym; int type; tristate oldval;
sym = item->menu ? item->menu->sym : 0; if (!sym) return;
type = sym_get_type(sym); switch (type) { case S_BOOLEAN: case S_TRISTATE: oldval = sym_get_tristate_value(sym);
if (!sym_set_tristate_value(sym, val)) return; if (oldval == no && item->menu->list) item->setExpanded(true); ConfigList::updateListForAll(); break; }}
void ConfigList::changeValue(ConfigItem* item){ struct symbol* sym; struct menu* menu; int type, oldexpr, newexpr;
menu = item->menu; if (!menu) return; sym = menu->sym; if (!sym) { if (item->menu->list) item->setExpanded(!item->isExpanded()); return; }
type = sym_get_type(sym); switch (type) { case S_BOOLEAN: case S_TRISTATE: oldexpr = sym_get_tristate_value(sym); newexpr = sym_toggle_tristate_value(sym); if (item->menu->list) { if (oldexpr == newexpr) item->setExpanded(!item->isExpanded()); else if (oldexpr == no) item->setExpanded(true); } if (oldexpr != newexpr) ConfigList::updateListForAll(); break; default: break; }}
void ConfigList::setRootMenu(struct menu *menu){ enum prop_type type;
if (rootEntry == menu) return; type = menu && menu->prompt ? menu->prompt->type : P_UNKNOWN; if (type != P_MENU) return; updateMenuList(0); rootEntry = menu; updateListAll(); if (currentItem()) { setSelected(currentItem(), hasFocus()); scrollToItem(currentItem()); }}
void ConfigList::setParentMenu(void){ ConfigItem* item; struct menu *oldroot;
oldroot = rootEntry; if (rootEntry == &rootmenu) return; setRootMenu(menu_get_menu_or_parent_menu(rootEntry->parent));
QTreeWidgetItemIterator it(this); while (*it) { item = (ConfigItem *)(*it); if (item->menu == oldroot) { setCurrentItem(item); scrollToItem(item); break; }
++it; }}
/* * update all the children of a menu entry * removes/adds the entries from the parent widget as necessary * * parent: either the menu list widget or a menu entry widget * menu: entry to be updated */void ConfigList::updateMenuList(ConfigItem *parent, struct menu* menu){ struct menu* child; ConfigItem* item; ConfigItem* last; enum prop_type type;
if (!menu) { while (parent->childCount() > 0) { delete parent->takeChild(0); }
return; }
last = parent->firstChild(); if (last && !last->goParent) last = 0; for (child = menu->list; child; child = child->next) { item = last ? last->nextSibling() : parent->firstChild(); type = child->prompt ? child->prompt->type : P_UNKNOWN;
switch (mode) { case menuMode: if (!(child->flags & MENU_ROOT)) goto hide; break; case symbolMode: if (child->flags & MENU_ROOT) goto hide; break; default: break; }
if (!menuSkip(child)) { if (!child->sym && !child->list && !child->prompt) continue; if (!item || item->menu != child) item = new ConfigItem(parent, last, child); else item->testUpdateMenu();
if (mode == fullMode || mode == menuMode || type != P_MENU) updateMenuList(item, child); else updateMenuList(item, 0); last = item; continue; }hide: if (item && item->menu == child) { last = parent->firstChild(); if (last == item) last = 0; else while (last->nextSibling() != item) last = last->nextSibling(); delete item; } }}
void ConfigList::updateMenuList(struct menu *menu){ struct menu* child; ConfigItem* item; ConfigItem* last; enum prop_type type;
if (!menu) { while (topLevelItemCount() > 0) { delete takeTopLevelItem(0); }
return; }
last = (ConfigItem *)topLevelItem(0); if (last && !last->goParent) last = 0; for (child = menu->list; child; child = child->next) { item = last ? last->nextSibling() : (ConfigItem *)topLevelItem(0); type = child->prompt ? child->prompt->type : P_UNKNOWN;
switch (mode) { case menuMode: if (!(child->flags & MENU_ROOT)) goto hide; break; case symbolMode: if (child->flags & MENU_ROOT) goto hide; break; default: break; }
if (!menuSkip(child)) { if (!child->sym && !child->list && !child->prompt) continue; if (!item || item->menu != child) item = new ConfigItem(this, last, child); else item->testUpdateMenu();
if (mode == fullMode || mode == menuMode || type != P_MENU) updateMenuList(item, child); else updateMenuList(item, 0); last = item; continue; }hide: if (item && item->menu == child) { last = (ConfigItem *)topLevelItem(0); if (last == item) last = 0; else while (last->nextSibling() != item) last = last->nextSibling(); delete item; } }}
void ConfigList::keyPressEvent(QKeyEvent* ev){ QTreeWidgetItem* i = currentItem(); ConfigItem* item; struct menu *menu; enum prop_type type;
if (ev->key() == Qt::Key_Escape && mode == singleMode) { emit parentSelected(); ev->accept(); return; }
if (!i) { Parent::keyPressEvent(ev); return; } item = (ConfigItem*)i;
switch (ev->key()) { case Qt::Key_Return: case Qt::Key_Enter: if (item->goParent) { emit parentSelected(); break; } menu = item->menu; if (!menu) break; type = menu->prompt ? menu->prompt->type : P_UNKNOWN; if (type == P_MENU && rootEntry != menu && mode != fullMode && mode != menuMode) { if (mode == menuMode) emit menuSelected(menu); else emit itemSelected(menu); break; } case Qt::Key_Space: changeValue(item); break; case Qt::Key_N: setValue(item, no); break; case Qt::Key_M: setValue(item, mod); break; case Qt::Key_Y: setValue(item, yes); break; default: Parent::keyPressEvent(ev); return; } ev->accept();}
void ConfigList::mouseReleaseEvent(QMouseEvent* e){ QPoint p = e->pos(); ConfigItem* item = (ConfigItem*)itemAt(p); struct menu *menu; enum prop_type ptype; QIcon icon; int idx, x;
if (!item) goto skip;
menu = item->menu; x = header()->offset() + p.x(); idx = header()->logicalIndexAt(x); switch (idx) { case promptColIdx: icon = item->icon(promptColIdx); if (!icon.isNull()) { int off = header()->sectionPosition(0) + visualRect(indexAt(p)).x() + 4; // 4 is Hardcoded image offset. There might be a way to do it properly. if (x >= off && x < off + icon.availableSizes().first().width()) { if (item->goParent) { emit parentSelected(); break; } else if (!menu) break; ptype = menu->prompt ? menu->prompt->type : P_UNKNOWN; if (ptype == P_MENU && rootEntry != menu && mode != fullMode && mode != menuMode && mode != listMode) emit menuSelected(menu); else changeValue(item); } } break; case dataColIdx: changeValue(item); break; }
skip: //printf("contentsMouseReleaseEvent: %d,%d\n", p.x(), p.y()); Parent::mouseReleaseEvent(e);}
void ConfigList::mouseDoubleClickEvent(QMouseEvent* e){ QPoint p = e->pos(); ConfigItem* item = (ConfigItem*)itemAt(p); struct menu *menu; enum prop_type ptype;
if (!item) goto skip; if (item->goParent) { emit parentSelected(); goto skip; } menu = item->menu; if (!menu) goto skip; ptype = menu->prompt ? menu->prompt->type : P_UNKNOWN; if (ptype == P_MENU && mode != listMode) { if (mode == singleMode) emit itemSelected(menu); else if (mode == symbolMode) emit menuSelected(menu); } else if (menu->sym) changeValue(item);
skip: //printf("contentsMouseDoubleClickEvent: %d,%d\n", p.x(), p.y()); Parent::mouseDoubleClickEvent(e);}
void ConfigList::focusInEvent(QFocusEvent *e){ struct menu *menu = NULL;
Parent::focusInEvent(e);
ConfigItem* item = (ConfigItem *)currentItem(); if (item) { setSelected(item, true); menu = item->menu; } emit gotFocus(menu);}
void ConfigList::contextMenuEvent(QContextMenuEvent *e){ if (!headerPopup) { QAction *action;
headerPopup = new QMenu(this); action = new QAction("Show Name", this); action->setCheckable(true); connect(action, &QAction::toggled, this, &ConfigList::setShowName); connect(this, &ConfigList::showNameChanged, action, &QAction::setChecked); action->setChecked(showName); headerPopup->addAction(action); }
headerPopup->exec(e->globalPos()); e->accept();}
void ConfigList::setShowName(bool on){ if (showName == on) return;
showName = on; reinit(); emit showNameChanged(on);}
QList<ConfigList *> ConfigList::allLists;QAction *ConfigList::showNormalAction;QAction *ConfigList::showAllAction;QAction *ConfigList::showPromptAction;
void ConfigList::setAllOpen(bool open){ QTreeWidgetItemIterator it(this);
while (*it) { (*it)->setExpanded(open);
++it; }}
ConfigInfoView::ConfigInfoView(QWidget* parent, const char *name) : Parent(parent), sym(0), _menu(0){ setObjectName(name); setOpenLinks(false);
if (!objectName().isEmpty()) { configSettings->beginGroup(objectName()); setShowDebug(configSettings->value("/showDebug", false).toBool()); configSettings->endGroup(); connect(configApp, &QApplication::aboutToQuit, this, &ConfigInfoView::saveSettings); }
contextMenu = createStandardContextMenu(); QAction *action = new QAction("Show Debug Info", contextMenu);
action->setCheckable(true); connect(action, &QAction::toggled, this, &ConfigInfoView::setShowDebug); connect(this, &ConfigInfoView::showDebugChanged, action, &QAction::setChecked); action->setChecked(showDebug()); contextMenu->addSeparator(); contextMenu->addAction(action);}
void ConfigInfoView::saveSettings(void){ if (!objectName().isEmpty()) { configSettings->beginGroup(objectName()); configSettings->setValue("/showDebug", showDebug()); configSettings->endGroup(); }}
void ConfigInfoView::setShowDebug(bool b){ if (_showDebug != b) { _showDebug = b; if (_menu) menuInfo(); else if (sym) symbolInfo(); emit showDebugChanged(b); }}
void ConfigInfoView::setInfo(struct menu *m){ if (_menu == m) return; _menu = m; sym = NULL; if (!_menu) clear(); else menuInfo();}
void ConfigInfoView::symbolInfo(void){ QString str;
str += "<big>Symbol: <b>"; str += print_filter(sym->name); str += "</b></big><br><br>value: "; str += print_filter(sym_get_string_value(sym)); str += "<br>visibility: "; str += sym->visible == yes ? "y" : sym->visible == mod ? "m" : "n"; str += "<br>"; str += debug_info(sym);
setText(str);}
void ConfigInfoView::menuInfo(void){ struct symbol* sym; QString info; QTextStream stream(&info);
sym = _menu->sym; if (sym) { if (_menu->prompt) { stream << "<big><b>"; stream << print_filter(_menu->prompt->text); stream << "</b></big>"; if (sym->name) { stream << " ("; if (showDebug()) stream << "<a href=\"" << sym->name << "\">"; stream << print_filter(sym->name); if (showDebug()) stream << "</a>"; stream << ")"; } } else if (sym->name) { stream << "<big><b>"; if (showDebug()) stream << "<a href=\"" << sym->name << "\">"; stream << print_filter(sym->name); if (showDebug()) stream << "</a>"; stream << "</b></big>"; } stream << "<br><br>";
if (showDebug()) stream << debug_info(sym);
struct gstr help_gstr = str_new();
menu_get_ext_help(_menu, &help_gstr); stream << print_filter(str_get(&help_gstr)); str_free(&help_gstr); } else if (_menu->prompt) { stream << "<big><b>"; stream << print_filter(_menu->prompt->text); stream << "</b></big><br><br>"; if (showDebug()) { if (_menu->prompt->visible.expr) { stream << " dep: "; expr_print(_menu->prompt->visible.expr, expr_print_help, &stream, E_NONE); stream << "<br><br>"; }
stream << "defined at " << _menu->filename << ":" << _menu->lineno << "<br><br>"; } }
setText(info);}
QString ConfigInfoView::debug_info(struct symbol *sym){ QString debug; QTextStream stream(&debug);
stream << "type: "; stream << print_filter(sym_type_name(sym->type)); if (sym_is_choice(sym)) stream << " (choice)"; debug += "<br>"; if (sym->rev_dep.expr) { stream << "reverse dep: "; expr_print(sym->rev_dep.expr, expr_print_help, &stream, E_NONE); stream << "<br>"; } for (struct property *prop = sym->prop; prop; prop = prop->next) { switch (prop->type) { case P_PROMPT: case P_MENU: stream << "prompt: "; stream << print_filter(prop->text); stream << "<br>"; break; case P_DEFAULT: case P_SELECT: case P_RANGE: case P_COMMENT: case P_IMPLY: stream << prop_get_type_name(prop->type); stream << ": "; expr_print(prop->expr, expr_print_help, &stream, E_NONE); stream << "<br>"; break; default: stream << "unknown property: "; stream << prop_get_type_name(prop->type); stream << "<br>"; } if (prop->visible.expr) { stream << " dep: "; expr_print(prop->visible.expr, expr_print_help, &stream, E_NONE); stream << "<br>"; } } stream << "<br>";
return debug;}
QString ConfigInfoView::print_filter(const QString &str){ QRegularExpression re("[<>&\"\\n]"); QString res = str;
QHash<QChar, QString> patterns; patterns['<'] = "<"; patterns['>'] = ">"; patterns['&'] = "&"; patterns['"'] = """; patterns['\n'] = "<br>";
for (int i = 0; (i = res.indexOf(re, i)) >= 0;) { const QString n = patterns.value(res[i], QString()); if (!n.isEmpty()) { res.replace(i, 1, n); i += n.length(); } } return res;}
void ConfigInfoView::expr_print_help(void *data, struct symbol *sym, const char *str){ QTextStream *stream = reinterpret_cast<QTextStream *>(data);
if (sym && sym->name && !(sym->flags & SYMBOL_CONST)) { *stream << "<a href=\"" << sym->name << "\">"; *stream << print_filter(str); *stream << "</a>"; } else { *stream << print_filter(str); }}
void ConfigInfoView::clicked(const QUrl &url){ struct menu *m;
sym = sym_find(url.toEncoded().constData());
m = sym_get_prompt_menu(sym); if (!m) { /* Symbol is not visible as a menu */ symbolInfo(); emit showDebugChanged(true); } else { emit menuSelected(m); }}
void ConfigInfoView::contextMenuEvent(QContextMenuEvent *event){ contextMenu->popup(event->globalPos()); event->accept();}
ConfigSearchWindow::ConfigSearchWindow(ConfigMainWindow *parent) : Parent(parent), result(NULL){ setObjectName("search"); setWindowTitle("Search Config");
QVBoxLayout* layout1 = new QVBoxLayout(this); layout1->setContentsMargins(11, 11, 11, 11); layout1->setSpacing(6);
QHBoxLayout* layout2 = new QHBoxLayout(); layout2->setContentsMargins(0, 0, 0, 0); layout2->setSpacing(6); layout2->addWidget(new QLabel("Find:", this)); editField = new QLineEdit(this); connect(editField, &QLineEdit::returnPressed, this, &ConfigSearchWindow::search); layout2->addWidget(editField); searchButton = new QPushButton("Search", this); searchButton->setAutoDefault(false); connect(searchButton, &QPushButton::clicked, this, &ConfigSearchWindow::search); layout2->addWidget(searchButton); layout1->addLayout(layout2);
split = new QSplitter(Qt::Vertical, this); list = new ConfigList(split, "search"); list->mode = listMode; info = new ConfigInfoView(split, "search"); connect(list, &ConfigList::menuChanged, info, &ConfigInfoView::setInfo); connect(list, &ConfigList::menuChanged, parent, &ConfigMainWindow::setMenuLink);
layout1->addWidget(split);
QVariant x, y; int width, height; bool ok;
configSettings->beginGroup("search"); width = configSettings->value("/window width", parent->width() / 2).toInt(); height = configSettings->value("/window height", parent->height() / 2).toInt(); resize(width, height); x = configSettings->value("/window x"); y = configSettings->value("/window y"); if (x.isValid() && y.isValid()) move(x.toInt(), y.toInt()); QList<int> sizes = configSettings->readSizes("/split", &ok); if (ok) split->setSizes(sizes); configSettings->endGroup(); connect(configApp, &QApplication::aboutToQuit, this, &ConfigSearchWindow::saveSettings);}
void ConfigSearchWindow::saveSettings(void){ if (!objectName().isEmpty()) { configSettings->beginGroup(objectName()); configSettings->setValue("/window x", pos().x()); configSettings->setValue("/window y", pos().y()); configSettings->setValue("/window width", size().width()); configSettings->setValue("/window height", size().height()); configSettings->writeSizes("/split", split->sizes()); configSettings->endGroup(); }}
void ConfigSearchWindow::search(void){ struct symbol **p; struct property *prop; ConfigItem *lastItem = NULL;
free(result); list->clear(); info->clear();
result = sym_re_search(editField->text().toLatin1()); if (!result) return; for (p = result; *p; p++) { for_all_prompts((*p), prop) lastItem = new ConfigItem(list, lastItem, prop->menu); }}
/* * Construct the complete config widget */ConfigMainWindow::ConfigMainWindow(void) : searchWindow(0){ bool ok = true; QVariant x, y; int width, height; char title[256];
snprintf(title, sizeof(title), "%s%s", rootmenu.prompt->text, "" ); setWindowTitle(title);
QRect g = configApp->primaryScreen()->geometry(); width = configSettings->value("/window width", g.width() - 64).toInt(); height = configSettings->value("/window height", g.height() - 64).toInt(); resize(width, height); x = configSettings->value("/window x"); y = configSettings->value("/window y"); if ((x.isValid())&&(y.isValid())) move(x.toInt(), y.toInt());
// set up icons QString iconsDir = QString(getenv(SRCTREE) ? getenv(SRCTREE) : QDir::currentPath()) + "/scripts/kconfig/icons/"; ConfigItem::symbolYesIcon = QIcon(QPixmap(iconsDir + "symbol_yes.xpm")); ConfigItem::symbolModIcon = QIcon(QPixmap(iconsDir + "symbol_mod.xpm")); ConfigItem::symbolNoIcon = QIcon(QPixmap(iconsDir + "symbol_no.xpm")); ConfigItem::choiceYesIcon = QIcon(QPixmap(iconsDir + "choice_yes.xpm")); ConfigItem::choiceNoIcon = QIcon(QPixmap(iconsDir + "choice_no.xpm")); ConfigItem::menuIcon = QIcon(QPixmap(iconsDir + "menu.xpm")); ConfigItem::menubackIcon = QIcon(QPixmap(iconsDir + "menuback.xpm"));
QWidget *widget = new QWidget(this); setCentralWidget(widget);
QVBoxLayout *layout = new QVBoxLayout(widget);
split2 = new QSplitter(Qt::Vertical, widget); layout->addWidget(split2); split2->setChildrenCollapsible(false);
split1 = new QSplitter(Qt::Horizontal, split2); split1->setChildrenCollapsible(false);
configList = new ConfigList(split1, "config");
menuList = new ConfigList(split1, "menu");
helpText = new ConfigInfoView(split2, "help"); setTabOrder(configList, helpText);
configList->setFocus();
backAction = new QAction(QPixmap(iconsDir + "back.xpm"), "Back", this); backAction->setShortcut(QKeySequence::Back); connect(backAction, &QAction::triggered, this, &ConfigMainWindow::goBack);
QAction *quitAction = new QAction("&Quit", this); quitAction->setShortcut(QKeySequence::Quit); connect(quitAction, &QAction::triggered, this, &ConfigMainWindow::close);
QAction *loadAction = new QAction(QPixmap(iconsDir + "load.xpm"), "&Open", this); loadAction->setShortcut(QKeySequence::Open); connect(loadAction, &QAction::triggered, this, &ConfigMainWindow::loadConfig);
saveAction = new QAction(QPixmap(iconsDir + "save.xpm"), "&Save", this); saveAction->setShortcut(QKeySequence::Save); connect(saveAction, &QAction::triggered, this, &ConfigMainWindow::saveConfig);
conf_set_changed_callback(conf_changed);
configname = conf_get_configname();
QAction *saveAsAction = new QAction("Save &As...", this); saveAsAction->setShortcut(QKeySequence::SaveAs); connect(saveAsAction, &QAction::triggered, this, &ConfigMainWindow::saveConfigAs); QAction *searchAction = new QAction("&Find", this); searchAction->setShortcut(QKeySequence::Find); connect(searchAction, &QAction::triggered, this, &ConfigMainWindow::searchConfig); singleViewAction = new QAction(QPixmap(iconsDir + "single_view.xpm"), "Single View", this); singleViewAction->setCheckable(true); connect(singleViewAction, &QAction::triggered, this, &ConfigMainWindow::showSingleView); splitViewAction = new QAction(QPixmap(iconsDir + "split_view.xpm"), "Split View", this); splitViewAction->setCheckable(true); connect(splitViewAction, &QAction::triggered, this, &ConfigMainWindow::showSplitView); fullViewAction = new QAction(QPixmap(iconsDir + "tree_view.xpm"), "Full View", this); fullViewAction->setCheckable(true); connect(fullViewAction, &QAction::triggered, this, &ConfigMainWindow::showFullView);
QAction *showNameAction = new QAction("Show Name", this); showNameAction->setCheckable(true); connect(showNameAction, &QAction::toggled, configList, &ConfigList::setShowName); showNameAction->setChecked(configList->showName);
QActionGroup *optGroup = new QActionGroup(this); optGroup->setExclusive(true); connect(optGroup, &QActionGroup::triggered, configList, &ConfigList::setOptionMode); connect(optGroup, &QActionGroup::triggered, menuList, &ConfigList::setOptionMode);
ConfigList::showNormalAction = new QAction("Show Normal Options", optGroup); ConfigList::showNormalAction->setCheckable(true); ConfigList::showAllAction = new QAction("Show All Options", optGroup); ConfigList::showAllAction->setCheckable(true); ConfigList::showPromptAction = new QAction("Show Prompt Options", optGroup); ConfigList::showPromptAction->setCheckable(true);
switch (configList->optMode) { case allOpt: ConfigList::showAllAction->setChecked(true); break; case promptOpt: ConfigList::showPromptAction->setChecked(true); break; case normalOpt: default: ConfigList::showNormalAction->setChecked(true); break; }
QAction *showDebugAction = new QAction("Show Debug Info", this); showDebugAction->setCheckable(true); connect(showDebugAction, &QAction::toggled, helpText, &ConfigInfoView::setShowDebug); showDebugAction->setChecked(helpText->showDebug());
QAction *showIntroAction = new QAction("Introduction", this); connect(showIntroAction, &QAction::triggered, this, &ConfigMainWindow::showIntro); QAction *showAboutAction = new QAction("About", this); connect(showAboutAction, &QAction::triggered, this, &ConfigMainWindow::showAbout);
// init tool bar QToolBar *toolBar = addToolBar("Tools"); toolBar->addAction(backAction); toolBar->addSeparator(); toolBar->addAction(loadAction); toolBar->addAction(saveAction); toolBar->addSeparator(); toolBar->addAction(singleViewAction); toolBar->addAction(splitViewAction); toolBar->addAction(fullViewAction);
// create file menu QMenu *menu = menuBar()->addMenu("&File"); menu->addAction(loadAction); menu->addAction(saveAction); menu->addAction(saveAsAction); menu->addSeparator(); menu->addAction(quitAction);
// create edit menu menu = menuBar()->addMenu("&Edit"); menu->addAction(searchAction);
// create options menu menu = menuBar()->addMenu("&Option"); menu->addAction(showNameAction); menu->addSeparator(); menu->addActions(optGroup->actions()); menu->addSeparator(); menu->addAction(showDebugAction);
// create help menu menu = menuBar()->addMenu("&Help"); menu->addAction(showIntroAction); menu->addAction(showAboutAction);
connect(helpText, &ConfigInfoView::anchorClicked, helpText, &ConfigInfoView::clicked);
connect(configList, &ConfigList::menuChanged, helpText, &ConfigInfoView::setInfo); connect(configList, &ConfigList::menuSelected, this, &ConfigMainWindow::changeMenu); connect(configList, &ConfigList::itemSelected, this, &ConfigMainWindow::changeItens); connect(configList, &ConfigList::parentSelected, this, &ConfigMainWindow::goBack); connect(menuList, &ConfigList::menuChanged, helpText, &ConfigInfoView::setInfo); connect(menuList, &ConfigList::menuSelected, this, &ConfigMainWindow::changeMenu);
connect(configList, &ConfigList::gotFocus, helpText, &ConfigInfoView::setInfo); connect(menuList, &ConfigList::gotFocus, helpText, &ConfigInfoView::setInfo); connect(menuList, &ConfigList::gotFocus, this, &ConfigMainWindow::listFocusChanged); connect(helpText, &ConfigInfoView::menuSelected, this, &ConfigMainWindow::setMenuLink);
connect(configApp, &QApplication::aboutToQuit, this, &ConfigMainWindow::saveSettings);
conf_read(NULL);
QString listMode = configSettings->value("/listMode", "symbol").toString(); if (listMode == "single") showSingleView(); else if (listMode == "full") showFullView(); else /*if (listMode == "split")*/ showSplitView();
// UI setup done, restore splitter positions QList<int> sizes = configSettings->readSizes("/split1", &ok); if (ok) split1->setSizes(sizes);
sizes = configSettings->readSizes("/split2", &ok); if (ok) split2->setSizes(sizes);}
void ConfigMainWindow::loadConfig(void){ QString str;
str = QFileDialog::getOpenFileName(this, QString(), configname); if (str.isEmpty()) return;
if (conf_read(str.toLocal8Bit().constData())) QMessageBox::information(this, "qconf", "Unable to load configuration!");
configname = str;
ConfigList::updateListAllForAll();}
bool ConfigMainWindow::saveConfig(void){ if (conf_write(configname.toLocal8Bit().constData())) { QMessageBox::information(this, "qconf", "Unable to save configuration!"); return false; } conf_write_autoconf(0);
return true;}
void ConfigMainWindow::saveConfigAs(void){ QString str;
str = QFileDialog::getSaveFileName(this, QString(), configname); if (str.isEmpty()) return;
if (conf_write(str.toLocal8Bit().constData())) { QMessageBox::information(this, "qconf", "Unable to save configuration!"); } conf_write_autoconf(0);
configname = str;}
void ConfigMainWindow::searchConfig(void){ if (!searchWindow) searchWindow = new ConfigSearchWindow(this); searchWindow->show();}
void ConfigMainWindow::changeItens(struct menu *menu){ configList->setRootMenu(menu);}
void ConfigMainWindow::changeMenu(struct menu *menu){ menuList->setRootMenu(menu);}
void ConfigMainWindow::setMenuLink(struct menu *menu){ struct menu *parent; ConfigList* list = NULL; ConfigItem* item;
if (configList->menuSkip(menu)) return;
switch (configList->mode) { case singleMode: list = configList; parent = menu_get_menu_or_parent_menu(menu); if (!parent) return; list->setRootMenu(parent); break; case menuMode: if (menu->flags & MENU_ROOT) { menuList->setRootMenu(menu); configList->clearSelection(); list = configList; } else { parent = menu_get_menu_or_parent_menu(menu->parent); if (!parent) return;
/* Select the config view */ item = configList->findConfigItem(parent); if (item) { configList->setSelected(item, true); configList->scrollToItem(item); }
menuList->setRootMenu(parent); menuList->clearSelection(); list = menuList; } break; case fullMode: list = configList; break; default: break; }
if (list) { item = list->findConfigItem(menu); if (item) { list->setSelected(item, true); list->scrollToItem(item); list->setFocus(); helpText->setInfo(menu); } }}
void ConfigMainWindow::listFocusChanged(void){ if (menuList->mode == menuMode) configList->clearSelection();}
void ConfigMainWindow::goBack(void){ configList->setParentMenu();}
void ConfigMainWindow::showSingleView(void){ singleViewAction->setEnabled(false); singleViewAction->setChecked(true); splitViewAction->setEnabled(true); splitViewAction->setChecked(false); fullViewAction->setEnabled(true); fullViewAction->setChecked(false);
backAction->setEnabled(true);
menuList->hide(); menuList->setRootMenu(0); configList->mode = singleMode; if (configList->rootEntry == &rootmenu) configList->updateListAll(); else configList->setRootMenu(&rootmenu); configList->setFocus();}
void ConfigMainWindow::showSplitView(void){ singleViewAction->setEnabled(true); singleViewAction->setChecked(false); splitViewAction->setEnabled(false); splitViewAction->setChecked(true); fullViewAction->setEnabled(true); fullViewAction->setChecked(false);
backAction->setEnabled(false);
configList->mode = menuMode; if (configList->rootEntry == &rootmenu) configList->updateListAll(); else configList->setRootMenu(&rootmenu); configList->setAllOpen(true); configApp->processEvents(); menuList->mode = symbolMode; menuList->setRootMenu(&rootmenu); menuList->setAllOpen(true); menuList->show(); menuList->setFocus();}
void ConfigMainWindow::showFullView(void){ singleViewAction->setEnabled(true); singleViewAction->setChecked(false); splitViewAction->setEnabled(true); splitViewAction->setChecked(false); fullViewAction->setEnabled(false); fullViewAction->setChecked(true);
backAction->setEnabled(false);
menuList->hide(); menuList->setRootMenu(0); configList->mode = fullMode; if (configList->rootEntry == &rootmenu) configList->updateListAll(); else configList->setRootMenu(&rootmenu); configList->setFocus();}
/* * ask for saving configuration before quitting */void ConfigMainWindow::closeEvent(QCloseEvent* e){ if (!conf_get_changed()) { e->accept(); return; }
QMessageBox mb(QMessageBox::Icon::Warning, "qconf", "Save configuration?");
QPushButton *yb = mb.addButton(QMessageBox::Yes); QPushButton *db = mb.addButton(QMessageBox::No); QPushButton *cb = mb.addButton(QMessageBox::Cancel);
yb->setText("&Save Changes"); db->setText("&Discard Changes"); cb->setText("Cancel Exit");
mb.setDefaultButton(yb); mb.setEscapeButton(cb);
switch (mb.exec()) { case QMessageBox::Yes: if (saveConfig()) e->accept(); else e->ignore(); break; case QMessageBox::No: e->accept(); break; case QMessageBox::Cancel: e->ignore(); break; }}
void ConfigMainWindow::showIntro(void){ static const QString str = "Welcome to the qconf graphical configuration tool.\n" "\n" "For bool and tristate options, a blank box indicates the " "feature is disabled, a check indicates it is enabled, and a " "dot indicates that it is to be compiled as a module. Clicking " "on the box will cycle through the three states. For int, hex, " "and string options, double-clicking or pressing F2 on the " "Value cell will allow you to edit the value.\n" "\n" "If you do not see an option (e.g., a device driver) that you " "believe should be present, try turning on Show All Options " "under the Options menu. Enabling Show Debug Info will help you" "figure out what other options must be enabled to support the " "option you are interested in, and hyperlinks will navigate to " "them.\n" "\n" "Toggling Show Debug Info under the Options menu will show the " "dependencies, which you can then match by examining other " "options.\n";
QMessageBox::information(this, "qconf", str);}
void ConfigMainWindow::showAbout(void){ static const QString str = "qconf is Copyright (C) 2002 Roman Zippel <zippel@linux-m68k.org>.\n" "Copyright (C) 2015 Boris Barbulovski <bbarbulovski@gmail.com>.\n" "\n" "Bug reports and feature request can also be entered at http://bugzilla.kernel.org/\n" "\n" "Qt Version: ";
QMessageBox::information(this, "qconf", str + qVersion());}
void ConfigMainWindow::saveSettings(void){ configSettings->setValue("/window x", pos().x()); configSettings->setValue("/window y", pos().y()); configSettings->setValue("/window width", size().width()); configSettings->setValue("/window height", size().height());
QString entry; switch(configList->mode) { case singleMode : entry = "single"; break;
case symbolMode : entry = "split"; break;
case fullMode : entry = "full"; break;
default: break; } configSettings->setValue("/listMode", entry);
configSettings->writeSizes("/split1", split1->sizes()); configSettings->writeSizes("/split2", split2->sizes());}
void ConfigMainWindow::conf_changed(bool dirty){ if (saveAction) saveAction->setEnabled(dirty);}
void fixup_rootmenu(struct menu *menu){ struct menu *child; static int menu_cnt = 0;
menu->flags |= MENU_ROOT; for (child = menu->list; child; child = child->next) { if (child->prompt && child->prompt->type == P_MENU) { menu_cnt++; fixup_rootmenu(child); menu_cnt--; } else if (!menu_cnt) fixup_rootmenu(child); }}
static const char *progname;
static void usage(void){ printf("%s [-s] <config>\n", progname); exit(0);}
int main(int ac, char** av){ ConfigMainWindow* v; const char *name;
progname = av[0]; if (ac > 1 && av[1][0] == '-') { switch (av[1][1]) { case 's': conf_set_message_callback(NULL); break; case 'h': case '?': usage(); } name = av[2]; } else name = av[1]; if (!name) usage();
conf_parse(name); fixup_rootmenu(&rootmenu); //zconfdump(stdout);
configApp = new QApplication(ac, av);
configSettings = new ConfigSettings(); v = new ConfigMainWindow();
//zconfdump(stdout);
v->show(); configApp->exec();
delete configSettings; delete v; delete configApp;
return 0;}