Skip to content

Commit e47a8b7

Browse files
committed
Automatically add selected engines at once
Add an "auto add"-button to EngineManagementWidget. Add methods addEngines, onDetectionTimer, and detectEngine to EngineManagementWidget. Add method probe and signal hasError() to EngineConfigurationDialog. Avoid showing warnings by QMessageBox when auto probing. Resolves #687 Resolves #669
1 parent e47db4d commit e47a8b7

File tree

7 files changed

+144
-4
lines changed

7 files changed

+144
-4
lines changed

projects/gui/res/icons/icons.qrc

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,5 +15,6 @@
1515
<file>toolbutton/next_16x16.png</file>
1616
<file>toolbutton/previous_16x16.png</file>
1717
<file>toolbutton/remove_16x16.png</file>
18+
<file>toolbutton/autoadd_16x16.png</file>
1819
</qresource>
1920
</RCC>
468 Bytes
Loading

projects/gui/src/engineconfigurationdlg.cpp

Lines changed: 27 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -307,12 +307,14 @@ void EngineConfigurationDialog::detectEngineOptions()
307307
else
308308
{
309309
m_hasError = true;
310-
QMessageBox::critical(this, tr("Engine Error"), error);
310+
if (isVisible())
311+
QMessageBox::critical(this, tr("Engine Error"), error);
311312

312313
ui->m_detectBtn->setEnabled(true);
313314
ui->m_restoreBtn->setEnabled(true);
314315
ui->m_progressBar->hide();
315316
emit detectionFinished();
317+
emit hasError();
316318
}
317319
}
318320

@@ -343,8 +345,10 @@ void EngineConfigurationDialog::onEngineQuit()
343345
if (m_engine->hasError())
344346
{
345347
m_hasError = true;
346-
QMessageBox::critical(this, tr("Engine Error"),
347-
m_engine->errorString());
348+
if (isVisible())
349+
QMessageBox::critical(this, tr("Engine Error"),
350+
m_engine->errorString());
351+
emit hasError();
348352
}
349353
m_engine->deleteLater();
350354
m_engine = nullptr;
@@ -405,3 +409,23 @@ void EngineConfigurationDialog::restoreDefaults()
405409

406410
m_engineOptionModel->setOptions(m_options);
407411
}
412+
413+
void EngineConfigurationDialog::probe(const QString& filename,
414+
const QString& protocol)
415+
{
416+
setExecutable(filename);
417+
418+
// Handling of duplicate configuration names
419+
int n = 2;
420+
QString name = ui->m_nameEdit->text();
421+
if (m_reservedNames.contains(name))
422+
ui->m_nameEdit->setText(QString("%1 (%2)").arg(name, protocol));
423+
while (m_reservedNames.contains(ui->m_nameEdit->text()))
424+
ui->m_nameEdit->setText(QString("%1 (%2)(%3)").arg(name, protocol).arg(n++));
425+
426+
connect(this, SIGNAL(detectionFinished()),
427+
this, SLOT(onDetectionFinished()));
428+
429+
ui->m_protocolCombo->setCurrentText(protocol);
430+
detectEngineOptions();
431+
}

projects/gui/src/engineconfigurationdlg.h

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -73,9 +73,16 @@ class EngineConfigurationDialog : public QDialog
7373
* warning message.
7474
*/
7575
void setReservedNames(const QSet<QString>& names);
76+
/*!
77+
* Probes the engine executable in \a filename using the
78+
* engine interface \a protocol.
79+
*/
80+
void probe(const QString& filename,
81+
const QString& protocol);
7682

7783
signals:
7884
void detectionFinished();
85+
void hasError();
7986

8087
private slots:
8188
void browseCommand();

projects/gui/src/enginemanagementwidget.cpp

Lines changed: 83 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -26,17 +26,18 @@
2626
#include <algorithm>
2727

2828
#include <enginemanager.h>
29+
#include <enginefactory.h>
2930

3031
#include "cutechessapp.h"
3132
#include "engineconfigurationmodel.h"
3233
#include "engineconfigurationdlg.h"
3334

34-
3535
EngineManagementWidget::EngineManagementWidget(QWidget* parent)
3636
: QWidget(parent),
3737
m_engineManager(CuteChessApplication::instance()->engineManager()),
3838
m_hasChanged(false),
3939
m_filteredModel(new QSortFilterProxyModel(this)),
40+
m_detectionTimer(nullptr),
4041
ui(new Ui::EngineManagementWidget)
4142
{
4243
ui->setupUi(this);
@@ -66,6 +67,9 @@ EngineManagementWidget::EngineManagementWidget(QWidget* parent)
6667
// Configure button
6768
connect(ui->m_configureBtn, SIGNAL(clicked(bool)), this,
6869
SLOT(configureEngine()));
70+
71+
// Auto Add button
72+
connect(ui->m_autoAddBtn, SIGNAL(clicked(bool)), this, SLOT(addEngines()));
6973

7074
// Remove button
7175
connect(ui->m_removeBtn, SIGNAL(clicked(bool)), this, SLOT(removeEngine()));
@@ -79,6 +83,10 @@ EngineManagementWidget::EngineManagementWidget(QWidget* parent)
7983
connect(ui->m_browseDefaultLocationBtn, SIGNAL(clicked()),
8084
this, SLOT(browseDefaultLocation()));
8185

86+
// Auto engine detection timer
87+
connect(&m_detectionTimer, &QTimer::timeout,
88+
this, &EngineManagementWidget::onDetectionTimer);
89+
8290
updateEngineCount();
8391
}
8492

@@ -170,6 +178,80 @@ void EngineManagementWidget::configureEngine(const QModelIndex& index)
170178
dlg->open();
171179
}
172180

181+
void EngineManagementWidget::addEngines()
182+
{
183+
const QStringList& protocols = EngineFactory::protocols();
184+
QString defaultDir = QSettings().value("ui/default_engine_location").toString();
185+
186+
// Use file extensions only on Windows
187+
#ifdef Q_OS_WIN32
188+
const QString filter = tr("Executables (*.exe *.bat *.cmd);;All Files (*.*)");
189+
#else
190+
const QString filter = tr("All Files (*)");
191+
#endif
192+
193+
auto fileDlg = new QFileDialog(
194+
this, tr("Select Engine Executables"),
195+
defaultDir, filter);
196+
fileDlg->setAttribute(Qt::WA_DeleteOnClose);
197+
fileDlg->setFileMode(QFileDialog::ExistingFiles);
198+
fileDlg->setAcceptMode(QFileDialog::AcceptOpen);
199+
200+
connect(fileDlg, &QFileDialog::accepted, [=]()
201+
{
202+
const QStringList& files = fileDlg->selectedFiles();
203+
for (const QString& proto: protocols)
204+
{
205+
for (const auto& file: files)
206+
m_detectionList.append({file, proto});
207+
}
208+
m_detectionTimer.start(50);
209+
});
210+
fileDlg->open();
211+
}
212+
213+
void EngineManagementWidget::onDetectionTimer()
214+
{
215+
if (m_detectionList.isEmpty())
216+
{
217+
m_detectionTimer.stop();
218+
return;
219+
}
220+
DetectionData candidate = m_detectionList.first();
221+
detectEngine(candidate.name, candidate.protocol);
222+
m_detectionList.removeFirst();
223+
}
224+
225+
void EngineManagementWidget::detectEngine(const QString& file,
226+
const QString& proto)
227+
{
228+
// Hidden EngineConfigurationDialog as worker
229+
auto dlg = new EngineConfigurationDialog(
230+
EngineConfigurationDialog::AddEngine, this);
231+
dlg->setReservedNames(m_engineManager->engineNames());
232+
dlg->setAttribute(Qt::WA_DeleteOnClose);
233+
234+
connect(dlg, &EngineConfigurationDialog::finished, [=](int result)
235+
{
236+
auto config = dlg->engineConfiguration();
237+
if (result && config.options().count() > 0)
238+
{
239+
while (m_engineManager->engineNames().contains(config.name()))
240+
config.setName( QString( "%1 (%2)[%3]")
241+
.arg(config.name(), proto).arg(rand(), 8, 16));
242+
m_engineManager->addEngine(config);
243+
m_hasChanged = true;
244+
updateEngineCount();
245+
}
246+
});
247+
connect(dlg, &EngineConfigurationDialog::hasError, [=]()
248+
{
249+
dlg->close();
250+
});
251+
252+
dlg->probe(file, proto);
253+
}
254+
173255
void EngineManagementWidget::removeEngine()
174256
{
175257
const QItemSelection selection =

projects/gui/src/enginemanagementwidget.h

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@
2121

2222
#include <QWidget>
2323
#include <engineconfiguration.h>
24+
#include <QTimer>
2425

2526
class EngineManager;
2627
class QSortFilterProxyModel;
@@ -57,18 +58,29 @@ class EngineManagementWidget : public QWidget
5758
void updateUi();
5859
void updateSearch(const QString& terms);
5960
void addEngine();
61+
void addEngines();
6062
void configureEngine();
6163
void configureEngine(const QModelIndex& index);
6264
void removeEngine();
6365
void cloneEngine();
6466
void browseDefaultLocation();
67+
void onDetectionTimer();
6568

6669
private:
6770
void updateEngineCount();
71+
void detectEngine(const QString& file,
72+
const QString& proto);
6873

6974
EngineManager* m_engineManager;
7075
bool m_hasChanged;
7176
QSortFilterProxyModel* m_filteredModel;
77+
QTimer m_detectionTimer;
78+
struct DetectionData
79+
{
80+
QString name;
81+
QString protocol;
82+
};
83+
QVector<DetectionData> m_detectionList;
7284
Ui::EngineManagementWidget* ui;
7385
};
7486

projects/gui/ui/enginemanagementwidget.ui

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -77,6 +77,20 @@
7777
<property name="spacing">
7878
<number>0</number>
7979
</property>
80+
<item>
81+
<widget class="QToolButton" name="m_autoAddBtn">
82+
<property name="toolTip">
83+
<string>Add multiple new engines</string>
84+
</property>
85+
<property name="text">
86+
<string>++</string>
87+
</property>
88+
<property name="icon">
89+
<iconset resource="../res/icons/icons.qrc">
90+
<normaloff>:/icons/toolbutton/autoadd_16x16.png</normaloff>:/icons/toolbutton/autoadd_16x16.png</iconset>
91+
</property>
92+
</widget>
93+
</item>
8094
<item>
8195
<widget class="QToolButton" name="m_addBtn">
8296
<property name="toolTip">

0 commit comments

Comments
 (0)