Skip to content

Commit c1eb6fa

Browse files
alweyartoj
authored andcommitted
GUI: Option to use split time controls for White and Black in individual games
Use the new TimeControlWidget in support of TimeControlDialog. Enable second TimeControlWidget for Black on demand. Add timeControl2 to GameSettingsWidget, save/read settings for 2nd control. Add extra control logic for hourglass mode. GUI: Option to use individual time controls in tournaments Add a context menu to the tournament players' list. Add function to edit time controls individually. Use a simplified time control dialog (2nd time control unused). Add QVector of individual time controls to NewTournamentDialog. Support multi-engine selection for time control updates. Use an individual time control when valid else tournament controls. At tournament creation hourglass mode is enabled or disabled uniformly according to the tournament's common settings.
1 parent c4afd36 commit c1eb6fa

12 files changed

+809
-409
lines changed

projects/gui/src/gamesettingswidget.cpp

Lines changed: 50 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,7 @@
3131
GameSettingsWidget::GameSettingsWidget(QWidget *parent)
3232
: QWidget(parent),
3333
ui(new Ui::GameSettingsWidget),
34+
m_splitTimeControls(false),
3435
m_board(nullptr),
3536
m_isValid(true)
3637
{
@@ -46,6 +47,9 @@ GameSettingsWidget::GameSettingsWidget(QWidget *parent)
4647
this, SLOT(showTimeControlDialog()));
4748
m_timeControl.setMovesPerTc(40);
4849
m_timeControl.setTimePerTc(300000);
50+
m_timeControl2.setMovesPerTc(40);
51+
m_timeControl2.setTimePerTc(300000);
52+
4953
ui->m_timeControlBtn->setText(m_timeControl.toVerboseString());
5054

5155
connect(ui->m_browseOpeningSuiteBtn, &QPushButton::clicked, this, [=]()
@@ -129,6 +133,11 @@ TimeControl GameSettingsWidget::timeControl() const
129133
return m_timeControl;
130134
}
131135

136+
TimeControl GameSettingsWidget::timeControl2() const
137+
{
138+
return m_timeControl2;
139+
}
140+
132141
bool GameSettingsWidget::pondering() const
133142
{
134143
return ui->m_ponderingCheck->isChecked();
@@ -231,15 +240,20 @@ void GameSettingsWidget::readSettings()
231240

232241
ui->m_variantCombo->setCurrentText(s.value("variant").toString());
233242
m_timeControl.readSettings(&s);
234-
ui->m_timeControlBtn->setText(m_timeControl.toVerboseString());
243+
244+
s.beginGroup("second_time_control");
245+
m_timeControl2.readSettings(&s);
246+
s.endGroup(); // "second_time_control"
247+
248+
updateButtonText();
235249

236250
s.beginGroup("opening_suite");
237251
ui->m_fenEdit->setText(s.value("fen").toString());
238252
ui->m_openingSuiteEdit->setText(s.value("file").toString());
239253
ui->m_openingSuiteDepthSpin->setValue(s.value("depth", 1).toInt());
240254
if (s.value("random_order").toBool())
241255
ui->m_randomOrderRadio->setChecked(true);
242-
s.endGroup();
256+
s.endGroup(); // "games"
243257

244258
s.beginGroup("opening_book");
245259
ui->m_polyglotFileEdit->setText(s.value("file").toString());
@@ -283,7 +297,12 @@ void GameSettingsWidget::enableSettingsUpdates()
283297
QSettings s;
284298
s.beginGroup("games");
285299
m_timeControl.writeSettings(&s);
286-
s.endGroup();
300+
301+
s.beginGroup("second_time_control");
302+
m_timeControl2.writeSettings(&s);
303+
s.endGroup(); // "second_time_control"
304+
305+
s.endGroup(); // "games"
287306
});
288307

289308
connect(ui->m_tbCheck, &QCheckBox::toggled, [=](bool checked)
@@ -417,13 +436,38 @@ void GameSettingsWidget::validateFen(const QString& fen)
417436
}
418437
}
419438

439+
void GameSettingsWidget::updateButtonText()
440+
{
441+
QString str(m_timeControl.toVerboseString());
442+
443+
if (!(m_timeControl == m_timeControl2) && m_splitTimeControls)
444+
str += " vs " + m_timeControl2.toVerboseString();
445+
446+
ui->m_timeControlBtn->setText(str);
447+
}
448+
449+
void GameSettingsWidget::enableSplitTimeControls(bool enable)
450+
{
451+
m_splitTimeControls = enable;
452+
updateButtonText();
453+
}
454+
420455
void GameSettingsWidget::showTimeControlDialog()
421456
{
422-
TimeControlDialog dlg(m_timeControl);
457+
TimeControlDialog dlg(m_timeControl,
458+
m_splitTimeControls ? m_timeControl2 : TimeControl());
459+
423460
if (dlg.exec() == QDialog::Accepted)
424461
{
425-
m_timeControl = dlg.timeControl();
426-
ui->m_timeControlBtn->setText(m_timeControl.toVerboseString());
462+
m_timeControl = dlg.timeControlWhite();
463+
m_timeControl2 = dlg.timeControlBlack();
464+
QString str(m_timeControl.toVerboseString());
465+
466+
if (!(m_timeControl == m_timeControl2))
467+
str += " vs " + m_timeControl2.toVerboseString();
468+
469+
ui->m_timeControlBtn->setText(str);
470+
427471
emit timeControlChanged();
428472
}
429473
}

projects/gui/src/gamesettingswidget.h

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -43,6 +43,7 @@ class GameSettingsWidget : public QWidget
4343

4444
QString chessVariant() const;
4545
TimeControl timeControl() const;
46+
TimeControl timeControl2() const;
4647
bool pondering() const;
4748
GameAdjudicator adjudicator() const;
4849
OpeningSuite* openingSuite() const;
@@ -53,6 +54,7 @@ class GameSettingsWidget : public QWidget
5354

5455
void applyEngineConfiguration(EngineConfiguration* config);
5556
void enableSettingsUpdates();
57+
void enableSplitTimeControls(bool enable);
5658

5759
public slots:
5860
void onHumanCountChanged(int count);
@@ -68,9 +70,12 @@ class GameSettingsWidget : public QWidget
6870

6971
private:
7072
void readSettings();
73+
void updateButtonText();
7174

7275
Ui::GameSettingsWidget *ui;
76+
bool m_splitTimeControls;
7377
TimeControl m_timeControl;
78+
TimeControl m_timeControl2;
7479
Chess::Board* m_board;
7580
QPalette m_defaultPalette;
7681
bool m_isValid;

projects/gui/src/newgamedlg.cpp

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -47,6 +47,7 @@ NewGameDialog::NewGameDialog(EngineManager* engineManager, QWidget* parent)
4747
{
4848
Q_ASSERT(engineManager != nullptr);
4949
ui->setupUi(this);
50+
ui->m_gameSettings->enableSplitTimeControls(true);
5051

5152
m_engines = new EngineConfigurationModel(m_engineManager, this);
5253
#if 0
@@ -112,7 +113,9 @@ ChessGame* NewGameDialog::createGame() const
112113
pgn->setSite(QSettings().value("pgn/site").toString());
113114
auto game = new ChessGame(board, pgn);
114115

115-
game->setTimeControl(ui->m_gameSettings->timeControl());
116+
game->setTimeControl(ui->m_gameSettings->timeControl(), Chess::Side::White);
117+
game->setTimeControl(ui->m_gameSettings->timeControl2(), Chess::Side::Black);
118+
116119
game->setAdjudicator(ui->m_gameSettings->adjudicator());
117120

118121
auto suite = ui->m_gameSettings->openingSuite();

projects/gui/src/newtournamentdialog.cpp

Lines changed: 56 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@
2020

2121
#include <QFileDialog>
2222
#include <QSettings>
23+
#include <QMenu>
2324
#include <functional>
2425
#include <algorithm>
2526

@@ -112,6 +113,10 @@ NewTournamentDialog::NewTournamentDialog(EngineManager* engineManager,
112113
connect(ui->m_playersList, SIGNAL(doubleClicked(QModelIndex)),
113114
this, SLOT(configureEngine(QModelIndex)));
114115

116+
ui->m_playersList->setContextMenuPolicy(Qt::ContextMenuPolicy::CustomContextMenu);
117+
connect(ui->m_playersList, SIGNAL(customContextMenuRequested(const QPoint&)),
118+
this, SLOT(onContextMenuRequest()));
119+
115120
ui->buttonBox->button(QDialogButtonBox::Ok)->setEnabled(false);
116121
connect(ui->m_gameSettings, &GameSettingsWidget::statusChanged, [=](bool ok)
117122
{
@@ -136,6 +141,7 @@ void NewTournamentDialog::addEngineOnDblClick(const QModelIndex& index)
136141
const QModelIndex& idx = m_proxyModel->mapToSource(index);
137142

138143
m_addedEnginesManager->addEngine(m_srcEngineManager->engineAt(idx.row()));
144+
m_timeControls << TimeControl();
139145
listView->selectionModel()->select(index, QItemSelectionModel::Deselect);
140146

141147
QPushButton* button = ui->buttonBox->button(QDialogButtonBox::Ok);
@@ -157,7 +163,10 @@ void NewTournamentDialog::addEngine()
157163

158164
const QModelIndexList list(dlg.selection().indexes());
159165
for (const QModelIndex& index : list)
166+
{
160167
m_addedEnginesManager->addEngine(m_srcEngineManager->engineAt(index.row()));
168+
m_timeControls << TimeControl();
169+
}
161170

162171
QPushButton* button = ui->buttonBox->button(QDialogButtonBox::Ok);
163172
button->setEnabled(canStart());
@@ -176,7 +185,10 @@ void NewTournamentDialog::removeEngine()
176185
});
177186

178187
for (const QModelIndex& index : qAsConst(selected))
188+
{
179189
m_addedEnginesManager->removeEngineAt(index.row());
190+
m_timeControls.remove(index.row());
191+
}
180192

181193
QPushButton* button = ui->buttonBox->button(QDialogButtonBox::Ok);
182194
button->setEnabled(canStart());
@@ -207,10 +219,14 @@ void NewTournamentDialog::moveEngine(int offset)
207219
int row1 = index.row();
208220
int row2 = row1 + offset;
209221
EngineConfiguration tmp(m_addedEnginesManager->engineAt(row1));
222+
TimeControl tc = m_timeControls.at(row1);
210223

211224
m_addedEnginesManager->updateEngineAt(row1, m_addedEnginesManager->engineAt(row2));
212225
m_addedEnginesManager->updateEngineAt(row2, tmp);
213226

227+
m_timeControls[row1] = m_timeControls.at(row2);
228+
m_timeControls[row2]= tc;
229+
214230
ui->m_playersList->setCurrentIndex(index.sibling(row2, 0));
215231
}
216232

@@ -264,6 +280,37 @@ void NewTournamentDialog::onPlayerSelectionChanged(const QItemSelection& selecte
264280
ui->m_moveEngineDownBtn->setEnabled(enable && i < m_addedEnginesManager->engineCount() - 1);
265281
}
266282

283+
void NewTournamentDialog::onContextMenuRequest()
284+
{
285+
QList<QModelIndex> selected = ui->m_playersList->selectionModel()->selectedRows();
286+
if (selected.isEmpty())
287+
return;
288+
289+
QMenu menu(ui->m_playersList);
290+
291+
auto editTimeControlAct = menu.addAction(tr("Edit Time Control"));
292+
connect(editTimeControlAct, &QAction::triggered, this, [=]()
293+
{
294+
int i = selected.first().row();
295+
TimeControl tc {m_timeControls.at(i)};
296+
if (!tc.isValid())
297+
tc = ui->m_gameSettings->timeControl();
298+
299+
auto dlg = new TimeControlDialog(tc);
300+
QString name {m_addedEnginesManager->engines().at(i).name()};
301+
if (selected.count() > 1)
302+
name.append(tr(" - %0 engines").arg(selected.count()));
303+
dlg->setWindowTitle(tr("Time Control - %0").arg(name));
304+
305+
if (dlg->exec() == QDialog::Accepted)
306+
for (QModelIndex index: selected)
307+
m_timeControls[index.row()] = dlg->timeControlWhite();
308+
delete dlg;
309+
});
310+
311+
menu.exec(QCursor::pos());
312+
}
313+
267314
Tournament* NewTournamentDialog::createTournament(GameManager* gameManager) const
268315
{
269316
Q_ASSERT(gameManager != nullptr);
@@ -301,12 +348,19 @@ Tournament* NewTournamentDialog::createTournament(GameManager* gameManager) cons
301348
t->setReverseSides(ts->reversingSchedule());
302349
t->setResultFormat(ts->resultFormat());
303350

351+
bool isHourglass = ui->m_gameSettings->timeControl().isHourglass();
352+
304353
const auto engines = m_addedEnginesManager->engines();
305-
for (EngineConfiguration config : engines)
354+
for (int i = 0; i < engines.count(); i++)
306355
{
356+
EngineConfiguration config = engines.at(i);
307357
ui->m_gameSettings->applyEngineConfiguration(&config);
358+
TimeControl tc = m_timeControls.at(i);
359+
// Hourglass mode must be the same for all players
360+
tc.setHourglass(isHourglass);
361+
308362
t->addPlayer(new EngineBuilder(config),
309-
ui->m_gameSettings->timeControl(),
363+
tc.isValid() ? tc : ui->m_gameSettings->timeControl(),
310364
book,
311365
bookDepth);
312366
}

projects/gui/src/newtournamentdialog.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -53,6 +53,7 @@ class NewTournamentDialog : public QDialog
5353
void onVariantChanged(const QString& variant);
5454
void onPlayerSelectionChanged(const QItemSelection& selected,
5555
const QItemSelection& deselected);
56+
void onContextMenuRequest();
5657

5758
private:
5859
void moveEngine(int offset);
@@ -64,6 +65,7 @@ class NewTournamentDialog : public QDialog
6465
EngineConfigurationModel* m_srcEnginesModel;
6566
EngineConfigurationModel* m_addedEnginesModel;
6667
EngineConfigurationProxyModel* m_proxyModel;
68+
QVector<TimeControl> m_timeControls;
6769
Ui::NewTournamentDialog* ui;
6870
};
6971

projects/gui/src/settingsdlg.cpp

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,7 @@ SettingsDialog::SettingsDialog(QWidget* parent)
2929
ui(new Ui::SettingsDialog)
3030
{
3131
ui->setupUi(this);
32+
ui->m_gameSettings->enableSplitTimeControls(true);
3233

3334
readSettings();
3435

0 commit comments

Comments
 (0)