2 This file is part of SloppyGUI.
4 SloppyGUI 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 SloppyGUI 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 SloppyGUI. If not, see <http://www.gnu.org/licenses/>.
20 #include <QApplication>
21 #include <QVBoxLayout>
22 #include <QHBoxLayout>
24 #include <chessgame.h>
25 #include <chessplayer.h>
26 #include <xboardengine.h>
27 #include <uciengine.h>
28 #include <timecontrol.h>
29 #include <engineconfiguration.h>
31 #include "mainwindow.h"
32 #include "graphicschessboarditem.h"
33 #include "chessboardview.h"
34 #include "newgamedlg.h"
35 #include "chessclock.h"
36 #include "engineconfigurationmodel.h"
37 #include "enginemanagementdlg.h"
39 MainWindow::MainWindow()
41 QHBoxLayout
* clockLayout
= new QHBoxLayout();
42 for (int i
= 0; i
< 2; i
++)
44 m_chessClock
[i
] = new ChessClock();
45 clockLayout
->addWidget(m_chessClock
[i
]);
48 m_chessboardView
= new ChessboardView
;
49 m_chessboardScene
= new QGraphicsScene(m_chessboardView
);
50 m_chessboardView
->setScene(m_chessboardScene
);
51 m_chessboardView
->setMinimumSize(400, 400);
53 QVBoxLayout
* mainLayout
= new QVBoxLayout();
54 mainLayout
->addLayout(clockLayout
);
55 mainLayout
->addWidget(m_chessboardView
);
57 m_visualChessboard
= new GraphicsChessboardItem();
58 m_chessboardScene
->addItem(m_visualChessboard
);
60 QWidget
* mainWidget
= new QWidget(this);
61 mainWidget
->setLayout(mainLayout
);
62 setCentralWidget(mainWidget
);
64 setStatusBar(new QStatusBar());
66 m_engineConfigurations
= new EngineConfigurationModel(this);
76 void MainWindow::closeEvent(QCloseEvent
* event
)
82 void MainWindow::createActions()
84 m_newGameAct
= new QAction(tr("&New game..."), this);
85 m_newGameAct
->setShortcut(QKeySequence("Ctrl+N"));
87 m_printGameAct
= new QAction(tr("&Print..."), this);
89 m_quitGameAct
= new QAction(tr("&Quit"), this);
90 m_quitGameAct
->setShortcut(QKeySequence(tr("Ctrl+Q")));
92 m_manageEnginesAct
= new QAction(tr("Manage..."), this);
94 connect(m_newGameAct
, SIGNAL(triggered(bool)), this, SLOT(newGame()));
95 connect(m_printGameAct
, SIGNAL(triggered(bool)), this, SLOT(printGame()));
96 connect(m_quitGameAct
, SIGNAL(triggered(bool)), this, SLOT(close()));
98 connect (m_manageEnginesAct
, SIGNAL(triggered(bool)), this,
99 SLOT(manageEngines()));
102 void MainWindow::createMenus()
104 m_gameMenu
= menuBar()->addMenu(tr("&Game"));
105 m_gameMenu
->addAction(m_newGameAct
);
106 m_gameMenu
->addSeparator();
107 m_gameMenu
->addAction(m_printGameAct
);
108 m_gameMenu
->addSeparator();
109 m_gameMenu
->addAction(m_quitGameAct
);
111 m_viewMenu
= menuBar()->addMenu(tr("&View"));
113 m_enginesMenu
= menuBar()->addMenu(tr("En&gines"));
114 m_enginesMenu
->addAction(m_manageEnginesAct
);
116 m_helpMenu
= menuBar()->addMenu(tr("&Help"));
118 m_debugMenu
= menuBar()->addMenu("&Debug");
121 void MainWindow::createToolBars()
123 // Create tool bars here, use actions from createActions()
124 // See: createActions(), QToolBar documentation
127 void MainWindow::createDockWindows()
130 QDockWidget
* logDock
= new QDockWidget(tr("Log"), this);
131 QTextEdit
* logTextEdit
= new QTextEdit(logDock
);
132 logTextEdit
->setReadOnly(true);
133 logDock
->setWidget(logTextEdit
);
135 addDockWidget(Qt::BottomDockWidgetArea
, logDock
);
138 QDockWidget
* engineDebugDock
= new QDockWidget(tr("Engine Debug"), this);
139 m_engineDebugTextEdit
= new QTextEdit(engineDebugDock
);
140 m_engineDebugTextEdit
->setReadOnly(true);
141 engineDebugDock
->setWidget(m_engineDebugTextEdit
);
143 addDockWidget(Qt::BottomDockWidgetArea
, engineDebugDock
);
146 void MainWindow::writeSettings()
148 QSettings
settings(QSettings::IniFormat
, QSettings::UserScope
,
149 QCoreApplication::organizationName(),
150 QCoreApplication::applicationName());
152 const QList
<EngineConfiguration
> engines
= m_engineConfigurations
->configurations();
154 settings
.beginWriteArray("engines");
155 for (int i
= 0; i
< engines
.size(); i
++)
157 settings
.setArrayIndex(i
);
158 settings
.setValue("name", engines
.at(i
).name());
159 settings
.setValue("command", engines
.at(i
).command());
160 settings
.setValue("working_directory", engines
.at(i
).workingDirectory());
161 settings
.setValue("protocol", engines
.at(i
).protocol());
166 void MainWindow::readSettings()
168 QSettings
settings(QSettings::IniFormat
, QSettings::UserScope
,
169 QCoreApplication::organizationName(),
170 QCoreApplication::applicationName());
172 int size
= settings
.beginReadArray("engines");
173 for (int i
= 0; i
< size
; i
++)
175 settings
.setArrayIndex(i
);
176 EngineConfiguration config
;
177 config
.setName(settings
.value("name").toString());
178 config
.setCommand(settings
.value("command").toString());
179 config
.setWorkingDirectory(
180 settings
.value("working_directory").toString());
181 config
.setProtocol(EngineConfiguration::ChessEngineProtocol(
182 settings
.value("protocol").toInt()));
184 m_engineConfigurations
->addConfiguration(config
);
189 void MainWindow::newGame()
191 NewGameDialog
dlg(m_engineConfigurations
, this);
192 if (dlg
.exec() != QDialog::Accepted
)
195 if (dlg
.whitePlayerType() == NewGameDialog::Human
||
196 dlg
.blackPlayerType() == NewGameDialog::Human
)
198 qDebug() << "Human players are not currently supported.";
202 const EngineConfiguration engineConfig
[2] =
204 m_engineConfigurations
->configurations().at(dlg
.selectedWhiteEngine()),
205 m_engineConfigurations
->configurations().at(dlg
.selectedBlackEngine())
208 QProcess
* engineProcess
[2] = { new QProcess(this), new QProcess(this) };
210 // Set up working directories for the engines:
211 // If user hasn't set any directory, use temp
212 for (int i
= 0; i
< 2; i
++)
214 QProcess
* engine
= engineProcess
[i
];
215 const EngineConfiguration
& config
= engineConfig
[i
];
217 if (config
.workingDirectory().isEmpty())
218 engine
->setWorkingDirectory(QDir::tempPath());
220 engine
->setWorkingDirectory(config
.workingDirectory());
222 engine
->start(config
.command());
223 if (!engine
->waitForStarted())
225 qDebug() << "Cannot start the engine process:" << config
.command();
230 ChessGame
* chessgame
= new ChessGame(this);
232 connect(chessgame
, SIGNAL(moveHappened(const Chess::Move
&)),
233 m_visualChessboard
, SLOT(makeMove(const Chess::Move
&)));
235 ChessPlayer
* player
[2] = { 0, 0 };
238 tc
.setTimePerTc(180000);
239 tc
.setMovesPerTc(40);
241 for (int i
= 0; i
< 2; i
++)
243 switch (engineConfig
[i
].protocol())
245 case EngineConfiguration::UCI
:
246 player
[i
] = new UciEngine(engineProcess
[i
], chessgame
->chessboard(), tc
, this);
249 player
[i
] = new XboardEngine(engineProcess
[i
], chessgame
->chessboard(), tc
, this);
253 connect(player
[i
], SIGNAL(startedThinking(int)),
254 m_chessClock
[i
], SLOT(start(int)));
256 connect(player
[i
], SIGNAL(moveMade(const Chess::Move
&)),
257 m_chessClock
[i
], SLOT(stop()));
259 connect(player
[i
], SIGNAL(resign()),
260 m_chessClock
[i
], SLOT(stop()));
262 connect(player
[i
], SIGNAL(debugMessage(const QString
&)),
263 m_engineDebugTextEdit
, SLOT(append(const QString
&)));
266 chessgame
->newGame(player
[0], player
[1]);
269 void MainWindow::printGame()
271 QPrinter
printer(QPrinter::HighResolution
);
273 QPrintDialog
* printDialog
= new QPrintDialog(&printer
, this);
274 printDialog
->setWindowTitle(tr("Print game"));
276 if (printDialog
->exec() != QDialog::Accepted
)
280 painter
.begin(&printer
);
282 m_chessboardView
->render(&painter
);
287 void MainWindow::manageEngines()
289 QList
<EngineConfiguration
> oldConfigurations
=
290 m_engineConfigurations
->configurations();
292 EngineManagementDialog
dlg(m_engineConfigurations
, this);
293 if (dlg
.exec() != QDialog::Accepted
)
295 // Release the engine configurations model and use
296 // the old configurations as base for the new model
297 delete m_engineConfigurations
;
298 m_engineConfigurations
= new EngineConfigurationModel(oldConfigurations
);