From: Thorsten Berger <thorsten.berger@rub.de>
To: linux-kbuild@vger.kernel.org
Cc: deltaone@debian.org, phayax@gmail.com,
Eugene Groshev <eugene.groshev@gmail.com>,
Sarah Nadi <nadi@ualberta.ca>, Mel Gorman <mgorman@suse.de>,
"Luis R. Rodriguez" <mcgrof@suse.com>
Subject: [RFC v3 11/12] Add xconfig-modifications
Date: Fri, 22 Oct 2021 15:47:26 +0200 [thread overview]
Message-ID: <c3df3ea3-a711-dff7-4ae4-b0e77f05a983@rub.de> (raw)
In-Reply-To: <7706ed5e-4771-770a-5cf2-d3c8346fa1dc@rub.de>
Co-developed-by: Patrick Franz <deltaone@debian.org>
Signed-off-by: Patrick Franz <deltaone@debian.org>
Co-developed-by: Ibrahim Fayaz <phayax@gmail.com>
Signed-off-by: Ibrahim Fayaz <phayax@gmail.com>
Reviewed-by: Luis Chamberlain <mcgrof@suse.com>
Tested-by: Evgeny Groshev <eugene.groshev@gmail.com>
Suggested-by: Sarah Nadi <nadi@ualberta.ca>
Suggested-by: Thorsten Berger <thorsten.berger@rub.de>
Signed-off-by: Thorsten Berger <thorsten.berger@rub.de>
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@linux-m68k.org>.\n"
- "Copyright (C) 2015 Boris Barbulovski <bbarbulovski@gmail.com>.\n"
- "\n"
- "Bug reports and feature request can also be entered at http://bugzilla.kernel.org/\n"
- "\n"
- "Qt Version: ";
+ "Copyright (C) 2015 Boris Barbulovski <bbarbulovski@gmail.com>.\n\n"
+ "Bug reports and feature request can also be entered at http://bugzilla.kernel.org/\n";
- 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
next prev parent reply other threads:[~2021-10-22 13:47 UTC|newest]
Thread overview: 22+ messages / expand[flat|nested] mbox.gz Atom feed top
2021-10-22 13:34 [RFC v3 00/12] kconfig: add support for conflict resolution Thorsten Berger
2021-10-22 13:35 ` [RFC v3 01/12] Add picosat.h Thorsten Berger
2021-10-22 16:57 ` Luis Chamberlain
2021-10-22 13:36 ` [RFC v3 02/12] Add picosat.c (1/3) Thorsten Berger
2021-10-22 16:58 ` Luis Chamberlain
2021-10-22 13:38 ` [RFC v3 03/12] Add picosat.c (2/3) Thorsten Berger
2021-10-22 16:59 ` Luis Chamberlain
2021-10-24 9:05 ` Masahiro Yamada
2021-10-24 23:52 ` Thorsten Berger
2021-10-22 13:39 ` [RFC v3 04/12] Add picosat.c (3/3) Thorsten Berger
2021-10-22 13:40 ` [RFC v3 05/12] Add definitions Thorsten Berger
2021-10-22 16:56 ` Luis Chamberlain
2021-10-22 13:41 ` [RFC v3 06/12] Add files for building constraints Thorsten Berger
2021-10-22 16:56 ` Luis Chamberlain
2021-10-22 13:43 ` [RFC v3 07/12] Add files for handling expressions Thorsten Berger
2021-10-22 13:44 ` [RFC v3 08/12] Add files for RangeFix Thorsten Berger
2021-10-22 13:45 ` [RFC v3 09/12] Add files with utility functions Thorsten Berger
2021-10-22 13:46 ` [RFC v3 10/12] Add tools Thorsten Berger
2021-10-22 13:47 ` Thorsten Berger [this message]
2021-11-04 9:30 ` [RFC v3 11/12] Add xconfig-modifications Masahiro Yamada
2021-10-22 13:48 ` [RFC v3 12/12] Simplify dependencies for MODULE_SIG_KEY_TYPE_RSA & MODULE_SIG_KEY_TYPE_ECDSA Thorsten Berger
2021-10-22 17:03 ` Luis Chamberlain
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=c3df3ea3-a711-dff7-4ae4-b0e77f05a983@rub.de \
--to=thorsten.berger@rub.de \
--cc=deltaone@debian.org \
--cc=eugene.groshev@gmail.com \
--cc=linux-kbuild@vger.kernel.org \
--cc=mcgrof@suse.com \
--cc=mgorman@suse.de \
--cc=nadi@ualberta.ca \
--cc=phayax@gmail.com \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox