2 This file is part of Cute Chess.
4 Cute Chess is free software: you can redistribute it and/or modify
5 it under the terms of the GNU General Public License as published by
6 the Free Software Foundation, either version 3 of the License, or
7 (at your option) any later version.
9 Cute Chess is distributed in the hope that it will be useful,
10 but WITHOUT ANY WARRANTY; without even the implied warranty of
11 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 GNU General Public License for more details.
14 You should have received a copy of the GNU General Public License
15 along with Cute Chess. If not, see <http://www.gnu.org/licenses/>.
20 #include <chessgame.h>
21 #include <chessplayer.h>
22 #include <timecontrol.h>
23 #include <engineconfiguration.h>
24 #include <enginefactory.h>
25 #include <engineprocess.h>
26 #include <humanplayer.h>
28 #include "mainwindow.h"
29 #include "chessboardview.h"
30 #include "chessboardmodel.h"
31 #include "newgamedlg.h"
32 #include "chessclock.h"
33 #include "engineconfigurationmodel.h"
34 #include "enginemanagementdlg.h"
36 MainWindow::MainWindow()
38 setWindowTitle("Cute Chess");
40 QHBoxLayout
* clockLayout
= new QHBoxLayout();
41 for (int i
= 0; i
< 2; i
++)
43 m_chessClock
[i
] = new ChessClock();
44 clockLayout
->addWidget(m_chessClock
[i
]);
47 m_boardModel
= new ChessboardModel(this);
48 m_chessboardView
= new ChessboardView(this);
49 m_chessboardView
->setModel(m_boardModel
);
50 connect(m_boardModel
, SIGNAL(moveMade(const QModelIndex
&, const QModelIndex
&)),
51 m_chessboardView
, SLOT(onMoveMade(const QModelIndex
&, const QModelIndex
&)));
53 QVBoxLayout
* mainLayout
= new QVBoxLayout();
54 mainLayout
->addLayout(clockLayout
);
55 mainLayout
->addWidget(m_chessboardView
);
57 // The content margins look stupid when used with dock widgets. Drop the
58 // margins except from the top so that the chess clocks have spacing
59 mainLayout
->setContentsMargins(0,
60 style()->pixelMetric(QStyle::PM_LayoutTopMargin
), 0, 0);
62 QWidget
* mainWidget
= new QWidget(this);
63 mainWidget
->setLayout(mainLayout
);
64 setCentralWidget(mainWidget
);
66 setStatusBar(new QStatusBar());
68 m_engineConfigurations
= new EngineConfigurationModel(this);
78 void MainWindow::createActions()
80 m_newGameAct
= new QAction(tr("&New game..."), this);
81 m_newGameAct
->setShortcut(QKeySequence("Ctrl+N"));
83 m_printGameAct
= new QAction(tr("&Print..."), this);
85 m_quitGameAct
= new QAction(tr("&Quit"), this);
86 m_quitGameAct
->setShortcut(QKeySequence(tr("Ctrl+Q")));
88 m_manageEnginesAct
= new QAction(tr("Manage..."), this);
90 m_openConfigurationFileAct
= new QAction("Open configuration file", this);
92 connect(m_newGameAct
, SIGNAL(triggered(bool)), this, SLOT(newGame()));
93 connect(m_printGameAct
, SIGNAL(triggered(bool)), this, SLOT(printGame()));
94 connect(m_quitGameAct
, SIGNAL(triggered(bool)), this, SLOT(close()));
96 connect (m_manageEnginesAct
, SIGNAL(triggered(bool)), this,
97 SLOT(manageEngines()));
99 connect(m_openConfigurationFileAct
, SIGNAL(triggered(bool)), this,
100 SLOT(openConfigurationFile()));
103 void MainWindow::createMenus()
105 m_gameMenu
= menuBar()->addMenu(tr("&Game"));
106 m_gameMenu
->addAction(m_newGameAct
);
107 m_gameMenu
->addSeparator();
108 m_gameMenu
->addAction(m_printGameAct
);
109 m_gameMenu
->addSeparator();
110 m_gameMenu
->addAction(m_quitGameAct
);
112 m_viewMenu
= menuBar()->addMenu(tr("&View"));
114 m_enginesMenu
= menuBar()->addMenu(tr("En&gines"));
115 m_enginesMenu
->addAction(m_manageEnginesAct
);
117 m_helpMenu
= menuBar()->addMenu(tr("&Help"));
119 m_debugMenu
= menuBar()->addMenu("&Debug");
120 m_debugMenu
->addAction(m_openConfigurationFileAct
);
123 void MainWindow::createToolBars()
125 // Create tool bars here, use actions from createActions()
126 // See: createActions(), QToolBar documentation
129 void MainWindow::createDockWindows()
132 QDockWidget
* logDock
= new QDockWidget(tr("Log"), this);
133 QTextEdit
* logTextEdit
= new QTextEdit(logDock
);
134 logTextEdit
->setReadOnly(true);
135 logDock
->setWidget(logTextEdit
);
137 addDockWidget(Qt::BottomDockWidgetArea
, logDock
);
140 QDockWidget
* engineDebugDock
= new QDockWidget(tr("Engine Debug"), this);
141 m_engineDebugTextEdit
= new QTextEdit(engineDebugDock
);
142 m_engineDebugTextEdit
->setReadOnly(true);
143 engineDebugDock
->setWidget(m_engineDebugTextEdit
);
145 addDockWidget(Qt::BottomDockWidgetArea
, engineDebugDock
);
148 void MainWindow::readSettings()
152 int size
= settings
.beginReadArray("engines");
153 for (int i
= 0; i
< size
; i
++)
155 settings
.setArrayIndex(i
);
156 EngineConfiguration config
;
157 config
.setName(settings
.value("name").toString());
158 config
.setCommand(settings
.value("command").toString());
159 config
.setWorkingDirectory(
160 settings
.value("working_directory").toString());
161 config
.setProtocol(ChessEngine::Protocol(
162 settings
.value("protocol").toInt()));
164 m_engineConfigurations
->addConfiguration(config
);
169 void MainWindow::newGame()
171 NewGameDialog
dlg(m_engineConfigurations
, this);
172 if (dlg
.exec() != QDialog::Accepted
)
175 ChessPlayer
* player
[2] = { 0, 0 };
176 ChessGame
* chessgame
= new ChessGame(Chess::Variant::Standard
, this);
179 tc
.setTimePerTc(180000);
180 tc
.setMovesPerTc(40);
182 for (int i
= 0; i
< 2; i
++)
184 Chess::Side side
= (Chess::Side
)i
;
185 if (dlg
.playerType(side
) == NewGameDialog::CPU
)
187 EngineConfiguration config
= m_engineConfigurations
->configuration(dlg
.selectedEngine(side
));
189 QProcess
* process
= new QProcess(this);
191 if (config
.workingDirectory().isEmpty())
192 process
->setWorkingDirectory(QDir::tempPath());
194 process
->setWorkingDirectory(config
.workingDirectory());
196 process
->start(config
.command());
197 if (!process
->waitForStarted())
199 qDebug() << "Cannot start the engine process:" << config
.command();
202 ChessEngine
* engine
= EngineFactory::createEngine(config
.protocol(), process
, this);
204 engine
->setName(config
.name());
209 player
[i
] = new HumanPlayer(this);
210 connect(m_chessboardView
, SIGNAL(humanMove(const BookMove
&)),
211 player
[i
], SLOT(onHumanMove(const BookMove
&)));
214 player
[i
]->setTimeControl(tc
);
215 chessgame
->setPlayer(side
, player
[i
]);
217 connect(player
[i
], SIGNAL(startedThinking(int)),
218 m_chessClock
[i
], SLOT(start(int)));
219 connect(player
[i
], SIGNAL(moveMade(const Chess::Move
&)),
220 m_chessClock
[i
], SLOT(stop()));
221 connect(player
[i
], SIGNAL(humanTurn(bool)),
222 m_chessboardView
, SLOT(setEnabled(bool)));
223 connect(chessgame
, SIGNAL(gameEnded()),
224 m_chessClock
[i
], SLOT(stop()));
225 connect(player
[i
], SIGNAL(debugMessage(const QString
&)),
226 m_engineDebugTextEdit
, SLOT(append(const QString
&)));
229 m_boardModel
->setBoard(chessgame
->board());
233 void MainWindow::printGame()
235 QPrinter
printer(QPrinter::HighResolution
);
237 QPrintDialog
* printDialog
= new QPrintDialog(&printer
, this);
238 printDialog
->setWindowTitle(tr("Print game"));
240 if (printDialog
->exec() != QDialog::Accepted
)
244 painter
.begin(&printer
);
246 m_chessboardView
->render(&painter
);
251 void MainWindow::manageEngines()
253 QList
<EngineConfiguration
> oldConfigurations
=
254 m_engineConfigurations
->configurations();
256 EngineManagementDialog
dlg(m_engineConfigurations
, this);
258 if (dlg
.exec() == QDialog::Accepted
)
262 const QList
<EngineConfiguration
> engines
= m_engineConfigurations
->configurations();
264 settings
.beginWriteArray("engines");
265 for (int i
= 0; i
< engines
.size(); i
++)
267 settings
.setArrayIndex(i
);
268 settings
.setValue("name", engines
.at(i
).name());
269 settings
.setValue("command", engines
.at(i
).command());
270 settings
.setValue("working_directory", engines
.at(i
).workingDirectory());
271 settings
.setValue("protocol", engines
.at(i
).protocol());
275 // Make sure that the settings are flushed to disk now
280 // Release the engine configurations model and use
281 // the old configurations as base for the new model
282 delete m_engineConfigurations
;
283 m_engineConfigurations
= new EngineConfigurationModel(oldConfigurations
);
287 void MainWindow::openConfigurationFile()
291 if (QFile::exists(settings
.fileName()))
292 QDesktopServices::openUrl(QUrl("file://" + settings
.fileName()));
294 qDebug() << "Cannot open configuration file:" << settings
.fileName();