File indexing completed on 2024-04-28 04:03:11
0001 /*************************************************************************** 0002 File : enginesettings.cpp 0003 Project : Knights 0004 Description : Engine Settings 0005 -------------------------------------------------------------------- 0006 SPDX-FileCopyrightText: 2018 Alexander Semke (alexander.semke@web.de) 0007 SPDX-FileCopyrightText: 2009-2011 Miha Čančula (miha@noughmad.eu) 0008 0009 ***************************************************************************/ 0010 0011 /*************************************************************************** 0012 * * 0013 * SPDX-License-Identifier: GPL-2.0-or-later 0014 * * 0015 * This program is distributed in the hope that it will be useful, * 0016 * but WITHOUT ANY WARRANTY; without even the implied warranty of * 0017 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * 0018 * GNU General Public License for more details. * 0019 * * 0020 * You should have received a copy of the GNU General Public License * 0021 * along with this program; if not, write to the Free Software * 0022 * Foundation, Inc., 51 Franklin Street, Fifth Floor, * 0023 * Boston, MA 02110-1301 USA * 0024 * * 0025 ***************************************************************************/ 0026 0027 #include "enginesettings.h" 0028 #include "ui_enginesettings.h" 0029 #include "settings.h" 0030 0031 #include <KComboBox> 0032 0033 #include <QLabel> 0034 #include <QStandardPaths> 0035 0036 using namespace Knights; 0037 0038 EngineConfiguration::EngineConfiguration(const QString& string) : iface(Invalid) { 0039 QStringList list = string.split(QLatin1Char(':')); 0040 if ( list.size() > 2 ) { 0041 name = list[0]; 0042 commandLine = list[1]; 0043 if ( list[2] == QLatin1String("xboard") ) 0044 iface = XBoard; 0045 else if ( list[2] == QLatin1String("uci") ) 0046 iface = Uci; 0047 } 0048 } 0049 0050 const QString EngineConfiguration::toString() const { 0051 if ( iface == Invalid || commandLine.isEmpty() || name.isEmpty() ) 0052 return QString(); 0053 0054 QLatin1Char sep(':'); 0055 QString str = name + sep + commandLine + sep + ( iface == XBoard ? QLatin1String("xboard") : QLatin1String("uci") ); 0056 return str; 0057 } 0058 0059 EngineSettings::EngineSettings(QWidget* parent, Qt::WindowFlags f) : QWidget(parent, f), ui(new Ui::EngineSettings) { 0060 ui->setupUi(this); 0061 0062 ui->autoDetectButton->setIcon( QIcon::fromTheme(QStringLiteral("tools-wizard")) ); 0063 ui->addButton->setIcon( QIcon::fromTheme(QStringLiteral("list-add")) ); 0064 ui->removeButton->setIcon( QIcon::fromTheme(QStringLiteral("list-remove")) ); 0065 0066 //add saved engines 0067 int row = 0; 0068 for ( const QString& s : Settings::engineConfigurations() ) { 0069 addClicked(); 0070 EngineConfiguration c = EngineConfiguration ( s ); 0071 ui->tableWidget->setItem ( row, NameColumn, new QTableWidgetItem ( c.name ) ); 0072 ui->tableWidget->setItem ( row, CommandColumn, new QTableWidgetItem ( c.commandLine ) ); 0073 qobject_cast<KComboBox*> ( ui->tableWidget->cellWidget ( row, ProtocolColumn ) )->setCurrentIndex ( (int)c.iface ); 0074 checkInstalled(row, c.commandLine); 0075 ++row; 0076 } 0077 0078 ui->tableWidget->resizeColumnsToContents(); 0079 0080 //connects 0081 connect(ui->autoDetectButton, &QPushButton::clicked, this, &EngineSettings::autoDetectEngines); 0082 connect(ui->addButton, &QPushButton::clicked, this, &EngineSettings::addClicked); 0083 connect(ui->removeButton, &QPushButton::clicked, this, &EngineSettings::removeClicked); 0084 connect(ui->tableWidget, &QTableWidget::itemChanged, this, &EngineSettings::tableItemChanged); 0085 } 0086 0087 EngineSettings::~EngineSettings() { 0088 delete ui; 0089 } 0090 0091 void EngineSettings::checkInstalled(int row, const QString& name) { 0092 const bool exists = !QStandardPaths::findExecutable(name).isEmpty(); 0093 const char* iconName = exists ? "dialog-ok" : "dialog-error"; 0094 QLabel* label = new QLabel(this); 0095 label->setPixmap ( QIcon::fromTheme(QLatin1String(iconName)).pixmap(32, 32) ); 0096 ui->tableWidget->setCellWidget(row, InstalledColumn, label ); 0097 } 0098 0099 void EngineSettings::tableItemChanged(QTableWidgetItem* item) { 0100 //if the name of the executable was changed, check whether it's available 0101 if (item->column() == CommandColumn) 0102 checkInstalled(item->row(), item->text()); 0103 } 0104 0105 void EngineSettings::addClicked() { 0106 int n = ui->tableWidget->rowCount(); 0107 ui->tableWidget->insertRow ( n ); 0108 KComboBox* box = new KComboBox ( this ); 0109 box->insertItems(0, {i18nc("Protocol name", "XBoard"), i18nc("Protocol name", "UCI")}); 0110 ui->tableWidget->setCellWidget ( n, ProtocolColumn, box ); 0111 ui->tableWidget->edit ( ui->tableWidget->model()->index ( n, NameColumn ) ); 0112 } 0113 0114 void EngineSettings::removeClicked() { 0115 if ( ui->tableWidget->selectionModel()->selectedRows().isEmpty() ) 0116 return; 0117 0118 int i = ui->tableWidget->selectionModel()->selectedRows().first().row(); 0119 if (i != -1) 0120 ui->tableWidget->removeRow(i); 0121 } 0122 0123 void EngineSettings::autoDetectEngines() { 0124 //descriptions for couple of known/popular open-source chess engines: 0125 //provide the name/Description of the engine, the name of the executable and the protocol, 0126 //keep the order within the three string lists in sync 0127 0128 QStringList names; 0129 names << QStringLiteral("GNU Chess"); 0130 names << QStringLiteral("Crafty"); 0131 names << QStringLiteral("Stockfish"); 0132 names << QStringLiteral("Stockfish v1.4"); 0133 names << QStringLiteral("Stockfish v1.6"); 0134 names << QStringLiteral("Stockfish v1.7"); 0135 names << QStringLiteral("Stockfish v1.8"); 0136 names << QStringLiteral("Stockfish v1.9"); 0137 names << QStringLiteral("Stockfish v2.0"); 0138 names << QStringLiteral("Sjeng"); 0139 names << QStringLiteral("Phalanx"); 0140 names << QStringLiteral("Fruit"); 0141 names << QStringLiteral("Fruit v2.1"); 0142 names << QStringLiteral("TogaII"); 0143 names << QStringLiteral("TogaII v.1.4.2"); 0144 names << QStringLiteral("Glaurung"); 0145 names << QStringLiteral("HoiChess"); 0146 0147 QStringList commands; 0148 commands << QStringLiteral("gnuchess"); 0149 commands << QStringLiteral("crafty"); 0150 commands << QStringLiteral("stockfish"); 0151 commands << QStringLiteral("stockfish14"); 0152 commands << QStringLiteral("stockfish16"); 0153 commands << QStringLiteral("stockfish17"); 0154 commands << QStringLiteral("stockfish18"); 0155 commands << QStringLiteral("stockfish19"); 0156 commands << QStringLiteral("stockfish20"); 0157 commands << QStringLiteral("sjeng"); 0158 commands << QStringLiteral("phalanx"); 0159 commands << QStringLiteral("fruit"); 0160 commands << QStringLiteral("fruit21"); 0161 commands << QStringLiteral("toga2"); 0162 commands << QStringLiteral("togaII-142"); //openSUSE naming convention 0163 commands << QStringLiteral("glaurung"); 0164 commands << QStringLiteral("hoichess"); 0165 0166 QList<EngineConfiguration::Interface> interfaces; 0167 interfaces << EngineConfiguration::XBoard; //gnuchess 0168 interfaces << EngineConfiguration::XBoard; //crafty 0169 interfaces << EngineConfiguration::Uci; //stockfish 0170 interfaces << EngineConfiguration::Uci; //stockfish14 0171 interfaces << EngineConfiguration::Uci; //stockfish16 0172 interfaces << EngineConfiguration::Uci; //stockfish17 0173 interfaces << EngineConfiguration::Uci; //stockfish18 0174 interfaces << EngineConfiguration::Uci; //stockfish19 0175 interfaces << EngineConfiguration::Uci; //stockfish20 0176 interfaces << EngineConfiguration::XBoard; //sjeng 0177 interfaces << EngineConfiguration::XBoard; //phalanx //TODO: check this 0178 interfaces << EngineConfiguration::Uci; //fruit 0179 interfaces << EngineConfiguration::Uci; //fruit21 0180 interfaces << EngineConfiguration::Uci; //toga2 0181 interfaces << EngineConfiguration::Uci; //togaII-142 0182 interfaces << EngineConfiguration::Uci; //glaurung 0183 interfaces << EngineConfiguration::XBoard; //hoichess 0184 0185 //remove all available engines first 0186 ui->tableWidget->setRowCount(0); 0187 0188 //check the presence of the known engines defined above and add the corresponding entries in the table widget 0189 for (int i = 0; i < commands.size(); ++i) { 0190 const QString& command = commands.at(i); 0191 const bool exists = !QStandardPaths::findExecutable(command).isEmpty(); 0192 if (!exists) 0193 continue; 0194 0195 const int row = ui->tableWidget->rowCount(); 0196 ui->tableWidget->insertRow(row); 0197 0198 //name 0199 QTableWidgetItem* item = new QTableWidgetItem(names.at(i)); 0200 ui->tableWidget->setItem(row, NameColumn, item); 0201 item->setFlags(item->flags() & (~Qt::ItemIsEditable)); 0202 0203 //command 0204 item = new QTableWidgetItem(command); 0205 ui->tableWidget->setItem(row, CommandColumn, item); 0206 item->setFlags(item->flags() & (~Qt::ItemIsEditable)); 0207 0208 //interface 0209 const QString interface = (interfaces.at(i) == EngineConfiguration::XBoard) ? QStringLiteral("XBoard") : QStringLiteral("UCI"); 0210 item = new QTableWidgetItem(interface); 0211 ui->tableWidget->setItem(row, ProtocolColumn, item); 0212 item->setFlags(item->flags() & (~Qt::ItemIsEditable)); 0213 0214 //icon 0215 QLabel* label = new QLabel(this); 0216 label->setPixmap( QIcon::fromTheme(QStringLiteral("dialog-ok")).pixmap(32, 32) ); 0217 ui->tableWidget->setCellWidget(row, InstalledColumn, label); 0218 } 0219 } 0220 0221 void EngineSettings::save() { 0222 QStringList out; 0223 for ( int i = 0; i < ui->tableWidget->rowCount(); ++i ) { 0224 EngineConfiguration c = EngineConfiguration ( QString() ); 0225 0226 //name 0227 QTableWidgetItem* item = ui->tableWidget->item (i, NameColumn); 0228 if (!item) continue; 0229 c.name = item->text(); 0230 0231 //command 0232 item = ui->tableWidget->item (i, CommandColumn); 0233 if (!item) continue; 0234 c.commandLine = item->text(); 0235 0236 //interface 0237 QWidget* w = ui->tableWidget->cellWidget(i, ProtocolColumn); 0238 const KComboBox* box = dynamic_cast<const KComboBox*>(w); 0239 if (box) 0240 c.iface = (EngineConfiguration::Interface)box->currentIndex(); 0241 else if (ui->tableWidget->item(i, ProtocolColumn)->text() == QLatin1String("XBoard")) 0242 c.iface = EngineConfiguration::XBoard; 0243 else 0244 c.iface = EngineConfiguration::Uci; 0245 0246 const QString str = c.toString(); 0247 if(!str.isEmpty()) 0248 out << c.toString(); 0249 } 0250 0251 Settings::setEngineConfigurations(out); 0252 } 0253 0254 #include "moc_enginesettings.cpp"