0001
0002
0003
0004
0005
0006
0007 #include <QAction>
0008 #include <QApplication>
0009 #include <QCloseEvent>
0010 #include <QDebug>
0011 #include <QDesktopWidget>
0012 #include <QFileDialog>
0013 #include <QLabel>
0014 #include <QLayout>
0015 #include <QList>
0016 #include <QMenu>
0017 #include <QMenuBar>
0018 #include <QMessageBox>
0019 #include <QToolBar>
0020
0021 #include <stdlib.h>
0022
0023 #include "lkc.h"
0024 #include "qconf.h"
0025
0026 #include "images.h"
0027
0028
0029 static QApplication *configApp;
0030 static ConfigSettings *configSettings;
0031
0032 QAction *ConfigMainWindow::saveAction;
0033
0034 ConfigSettings::ConfigSettings()
0035 : QSettings("kernel.org", "qconf")
0036 {
0037 }
0038
0039
0040
0041
0042 QList<int> ConfigSettings::readSizes(const QString& key, bool *ok)
0043 {
0044 QList<int> result;
0045
0046 if (contains(key))
0047 {
0048 QStringList entryList = value(key).toStringList();
0049 QStringList::Iterator it;
0050
0051 for (it = entryList.begin(); it != entryList.end(); ++it)
0052 result.push_back((*it).toInt());
0053
0054 *ok = true;
0055 }
0056 else
0057 *ok = false;
0058
0059 return result;
0060 }
0061
0062
0063
0064
0065 bool ConfigSettings::writeSizes(const QString& key, const QList<int>& value)
0066 {
0067 QStringList stringList;
0068 QList<int>::ConstIterator it;
0069
0070 for (it = value.begin(); it != value.end(); ++it)
0071 stringList.push_back(QString::number(*it));
0072 setValue(key, stringList);
0073
0074 return true;
0075 }
0076
0077 QIcon ConfigItem::symbolYesIcon;
0078 QIcon ConfigItem::symbolModIcon;
0079 QIcon ConfigItem::symbolNoIcon;
0080 QIcon ConfigItem::choiceYesIcon;
0081 QIcon ConfigItem::choiceNoIcon;
0082 QIcon ConfigItem::menuIcon;
0083 QIcon ConfigItem::menubackIcon;
0084
0085
0086
0087
0088 void ConfigItem::updateMenu(void)
0089 {
0090 ConfigList* list;
0091 struct symbol* sym;
0092 struct property *prop;
0093 QString prompt;
0094 int type;
0095 tristate expr;
0096
0097 list = listView();
0098 if (goParent) {
0099 setIcon(promptColIdx, menubackIcon);
0100 prompt = "..";
0101 goto set_prompt;
0102 }
0103
0104 sym = menu->sym;
0105 prop = menu->prompt;
0106 prompt = menu_get_prompt(menu);
0107
0108 if (prop) switch (prop->type) {
0109 case P_MENU:
0110 if (list->mode == singleMode || list->mode == symbolMode) {
0111
0112
0113
0114 if (sym && list->rootEntry == menu)
0115 break;
0116 setIcon(promptColIdx, menuIcon);
0117 } else {
0118 if (sym)
0119 break;
0120 setIcon(promptColIdx, QIcon());
0121 }
0122 goto set_prompt;
0123 case P_COMMENT:
0124 setIcon(promptColIdx, QIcon());
0125 prompt = "*** " + prompt + " ***";
0126 goto set_prompt;
0127 default:
0128 ;
0129 }
0130 if (!sym)
0131 goto set_prompt;
0132
0133 setText(nameColIdx, sym->name);
0134
0135 type = sym_get_type(sym);
0136 switch (type) {
0137 case S_BOOLEAN:
0138 case S_TRISTATE:
0139 char ch;
0140
0141 if (!sym_is_changeable(sym) && list->optMode == normalOpt) {
0142 setIcon(promptColIdx, QIcon());
0143 break;
0144 }
0145 expr = sym_get_tristate_value(sym);
0146 switch (expr) {
0147 case yes:
0148 if (sym_is_choice_value(sym) && type == S_BOOLEAN)
0149 setIcon(promptColIdx, choiceYesIcon);
0150 else
0151 setIcon(promptColIdx, symbolYesIcon);
0152 ch = 'Y';
0153 break;
0154 case mod:
0155 setIcon(promptColIdx, symbolModIcon);
0156 ch = 'M';
0157 break;
0158 default:
0159 if (sym_is_choice_value(sym) && type == S_BOOLEAN)
0160 setIcon(promptColIdx, choiceNoIcon);
0161 else
0162 setIcon(promptColIdx, symbolNoIcon);
0163 ch = 'N';
0164 break;
0165 }
0166
0167 setText(dataColIdx, QChar(ch));
0168 break;
0169 case S_INT:
0170 case S_HEX:
0171 case S_STRING:
0172 setText(dataColIdx, sym_get_string_value(sym));
0173 break;
0174 }
0175 if (!sym_has_value(sym) && visible)
0176 prompt += " (NEW)";
0177 set_prompt:
0178 setText(promptColIdx, prompt);
0179 }
0180
0181 void ConfigItem::testUpdateMenu(bool v)
0182 {
0183 ConfigItem* i;
0184
0185 visible = v;
0186 if (!menu)
0187 return;
0188
0189 sym_calc_value(menu->sym);
0190 if (menu->flags & MENU_CHANGED) {
0191
0192 menu->flags &= ~MENU_CHANGED;
0193 for (i = (ConfigItem*)menu->data; i; i = i->nextItem)
0194 i->updateMenu();
0195 } else if (listView()->updateAll)
0196 updateMenu();
0197 }
0198
0199
0200
0201
0202
0203 void ConfigItem::init(void)
0204 {
0205 if (menu) {
0206 ConfigList* list = listView();
0207 nextItem = (ConfigItem*)menu->data;
0208 menu->data = this;
0209
0210 if (list->mode != fullMode)
0211 setExpanded(true);
0212 sym_calc_value(menu->sym);
0213
0214 if (menu->sym) {
0215 enum symbol_type type = menu->sym->type;
0216
0217
0218
0219
0220
0221 if (type == S_INT || type == S_HEX || type == S_STRING)
0222 setFlags(flags() | Qt::ItemIsEditable);
0223 }
0224 }
0225 updateMenu();
0226 }
0227
0228
0229
0230
0231 ConfigItem::~ConfigItem(void)
0232 {
0233 if (menu) {
0234 ConfigItem** ip = (ConfigItem**)&menu->data;
0235 for (; *ip; ip = &(*ip)->nextItem) {
0236 if (*ip == this) {
0237 *ip = nextItem;
0238 break;
0239 }
0240 }
0241 }
0242 }
0243
0244 QWidget *ConfigItemDelegate::createEditor(QWidget *parent,
0245 const QStyleOptionViewItem &option,
0246 const QModelIndex &index) const
0247 {
0248 ConfigItem *item;
0249
0250
0251 if (index.column() != dataColIdx)
0252 return nullptr;
0253
0254
0255 item = static_cast<ConfigItem *>(index.internalPointer());
0256 if (!item || !item->menu || !menu_is_visible(item->menu))
0257 return nullptr;
0258
0259 return QStyledItemDelegate::createEditor(parent, option, index);
0260 }
0261
0262 void ConfigItemDelegate::setModelData(QWidget *editor,
0263 QAbstractItemModel *model,
0264 const QModelIndex &index) const
0265 {
0266 QLineEdit *lineEdit;
0267 ConfigItem *item;
0268 struct symbol *sym;
0269 bool success;
0270
0271 lineEdit = qobject_cast<QLineEdit *>(editor);
0272
0273
0274 if (!lineEdit)
0275 goto parent;
0276
0277 item = static_cast<ConfigItem *>(index.internalPointer());
0278 if (!item || !item->menu)
0279 goto parent;
0280
0281 sym = item->menu->sym;
0282 if (!sym)
0283 goto parent;
0284
0285 success = sym_set_string_value(sym, lineEdit->text().toUtf8().data());
0286 if (success) {
0287 ConfigList::updateListForAll();
0288 } else {
0289 QMessageBox::information(editor, "qconf",
0290 "Cannot set the data (maybe due to out of range).\n"
0291 "Setting the old value.");
0292 lineEdit->setText(sym_get_string_value(sym));
0293 }
0294
0295 parent:
0296 QStyledItemDelegate::setModelData(editor, model, index);
0297 }
0298
0299 ConfigList::ConfigList(QWidget *parent, const char *name)
0300 : QTreeWidget(parent),
0301 updateAll(false),
0302 showName(false), mode(singleMode), optMode(normalOpt),
0303 rootEntry(0), headerPopup(0)
0304 {
0305 setObjectName(name);
0306 setSortingEnabled(false);
0307 setRootIsDecorated(true);
0308
0309 setVerticalScrollMode(ScrollPerPixel);
0310 setHorizontalScrollMode(ScrollPerPixel);
0311
0312 setHeaderLabels(QStringList() << "Option" << "Name" << "Value");
0313
0314 connect(this, &ConfigList::itemSelectionChanged,
0315 this, &ConfigList::updateSelection);
0316
0317 if (name) {
0318 configSettings->beginGroup(name);
0319 showName = configSettings->value("/showName", false).toBool();
0320 optMode = (enum optionMode)configSettings->value("/optionMode", 0).toInt();
0321 configSettings->endGroup();
0322 connect(configApp, &QApplication::aboutToQuit,
0323 this, &ConfigList::saveSettings);
0324 }
0325
0326 showColumn(promptColIdx);
0327
0328 setItemDelegate(new ConfigItemDelegate(this));
0329
0330 allLists.append(this);
0331
0332 reinit();
0333 }
0334
0335 ConfigList::~ConfigList()
0336 {
0337 allLists.removeOne(this);
0338 }
0339
0340 bool ConfigList::menuSkip(struct menu *menu)
0341 {
0342 if (optMode == normalOpt && menu_is_visible(menu))
0343 return false;
0344 if (optMode == promptOpt && menu_has_prompt(menu))
0345 return false;
0346 if (optMode == allOpt)
0347 return false;
0348 return true;
0349 }
0350
0351 void ConfigList::reinit(void)
0352 {
0353 hideColumn(nameColIdx);
0354
0355 if (showName)
0356 showColumn(nameColIdx);
0357
0358 updateListAll();
0359 }
0360
0361 void ConfigList::setOptionMode(QAction *action)
0362 {
0363 if (action == showNormalAction)
0364 optMode = normalOpt;
0365 else if (action == showAllAction)
0366 optMode = allOpt;
0367 else
0368 optMode = promptOpt;
0369
0370 updateListAll();
0371 }
0372
0373 void ConfigList::saveSettings(void)
0374 {
0375 if (!objectName().isEmpty()) {
0376 configSettings->beginGroup(objectName());
0377 configSettings->setValue("/showName", showName);
0378 configSettings->setValue("/optionMode", (int)optMode);
0379 configSettings->endGroup();
0380 }
0381 }
0382
0383 ConfigItem* ConfigList::findConfigItem(struct menu *menu)
0384 {
0385 ConfigItem* item = (ConfigItem*)menu->data;
0386
0387 for (; item; item = item->nextItem) {
0388 if (this == item->listView())
0389 break;
0390 }
0391
0392 return item;
0393 }
0394
0395 void ConfigList::updateSelection(void)
0396 {
0397 struct menu *menu;
0398 enum prop_type type;
0399
0400 if (selectedItems().count() == 0)
0401 return;
0402
0403 ConfigItem* item = (ConfigItem*)selectedItems().first();
0404 if (!item)
0405 return;
0406
0407 menu = item->menu;
0408 emit menuChanged(menu);
0409 if (!menu)
0410 return;
0411 type = menu->prompt ? menu->prompt->type : P_UNKNOWN;
0412 if (mode == menuMode && type == P_MENU)
0413 emit menuSelected(menu);
0414 }
0415
0416 void ConfigList::updateList()
0417 {
0418 ConfigItem* last = 0;
0419 ConfigItem *item;
0420
0421 if (!rootEntry) {
0422 if (mode != listMode)
0423 goto update;
0424 QTreeWidgetItemIterator it(this);
0425
0426 while (*it) {
0427 item = (ConfigItem*)(*it);
0428 if (!item->menu)
0429 continue;
0430 item->testUpdateMenu(menu_is_visible(item->menu));
0431
0432 ++it;
0433 }
0434 return;
0435 }
0436
0437 if (rootEntry != &rootmenu && (mode == singleMode ||
0438 (mode == symbolMode && rootEntry->parent != &rootmenu))) {
0439 item = (ConfigItem *)topLevelItem(0);
0440 if (!item)
0441 item = new ConfigItem(this, 0, true);
0442 last = item;
0443 }
0444 if ((mode == singleMode || (mode == symbolMode && !(rootEntry->flags & MENU_ROOT))) &&
0445 rootEntry->sym && rootEntry->prompt) {
0446 item = last ? last->nextSibling() : nullptr;
0447 if (!item)
0448 item = new ConfigItem(this, last, rootEntry, true);
0449 else
0450 item->testUpdateMenu(true);
0451
0452 updateMenuList(item, rootEntry);
0453 update();
0454 resizeColumnToContents(0);
0455 return;
0456 }
0457 update:
0458 updateMenuList(rootEntry);
0459 update();
0460 resizeColumnToContents(0);
0461 }
0462
0463 void ConfigList::updateListForAll()
0464 {
0465 QListIterator<ConfigList *> it(allLists);
0466
0467 while (it.hasNext()) {
0468 ConfigList *list = it.next();
0469
0470 list->updateList();
0471 }
0472 }
0473
0474 void ConfigList::updateListAllForAll()
0475 {
0476 QListIterator<ConfigList *> it(allLists);
0477
0478 while (it.hasNext()) {
0479 ConfigList *list = it.next();
0480
0481 list->updateList();
0482 }
0483 }
0484
0485 void ConfigList::setValue(ConfigItem* item, tristate val)
0486 {
0487 struct symbol* sym;
0488 int type;
0489 tristate oldval;
0490
0491 sym = item->menu ? item->menu->sym : 0;
0492 if (!sym)
0493 return;
0494
0495 type = sym_get_type(sym);
0496 switch (type) {
0497 case S_BOOLEAN:
0498 case S_TRISTATE:
0499 oldval = sym_get_tristate_value(sym);
0500
0501 if (!sym_set_tristate_value(sym, val))
0502 return;
0503 if (oldval == no && item->menu->list)
0504 item->setExpanded(true);
0505 ConfigList::updateListForAll();
0506 break;
0507 }
0508 }
0509
0510 void ConfigList::changeValue(ConfigItem* item)
0511 {
0512 struct symbol* sym;
0513 struct menu* menu;
0514 int type, oldexpr, newexpr;
0515
0516 menu = item->menu;
0517 if (!menu)
0518 return;
0519 sym = menu->sym;
0520 if (!sym) {
0521 if (item->menu->list)
0522 item->setExpanded(!item->isExpanded());
0523 return;
0524 }
0525
0526 type = sym_get_type(sym);
0527 switch (type) {
0528 case S_BOOLEAN:
0529 case S_TRISTATE:
0530 oldexpr = sym_get_tristate_value(sym);
0531 newexpr = sym_toggle_tristate_value(sym);
0532 if (item->menu->list) {
0533 if (oldexpr == newexpr)
0534 item->setExpanded(!item->isExpanded());
0535 else if (oldexpr == no)
0536 item->setExpanded(true);
0537 }
0538 if (oldexpr != newexpr)
0539 ConfigList::updateListForAll();
0540 break;
0541 default:
0542 break;
0543 }
0544 }
0545
0546 void ConfigList::setRootMenu(struct menu *menu)
0547 {
0548 enum prop_type type;
0549
0550 if (rootEntry == menu)
0551 return;
0552 type = menu && menu->prompt ? menu->prompt->type : P_UNKNOWN;
0553 if (type != P_MENU)
0554 return;
0555 updateMenuList(0);
0556 rootEntry = menu;
0557 updateListAll();
0558 if (currentItem()) {
0559 setSelected(currentItem(), hasFocus());
0560 scrollToItem(currentItem());
0561 }
0562 }
0563
0564 void ConfigList::setParentMenu(void)
0565 {
0566 ConfigItem* item;
0567 struct menu *oldroot;
0568
0569 oldroot = rootEntry;
0570 if (rootEntry == &rootmenu)
0571 return;
0572 setRootMenu(menu_get_parent_menu(rootEntry->parent));
0573
0574 QTreeWidgetItemIterator it(this);
0575 while (*it) {
0576 item = (ConfigItem *)(*it);
0577 if (item->menu == oldroot) {
0578 setCurrentItem(item);
0579 scrollToItem(item);
0580 break;
0581 }
0582
0583 ++it;
0584 }
0585 }
0586
0587
0588
0589
0590
0591
0592
0593
0594 void ConfigList::updateMenuList(ConfigItem *parent, struct menu* menu)
0595 {
0596 struct menu* child;
0597 ConfigItem* item;
0598 ConfigItem* last;
0599 bool visible;
0600 enum prop_type type;
0601
0602 if (!menu) {
0603 while (parent->childCount() > 0)
0604 {
0605 delete parent->takeChild(0);
0606 }
0607
0608 return;
0609 }
0610
0611 last = parent->firstChild();
0612 if (last && !last->goParent)
0613 last = 0;
0614 for (child = menu->list; child; child = child->next) {
0615 item = last ? last->nextSibling() : parent->firstChild();
0616 type = child->prompt ? child->prompt->type : P_UNKNOWN;
0617
0618 switch (mode) {
0619 case menuMode:
0620 if (!(child->flags & MENU_ROOT))
0621 goto hide;
0622 break;
0623 case symbolMode:
0624 if (child->flags & MENU_ROOT)
0625 goto hide;
0626 break;
0627 default:
0628 break;
0629 }
0630
0631 visible = menu_is_visible(child);
0632 if (!menuSkip(child)) {
0633 if (!child->sym && !child->list && !child->prompt)
0634 continue;
0635 if (!item || item->menu != child)
0636 item = new ConfigItem(parent, last, child, visible);
0637 else
0638 item->testUpdateMenu(visible);
0639
0640 if (mode == fullMode || mode == menuMode || type != P_MENU)
0641 updateMenuList(item, child);
0642 else
0643 updateMenuList(item, 0);
0644 last = item;
0645 continue;
0646 }
0647 hide:
0648 if (item && item->menu == child) {
0649 last = parent->firstChild();
0650 if (last == item)
0651 last = 0;
0652 else while (last->nextSibling() != item)
0653 last = last->nextSibling();
0654 delete item;
0655 }
0656 }
0657 }
0658
0659 void ConfigList::updateMenuList(struct menu *menu)
0660 {
0661 struct menu* child;
0662 ConfigItem* item;
0663 ConfigItem* last;
0664 bool visible;
0665 enum prop_type type;
0666
0667 if (!menu) {
0668 while (topLevelItemCount() > 0)
0669 {
0670 delete takeTopLevelItem(0);
0671 }
0672
0673 return;
0674 }
0675
0676 last = (ConfigItem *)topLevelItem(0);
0677 if (last && !last->goParent)
0678 last = 0;
0679 for (child = menu->list; child; child = child->next) {
0680 item = last ? last->nextSibling() : (ConfigItem *)topLevelItem(0);
0681 type = child->prompt ? child->prompt->type : P_UNKNOWN;
0682
0683 switch (mode) {
0684 case menuMode:
0685 if (!(child->flags & MENU_ROOT))
0686 goto hide;
0687 break;
0688 case symbolMode:
0689 if (child->flags & MENU_ROOT)
0690 goto hide;
0691 break;
0692 default:
0693 break;
0694 }
0695
0696 visible = menu_is_visible(child);
0697 if (!menuSkip(child)) {
0698 if (!child->sym && !child->list && !child->prompt)
0699 continue;
0700 if (!item || item->menu != child)
0701 item = new ConfigItem(this, last, child, visible);
0702 else
0703 item->testUpdateMenu(visible);
0704
0705 if (mode == fullMode || mode == menuMode || type != P_MENU)
0706 updateMenuList(item, child);
0707 else
0708 updateMenuList(item, 0);
0709 last = item;
0710 continue;
0711 }
0712 hide:
0713 if (item && item->menu == child) {
0714 last = (ConfigItem *)topLevelItem(0);
0715 if (last == item)
0716 last = 0;
0717 else while (last->nextSibling() != item)
0718 last = last->nextSibling();
0719 delete item;
0720 }
0721 }
0722 }
0723
0724 void ConfigList::keyPressEvent(QKeyEvent* ev)
0725 {
0726 QTreeWidgetItem* i = currentItem();
0727 ConfigItem* item;
0728 struct menu *menu;
0729 enum prop_type type;
0730
0731 if (ev->key() == Qt::Key_Escape && mode != fullMode && mode != listMode) {
0732 emit parentSelected();
0733 ev->accept();
0734 return;
0735 }
0736
0737 if (!i) {
0738 Parent::keyPressEvent(ev);
0739 return;
0740 }
0741 item = (ConfigItem*)i;
0742
0743 switch (ev->key()) {
0744 case Qt::Key_Return:
0745 case Qt::Key_Enter:
0746 if (item->goParent) {
0747 emit parentSelected();
0748 break;
0749 }
0750 menu = item->menu;
0751 if (!menu)
0752 break;
0753 type = menu->prompt ? menu->prompt->type : P_UNKNOWN;
0754 if (type == P_MENU && rootEntry != menu &&
0755 mode != fullMode && mode != menuMode) {
0756 if (mode == menuMode)
0757 emit menuSelected(menu);
0758 else
0759 emit itemSelected(menu);
0760 break;
0761 }
0762 case Qt::Key_Space:
0763 changeValue(item);
0764 break;
0765 case Qt::Key_N:
0766 setValue(item, no);
0767 break;
0768 case Qt::Key_M:
0769 setValue(item, mod);
0770 break;
0771 case Qt::Key_Y:
0772 setValue(item, yes);
0773 break;
0774 default:
0775 Parent::keyPressEvent(ev);
0776 return;
0777 }
0778 ev->accept();
0779 }
0780
0781 void ConfigList::mousePressEvent(QMouseEvent* e)
0782 {
0783
0784
0785 Parent::mousePressEvent(e);
0786 }
0787
0788 void ConfigList::mouseReleaseEvent(QMouseEvent* e)
0789 {
0790 QPoint p = e->pos();
0791 ConfigItem* item = (ConfigItem*)itemAt(p);
0792 struct menu *menu;
0793 enum prop_type ptype;
0794 QIcon icon;
0795 int idx, x;
0796
0797 if (!item)
0798 goto skip;
0799
0800 menu = item->menu;
0801 x = header()->offset() + p.x();
0802 idx = header()->logicalIndexAt(x);
0803 switch (idx) {
0804 case promptColIdx:
0805 icon = item->icon(promptColIdx);
0806 if (!icon.isNull()) {
0807 int off = header()->sectionPosition(0) + visualRect(indexAt(p)).x() + 4;
0808 if (x >= off && x < off + icon.availableSizes().first().width()) {
0809 if (item->goParent) {
0810 emit parentSelected();
0811 break;
0812 } else if (!menu)
0813 break;
0814 ptype = menu->prompt ? menu->prompt->type : P_UNKNOWN;
0815 if (ptype == P_MENU && rootEntry != menu &&
0816 mode != fullMode && mode != menuMode &&
0817 mode != listMode)
0818 emit menuSelected(menu);
0819 else
0820 changeValue(item);
0821 }
0822 }
0823 break;
0824 case dataColIdx:
0825 changeValue(item);
0826 break;
0827 }
0828
0829 skip:
0830
0831 Parent::mouseReleaseEvent(e);
0832 }
0833
0834 void ConfigList::mouseMoveEvent(QMouseEvent* e)
0835 {
0836
0837
0838 Parent::mouseMoveEvent(e);
0839 }
0840
0841 void ConfigList::mouseDoubleClickEvent(QMouseEvent* e)
0842 {
0843 QPoint p = e->pos();
0844 ConfigItem* item = (ConfigItem*)itemAt(p);
0845 struct menu *menu;
0846 enum prop_type ptype;
0847
0848 if (!item)
0849 goto skip;
0850 if (item->goParent) {
0851 emit parentSelected();
0852 goto skip;
0853 }
0854 menu = item->menu;
0855 if (!menu)
0856 goto skip;
0857 ptype = menu->prompt ? menu->prompt->type : P_UNKNOWN;
0858 if (ptype == P_MENU && mode != listMode) {
0859 if (mode == singleMode)
0860 emit itemSelected(menu);
0861 else if (mode == symbolMode)
0862 emit menuSelected(menu);
0863 } else if (menu->sym)
0864 changeValue(item);
0865
0866 skip:
0867
0868 Parent::mouseDoubleClickEvent(e);
0869 }
0870
0871 void ConfigList::focusInEvent(QFocusEvent *e)
0872 {
0873 struct menu *menu = NULL;
0874
0875 Parent::focusInEvent(e);
0876
0877 ConfigItem* item = (ConfigItem *)currentItem();
0878 if (item) {
0879 setSelected(item, true);
0880 menu = item->menu;
0881 }
0882 emit gotFocus(menu);
0883 }
0884
0885 void ConfigList::contextMenuEvent(QContextMenuEvent *e)
0886 {
0887 if (!headerPopup) {
0888 QAction *action;
0889
0890 headerPopup = new QMenu(this);
0891 action = new QAction("Show Name", this);
0892 action->setCheckable(true);
0893 connect(action, &QAction::toggled,
0894 this, &ConfigList::setShowName);
0895 connect(this, &ConfigList::showNameChanged,
0896 action, &QAction::setChecked);
0897 action->setChecked(showName);
0898 headerPopup->addAction(action);
0899 }
0900
0901 headerPopup->exec(e->globalPos());
0902 e->accept();
0903 }
0904
0905 void ConfigList::setShowName(bool on)
0906 {
0907 if (showName == on)
0908 return;
0909
0910 showName = on;
0911 reinit();
0912 emit showNameChanged(on);
0913 }
0914
0915 QList<ConfigList *> ConfigList::allLists;
0916 QAction *ConfigList::showNormalAction;
0917 QAction *ConfigList::showAllAction;
0918 QAction *ConfigList::showPromptAction;
0919
0920 void ConfigList::setAllOpen(bool open)
0921 {
0922 QTreeWidgetItemIterator it(this);
0923
0924 while (*it) {
0925 (*it)->setExpanded(open);
0926
0927 ++it;
0928 }
0929 }
0930
0931 ConfigInfoView::ConfigInfoView(QWidget* parent, const char *name)
0932 : Parent(parent), sym(0), _menu(0)
0933 {
0934 setObjectName(name);
0935 setOpenLinks(false);
0936
0937 if (!objectName().isEmpty()) {
0938 configSettings->beginGroup(objectName());
0939 setShowDebug(configSettings->value("/showDebug", false).toBool());
0940 configSettings->endGroup();
0941 connect(configApp, &QApplication::aboutToQuit,
0942 this, &ConfigInfoView::saveSettings);
0943 }
0944
0945 contextMenu = createStandardContextMenu();
0946 QAction *action = new QAction("Show Debug Info", contextMenu);
0947
0948 action->setCheckable(true);
0949 connect(action, &QAction::toggled,
0950 this, &ConfigInfoView::setShowDebug);
0951 connect(this, &ConfigInfoView::showDebugChanged,
0952 action, &QAction::setChecked);
0953 action->setChecked(showDebug());
0954 contextMenu->addSeparator();
0955 contextMenu->addAction(action);
0956 }
0957
0958 void ConfigInfoView::saveSettings(void)
0959 {
0960 if (!objectName().isEmpty()) {
0961 configSettings->beginGroup(objectName());
0962 configSettings->setValue("/showDebug", showDebug());
0963 configSettings->endGroup();
0964 }
0965 }
0966
0967 void ConfigInfoView::setShowDebug(bool b)
0968 {
0969 if (_showDebug != b) {
0970 _showDebug = b;
0971 if (_menu)
0972 menuInfo();
0973 else if (sym)
0974 symbolInfo();
0975 emit showDebugChanged(b);
0976 }
0977 }
0978
0979 void ConfigInfoView::setInfo(struct menu *m)
0980 {
0981 if (_menu == m)
0982 return;
0983 _menu = m;
0984 sym = NULL;
0985 if (!_menu)
0986 clear();
0987 else
0988 menuInfo();
0989 }
0990
0991 void ConfigInfoView::symbolInfo(void)
0992 {
0993 QString str;
0994
0995 str += "<big>Symbol: <b>";
0996 str += print_filter(sym->name);
0997 str += "</b></big><br><br>value: ";
0998 str += print_filter(sym_get_string_value(sym));
0999 str += "<br>visibility: ";
1000 str += sym->visible == yes ? "y" : sym->visible == mod ? "m" : "n";
1001 str += "<br>";
1002 str += debug_info(sym);
1003
1004 setText(str);
1005 }
1006
1007 void ConfigInfoView::menuInfo(void)
1008 {
1009 struct symbol* sym;
1010 QString info;
1011 QTextStream stream(&info);
1012
1013 sym = _menu->sym;
1014 if (sym) {
1015 if (_menu->prompt) {
1016 stream << "<big><b>";
1017 stream << print_filter(_menu->prompt->text);
1018 stream << "</b></big>";
1019 if (sym->name) {
1020 stream << " (";
1021 if (showDebug())
1022 stream << "<a href=\"s" << sym->name << "\">";
1023 stream << print_filter(sym->name);
1024 if (showDebug())
1025 stream << "</a>";
1026 stream << ")";
1027 }
1028 } else if (sym->name) {
1029 stream << "<big><b>";
1030 if (showDebug())
1031 stream << "<a href=\"s" << sym->name << "\">";
1032 stream << print_filter(sym->name);
1033 if (showDebug())
1034 stream << "</a>";
1035 stream << "</b></big>";
1036 }
1037 stream << "<br><br>";
1038
1039 if (showDebug())
1040 stream << debug_info(sym);
1041
1042 struct gstr help_gstr = str_new();
1043
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>";
1051 if (showDebug()) {
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>";
1057 }
1058
1059 stream << "defined at " << _menu->file->name << ":"
1060 << _menu->lineno << "<br><br>";
1061 }
1062 }
1063
1064 setText(info);
1065 }
1066
1067 QString ConfigInfoView::debug_info(struct symbol *sym)
1068 {
1069 QString debug;
1070 QTextStream stream(&debug);
1071
1072 stream << "type: ";
1073 stream << print_filter(sym_type_name(sym->type));
1074 if (sym_is_choice(sym))
1075 stream << " (choice)";
1076 debug += "<br>";
1077 if (sym->rev_dep.expr) {
1078 stream << "reverse dep: ";
1079 expr_print(sym->rev_dep.expr, expr_print_help, &stream, E_NONE);
1080 stream << "<br>";
1081 }
1082 for (struct property *prop = sym->prop; prop; prop = prop->next) {
1083 switch (prop->type) {
1084 case P_PROMPT:
1085 case P_MENU:
1086 stream << "prompt: <a href=\"m" << sym->name << "\">";
1087 stream << print_filter(prop->text);
1088 stream << "</a><br>";
1089 break;
1090 case P_DEFAULT:
1091 case P_SELECT:
1092 case P_RANGE:
1093 case P_COMMENT:
1094 case P_IMPLY:
1095 case P_SYMBOL:
1096 stream << prop_get_type_name(prop->type);
1097 stream << ": ";
1098 expr_print(prop->expr, expr_print_help,
1099 &stream, E_NONE);
1100 stream << "<br>";
1101 break;
1102 case P_CHOICE:
1103 if (sym_is_choice(sym)) {
1104 stream << "choice: ";
1105 expr_print(prop->expr, expr_print_help,
1106 &stream, E_NONE);
1107 stream << "<br>";
1108 }
1109 break;
1110 default:
1111 stream << "unknown property: ";
1112 stream << prop_get_type_name(prop->type);
1113 stream << "<br>";
1114 }
1115 if (prop->visible.expr) {
1116 stream << " dep: ";
1117 expr_print(prop->visible.expr, expr_print_help,
1118 &stream, E_NONE);
1119 stream << "<br>";
1120 }
1121 }
1122 stream << "<br>";
1123
1124 return debug;
1125 }
1126
1127 QString ConfigInfoView::print_filter(const QString &str)
1128 {
1129 QRegExp re("[<>&\"\\n]");
1130 QString res = str;
1131 for (int i = 0; (i = res.indexOf(re, i)) >= 0;) {
1132 switch (res[i].toLatin1()) {
1133 case '<':
1134 res.replace(i, 1, "<");
1135 i += 4;
1136 break;
1137 case '>':
1138 res.replace(i, 1, ">");
1139 i += 4;
1140 break;
1141 case '&':
1142 res.replace(i, 1, "&");
1143 i += 5;
1144 break;
1145 case '"':
1146 res.replace(i, 1, """);
1147 i += 6;
1148 break;
1149 case '\n':
1150 res.replace(i, 1, "<br>");
1151 i += 4;
1152 break;
1153 }
1154 }
1155 return res;
1156 }
1157
1158 void ConfigInfoView::expr_print_help(void *data, struct symbol *sym, const char *str)
1159 {
1160 QTextStream *stream = reinterpret_cast<QTextStream *>(data);
1161
1162 if (sym && sym->name && !(sym->flags & SYMBOL_CONST)) {
1163 *stream << "<a href=\"s" << sym->name << "\">";
1164 *stream << print_filter(str);
1165 *stream << "</a>";
1166 } else {
1167 *stream << print_filter(str);
1168 }
1169 }
1170
1171 void ConfigInfoView::clicked(const QUrl &url)
1172 {
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;
1178
1179 if (count < 1) {
1180 delete[] data;
1181 return;
1182 }
1183
1184 memcpy(data, str.constData(), count);
1185 data[count] = '\0';
1186
1187
1188 data[0] = '^';
1189 strcat(data, "$");
1190 result = sym_re_search(data);
1191 if (!result) {
1192 delete[] data;
1193 return;
1194 }
1195
1196 sym = *result;
1197
1198
1199 for (struct property *prop = sym->prop; prop; prop = prop->next) {
1200 if (prop->type != P_PROMPT && prop->type != P_MENU)
1201 continue;
1202 m = prop->menu;
1203 break;
1204 }
1205
1206 if (!m) {
1207
1208 symbolInfo();
1209 emit showDebugChanged(true);
1210 } else {
1211 emit menuSelected(m);
1212 }
1213
1214 free(result);
1215 delete[] data;
1216 }
1217
1218 void ConfigInfoView::contextMenuEvent(QContextMenuEvent *event)
1219 {
1220 contextMenu->popup(event->globalPos());
1221 event->accept();
1222 }
1223
1224 ConfigSearchWindow::ConfigSearchWindow(ConfigMainWindow *parent)
1225 : Parent(parent), result(NULL)
1226 {
1227 setObjectName("search");
1228 setWindowTitle("Search Config");
1229
1230 QVBoxLayout* layout1 = new QVBoxLayout(this);
1231 layout1->setContentsMargins(11, 11, 11, 11);
1232 layout1->setSpacing(6);
1233
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);
1248
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);
1258
1259 layout1->addWidget(split);
1260
1261 QVariant x, y;
1262 int width, height;
1263 bool ok;
1264
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);
1274 if (ok)
1275 split->setSizes(sizes);
1276 configSettings->endGroup();
1277 connect(configApp, &QApplication::aboutToQuit,
1278 this, &ConfigSearchWindow::saveSettings);
1279 }
1280
1281 void ConfigSearchWindow::saveSettings(void)
1282 {
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();
1291 }
1292 }
1293
1294 void ConfigSearchWindow::search(void)
1295 {
1296 struct symbol **p;
1297 struct property *prop;
1298 ConfigItem *lastItem = NULL;
1299
1300 free(result);
1301 list->clear();
1302 info->clear();
1303
1304 result = sym_re_search(editField->text().toLatin1());
1305 if (!result)
1306 return;
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));
1311 }
1312 }
1313
1314
1315
1316
1317 ConfigMainWindow::ConfigMainWindow(void)
1318 : searchWindow(0)
1319 {
1320 bool ok = true;
1321 QVariant x, y;
1322 int width, height;
1323 char title[256];
1324
1325 QDesktopWidget *d = configApp->desktop();
1326 snprintf(title, sizeof(title), "%s%s",
1327 rootmenu.prompt->text,
1328 ""
1329 );
1330 setWindowTitle(title);
1331
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());
1339
1340
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));
1348
1349 QWidget *widget = new QWidget(this);
1350 QVBoxLayout *layout = new QVBoxLayout(widget);
1351 setCentralWidget(widget);
1352
1353 split1 = new QSplitter(widget);
1354 split1->setOrientation(Qt::Horizontal);
1355 split1->setChildrenCollapsible(false);
1356
1357 menuList = new ConfigList(widget, "menu");
1358
1359 split2 = new QSplitter(widget);
1360 split2->setChildrenCollapsible(false);
1361 split2->setOrientation(Qt::Vertical);
1362
1363
1364 configList = new ConfigList(widget, "config");
1365
1366 helpText = new ConfigInfoView(widget, "help");
1367
1368 layout->addWidget(split2);
1369 split2->addWidget(split1);
1370 split1->addWidget(configList);
1371 split1->addWidget(menuList);
1372 split2->addWidget(helpText);
1373
1374 setTabOrder(configList, helpText);
1375 configList->setFocus();
1376
1377 backAction = new QAction(QPixmap(xpm_back), "Back", this);
1378 connect(backAction, &QAction::triggered,
1379 this, &ConfigMainWindow::goBack);
1380
1381 QAction *quitAction = new QAction("&Quit", this);
1382 quitAction->setShortcut(Qt::CTRL + Qt::Key_Q);
1383 connect(quitAction, &QAction::triggered,
1384 this, &ConfigMainWindow::close);
1385
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);
1390
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);
1395
1396 conf_set_changed_callback(conf_changed);
1397
1398
1399 conf_changed();
1400 configname = xstrdup(conf_get_configname());
1401
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);
1421
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);
1427
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);
1434
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);
1441
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());
1447
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);
1454
1455
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);
1465
1466
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);
1473
1474
1475 menu = menuBar()->addMenu("&Edit");
1476 menu->addAction(searchAction);
1477
1478
1479 menu = menuBar()->addMenu("&Option");
1480 menu->addAction(showNameAction);
1481 menu->addSeparator();
1482 menu->addActions(optGroup->actions());
1483 menu->addSeparator();
1484 menu->addAction(showDebugAction);
1485
1486
1487 menu = menuBar()->addMenu("&Help");
1488 menu->addAction(showIntroAction);
1489 menu->addAction(showAboutAction);
1490
1491 connect(helpText, &ConfigInfoView::anchorClicked,
1492 helpText, &ConfigInfoView::clicked);
1493
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);
1506
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);
1515
1516 QString listMode = configSettings->value("/listMode", "symbol").toString();
1517 if (listMode == "single")
1518 showSingleView();
1519 else if (listMode == "full")
1520 showFullView();
1521 else
1522 showSplitView();
1523
1524
1525 QList<int> sizes = configSettings->readSizes("/split1", &ok);
1526 if (ok)
1527 split1->setSizes(sizes);
1528
1529 sizes = configSettings->readSizes("/split2", &ok);
1530 if (ok)
1531 split2->setSizes(sizes);
1532 }
1533
1534 void ConfigMainWindow::loadConfig(void)
1535 {
1536 QString str;
1537 QByteArray ba;
1538 const char *name;
1539
1540 str = QFileDialog::getOpenFileName(this, "", configname);
1541 if (str.isNull())
1542 return;
1543
1544 ba = str.toLocal8Bit();
1545 name = ba.data();
1546
1547 if (conf_read(name))
1548 QMessageBox::information(this, "qconf", "Unable to load configuration!");
1549
1550 free(configname);
1551 configname = xstrdup(name);
1552
1553 ConfigList::updateListAllForAll();
1554 }
1555
1556 bool ConfigMainWindow::saveConfig(void)
1557 {
1558 if (conf_write(configname)) {
1559 QMessageBox::information(this, "qconf", "Unable to save configuration!");
1560 return false;
1561 }
1562 conf_write_autoconf(0);
1563
1564 return true;
1565 }
1566
1567 void ConfigMainWindow::saveConfigAs(void)
1568 {
1569 QString str;
1570 QByteArray ba;
1571 const char *name;
1572
1573 str = QFileDialog::getSaveFileName(this, "", configname);
1574 if (str.isNull())
1575 return;
1576
1577 ba = str.toLocal8Bit();
1578 name = ba.data();
1579
1580 if (conf_write(name)) {
1581 QMessageBox::information(this, "qconf", "Unable to save configuration!");
1582 }
1583 conf_write_autoconf(0);
1584
1585 free(configname);
1586 configname = xstrdup(name);
1587 }
1588
1589 void ConfigMainWindow::searchConfig(void)
1590 {
1591 if (!searchWindow)
1592 searchWindow = new ConfigSearchWindow(this);
1593 searchWindow->show();
1594 }
1595
1596 void ConfigMainWindow::changeItens(struct menu *menu)
1597 {
1598 configList->setRootMenu(menu);
1599 }
1600
1601 void ConfigMainWindow::changeMenu(struct menu *menu)
1602 {
1603 menuList->setRootMenu(menu);
1604 }
1605
1606 void ConfigMainWindow::setMenuLink(struct menu *menu)
1607 {
1608 struct menu *parent;
1609 ConfigList* list = NULL;
1610 ConfigItem* item;
1611
1612 if (configList->menuSkip(menu))
1613 return;
1614
1615 switch (configList->mode) {
1616 case singleMode:
1617 list = configList;
1618 parent = menu_get_parent_menu(menu);
1619 if (!parent)
1620 return;
1621 list->setRootMenu(parent);
1622 break;
1623 case menuMode:
1624 if (menu->flags & MENU_ROOT) {
1625 menuList->setRootMenu(menu);
1626 configList->clearSelection();
1627 list = configList;
1628 } else {
1629 parent = menu_get_parent_menu(menu->parent);
1630 if (!parent)
1631 return;
1632
1633
1634 item = configList->findConfigItem(parent);
1635 if (item) {
1636 configList->setSelected(item, true);
1637 configList->scrollToItem(item);
1638 }
1639
1640 menuList->setRootMenu(parent);
1641 menuList->clearSelection();
1642 list = menuList;
1643 }
1644 break;
1645 case fullMode:
1646 list = configList;
1647 break;
1648 default:
1649 break;
1650 }
1651
1652 if (list) {
1653 item = list->findConfigItem(menu);
1654 if (item) {
1655 list->setSelected(item, true);
1656 list->scrollToItem(item);
1657 list->setFocus();
1658 helpText->setInfo(menu);
1659 }
1660 }
1661 }
1662
1663 void ConfigMainWindow::listFocusChanged(void)
1664 {
1665 if (menuList->mode == menuMode)
1666 configList->clearSelection();
1667 }
1668
1669 void ConfigMainWindow::goBack(void)
1670 {
1671 if (configList->rootEntry == &rootmenu)
1672 return;
1673
1674 configList->setParentMenu();
1675 }
1676
1677 void ConfigMainWindow::showSingleView(void)
1678 {
1679 singleViewAction->setEnabled(false);
1680 singleViewAction->setChecked(true);
1681 splitViewAction->setEnabled(true);
1682 splitViewAction->setChecked(false);
1683 fullViewAction->setEnabled(true);
1684 fullViewAction->setChecked(false);
1685
1686 backAction->setEnabled(true);
1687
1688 menuList->hide();
1689 menuList->setRootMenu(0);
1690 configList->mode = singleMode;
1691 if (configList->rootEntry == &rootmenu)
1692 configList->updateListAll();
1693 else
1694 configList->setRootMenu(&rootmenu);
1695 configList->setFocus();
1696 }
1697
1698 void ConfigMainWindow::showSplitView(void)
1699 {
1700 singleViewAction->setEnabled(true);
1701 singleViewAction->setChecked(false);
1702 splitViewAction->setEnabled(false);
1703 splitViewAction->setChecked(true);
1704 fullViewAction->setEnabled(true);
1705 fullViewAction->setChecked(false);
1706
1707 backAction->setEnabled(false);
1708
1709 configList->mode = menuMode;
1710 if (configList->rootEntry == &rootmenu)
1711 configList->updateListAll();
1712 else
1713 configList->setRootMenu(&rootmenu);
1714 configList->setAllOpen(true);
1715 configApp->processEvents();
1716 menuList->mode = symbolMode;
1717 menuList->setRootMenu(&rootmenu);
1718 menuList->setAllOpen(true);
1719 menuList->show();
1720 menuList->setFocus();
1721 }
1722
1723 void ConfigMainWindow::showFullView(void)
1724 {
1725 singleViewAction->setEnabled(true);
1726 singleViewAction->setChecked(false);
1727 splitViewAction->setEnabled(true);
1728 splitViewAction->setChecked(false);
1729 fullViewAction->setEnabled(false);
1730 fullViewAction->setChecked(true);
1731
1732 backAction->setEnabled(false);
1733
1734 menuList->hide();
1735 menuList->setRootMenu(0);
1736 configList->mode = fullMode;
1737 if (configList->rootEntry == &rootmenu)
1738 configList->updateListAll();
1739 else
1740 configList->setRootMenu(&rootmenu);
1741 configList->setFocus();
1742 }
1743
1744
1745
1746
1747 void ConfigMainWindow::closeEvent(QCloseEvent* e)
1748 {
1749 if (!conf_get_changed()) {
1750 e->accept();
1751 return;
1752 }
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:
1760 if (saveConfig())
1761 e->accept();
1762 else
1763 e->ignore();
1764 break;
1765 case QMessageBox::No:
1766 e->accept();
1767 break;
1768 case QMessageBox::Cancel:
1769 e->ignore();
1770 break;
1771 }
1772 }
1773
1774 void ConfigMainWindow::showIntro(void)
1775 {
1776 static const QString str =
1777 "Welcome to the qconf graphical configuration tool.\n"
1778 "\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"
1785 "\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 "
1791 "them.\n"
1792 "\n"
1793 "Toggling Show Debug Info under the Options menu will show the "
1794 "dependencies, which you can then match by examining other "
1795 "options.\n";
1796
1797 QMessageBox::information(this, "qconf", str);
1798 }
1799
1800 void ConfigMainWindow::showAbout(void)
1801 {
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"
1804 "\n"
1805 "Bug reports and feature request can also be entered at http://bugzilla.kernel.org/\n"
1806 "\n"
1807 "Qt Version: ";
1808
1809 QMessageBox::information(this, "qconf", str + qVersion());
1810 }
1811
1812 void ConfigMainWindow::saveSettings(void)
1813 {
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());
1818
1819 QString entry;
1820 switch(configList->mode) {
1821 case singleMode :
1822 entry = "single";
1823 break;
1824
1825 case symbolMode :
1826 entry = "split";
1827 break;
1828
1829 case fullMode :
1830 entry = "full";
1831 break;
1832
1833 default:
1834 break;
1835 }
1836 configSettings->setValue("/listMode", entry);
1837
1838 configSettings->writeSizes("/split1", split1->sizes());
1839 configSettings->writeSizes("/split2", split2->sizes());
1840 }
1841
1842 void ConfigMainWindow::conf_changed(void)
1843 {
1844 if (saveAction)
1845 saveAction->setEnabled(conf_get_changed());
1846 }
1847
1848 void fixup_rootmenu(struct menu *menu)
1849 {
1850 struct menu *child;
1851 static int menu_cnt = 0;
1852
1853 menu->flags |= MENU_ROOT;
1854 for (child = menu->list; child; child = child->next) {
1855 if (child->prompt && child->prompt->type == P_MENU) {
1856 menu_cnt++;
1857 fixup_rootmenu(child);
1858 menu_cnt--;
1859 } else if (!menu_cnt)
1860 fixup_rootmenu(child);
1861 }
1862 }
1863
1864 static const char *progname;
1865
1866 static void usage(void)
1867 {
1868 printf("%s [-s] <config>\n", progname);
1869 exit(0);
1870 }
1871
1872 int main(int ac, char** av)
1873 {
1874 ConfigMainWindow* v;
1875 const char *name;
1876
1877 progname = av[0];
1878 if (ac > 1 && av[1][0] == '-') {
1879 switch (av[1][1]) {
1880 case 's':
1881 conf_set_message_callback(NULL);
1882 break;
1883 case 'h':
1884 case '?':
1885 usage();
1886 }
1887 name = av[2];
1888 } else
1889 name = av[1];
1890 if (!name)
1891 usage();
1892
1893 conf_parse(name);
1894 fixup_rootmenu(&rootmenu);
1895 conf_read(NULL);
1896
1897
1898 configApp = new QApplication(ac, av);
1899
1900 configSettings = new ConfigSettings();
1901 configSettings->beginGroup("/kconfig/qconf");
1902 v = new ConfigMainWindow();
1903
1904
1905 configApp->connect(configApp, SIGNAL(lastWindowClosed()), SLOT(quit()));
1906 configApp->connect(configApp, SIGNAL(aboutToQuit()), v, SLOT(saveSettings()));
1907 v->show();
1908 configApp->exec();
1909
1910 configSettings->endGroup();
1911 delete configSettings;
1912 delete v;
1913 delete configApp;
1914
1915 return 0;
1916 }