From nobody Wed Dec 17 15:33:14 2025 Received: from mail-ed1-f46.google.com (mail-ed1-f46.google.com [209.85.208.46]) (using TLSv1.2 with cipher ECDHE-RSA-AES128-GCM-SHA256 (128/128 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id E8D6684D10; Wed, 10 Jul 2024 06:54:46 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=209.85.208.46 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1720594490; cv=none; b=oYllZyOW2t19RZLfzHLgbw7MXXWY/Kn6CqwzY2ng4BRUQWngwGql/DJB2qfcqn+gIxsns9HBmafIPmEXHrRIB75L6HReOW5Yi3ApT/wT7bfGItl+3YflFxrFNC7gbCY6v30M+9Els2yeHd6ZIif9aZfWZ4LKMY+KT3YUs+p/w+w= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1720594490; c=relaxed/simple; bh=eE6kwwaimB5RYAjZPlQSf8gzYv1dHn78EcD86LQMjGw=; h=From:To:Cc:Subject:Date:Message-Id:In-Reply-To:References: MIME-Version; b=DosZhPWy4HApA1p1v00J4h1p5UWtAOgymk/5FtONZN2q1Lniba55xCtE9qOA+eq/qDWwlVM6lXrT6uH/ixC2PnWufL0ZGrF+qrZYwxEzUILdV3slsxlzV/82yjSWV8uzZxm/u9HnwUI34IHd3GK2CJpekEEaj3nN9Y+3irPq0L8= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=gmail.com; spf=pass smtp.mailfrom=gmail.com; dkim=pass (2048-bit key) header.d=gmail.com header.i=@gmail.com header.b=BE9BC5+Y; arc=none smtp.client-ip=209.85.208.46 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=gmail.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=gmail.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=gmail.com header.i=@gmail.com header.b="BE9BC5+Y" Received: by mail-ed1-f46.google.com with SMTP id 4fb4d7f45d1cf-58ba3e38028so7585404a12.0; Tue, 09 Jul 2024 23:54:46 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20230601; t=1720594485; x=1721199285; darn=vger.kernel.org; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:from:to:cc:subject:date :message-id:reply-to; bh=z45113346TfU/PYZcyxCx2fwuoLndYbTrwfmraUfJ2o=; b=BE9BC5+YkqZJWlOmvcwQWZk6VWOOzBVo9+8BvEnFLpkrs82m09NnI0fmsiKyXnttsg H7YZNOz3XFXpVrbdJIesawmATacyAippwhfjZIQG5BJYZ+zhuzfKZanRVJC80+Fbt8nr tBxnCQukRtxJ+PpLXA4Y89p9W9kzsfhxDVuwtzuazrTTPu4cThb+gaSpyhx0OSNRqDt1 6jTzQpCBi9H5XUzdRam5oG4l/drX/KN9i0ADjOh4kVNoyvDsXzUGzC1Tp4kZhV6qNlKf Hu5uecaZ/xEB324Xe9Ud6sM+UaSfs8eEiEum+asDcbqEJ5siyHB8O+LcVMuZtTkXzPQD 4Spg== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1720594485; x=1721199285; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:x-gm-message-state:from:to:cc :subject:date:message-id:reply-to; bh=z45113346TfU/PYZcyxCx2fwuoLndYbTrwfmraUfJ2o=; b=cxt0gVQz62AawDL6ol0KiRxMJT2WjY+Y4uhtIn2ud5mIU6GViJZ1yLoC3WrMqWbiZp PuAvp5kd0Vk/k/ieRMnzr+3BJRLYrrhGoZQNVTXZZczEgBy1v/nBY8FgQiav1cRLOKvd refh5LeZUqTjHDl3ynp7N6DSw6jb0OYuDHi8aWMrs3uNYzV2pf7YGglcFS1NXQtffNQo j9H7Eddgs0zaV537Hx6TLCflpBINKVakuf/uUjn3777KQvt7MqwL1JN6EYzTxKs98U/4 rgJrnNDNc/hTxpTg0qyOSY7ReyJ9UDIJuFCng3iRB86xvzPzHuzzEk1qLPvZmn3CGrri vRJg== X-Forwarded-Encrypted: i=1; AJvYcCXfygJRrM0BCbEKNEDS+Y7bbhxaI3KK1osR2Bx6NrTVxh7JxXPpL6ZnSrDpLoLPit+D18KV8Tx1CAKTt4oyuXwKsb1WbbDP95mWJyZg X-Gm-Message-State: AOJu0YzF9F6bbHafMQNNGnP+YKCNBpHTSdejESb9JBlp8orGAP1D6sRQ 6UrCN4ewzzUOaXKgVh51yRuiz7qEUo7vRo9SQjxhWCNdcgNqEABu2ib8LQ== X-Google-Smtp-Source: AGHT+IEG96msI0r8Fd7cTip+ItV8KktVXjM+bzUL/c33wcIYwo2TUVf2IrzPV4vYVSGiiqd5QUfIlA== X-Received: by 2002:aa7:d686:0:b0:594:4d8d:8cc6 with SMTP id 4fb4d7f45d1cf-594bbe2bbdcmr2378780a12.40.1720594485043; Tue, 09 Jul 2024 23:54:45 -0700 (PDT) Received: from localhost.localdomain ([2a02:908:e842:bf20::c7d2]) by smtp.gmail.com with ESMTPSA id 4fb4d7f45d1cf-594bc7c8a39sm1894590a12.55.2024.07.09.23.54.44 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Tue, 09 Jul 2024 23:54:44 -0700 (PDT) From: Ole Schuerks To: linux-kbuild@vger.kernel.org Cc: ole0811sch@gmail.com, jude.gyimah@rub.de, thorsten.berger@rub.de, deltaone@debian.org, jan.sollmann@rub.de, mcgrof@kernel.org, masahiroy@kernel.org, linux-kernel@vger.kernel.org Subject: [PATCH v4 11/12] kconfig: Add xconfig-modifications Date: Wed, 10 Jul 2024 08:52:54 +0200 Message-Id: <20240710065255.10338-12-ole0811sch@gmail.com> X-Mailer: git-send-email 2.39.2 In-Reply-To: <20240710065255.10338-1-ole0811sch@gmail.com> References: <20240710065255.10338-1-ole0811sch@gmail.com> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable Content-Type: text/plain; charset="utf-8" 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. Co-developed-by: Patrick Franz Signed-off-by: Patrick Franz Co-developed-by: Ibrahim Fayaz Signed-off-by: Ibrahim Fayaz Reviewed-by: Luis Chamberlain Tested-by: Evgeny Groshev Suggested-by: Sarah Nadi Suggested-by: Thorsten Berger Signed-off-by: Thorsten Berger Signed-off-by: Ole Schuerks --- scripts/kconfig/qconf.cc | 515 ++++++++++++++++++++++++++++++++++++++- scripts/kconfig/qconf.h | 103 ++++++++ 2 files changed, 616 insertions(+), 2 deletions(-) diff --git a/scripts/kconfig/qconf.cc b/scripts/kconfig/qconf.cc index 7d239c032b3d..20ca9936d592 100644 --- a/scripts/kconfig/qconf.cc +++ b/scripts/kconfig/qconf.cc @@ -3,7 +3,7 @@ * Copyright (C) 2002 Roman Zippel * Copyright (C) 2015 Boris Barbulovski */ - +#include "qnamespace.h" #include #include #include @@ -19,14 +19,27 @@ #include #include #include +#include +#include +#include +#include +#include +#include =20 #include +#include +#include +#include +#include =20 #include "lkc.h" #include "qconf.h" +#include "configfix.h" =20 #include "images.h" =20 +static QString tristate_value_to_string(tristate val); +static tristate string_value_to_tristate(QString s); =20 static QApplication *configApp; static ConfigSettings *configSettings; @@ -178,6 +191,7 @@ void ConfigItem::updateMenu(void) prompt +=3D " (NEW)"; set_prompt: setText(promptColIdx, prompt); + } =20 void ConfigItem::testUpdateMenu(bool v) @@ -225,6 +239,7 @@ void ConfigItem::init(void) } } updateMenu(); + } =20 /* @@ -405,7 +420,7 @@ void ConfigList::updateSelection(void) ConfigItem* item =3D (ConfigItem*)selectedItems().first(); if (!item) return; - + emit selectionChanged(selectedItems()); menu =3D item->menu; emit menuChanged(menu); if (!menu) @@ -471,6 +486,7 @@ void ConfigList::updateListForAll() =20 list->updateList(); } + } =20 void ConfigList::updateListAllForAll() @@ -539,6 +555,7 @@ void ConfigList::changeValue(ConfigItem* item) } if (oldexpr !=3D newexpr) ConfigList::updateListForAll(); + emit updateConflictsViewColorization(); break; default: break; @@ -898,6 +915,7 @@ void ConfigList::contextMenuEvent(QContextMenuEvent *e) action, &QAction::setChecked); action->setChecked(showName); headerPopup->addAction(action); + headerPopup->addAction(addSymbolFromContextMenu); } =20 headerPopup->exec(e->globalPos()); @@ -918,6 +936,7 @@ QList ConfigList::allLists; QAction *ConfigList::showNormalAction; QAction *ConfigList::showAllAction; QAction *ConfigList::showPromptAction; +QAction *ConfigList::addSymbolFromContextMenu; =20 void ConfigList::setAllOpen(bool open) { @@ -1249,7 +1268,10 @@ ConfigSearchWindow::ConfigSearchWindow(ConfigMainWin= dow *parent) info, &ConfigInfoView::setInfo); connect(list, &ConfigList::menuChanged, parent, &ConfigMainWindow::setMenuLink); + connect(list, &ConfigList::menuChanged, + parent, &ConfigMainWindow::conflictSelected); =20 + connect(list,&ConfigList::updateConflictsViewColorization,this,&ConfigSea= rchWindow::updateConflictsViewColorizationFowarder); layout1->addWidget(split); =20 QVariant x, y; @@ -1272,6 +1294,10 @@ ConfigSearchWindow::ConfigSearchWindow(ConfigMainWin= dow *parent) this, &ConfigSearchWindow::saveSettings); } =20 +void ConfigSearchWindow::updateConflictsViewColorizationFowarder(void){ + emit updateConflictsViewColorization(); +} + void ConfigSearchWindow::saveSettings(void) { if (!objectName().isEmpty()) { @@ -1364,6 +1390,17 @@ ConfigMainWindow::ConfigMainWindow(void) split1->addWidget(configList); split1->addWidget(menuList); split2->addWidget(helpText); + split3 =3D new QSplitter(split2); + split3->setOrientation(Qt::Vertical); + conflictsView =3D 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 tha= t was selected. + */ + connect(conflictsView,SIGNAL(conflictSelected(struct menu *)),SLOT(confli= ctSelected(struct menu *))); + connect(conflictsView,SIGNAL(refreshMenu()),SLOT(refreshMenu())); + connect(menuList,SIGNAL(updateConflictsViewColorization()),conflictsView,= SLOT(updateConflictsViewColorization())); + connect(configList,SIGNAL(updateConflictsViewColorization()),conflictsVie= w,SLOT(updateConflictsViewColorization())); =20 setTabOrder(configList, helpText); configList->setFocus(); @@ -1430,6 +1467,8 @@ ConfigMainWindow::ConfigMainWindow(void) ConfigList::showAllAction->setCheckable(true); ConfigList::showPromptAction =3D new QAction("Show Prompt Options", optGr= oup); ConfigList::showPromptAction->setCheckable(true); + ConfigList::addSymbolFromContextMenu =3D new QAction("Add symbol from con= text menu"); + connect(ConfigList::addSymbolFromContextMenu, &QAction::triggered, confli= ctsView, &ConflictsView::addSymbol); =20 QAction *showDebugAction =3D new QAction("Show Debug Info", this); showDebugAction->setCheckable(true); @@ -1485,6 +1524,8 @@ ConfigMainWindow::ConfigMainWindow(void) =20 connect(configList, &ConfigList::menuChanged, helpText, &ConfigInfoView::setInfo); + connect(configList, &ConfigList::menuChanged, + conflictsView, &ConflictsView::menuChanged); connect(configList, &ConfigList::menuSelected, this, &ConfigMainWindow::changeMenu); connect(configList, &ConfigList::itemSelected, @@ -1493,6 +1534,8 @@ ConfigMainWindow::ConfigMainWindow(void) this, &ConfigMainWindow::goBack); connect(menuList, &ConfigList::menuChanged, helpText, &ConfigInfoView::setInfo); + connect(menuList, &ConfigList::menuChanged, + conflictsView, &ConflictsView::menuChanged); connect(menuList, &ConfigList::menuSelected, this, &ConfigMainWindow::changeMenu); =20 @@ -1712,6 +1755,13 @@ void ConfigMainWindow::showSplitView(void) menuList->setFocus(); } =20 +void ConfigMainWindow::conflictSelected(struct menu * men) +{ + configList->clearSelection(); + menuList->clearSelection(); + emit(setMenuLink(men)); +} + void ConfigMainWindow::showFullView(void) { singleViewAction->setEnabled(true); @@ -1847,6 +1897,432 @@ void ConfigMainWindow::conf_changed(bool dirty) saveAction->setEnabled(dirty); } =20 +void ConfigMainWindow::refreshMenu(void) +{ + configList->updateListAll(); +} + +void QTableWidget::dropEvent(QDropEvent *event) +{ +} + +ConflictsView::ConflictsView(QWidget *parent, const char *name) + : Parent(parent) +{ + currentSelectedMenu =3D nullptr; + setObjectName(name); + QHBoxLayout *horizontalLayout =3D new QHBoxLayout(this); + QVBoxLayout *verticalLayout =3D new QVBoxLayout(); + verticalLayout->setContentsMargins(0, 0, 0, 0); + conflictsToolBar =3D new QToolBar("ConflictTools", this); + // toolbar buttons [n] [m] [y] [calculate fixes] [remove] + QAction *addSymbol =3D new QAction("Add Symbol"); + QAction *setConfigSymbolAsNo =3D new QAction("N"); + QAction *setConfigSymbolAsModule =3D new QAction("M"); + QAction *setConfigSymbolAsYes =3D new QAction("Y"); + fixConflictsAction_ =3D new QAction("Calculate Fixes"); + QAction *removeSymbol =3D new QAction("Remove Symbol"); + QMovie *loadingGif =3D new QMovie("scripts/kconfig/loader.gif"); + auto loadingLabel =3D new QLabel; + + if (loadingGif->isValid()) { + loadingGif->setScaledSize(loadingGif->scaledSize().scaled( + 20, 20, Qt::KeepAspectRatioByExpanding)); + loadingGif->start(); + loadingLabel->setMovie(loadingGif); + } else { + loadingLabel->setText("Calculating..."); + } + + //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); + // loadingLabel->setMargin(5); + loadingLabel->setContentsMargins(5, 5, 5, 5); + loadingAction =3D conflictsToolBar->addWidget(loadingLabel); + loadingAction->setVisible(false); + + + verticalLayout->addWidget(conflictsToolBar); + + connect(addSymbol, &QAction::triggered, this, &ConflictsView::addSymbol); + connect(setConfigSymbolAsNo, &QAction::triggered,this, &ConflictsView::ch= angeToNo); + connect(setConfigSymbolAsModule, &QAction::triggered,this, &ConflictsView= ::changeToModule); + connect(setConfigSymbolAsYes, &QAction::triggered,this, &ConflictsView::c= hangeToYes); + connect(removeSymbol, &QAction::triggered,this, &ConflictsView::removeSym= bol); + 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_, &QAction::triggered,this, &ConflictsView::ca= lculateFixes); + + conflictsTable =3D (QTableWidget *) new dropAbleView(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(i= nt,int))); + horizontalLayout->addLayout(verticalLayout); + + // populate the solution view on the right hand side: + QVBoxLayout *solutionLayout =3D new QVBoxLayout(); + solutionLayout->setContentsMargins(0, 0, 0, 0); + solutionSelector =3D new QComboBox(); + connect(solutionSelector, QOverload::of(&QComboBox::currentIndexChan= ged), + [=3D](int index){ changeSolutionTable(index); }); + solutionTable =3D new QTableWidget(); + solutionTable->setRowCount(0); + solutionTable->setColumnCount(2); + solutionTable->setHorizontalHeaderLabels(QStringList() << "Symbol" << "N= ew Value" ); + + applyFixButton =3D new QPushButton("Apply Selected solution"); + connect(applyFixButton, SIGNAL(clicked(bool)), SLOT(applyFixButtonClick()= )); + + numSolutionLabel =3D new QLabel("Solutions:"); + solutionLayout->addWidget(numSolutionLabel); + solutionLayout->addWidget(solutionSelector); + solutionLayout->addWidget(solutionTable); + solutionLayout->addWidget(applyFixButton); + + horizontalLayout->addLayout(solutionLayout); +} + + +void ConflictsView::changeToNo(){ + QItemSelectionModel *select =3D conflictsTable->selectionModel(); + if (select->hasSelection()){ + QModelIndexList rows =3D select->selectedRows(); + for (int i =3D 0;i < rows.count(); i++) + { + conflictsTable->item(rows[i].row(),1)->setText("NO"); + } + } +} + +void ConflictsView::applyFixButtonClick(){ + signed int solution_number =3D solutionSelector->currentIndex(); + + if (solution_number =3D=3D -1 || solution_output =3D=3D NULL) { + return; + } + + struct sfix_list * selected_solution =3D select_solution(solution_output,= solution_number); + apply_fix(selected_solution); + + + ConfigList::updateListForAll(); + for (int i =3D 0;i < conflictsTable->rowCount(); i++) + { + conflictsTable->item(i,2)->setText(conflictsTable->item(i,1)->text()); + } + updateConflictsViewColorization(); + QMessageBox msgBox; + msgBox.setText("The solution has been applied."); + msgBox.exec(); +} + +void ConflictsView::changeToYes(){ + QItemSelectionModel *select =3D conflictsTable->selectionModel(); + if (select->hasSelection()){ + QModelIndexList rows =3D select->selectedRows(); + for (int i =3D 0;i < rows.count(); i++) + { + conflictsTable->item(rows[i].row(),1)->setText("YES"); + } + } + +} + +void ConflictsView::changeToModule() { + QItemSelectionModel *select =3D conflictsTable->selectionModel(); + if (select->hasSelection()){ + QModelIndexList rows =3D select->selectedRows(); + for (int i =3D 0;i < rows.count(); i++) + { + conflictsTable->item(rows[i].row(),1)->setText("MODULE"); + } + } + +} + +void ConflictsView::menuChanged(struct menu *m) +{ + currentSelectedMenu =3D m; +} + +void ConflictsView::addSymbol() +{ + addSymbolFromMenu(currentSelectedMenu); +} + +void ConflictsView::selectionChanged(QList selection) +{ + currentSelection =3D selection; + +} + +void ConflictsView::addSymbolFromMenu(struct menu *m) +{ + // adds a symbol to the conflict resolver list + if (m !=3D nullptr){ + if (m->sym !=3D nullptr){ + struct symbol *sym =3D m->sym; + tristate currentval =3D sym_get_tristate_value(sym); + //if symbol is not added yet: + QAbstractItemModel *tableModel =3D conflictsTable->model(); + QModelIndexList matches =3D tableModel->match(tableModel->index(0,0), Q= t::DisplayRole, QString(sym->name)); + if (matches.isEmpty()){ + conflictsTable->insertRow(conflictsTable->rowCount()); + conflictsTable->setItem(conflictsTable->rowCount()-1,0,new QTableWidge= tItem(sym->name)); + conflictsTable->setItem(conflictsTable->rowCount()-1,1,new QTableWidge= tItem(tristate_value_to_string(currentval))); + conflictsTable->setItem(conflictsTable->rowCount()-1,2,new QTableWidge= tItem(tristate_value_to_string(currentval))); + }else{ + conflictsTable->item(matches[0].row(),2)->setText(tristate_value_to_st= ring(currentval)); + } + } + } +} + +void ConflictsView::addSymbolFromContextMenu() { + struct menu *menu; + + if (currentSelection.count() < 0){ + return; + } + for (auto el: currentSelection){ + ConfigItem *item =3D (ConfigItem *)el; + if (!item) + { + continue; + } + menu =3D item->menu; + addSymbolFromMenu(menu); + } + +} + +void ConflictsView::removeSymbol() +{ + QItemSelectionModel *select =3D conflictsTable->selectionModel(); + QAbstractItemModel *itemModel =3D select->model(); + if (select->hasSelection()){ + QModelIndexList rows =3D select->selectedRows(); + itemModel->removeRows(rows[0].row(),rows.size()); + } +} + +void ConflictsView::cellClicked(int row, int column) +{ + auto itemText =3D conflictsTable->item(row,0)->text().toUtf8().data(); + struct property *prop; + struct menu *men; + struct symbol *sym =3D sym_find(itemText); + + if (sym =3D=3D NULL) + return; + prop =3D sym->prop; + men =3D prop->menu; + // uncommenting following like somehow disables click signal of 'apply se= lected solution' + if (sym->type =3D=3D symbol_type::S_BOOLEAN) { + //disable module button + conflictsToolBar->actions()[2]->setDisabled(true); + } else { + //enable module button + conflictsToolBar->actions()[2]->setDisabled(false); + } + emit(conflictSelected(men)); +} + +void ConflictsView::changeSolutionTable(int solution_number){ + if (solution_output =3D=3D nullptr || solution_number < 0){ + return; + } + struct sfix_list *selected_solution =3D select_solution(solution_output, = solution_number); + current_solution_number =3D solution_number; + solutionTable->setRowCount(0); + for (unsigned int i =3D 0; i size; i++) + { + solutionTable->insertRow(solutionTable->rowCount()); + struct symbol_fix *cur_symbol =3D select_symbol(selected_solution,i); + + QTableWidgetItem *symbol_name =3D new QTableWidgetItem(cur_symbol->sym->= name); + + solutionTable->setItem(solutionTable->rowCount()-1,0,symbol_name); + + if (cur_symbol->type =3D=3D symbolfix_type::SF_BOOLEAN){ + QTableWidgetItem *symbol_value =3D new QTableWidgetItem(tristate_value_= to_string(cur_symbol->tri)); + solutionTable->setItem(solutionTable->rowCount()-1,1,symbol_value); + } else if(cur_symbol->type =3D=3D symbolfix_type::SF_NONBOOLEAN){ + QTableWidgetItem *symbol_value =3D new QTableWidgetItem(cur_symbol->nb_= val.s); + solutionTable->setItem(solutionTable->rowCount()-1,1,symbol_value); + } else { + QTableWidgetItem *symbol_value =3D new QTableWidgetItem(cur_symbol->dis= allowed.s); + solutionTable->setItem(solutionTable->rowCount()-1,1,symbol_value); + } + } + updateConflictsViewColorization(); +} + +void ConflictsView::updateConflictsViewColorization(void) +{ + auto green =3D QColor(0,170,0); + auto red =3D QColor(255,0,0); + auto grey =3D QColor(180,180,180); + + if (solutionTable->rowCount() =3D=3D 0 || current_solution_number < 0) + return; + + for (int i=3D0; i< solutionTable->rowCount(); i++) { + QTableWidgetItem *symbol =3D solutionTable->item(i,0); + //symbol from solution list + struct sfix_list *selected_solution =3D select_solution(solution_output,= current_solution_number); + struct symbol_fix *cur_symbol =3D select_symbol(selected_solution,i); + + // if symbol is editable but the value is not the target value from solu= tion we got, the color is red + // if symbol is editable but the value is the target value from solution= we got, the color is green + // if symbol is not editable , the value is not the target value, the co= lor is grey + // if symbol is not editable , the value is the target value, the color = is green + auto editable =3D sym_string_within_range(cur_symbol->sym, tristate_valu= e_to_string(cur_symbol->tri).toStdString().c_str()); + auto _symbol =3D solutionTable->item(i,0)->text().toUtf8().data(); + struct symbol *sym_ =3D sym_find(_symbol); + + tristate current_value_of_symbol =3D sym_get_tristate_value(sym_); + tristate target_value_of_symbol =3D string_value_to_tristate(solutionTab= le->item(i,1)->text()); + bool symbol_value_same_as_target =3D current_value_of_symbol =3D=3D targ= et_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 =3D nullptr; + p =3D static_cast(calloc(conflictsTable->rowCount= (),sizeof(struct symbol_dvalue))); + if (!p) + { + printf("memory allocation error\n"); + return; + } + + struct sdv_list *wanted_symbols =3D sdv_list_init(); + + for (int i =3D 0; i < conflictsTable->rowCount(); i++) + { + + struct symbol_dvalue *tmp =3D (p+i); + auto _symbol =3D conflictsTable->item(i,0)->text().toUtf8().data(); + struct symbol *sym =3D sym_find(_symbol); + + tmp->sym =3D sym; + tmp->type =3D static_cast(sym->type =3D=3D symbol_type::S= _BOOLEAN?0:1); + tmp->tri =3D string_value_to_tristate(conflictsTable->item(i,1)->text()); + sdv_list_add(wanted_symbols,tmp); + } + fixConflictsAction_->setText("Cancel"); + loadingAction->setVisible(true); + + struct sfl_list *ret =3D run_satconf(wanted_symbols); + solution_output =3D ret; + + free(p); + emit resultsReady(); + { + std::lock_guard lk{satconf_mutex}; + satconf_cancelled =3D true; + } + satconf_cancellation_cv.notify_one(); + +} + +void ConflictsView::updateResults(void) +{ + fixConflictsAction_->setText("Calculate Fixes"); + loadingAction->setVisible(false); + if (!(solution_output =3D=3D nullptr || solution_output->size =3D=3D 0)) + { + solutionSelector->clear(); + for (unsigned int i =3D 0; i < solution_output->size; i++) + { + solutionSelector->addItem(QString::number(i+1)); + } + // populate the solution table from the first solution gotten + numSolutionLabel->setText(QString("Solutions: (%1) found").arg(solution_= output->size)); + changeSolutionTable(0); + } + else { + QMessageBox msgBox; + msgBox.setText("All symbols are already within range."); + msgBox.exec(); + } + if (runSatConfAsyncThread->joinable()){ + runSatConfAsyncThread->join(); + delete runSatConfAsyncThread; + runSatConfAsyncThread =3D nullptr; + } + +} + +void ConflictsView::calculateFixes() +{ + if(conflictsTable->rowCount() =3D=3D 0) + { + printd("table is empty\n"); + return; + } + + if (runSatConfAsyncThread =3D=3D nullptr) + { + // fire away asynchronous call + std::unique_lock lk{satconf_mutex}; + + numSolutionLabel->setText(QString("Solutions: ")); + solutionSelector->clear(); + solutionTable->setRowCount(0); + satconf_cancelled =3D false; + runSatConfAsyncThread =3D new std::thread(&ConflictsView::runSatConfAsyn= c,this); + }else{ + printd("Interrupting rangefix\n"); + interrupt_rangefix(); + std::unique_lock lk{satconf_mutex}; + satconf_cancellation_cv.wait(lk,[this] {return satconf_cancelled =3D=3D = true;}); + } + +} + +void ConflictsView::changeAll(void) +{ + // not implemented for now + return; +} + +ConflictsView::~ConflictsView(void) +{ + +} + + void fixup_rootmenu(struct menu *menu) { struct menu *child; @@ -1918,3 +2394,38 @@ int main(int ac, char** av) =20 return 0; } + +dropAbleView::dropAbleView(QWidget *parent) : + QTableWidget(parent) {} + +dropAbleView::~dropAbleView() {} +void dropAbleView::dropEvent(QDropEvent *event) +{ + event->acceptProposedAction(); +} + +static 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(""); + } + +} + +static tristate string_value_to_tristate(QString s){ + if (s =3D=3D "YES") + return tristate::yes; + else if (s =3D=3D "MODULE") + return tristate::mod; + else if (s =3D=3D "NO") + return tristate::no; + else + return tristate::no; +} diff --git a/scripts/kconfig/qconf.h b/scripts/kconfig/qconf.h index 53373064d90a..1ace9f673fd0 100644 --- a/scripts/kconfig/qconf.h +++ b/scripts/kconfig/qconf.h @@ -14,9 +14,16 @@ #include #include #include +#include +#include +#include +#include +#include +#include =20 #include "expr.h" =20 + class ConfigList; class ConfigItem; class ConfigMainWindow; @@ -80,6 +87,8 @@ public slots: void parentSelected(void); void gotFocus(struct menu *); void showNameChanged(bool on); + void selectionChanged(QList selection); + void updateConflictsViewColorization(); =20 public: void updateListAll(void) @@ -111,6 +120,82 @@ public slots: static void updateListAllForAll(); =20 static QAction *showNormalAction, *showAllAction, *showPromptAction; + static QAction *addSymbolFromContextMenu; + +}; + +class ConflictsView : public QWidget { + Q_OBJECT + typedef class QWidget Parent; +private: + QAction *loadingAction; +public: + ConflictsView(QWidget *parent, const char *name =3D 0); + ~ConflictsView(void); + void addSymbolFromMenu(struct menu *m); + int current_solution_number =3D -1; + +public slots: + void cellClicked(int, int); + void changeAll(); + // triggered by Qactions on the tool bar that adds/remove symbol + void addSymbol(); + // triggered from config list right click -> add symbols + void addSymbolFromContextMenu(); + void removeSymbol(); + void menuChanged(struct menu *); + void changeToNo(); + void changeToYes(); + void changeToModule(); + void selectionChanged(QList selection); + + + void applyFixButtonClick(); + void updateConflictsViewColorization(); + void updateResults(); + + + + // switches the solution table with selected solution index from solutio= n_output + void changeSolutionTable(int solution_number); + + // calls satconfig to solve to get wanted value to current value + void calculateFixes(); +signals: + void showNameChanged(bool); + void showRangeChanged(bool); + void showDataChanged(bool); + void conflictSelected(struct menu *); + void refreshMenu(); + void resultsReady(); +public: + QTableWidget *conflictsTable; + + // the comobox on the right hand side. used to select a solution after + // getting solution from satconfig + QComboBox *solutionSelector{nullptr}; + + // the table which shows the selected solution showing variable =3D New v= alue changes + QTableWidget *solutionTable{nullptr}; + + // Apply fixes button on the solution view + QPushButton *applyFixButton{nullptr}; + + struct sfl_list *solution_output{nullptr}; + + QToolBar *conflictsToolBar; + struct menu *currentSelectedMenu; + QLabel *numSolutionLabel{nullptr}; + // currently selected config items in configlist. + QList currentSelection; + QAction *fixConflictsAction_{nullptr}; + void runSatConfAsync(); + std::thread *runSatConfAsyncThread{nullptr}; + + std::mutex satconf_mutex; + std::condition_variable satconf_cancellation_cv; + bool satconf_cancelled{false}; + }; =20 class ConfigItem : public QTreeWidgetItem { @@ -223,6 +308,9 @@ class ConfigSearchWindow : public QDialog { public slots: void saveSettings(void); void search(void); + void updateConflictsViewColorizationFowarder(); +signals: + void updateConflictsViewColorization(); =20 protected: QLineEdit* editField; @@ -258,6 +346,8 @@ public slots: void showIntro(void); void showAbout(void); void saveSettings(void); + void conflictSelected(struct menu *); + void refreshMenu(); =20 protected: void closeEvent(QCloseEvent *e); @@ -266,10 +356,23 @@ public slots: ConfigList *menuList; ConfigList *configList; ConfigInfoView *helpText; + ConflictsView *conflictsView; + QToolBar *conflictsToolBar; QAction *backAction; QAction *singleViewAction; QAction *splitViewAction; QAction *fullViewAction; QSplitter *split1; QSplitter *split2; + QSplitter *split3; +}; + +class dropAbleView : public QTableWidget +{ +public: + dropAbleView(QWidget *parent =3D nullptr); + ~dropAbleView(); + +protected: + void dropEvent(QDropEvent *event); }; --=20 2.39.2