Co-developed-by: Patrick Franz <deltaone@xxxxxxxxxx> Signed-off-by: Patrick Franz <deltaone@xxxxxxxxxx> Co-developed-by: Ibrahim Fayaz <phayax@xxxxxxxxx> Signed-off-by: Ibrahim Fayaz <phayax@xxxxxxxxx> Reviewed-by: Luis Chamberlain <mcgrof@xxxxxxxx> Tested-by: Evgeny Groshev <eugene.groshev@xxxxxxxxx> Suggested-by: Sarah Nadi <nadi@xxxxxxxxxxx> Suggested-by: Thorsten Berger <thorsten.berger@xxxxxx> Signed-off-by: Thorsten Berger <thorsten.berger@xxxxxx> The tool can be called from any configurator. We chose to modify xconfig for this purpose. These files contain the necessary modifications to xconfig in order to resolve conflicts. --- scripts/kconfig/qconf.cc | 1003 +++++++++++++++++++++++++++++--------- scripts/kconfig/qconf.h | 179 ++++++- 2 files changed, 929 insertions(+), 253 deletions(-) diff --git a/scripts/kconfig/qconf.cc b/scripts/kconfig/qconf.cc index 78087b2d9ac6..a86cd09a1096 100644 --- a/scripts/kconfig/qconf.cc +++ b/scripts/kconfig/qconf.cc @@ -17,6 +17,10 @@ #include <QMenuBar> #include <QMessageBox> #include <QToolBar> +#include <QListWidget> +#include <QComboBox> +#include <QTableWidget> +#include <QHBoxLayout> #include <stdlib.h> @@ -24,7 +28,14 @@ #include "qconf.h" #include "images.h" +#include <iostream> +#include <QAbstractItemView> +#include <QMimeData> +#include <QBrush> +#include <QColor> +#include <future> +#include <memory> static QApplication *configApp; static ConfigSettings *configSettings; @@ -82,6 +93,14 @@ QIcon ConfigItem::choiceNoIcon; QIcon ConfigItem::menuIcon; QIcon ConfigItem::menubackIcon; +/* + * set the new data + * TODO check the value + */ +void ConfigItem::okRename(int col) +{ +} + /* * update the displayed of a menu entry */ @@ -122,7 +141,6 @@ void ConfigItem::updateMenu(void) goto set_prompt; case P_COMMENT: setIcon(promptColIdx, QIcon()); - prompt = "*** " + prompt + " ***"; goto set_prompt; default: ; @@ -140,6 +158,9 @@ void ConfigItem::updateMenu(void) if (!sym_is_changeable(sym) && list->optMode == normalOpt) { setIcon(promptColIdx, QIcon()); + setText(noColIdx, QString()); + setText(modColIdx, QString()); + setText(yesColIdx, QString()); break; } expr = sym_get_tristate_value(sym); @@ -149,10 +170,12 @@ void ConfigItem::updateMenu(void) setIcon(promptColIdx, choiceYesIcon); else setIcon(promptColIdx, symbolYesIcon); + setText(yesColIdx, "Y"); ch = 'Y'; break; case mod: setIcon(promptColIdx, symbolModIcon); + setText(modColIdx, "M"); ch = 'M'; break; default: @@ -160,16 +183,31 @@ void ConfigItem::updateMenu(void) setIcon(promptColIdx, choiceNoIcon); else setIcon(promptColIdx, symbolNoIcon); + setText(noColIdx, "N"); ch = 'N'; break; } + if (expr != no) + setText(noColIdx, sym_tristate_within_range(sym, no) ? "_" : 0); + if (expr != mod) + setText(modColIdx, sym_tristate_within_range(sym, mod) ? "_" : 0); + if (expr != yes) + setText(yesColIdx, sym_tristate_within_range(sym, yes) ? "_" : 0); setText(dataColIdx, QChar(ch)); break; case S_INT: case S_HEX: case S_STRING: - setText(dataColIdx, sym_get_string_value(sym)); + const char* data; + + data = sym_get_string_value(sym); + + setText(dataColIdx, data); + if (type == S_STRING) + prompt = QString("%1: %2").arg(prompt).arg(data); + else + prompt = QString("(%2) %1").arg(prompt).arg(data); break; } if (!sym_has_value(sym) && visible) @@ -210,17 +248,6 @@ void ConfigItem::init(void) 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(); } @@ -241,65 +268,46 @@ ConfigItem::~ConfigItem(void) } } -QWidget *ConfigItemDelegate::createEditor(QWidget *parent, - const QStyleOptionViewItem &option, - const QModelIndex &index) const +ConfigLineEdit::ConfigLineEdit(ConfigView* parent) + : Parent(parent) { - 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); + connect(this, SIGNAL(editingFinished()), SLOT(hide())); } -void ConfigItemDelegate::setModelData(QWidget *editor, - QAbstractItemModel *model, - const QModelIndex &index) const +void ConfigLineEdit::show(ConfigItem* i) { - 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; + item = i; + if (sym_get_string_value(item->menu->sym)) + setText(sym_get_string_value(item->menu->sym)); + else + setText(QString()); + Parent::show(); + setFocus(); +} - 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)); +void ConfigLineEdit::keyPressEvent(QKeyEvent* e) +{ + switch (e->key()) { + case Qt::Key_Escape: + break; + case Qt::Key_Return: + case Qt::Key_Enter: + sym_set_string_value(item->menu->sym, text().toLatin1()); + parent()->updateList(); + break; + default: + Parent::keyPressEvent(e); + return; } - -parent: - QStyledItemDelegate::setModelData(editor, model, index); + e->accept(); + parent()->list->setFocus(); + hide(); } -ConfigList::ConfigList(QWidget *parent, const char *name) - : QTreeWidget(parent), +ConfigList::ConfigList(ConfigView* p, const char *name) + : Parent(p), updateAll(false), - showName(false), mode(singleMode), optMode(normalOpt), + showName(false), showRange(false), showData(false), mode(singleMode), optMode(normalOpt), rootEntry(0), headerPopup(0) { setObjectName(name); @@ -309,34 +317,26 @@ ConfigList::ConfigList(QWidget *parent, const char *name) setVerticalScrollMode(ScrollPerPixel); setHorizontalScrollMode(ScrollPerPixel); - setHeaderLabels(QStringList() << "Option" << "Name" << "Value"); + setHeaderLabels(QStringList() << "Option" << "Name" << "N" << "M" << "Y" << "Value"); - connect(this, &ConfigList::itemSelectionChanged, - this, &ConfigList::updateSelection); + connect(this, SIGNAL(itemSelectionChanged(void)), + SLOT(updateSelection(void))); if (name) { configSettings->beginGroup(name); showName = configSettings->value("/showName", false).toBool(); + showRange = configSettings->value("/showRange", false).toBool(); + showData = configSettings->value("/showData", false).toBool(); optMode = (enum optionMode)configSettings->value("/optionMode", 0).toInt(); configSettings->endGroup(); - connect(configApp, &QApplication::aboutToQuit, - this, &ConfigList::saveSettings); + connect(configApp, SIGNAL(aboutToQuit()), SLOT(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)) @@ -350,10 +350,21 @@ bool ConfigList::menuSkip(struct menu *menu) void ConfigList::reinit(void) { + hideColumn(dataColIdx); + hideColumn(yesColIdx); + hideColumn(modColIdx); + hideColumn(noColIdx); hideColumn(nameColIdx); if (showName) showColumn(nameColIdx); + if (showRange) { + showColumn(noColIdx); + showColumn(modColIdx); + showColumn(yesColIdx); + } + if (showData) + showColumn(dataColIdx); updateListAll(); } @@ -375,6 +386,8 @@ void ConfigList::saveSettings(void) if (!objectName().isEmpty()) { configSettings->beginGroup(objectName()); configSettings->setValue("/showName", showName); + configSettings->setValue("/showRange", showRange); + configSettings->setValue("/showData", showData); configSettings->setValue("/optionMode", (int)optMode); configSettings->endGroup(); } @@ -400,6 +413,7 @@ void ConfigList::updateSelection(void) if (selectedItems().count() == 0) return; + emit selectedChanged(selectedItems()); ConfigItem* item = (ConfigItem*)selectedItems().first(); if (!item) return; @@ -460,28 +474,6 @@ 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->updateList(); - } -} - void ConfigList::setValue(ConfigItem* item, tristate val) { struct symbol* sym; @@ -502,7 +494,7 @@ void ConfigList::setValue(ConfigItem* item, tristate val) return; if (oldval == no && item->menu->list) item->setExpanded(true); - ConfigList::updateListForAll(); + parent()->updateList(); break; } } @@ -536,9 +528,13 @@ void ConfigList::changeValue(ConfigItem* item) item->setExpanded(true); } if (oldexpr != newexpr) - ConfigList::updateListForAll(); + parent()->updateList(); + emit UpdateConflictsViewColorization(); break; - default: + case S_INT: + case S_HEX: + case S_STRING: + parent()->lineEdit->show(item); break; } } @@ -821,6 +817,15 @@ void ConfigList::mouseReleaseEvent(QMouseEvent* e) } } break; + case noColIdx: + setValue(item, no); + break; + case modColIdx: + setValue(item, mod); + break; + case yesColIdx: + setValue(item, yes); + break; case dataColIdx: changeValue(item); break; @@ -890,32 +895,107 @@ void ConfigList::contextMenuEvent(QContextMenuEvent *e) 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); + connect(action, SIGNAL(toggled(bool)), + parent(), SLOT(setShowName(bool))); + connect(parent(), SIGNAL(showNameChanged(bool)), + action, SLOT(setChecked(bool))); action->setChecked(showName); headerPopup->addAction(action); + + action = new QAction("Show Range", this); + action->setCheckable(true); + connect(action, SIGNAL(toggled(bool)), + parent(), SLOT(setShowRange(bool))); + connect(parent(), SIGNAL(showRangeChanged(bool)), + action, SLOT(setChecked(bool))); + action->setChecked(showRange); + headerPopup->addAction(action); + + action = new QAction("Show Data", this); + action->setCheckable(true); + connect(action, SIGNAL(toggled(bool)), + parent(), SLOT(setShowData(bool))); + connect(parent(), SIGNAL(showDataChanged(bool)), + action, SLOT(setChecked(bool))); + action->setChecked(showData); + headerPopup->addAction(action); } headerPopup->exec(e->globalPos()); e->accept(); } -void ConfigList::setShowName(bool on) +ConfigView*ConfigView::viewList; +QAction *ConfigList::showNormalAction; +QAction *ConfigList::showAllAction; +QAction *ConfigList::showPromptAction; +QAction *ConfigList::addSymbolsFromContextMenu; + +ConfigView::ConfigView(QWidget* parent, const char *name) + : Parent(parent) { - if (showName == on) - return; + setObjectName(name); + QVBoxLayout *verticalLayout = new QVBoxLayout(this); + verticalLayout->setContentsMargins(0, 0, 0, 0); - showName = on; - reinit(); - emit showNameChanged(on); + list = new ConfigList(this); + list->setSelectionMode(QAbstractItemView::ExtendedSelection); + list->setContextMenuPolicy(Qt::CustomContextMenu); + connect(list, SIGNAL(customContextMenuRequested(const QPoint &)), + this, SLOT(ShowContextMenu(const QPoint &))); + verticalLayout->addWidget(list); + lineEdit = new ConfigLineEdit(this); + lineEdit->hide(); + verticalLayout->addWidget(lineEdit); + + this->nextView = viewList; + viewList = this; } +void ConfigView::ShowContextMenu(const QPoint& pos){ + QMenu contextMenu(tr("Context menu"), this); -QList<ConfigList *> ConfigList::allLists; -QAction *ConfigList::showNormalAction; -QAction *ConfigList::showAllAction; -QAction *ConfigList::showPromptAction; + contextMenu.addAction(ConfigList::addSymbolsFromContextMenu); + contextMenu.exec(mapToGlobal(pos)); +} + +ConfigView::~ConfigView(void) +{ + ConfigView** vp; + + for (vp = &viewList; *vp; vp = &(*vp)->nextView) { + if (*vp == this) { + *vp = nextView; + break; + } + } +} + +void ConfigView::setShowName(bool b) +{ + if (list->showName != b) { + list->showName = b; + list->reinit(); + emit showNameChanged(b); + } +} + +void ConfigView::setShowRange(bool b) +{ + if (list->showRange != b) { + list->showRange = b; + list->reinit(); + emit showRangeChanged(b); + } +} + +void ConfigView::setShowData(bool b) +{ + if (list->showData != b) { + list->showData = b; + list->reinit(); + emit showDataChanged(b); + } +} void ConfigList::setAllOpen(bool open) { @@ -928,6 +1008,415 @@ void ConfigList::setAllOpen(bool open) } } +void ConfigView::updateList() +{ + ConfigView* v; + + for (v = viewList; v; v = v->nextView) + v->list->updateList(); +} + +void ConfigView::updateListAll(void) +{ + ConfigView* v; + + for (v = viewList; v; v = v->nextView) + v->list->updateListAll(); +} + +ConflictsView::ConflictsView(QWidget* parent, const char *name) + : Parent(parent) +{ + currentSelectedMenu = nullptr; + setObjectName(name); + QHBoxLayout *horizontalLayout = new QHBoxLayout(this); + QVBoxLayout *verticalLayout = new QVBoxLayout(); + verticalLayout->setContentsMargins(0, 0, 0, 0); + conflictsToolBar = new QToolBar("ConflictTools", this); + + // toolbar buttons [n] [m] [y] [calculate fixes] [remove] + QAction *addSymbol = new QAction("Add Symbol"); + QAction *setConfigSymbolAsNo = new QAction("N"); + QAction *setConfigSymbolAsModule = new QAction("M"); + QAction *setConfigSymbolAsYes = new QAction("Y"); + fixConflictsAction_ = new QAction("Calculate Fixes"); + QAction *removeSymbol = new QAction("Remove Symbol"); + + // If you change the order of buttons here, change the code where + // module button was disabled if symbol is boolean, selecting module + // button depends on a specific index in list of action + fixConflictsAction_->setCheckable(false); + conflictsToolBar->addAction(addSymbol); + conflictsToolBar->addAction(setConfigSymbolAsNo); + conflictsToolBar->addAction(setConfigSymbolAsModule); + conflictsToolBar->addAction(setConfigSymbolAsYes); + conflictsToolBar->addAction(fixConflictsAction_); + conflictsToolBar->addAction(removeSymbol); + + verticalLayout->addWidget(conflictsToolBar); + + connect(addSymbol, SIGNAL(triggered(bool)), SLOT(addSymbol())); + connect(setConfigSymbolAsNo, SIGNAL(triggered(bool)), SLOT(changeToNo())); + connect(setConfigSymbolAsModule, SIGNAL(triggered(bool)), SLOT(changeToModule())); + connect(setConfigSymbolAsYes, SIGNAL(triggered(bool)), SLOT(changeToYes())); + connect(removeSymbol, SIGNAL(triggered(bool)), SLOT(removeSymbol())); + connect(this, SIGNAL(resultsReady()), SLOT(updateResults())); + // connect clicking 'calculate fixes' to 'change all symbol values to fix all conflicts' + // no longer used anymore for now. + connect(fixConflictsAction_, SIGNAL(triggered(bool)), SLOT(calculateFixes())); + + conflictsTable = (QTableWidget*) new droppableView(this); + conflictsTable->setRowCount(0); + conflictsTable->setColumnCount(3); + conflictsTable->setSelectionBehavior(QAbstractItemView::SelectRows); + + conflictsTable->setHorizontalHeaderLabels(QStringList() << "Option" << "Wanted value" << "Current value" ); + verticalLayout->addWidget(conflictsTable); + + conflictsTable->setDragDropMode(QAbstractItemView::DropOnly); + setAcceptDrops(true); + + connect(conflictsTable, SIGNAL(cellClicked(int, int)), SLOT(cellClicked(int,int))); + horizontalLayout->addLayout(verticalLayout); + + // populate the solution view on the right hand side: + QVBoxLayout *solutionLayout = new QVBoxLayout(); + solutionLayout->setContentsMargins(0, 0, 0, 0); + solutionSelector = new QComboBox(); + connect(solutionSelector, QOverload<int>::of(&QComboBox::currentIndexChanged), + [=](int index){ changeSolutionTable(index); }); + solutionTable = new QTableWidget(); + solutionTable->setRowCount(0); + solutionTable->setColumnCount(2); + solutionTable->setHorizontalHeaderLabels(QStringList() << "Symbol" << "New Value" ); + + applyFixButton = new QPushButton("Apply Selected solution"); + connect(applyFixButton, SIGNAL(clicked(bool)), SLOT(applyFixButtonClick())); + + numSolutionLabel = new QLabel("Solutions:"); + solutionLayout->addWidget(numSolutionLabel); + solutionLayout->addWidget(solutionSelector); + solutionLayout->addWidget(solutionTable); + solutionLayout->addWidget(applyFixButton); + + horizontalLayout->addLayout(solutionLayout); + +} +void QTableWidget::dropEvent(QDropEvent *event) +{ +} + +void ConflictsView::changeToNo() +{ + QItemSelectionModel *select = conflictsTable->selectionModel(); + + if (select->hasSelection()) { + QModelIndexList rows = select->selectedRows(); + + for (int i = 0;i < rows.count(); i++) { + conflictsTable->item(rows[i].row(),1)->setText("NO"); + } + } +} + +void ConflictsView::applyFixButtonClick() +{ + signed int solution_number = solutionSelector->currentIndex(); + + if (solution_number == -1 || solution_output == NULL) { + return; + } + + struct sfix_list * selected_solution = select_solution(solution_output, solution_number); + + apply_fix(selected_solution); + ConfigView::updateListAll(); +} + +void ConflictsView::changeToYes() +{ + QItemSelectionModel *select = conflictsTable->selectionModel(); + + if (select->hasSelection()) { + QModelIndexList rows = select->selectedRows(); + + for (int i = 0;i < rows.count(); i++) { + conflictsTable->item(rows[i].row(),1)->setText("YES"); + } + } + +} +void ConflictsView::changeToModule() +{ + QItemSelectionModel *select = conflictsTable->selectionModel(); + + if (select->hasSelection()) { + QModelIndexList rows = select->selectedRows(); + + for (int i = 0;i < rows.count(); i++) { + conflictsTable->item(rows[i].row(),1)->setText("MODULE"); + } + } + +} + +void ConflictsView::menuChanged1(struct menu *m) +{ + currentSelectedMenu = m; +} + +void ConflictsView::addSymbol() +{ + addSymbol(currentSelectedMenu); +} + +void ConflictsView::selectedChanged(QList<QTreeWidgetItem *> selection) +{ + currentSelection = selection; + +} + +void ConflictsView::addSymbol(struct menu *m) +{ + if (m != nullptr) { + if (m->sym != nullptr) { + struct symbol *sym = m->sym; + tristate currentval = sym_get_tristate_value(sym); + // if symbol is not added yet: + QAbstractItemModel* tableModel = conflictsTable->model(); + QModelIndexList matches = tableModel->match(tableModel->index(0,0), Qt::DisplayRole, sym->name ); + + if (matches.isEmpty()) { + conflictsTable->insertRow(conflictsTable->rowCount()); + conflictsTable->setItem(conflictsTable->rowCount()-1,0,new QTableWidgetItem(sym->name)); + conflictsTable->setItem(conflictsTable->rowCount()-1,1,new QTableWidgetItem(tristate_value_to_string(currentval))); + conflictsTable->setItem(conflictsTable->rowCount()-1,2,new QTableWidgetItem(tristate_value_to_string(currentval))); + } else { + conflictsTable->item(matches[0].row(),2)->setText(tristate_value_to_string(currentval)); + } + } + } +} + +void ConflictsView::addSymbolFromContextMenu() +{ + struct menu *menu; + + if (currentSelection.count() == 0) + return; + + for (auto el: currentSelection) { + ConfigItem* item = (ConfigItem*)el; + + if (!item) { + continue; + } + + menu = item->menu; + addSymbol(menu); + } +} + +void ConflictsView::removeSymbol() +{ + QItemSelectionModel *select = conflictsTable->selectionModel(); + QAbstractItemModel *itemModel = select->model(); + + if (select->hasSelection()) { + QModelIndexList rows = select->selectedRows(); + itemModel->removeRows(rows[0].row(),rows.size()); + } +} + +void ConflictsView::cellClicked(int row, int column) +{ + auto itemText = conflictsTable->item(row,0)->text().toUtf8().data(); + + + struct symbol* sym = sym_find(itemText); + if (sym == NULL) { + return; + } + struct property* prop = sym->prop; + struct menu* men = prop->menu; + // uncommenting following like somehow disables click signal of 'apply selected solution' + if (sym->type == symbol_type::S_BOOLEAN) { + conflictsToolBar->actions()[2]->setDisabled(true); + } else { + conflictsToolBar->actions()[2]->setDisabled(false); + } + emit(conflictSelected(men)); +} + +void ConflictsView::changeSolutionTable(int solution_number) +{ + if(solution_output == nullptr || solution_number < 0) { + return; + } + + struct sfix_list* selected_solution = select_solution(solution_output, solution_number); + current_solution_number = solution_number; + solutionTable->setRowCount(0); + + for (unsigned int i = 0; i <selected_solution->size; i++) { + solutionTable->insertRow(solutionTable->rowCount()); + + struct symbol_fix* cur_symbol = select_symbol(selected_solution,i); + QTableWidgetItem* symbol_name = new QTableWidgetItem(cur_symbol->sym->name); + + solutionTable->setItem(solutionTable->rowCount()-1,0,symbol_name); + + if (cur_symbol->type == symbolfix_type::SF_BOOLEAN) { + QTableWidgetItem* symbol_value = + new QTableWidgetItem( + tristate_value_to_string(cur_symbol->tri)); + solutionTable->setItem( + solutionTable->rowCount() - 1, + 1, + symbol_value); + } else if (cur_symbol->type == symbolfix_type::SF_NONBOOLEAN) { + QTableWidgetItem* symbol_value = + new QTableWidgetItem(cur_symbol->nb_val.s); + solutionTable->setItem( + solutionTable->rowCount() - 1, + 1, + symbol_value); + } else { + QTableWidgetItem* symbol_value = + new QTableWidgetItem(cur_symbol->disallowed.s); + solutionTable->setItem( + solutionTable->rowCount() - 1, + 1, + symbol_value); + } + } + UpdateConflictsViewColorization(); +} + +void ConflictsView::UpdateConflictsViewColorization(void) +{ + auto green = QColor(0, 170, 0); + auto red = QColor(255, 0, 0); + auto grey = QColor(180, 180, 180); + + if (solutionTable->rowCount() == 0 || current_solution_number < 0) + return; + + for (int i = 0; i < solutionTable->rowCount(); i++) { + QTableWidgetItem *symbol = solutionTable->item(i, 0); + struct sfix_list * selected_solution = + select_solution(solution_output, current_solution_number); + struct symbol_fix* cur_symbol = select_symbol(selected_solution,i); + + // Red: symbol is editable but value is not from solution + // Green: symbol is editable and value is from solution + // Grey: symbol is not editable and value is not target value + // Green: symbol is not editable and value is target value + auto editable = sym_string_within_range(cur_symbol->sym, + tristate_value_to_string(cur_symbol->tri).toStdString().c_str()); + auto _symbol = solutionTable->item(i,0)->text().toUtf8().data(); + struct symbol* sym_ = sym_find(_symbol); + + tristate current_value_of_symbol = sym_get_tristate_value(sym_); + tristate target_value_of_symbol = string_value_to_tristate(solutionTable->item(i,1)->text()); + bool symbol_value_same_as_target = current_value_of_symbol == target_value_of_symbol; + + if (editable && !symbol_value_same_as_target) { + symbol->setForeground(red); + } else if (editable && symbol_value_same_as_target) { + symbol->setForeground(green); + } else if (!editable && !symbol_value_same_as_target) { + symbol->setForeground(grey); + } else if (!editable && symbol_value_same_as_target) { + symbol->setForeground(green); + } + } +} + +void ConflictsView::runSatConfAsync() +{ + // loop through the rows in conflicts table adding each row into the array: + struct symbol_dvalue* p = nullptr; + + p = static_cast<struct symbol_dvalue*>(calloc(conflictsTable->rowCount(),sizeof(struct symbol_dvalue))); + + if (!p) + return; + + struct sdv_list *wanted_symbols = sdv_list_init(); + + for (int i = 0; i < conflictsTable->rowCount(); i++) { + + struct symbol_dvalue *tmp = (p+i); + auto _symbol = conflictsTable->item(i,0)->text().toUtf8().data(); + struct symbol* sym = sym_find(_symbol); + + tmp->sym = sym; + tmp->type = static_cast<symboldv_type>(sym->type == symbol_type::S_BOOLEAN?0:1); + tmp->tri = string_value_to_tristate(conflictsTable->item(i,1)->text()); + sdv_list_add(wanted_symbols,tmp); + } + + fixConflictsAction_->setText("Cancel"); + struct sfl_list *ret = run_satconf(wanted_symbols); + solution_output = ret; + + free(p); + + emit resultsReady(); + { + std::lock_guard<std::mutex> lk{satconf_mutex}; + satconf_cancelled = true; + } + + satconf_cancellation_cv.notify_one(); +} + +void ConflictsView::updateResults(void) +{ + fixConflictsAction_->setText("Calculate Fixes"); + + if (!(solution_output == nullptr || solution_output->size == 0)) { + solutionSelector->clear(); + + for (unsigned int i = 0; i < solution_output->size; i++) { + solutionSelector->addItem(QString::number(i+1)); + } + + numSolutionLabel->setText(QString("Solutions: (%1) found").arg(solution_output->size)); + changeSolutionTable(0); + } + + if (runSatConfAsyncThread->joinable()) { + runSatConfAsyncThread->join(); + delete runSatConfAsyncThread; + runSatConfAsyncThread = nullptr; + } +} + +void ConflictsView::calculateFixes(void) +{ + if (conflictsTable->rowCount() == 0) + return; + + if (runSatConfAsyncThread == nullptr) { + std::unique_lock<std::mutex> lk{satconf_mutex}; + + numSolutionLabel->setText(QString("Solutions: ")); + solutionSelector->clear(); + solutionTable->setRowCount(0); + satconf_cancelled = false; + runSatConfAsyncThread = new std::thread(&ConflictsView::runSatConfAsync,this); + } else { + interrupt_rangefix(); + std::unique_lock<std::mutex> lk{satconf_mutex}; + satconf_cancellation_cv.wait(lk,[this] { + return satconf_cancelled == true; + }); + } + +} + ConfigInfoView::ConfigInfoView(QWidget* parent, const char *name) : Parent(parent), sym(0), _menu(0) { @@ -938,18 +1427,15 @@ ConfigInfoView::ConfigInfoView(QWidget* parent, const char *name) configSettings->beginGroup(objectName()); setShowDebug(configSettings->value("/showDebug", false).toBool()); configSettings->endGroup(); - connect(configApp, &QApplication::aboutToQuit, - this, &ConfigInfoView::saveSettings); + connect(configApp, SIGNAL(aboutToQuit()), SLOT(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); + connect(action, SIGNAL(toggled(bool)), SLOT(setShowDebug(bool))); + connect(this, SIGNAL(showDebugChanged(bool)), action, SLOT(setChecked(bool))); action->setChecked(showDebug()); contextMenu->addSeparator(); contextMenu->addAction(action); @@ -1236,26 +1722,27 @@ ConfigSearchWindow::ConfigSearchWindow(ConfigMainWindow *parent) layout2->setSpacing(6); layout2->addWidget(new QLabel("Find:", this)); editField = new QLineEdit(this); - connect(editField, &QLineEdit::returnPressed, - this, &ConfigSearchWindow::search); + connect(editField, SIGNAL(returnPressed()), SLOT(search())); layout2->addWidget(editField); searchButton = new QPushButton("Search", this); searchButton->setAutoDefault(false); - connect(searchButton, &QPushButton::clicked, - this, &ConfigSearchWindow::search); + connect(searchButton, SIGNAL(clicked()), SLOT(search())); layout2->addWidget(searchButton); layout1->addLayout(layout2); split = new QSplitter(this); split->setOrientation(Qt::Vertical); - list = new ConfigList(split, "search"); - list->mode = listMode; + list = new ConfigView(split, "search"); + list->list->mode = listMode; info = new ConfigInfoView(split, "search"); - connect(list, &ConfigList::menuChanged, - info, &ConfigInfoView::setInfo); - connect(list, &ConfigList::menuChanged, - parent, &ConfigMainWindow::setMenuLink); - + connect(list->list, SIGNAL(menuChanged(struct menu *)), + info, SLOT(setInfo(struct menu *))); + connect(list->list, SIGNAL(menuChanged(struct menu *)), + parent, SLOT(setMenuLink(struct menu *))); + connect(list->list, SIGNAL(menuChanged(struct menu *)), + parent, SLOT(conflictSelected(struct menu *))); + + connect(list->list,SIGNAL(UpdateConflictsViewColorization()),SLOT(UpdateConflictsViewColorizationFowarder())); layout1->addWidget(split); QVariant x, y; @@ -1274,10 +1761,12 @@ ConfigSearchWindow::ConfigSearchWindow(ConfigMainWindow *parent) if (ok) split->setSizes(sizes); configSettings->endGroup(); - connect(configApp, &QApplication::aboutToQuit, - this, &ConfigSearchWindow::saveSettings); + connect(configApp, SIGNAL(aboutToQuit()), SLOT(saveSettings())); } +void ConfigSearchWindow::UpdateConflictsViewColorizationFowarder(void){ + emit UpdateConflictsViewColorization(); +} void ConfigSearchWindow::saveSettings(void) { if (!objectName().isEmpty()) { @@ -1298,7 +1787,7 @@ void ConfigSearchWindow::search(void) ConfigItem *lastItem = NULL; free(result); - list->clear(); + list->list->clear(); info->clear(); result = sym_re_search(editField->text().toLatin1()); @@ -1306,7 +1795,7 @@ void ConfigSearchWindow::search(void) return; for (p = result; *p; p++) { for_all_prompts((*p), prop) - lastItem = new ConfigItem(list, lastItem, prop->menu, + lastItem = new ConfigItem(list->list, lastItem, prop->menu, menu_is_visible(prop->menu)); } } @@ -1354,44 +1843,59 @@ ConfigMainWindow::ConfigMainWindow(void) split1->setOrientation(Qt::Horizontal); split1->setChildrenCollapsible(false); - menuList = new ConfigList(widget, "menu"); + menuView = new ConfigView(widget, "menu"); + menuList = menuView->list; split2 = new QSplitter(widget); split2->setChildrenCollapsible(false); split2->setOrientation(Qt::Vertical); // create config tree - configList = new ConfigList(widget, "config"); + configView = new ConfigView(widget, "config"); + configList = configView->list; helpText = new ConfigInfoView(widget, "help"); layout->addWidget(split2); split2->addWidget(split1); - split1->addWidget(configList); - split1->addWidget(menuList); + split1->addWidget(configView); + split1->addWidget(menuView); split2->addWidget(helpText); + split3 = new QSplitter(split2); + split3->setOrientation(Qt::Vertical); + conflictsView = new ConflictsView(split3, "help"); + /* conflictsSelected signal in conflictsview triggers when a conflict is selected + in the view. this line connects that event to conflictselected event in mainwindow + which updates the selection to match (in the configlist) the symbol that was selected. + */ + connect(conflictsView,SIGNAL(conflictSelected(struct menu *)),SLOT(conflictSelected(struct menu *))); + connect(conflictsView,SIGNAL(refreshMenu()),SLOT(refreshMenu())); + connect(menuList,SIGNAL(UpdateConflictsViewColorization()),conflictsView,SLOT(UpdateConflictsViewColorization())); + connect(configList,SIGNAL(UpdateConflictsViewColorization()),conflictsView,SLOT(UpdateConflictsViewColorization())); setTabOrder(configList, helpText); + configList->setFocus(); + // menu = menuBar(); + toolBar = new QToolBar("Tools", this); + addToolBar(toolBar); + + backAction = new QAction(QPixmap(xpm_back), "Back", this); - connect(backAction, &QAction::triggered, - this, &ConfigMainWindow::goBack); + connect(backAction, SIGNAL(triggered(bool)), SLOT(goBack())); QAction *quitAction = new QAction("&Quit", this); quitAction->setShortcut(Qt::CTRL + Qt::Key_Q); - connect(quitAction, &QAction::triggered, - this, &ConfigMainWindow::close); + connect(quitAction, SIGNAL(triggered(bool)), SLOT(close())); QAction *loadAction = new QAction(QPixmap(xpm_load), "&Load", this); loadAction->setShortcut(Qt::CTRL + Qt::Key_L); - connect(loadAction, &QAction::triggered, - this, &ConfigMainWindow::loadConfig); + connect(loadAction, SIGNAL(triggered(bool)), SLOT(loadConfig())); saveAction = new QAction(QPixmap(xpm_save), "&Save", this); saveAction->setShortcut(Qt::CTRL + Qt::Key_S); - connect(saveAction, &QAction::triggered, - this, &ConfigMainWindow::saveConfig); + connect(saveAction, SIGNAL(triggered(bool)), SLOT(saveConfig())); conf_set_changed_callback(conf_changed); @@ -1400,37 +1904,39 @@ ConfigMainWindow::ConfigMainWindow(void) configname = xstrdup(conf_get_configname()); QAction *saveAsAction = new QAction("Save &As...", this); - connect(saveAsAction, &QAction::triggered, - this, &ConfigMainWindow::saveConfigAs); + connect(saveAsAction, SIGNAL(triggered(bool)), SLOT(saveConfigAs())); QAction *searchAction = new QAction("&Find", this); searchAction->setShortcut(Qt::CTRL + Qt::Key_F); - connect(searchAction, &QAction::triggered, - this, &ConfigMainWindow::searchConfig); + connect(searchAction, SIGNAL(triggered(bool)), SLOT(searchConfig())); singleViewAction = new QAction(QPixmap(xpm_single_view), "Single View", this); singleViewAction->setCheckable(true); - connect(singleViewAction, &QAction::triggered, - this, &ConfigMainWindow::showSingleView); + connect(singleViewAction, SIGNAL(triggered(bool)), SLOT(showSingleView())); splitViewAction = new QAction(QPixmap(xpm_split_view), "Split View", this); splitViewAction->setCheckable(true); - connect(splitViewAction, &QAction::triggered, - this, &ConfigMainWindow::showSplitView); + connect(splitViewAction, SIGNAL(triggered(bool)), SLOT(showSplitView())); fullViewAction = new QAction(QPixmap(xpm_tree_view), "Full View", this); fullViewAction->setCheckable(true); - connect(fullViewAction, &QAction::triggered, - this, &ConfigMainWindow::showFullView); + connect(fullViewAction, SIGNAL(triggered(bool)), SLOT(showFullView())); + + QAction *showNameAction = new QAction("Show Name", this); showNameAction->setCheckable(true); - connect(showNameAction, &QAction::toggled, - configList, &ConfigList::setShowName); - showNameAction->setChecked(configList->showName); + connect(showNameAction, SIGNAL(toggled(bool)), configView, SLOT(setShowName(bool))); + showNameAction->setChecked(configView->showName()); + QAction *showRangeAction = new QAction("Show Range", this); + showRangeAction->setCheckable(true); + connect(showRangeAction, SIGNAL(toggled(bool)), configView, SLOT(setShowRange(bool))); + QAction *showDataAction = new QAction("Show Data", this); + showDataAction->setCheckable(true); + connect(showDataAction, SIGNAL(toggled(bool)), configView, SLOT(setShowData(bool))); QActionGroup *optGroup = new QActionGroup(this); optGroup->setExclusive(true); - connect(optGroup, &QActionGroup::triggered, - configList, &ConfigList::setOptionMode); - connect(optGroup, &QActionGroup::triggered, - menuList, &ConfigList::setOptionMode); + connect(optGroup, SIGNAL(triggered(QAction*)), configList, + SLOT(setOptionMode(QAction *))); + connect(optGroup, SIGNAL(triggered(QAction *)), menuList, + SLOT(setOptionMode(QAction *))); ConfigList::showNormalAction = new QAction("Show Normal Options", optGroup); ConfigList::showNormalAction->setCheckable(true); @@ -1438,19 +1944,18 @@ ConfigMainWindow::ConfigMainWindow(void) ConfigList::showAllAction->setCheckable(true); ConfigList::showPromptAction = new QAction("Show Prompt Options", optGroup); ConfigList::showPromptAction->setCheckable(true); + ConfigList::addSymbolsFromContextMenu = new QAction("Add symbol from context menu"); + connect(ConfigList::addSymbolsFromContextMenu, SIGNAL(triggered()),conflictsView, SLOT(addSymbolFromContextMenu())); QAction *showDebugAction = new QAction("Show Debug Info", this); showDebugAction->setCheckable(true); - connect(showDebugAction, &QAction::toggled, - helpText, &ConfigInfoView::setShowDebug); + connect(showDebugAction, SIGNAL(toggled(bool)), helpText, SLOT(setShowDebug(bool))); showDebugAction->setChecked(helpText->showDebug()); QAction *showIntroAction = new QAction("Introduction", this); - connect(showIntroAction, &QAction::triggered, - this, &ConfigMainWindow::showIntro); + connect(showIntroAction, SIGNAL(triggered(bool)), SLOT(showIntro())); QAction *showAboutAction = new QAction("About", this); - connect(showAboutAction, &QAction::triggered, - this, &ConfigMainWindow::showAbout); + connect(showAboutAction, SIGNAL(triggered(bool)), SLOT(showAbout())); // init tool bar QToolBar *toolBar = addToolBar("Tools"); @@ -1462,6 +1967,7 @@ ConfigMainWindow::ConfigMainWindow(void) toolBar->addAction(singleViewAction); toolBar->addAction(splitViewAction); toolBar->addAction(fullViewAction); + toolBar->addSeparator(); // create file menu QMenu *menu = menuBar()->addMenu("&File"); @@ -1478,6 +1984,8 @@ ConfigMainWindow::ConfigMainWindow(void) // create options menu menu = menuBar()->addMenu("&Option"); menu->addAction(showNameAction); + menu->addAction(showRangeAction); + menu->addAction(showDataAction); menu->addSeparator(); menu->addActions(optGroup->actions()); menu->addSeparator(); @@ -1488,30 +1996,37 @@ ConfigMainWindow::ConfigMainWindow(void) 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 (helpText, SIGNAL (anchorClicked (const QUrl &)), + helpText, SLOT (clicked (const QUrl &)) ); + + connect(configList, SIGNAL(menuChanged(struct menu *)), + helpText, SLOT(setInfo(struct menu *))); + connect(configList, SIGNAL(menuSelected(struct menu *)), + SLOT(changeMenu(struct menu *))); + connect(configList, SIGNAL(itemSelected(struct menu *)), + SLOT(changeItens(struct menu *))); + connect(configList, SIGNAL(parentSelected()), + SLOT(goBack())); + connect(menuList, SIGNAL(menuChanged(struct menu *)), + helpText, SLOT(setInfo(struct menu *))); + connect(menuList, SIGNAL(menuSelected(struct menu *)), + SLOT(changeMenu(struct menu *))); + + //pass the list of selected items in configList to conflictsView so that + //when right click 'add symbols to conflict' is clicked it will be added + //to the list + connect(configList, SIGNAL(selectedChanged(QList<QTreeWidgetItem*>)), + conflictsView, SLOT(selectedChanged(QList<QTreeWidgetItem*>))); + connect(configList, SIGNAL(menuChanged(struct menu *)), + conflictsView, SLOT(menuChanged1(struct menu *))); + connect(configList, SIGNAL(gotFocus(struct menu *)), + helpText, SLOT(setInfo(struct menu *))); + connect(menuList, SIGNAL(gotFocus(struct menu *)), + helpText, SLOT(setInfo(struct menu *))); + connect(menuList, SIGNAL(gotFocus(struct menu *)), + SLOT(listFocusChanged(void))); + connect(helpText, SIGNAL(menuSelected(struct menu *)), + SLOT(setMenuLink(struct menu *))); QString listMode = configSettings->value("/listMode", "symbol").toString(); if (listMode == "single") @@ -1550,7 +2065,7 @@ void ConfigMainWindow::loadConfig(void) free(configname); configname = xstrdup(name); - ConfigList::updateListAllForAll(); + ConfigView::updateListAll(); } bool ConfigMainWindow::saveConfig(void) @@ -1588,8 +2103,10 @@ void ConfigMainWindow::saveConfigAs(void) void ConfigMainWindow::searchConfig(void) { - if (!searchWindow) + if (!searchWindow){ searchWindow = new ConfigSearchWindow(this); + connect(searchWindow,SIGNAL(UpdateConflictsViewColorization()),conflictsView,SLOT(UpdateConflictsViewColorization())); + } searchWindow->show(); } @@ -1685,7 +2202,7 @@ void ConfigMainWindow::showSingleView(void) backAction->setEnabled(true); - menuList->hide(); + menuView->hide(); menuList->setRootMenu(0); configList->mode = singleMode; if (configList->rootEntry == &rootmenu) @@ -1716,10 +2233,17 @@ void ConfigMainWindow::showSplitView(void) menuList->mode = symbolMode; menuList->setRootMenu(&rootmenu); menuList->setAllOpen(true); - menuList->show(); + menuView->show(); menuList->setFocus(); } +void ConfigMainWindow::conflictSelected(struct menu * men) +{ + configList->clearSelection(); + menuList->clearSelection(); + emit(setMenuLink(men)); +} + void ConfigMainWindow::showFullView(void) { singleViewAction->setEnabled(true); @@ -1731,7 +2255,7 @@ void ConfigMainWindow::showFullView(void) backAction->setEnabled(false); - menuList->hide(); + menuView->hide(); menuList->setRootMenu(0); configList->mode = fullMode; if (configList->rootEntry == &rootmenu) @@ -1773,26 +2297,17 @@ void ConfigMainWindow::closeEvent(QCloseEvent* e) 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"; + static const QString str = "Welcome to the qconf graphical configuration tool.\n\n" + "For each option, a blank box indicates the feature is disabled, a check\n" + "indicates it is enabled, and a dot indicates that it is to be compiled\n" + "as a module. Clicking on the box will cycle through the three states.\n\n" + "If you do not see an option (e.g., a device driver) that you believe\n" + "should be present, try turning on Show All Options under the Options menu.\n" + "Although there is no cross reference yet to help you figure out what other\n" + "options must be enabled to support the option you are interested in, you can\n" + "still view the help of a grayed-out option.\n\n" + "Toggling Show Debug Info under the Options menu will show the dependencies,\n" + "which you can then match by examining other options.\n\n"; QMessageBox::information(this, "qconf", str); } @@ -1800,13 +2315,10 @@ void ConfigMainWindow::showIntro(void) void ConfigMainWindow::showAbout(void) { static const QString str = "qconf is Copyright (C) 2002 Roman Zippel <zippel@xxxxxxxxxxxxxx>.\n" - "Copyright (C) 2015 Boris Barbulovski <bbarbulovski@xxxxxxxxx>.\n" - "\n" - "Bug reports and feature request can also be entered at http://bugzilla.kernel.org/\n" - "\n" - "Qt Version: "; + "Copyright (C) 2015 Boris Barbulovski <bbarbulovski@xxxxxxxxx>.\n\n" + "Bug reports and feature request can also be entered at http://bugzilla.kernel.org/\n"; - QMessageBox::information(this, "qconf", str + qVersion()); + QMessageBox::information(this, "qconf", str); } void ConfigMainWindow::saveSettings(void) @@ -1844,6 +2356,10 @@ void ConfigMainWindow::conf_changed(void) if (saveAction) saveAction->setEnabled(conf_get_changed()); } +void ConfigMainWindow::refreshMenu(void) +{ + configList->updateListAll(); +} void fixup_rootmenu(struct menu *menu) { @@ -1875,6 +2391,7 @@ int main(int ac, char** av) const char *name; progname = av[0]; + configApp = new QApplication(ac, av); if (ac > 1 && av[1][0] == '-') { switch (av[1][1]) { case 's': @@ -1895,8 +2412,6 @@ int main(int ac, char** av) conf_read(NULL); //zconfdump(stdout); - configApp = new QApplication(ac, av); - configSettings = new ConfigSettings(); configSettings->beginGroup("/kconfig/qconf"); v = new ConfigMainWindow(); @@ -1914,3 +2429,33 @@ int main(int ac, char** av) return 0; } + +void droppableView::dropEvent(QDropEvent *event) +{ + event->acceptProposedAction(); +} + +QString tristate_value_to_string(tristate val) +{ + switch (val) { + case yes: + return QString::fromStdString("YES"); + case mod: + return QString::fromStdString("MODULE"); + case no: + return QString::fromStdString("NO"); + default: + return QString::fromStdString(""); + } +} +tristate string_value_to_tristate(QString s) +{ + if (s == "YES") + return tristate::yes; + else if (s == "MODULE") + return tristate::mod; + else if (s == "NO") + return tristate::no; + else + return tristate::no; +} diff --git a/scripts/kconfig/qconf.h b/scripts/kconfig/qconf.h index 78b0a1dfcd53..3b0b398ebfe6 100644 --- a/scripts/kconfig/qconf.h +++ b/scripts/kconfig/qconf.h @@ -11,14 +11,25 @@ #include <QPushButton> #include <QSettings> #include <QSplitter> -#include <QStyledItemDelegate> #include <QTextBrowser> #include <QTreeWidget> +#include <QListWidget> +#include <QTableWidget> +#include <QList> +#include <QComboBox> +#include <QLabel> +#include <qstring.h> +#include <thread> +#include <condition_variable> #include "expr.h" +#include "configfix.h" + +class ConfigView; class ConfigList; class ConfigItem; +class ConfigLineEdit; class ConfigMainWindow; class ConfigSettings : public QSettings { @@ -29,7 +40,7 @@ class ConfigSettings : public QSettings { }; enum colIdx { - promptColIdx, nameColIdx, dataColIdx + promptColIdx, nameColIdx, noColIdx, modColIdx, yesColIdx, dataColIdx }; enum listMode { singleMode, menuMode, symbolMode, fullMode, listMode @@ -38,14 +49,31 @@ enum optionMode { normalOpt = 0, allOpt, promptOpt }; +enum symbolStatus { + UNSATISFIED, SATISFIED +}; + +typedef struct { + QString symbol; + QString change_needed; + enum symbolStatus status; + tristate change_requested; +} Constraint; + +QString tristate_value_to_string(tristate val); +tristate string_value_to_tristate(QString s); + class ConfigList : public QTreeWidget { Q_OBJECT typedef class QTreeWidget Parent; public: - ConfigList(QWidget *parent, const char *name = 0); - ~ConfigList(); + ConfigList(ConfigView* p, const char *name = 0); void reinit(void); ConfigItem* findConfigItem(struct menu *); + ConfigView* parent(void) const + { + return (ConfigView*)Parent::parent(); + } void setSelected(QTreeWidgetItem *item, bool enable) { for (int i = 0; i < selectedItems().size(); i++) selectedItems().at(i)->setSelected(false); @@ -71,7 +99,6 @@ public slots: void updateSelection(void); void saveSettings(void); void setOptionMode(QAction *action); - void setShowName(bool on); signals: void menuChanged(struct menu *menu); @@ -79,7 +106,8 @@ public slots: void itemSelected(struct menu *menu); void parentSelected(void); void gotFocus(struct menu *); - void showNameChanged(bool on); + void selectedChanged(QList<QTreeWidgetItem*> selection); + void UpdateConflictsViewColorization(); public: void updateListAll(void) @@ -98,7 +126,7 @@ public slots: bool updateAll; - bool showName; + bool showName, showRange, showData; enum listMode mode; enum optionMode optMode; struct menu *rootEntry; @@ -106,11 +134,7 @@ public slots: QPalette inactivedColorGroup; QMenu* headerPopup; - static QList<ConfigList *> allLists; - static void updateListForAll(); - static void updateListAllForAll(); - - static QAction *showNormalAction, *showAllAction, *showPromptAction; + static QAction *showNormalAction, *showAllAction, *showPromptAction, *addSymbolsFromContextMenu; }; class ConfigItem : public QTreeWidgetItem { @@ -133,6 +157,7 @@ class ConfigItem : public QTreeWidgetItem { } ~ConfigItem(void); void init(void); + void okRename(int col); void updateMenu(void); void testUpdateMenu(bool v); ConfigList* listView() const @@ -169,18 +194,104 @@ class ConfigItem : public QTreeWidgetItem { static QIcon menuIcon, menubackIcon; }; -class ConfigItemDelegate : public QStyledItemDelegate -{ -private: - struct menu *menu; +class ConfigLineEdit : public QLineEdit { + Q_OBJECT + typedef class QLineEdit Parent; +public: + ConfigLineEdit(ConfigView* parent); + ConfigView* parent(void) const + { + return (ConfigView*)Parent::parent(); + } + void show(ConfigItem *i); + void keyPressEvent(QKeyEvent *e); + +public: + ConfigItem *item; +}; + +class ConfigView : public QWidget { + Q_OBJECT + typedef class QWidget Parent; public: - ConfigItemDelegate(QObject *parent = nullptr) - : QStyledItemDelegate(parent) {} - QWidget *createEditor(QWidget *parent, - const QStyleOptionViewItem &option, - const QModelIndex &index) const override; - void setModelData(QWidget *editor, QAbstractItemModel *model, - const QModelIndex &index) const override; + ConfigView(QWidget* parent, const char *name = 0); + ~ConfigView(void); + static void updateList(); + static void updateListAll(void); + + bool showName(void) const { return list->showName; } + bool showRange(void) const { return list->showRange; } + bool showData(void) const { return list->showData; } +public slots: + void setShowName(bool); + void setShowRange(bool); + void setShowData(bool); + + void ShowContextMenu(const QPoint& p); +signals: + void showNameChanged(bool); + void showRangeChanged(bool); + void showDataChanged(bool); +public: + ConfigList* list; + ConfigLineEdit* lineEdit; + + static ConfigView* viewList; + ConfigView* nextView; + + static QAction *showNormalAction; + static QAction *showAllAction; + static QAction *showPromptAction; + static QAction *addSymbolsFromContextMenu; +}; +class ConflictsView : public QWidget { + ConfigLineEdit* lineEdit; + Q_OBJECT + typedef class QWidget Parent; +public: + ConflictsView(QWidget* parent, const char *name = 0); + void addSymbol(struct menu * m); + int current_solution_number = -1; + +public slots: + void cellClicked(int, int); + void addSymbol(); + void addSymbolFromContextMenu(); + void removeSymbol(); + void menuChanged1(struct menu *); + void changeToNo(); + void changeToYes(); + void changeToModule(); + void selectedChanged(QList<QTreeWidgetItem*> selection); + void applyFixButtonClick(); + void UpdateConflictsViewColorization(); + void updateResults(); + void changeSolutionTable(int solution_number); + void calculateFixes(); +signals: + void showNameChanged(bool); + void showRangeChanged(bool); + void showDataChanged(bool); + void conflictSelected(struct menu *); + void refreshMenu(); + void resultsReady(); +public: + QTableWidget* conflictsTable; + QList<Constraint> constraints; + QComboBox* solutionSelector{nullptr}; + QTableWidget* solutionTable{nullptr}; + QPushButton* applyFixButton{nullptr}; + struct sfl_list * solution_output{nullptr}; + QToolBar *conflictsToolBar; + struct menu * currentSelectedMenu ; + QLabel* numSolutionLabel{nullptr}; + QList<QTreeWidgetItem*> currentSelection; + QAction *fixConflictsAction_{nullptr}; + void runSatConfAsync(); + std::thread* runSatConfAsyncThread{nullptr}; + std::mutex satconf_mutex; + std::condition_variable satconf_cancellation_cv; + bool satconf_cancelled{false}; }; class ConfigInfoView : public QTextBrowser { @@ -223,17 +334,21 @@ class ConfigSearchWindow : public QDialog { public slots: void saveSettings(void); void search(void); + void UpdateConflictsViewColorizationFowarder(); +signals: + void UpdateConflictsViewColorization(); protected: QLineEdit* editField; QPushButton* searchButton; QSplitter* split; - ConfigList *list; + ConfigView* list; ConfigInfoView* info; struct symbol **result; }; + class ConfigMainWindow : public QMainWindow { Q_OBJECT @@ -258,18 +373,34 @@ public slots: void showIntro(void); void showAbout(void); void saveSettings(void); + void conflictSelected(struct menu *); + void refreshMenu(); protected: void closeEvent(QCloseEvent *e); ConfigSearchWindow *searchWindow; + ConfigView *menuView; ConfigList *menuList; + ConfigView *configView; ConfigList *configList; ConfigInfoView *helpText; + ConflictsView *conflictsView; + QToolBar *toolBar; + QToolBar *conflictsToolBar; QAction *backAction; QAction *singleViewAction; QAction *splitViewAction; QAction *fullViewAction; QSplitter *split1; QSplitter *split2; + QSplitter *split3; +}; + +class droppableView : public QTableWidget +{ +public: + droppableView(QWidget *parent = nullptr) {} +protected: + void dropEvent(QDropEvent *event); }; -- 2.33.0