Drop the contents margins from the main window.
[sloppygui.git] / projects / gui / src / mainwindow.cpp
blob28191f56afdb04f011a28530e0b17e72ba026b6b
1 /*
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/>.
18 #include <QtGui>
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);
70 createActions();
71 createMenus();
72 createToolBars();
73 createDockWindows();
75 readSettings();
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()
131 // Log
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);
139 // Engine debug
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()
150 QSettings settings;
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);
166 settings.endArray();
169 void MainWindow::newGame()
171 NewGameDialog dlg(m_engineConfigurations, this);
172 if (dlg.exec() != QDialog::Accepted)
173 return;
175 ChessPlayer* player[2] = { 0, 0 };
176 ChessGame* chessgame = new ChessGame(Chess::Variant::Standard, this);
178 TimeControl tc;
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());
193 else
194 process->setWorkingDirectory(config.workingDirectory());
196 process->start(config.command());
197 if (!process->waitForStarted())
199 qDebug() << "Cannot start the engine process:" << config.command();
200 return;
202 ChessEngine* engine = EngineFactory::createEngine(config.protocol(), process, this);
203 engine->start();
204 engine->setName(config.name());
205 player[i] = engine;
207 else
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());
230 chessgame->start();
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)
241 return;
243 QPainter painter;
244 painter.begin(&printer);
246 m_chessboardView->render(&painter);
248 painter.end();
251 void MainWindow::manageEngines()
253 QList<EngineConfiguration> oldConfigurations =
254 m_engineConfigurations->configurations();
256 EngineManagementDialog dlg(m_engineConfigurations, this);
258 if (dlg.exec() == QDialog::Accepted)
260 QSettings settings;
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());
273 settings.endArray();
275 // Make sure that the settings are flushed to disk now
276 settings.sync();
278 else
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()
289 QSettings settings;
291 if (QFile::exists(settings.fileName()))
292 QDesktopServices::openUrl(QUrl("file://" + settings.fileName()));
293 else
294 qDebug() << "Cannot open configuration file:" << settings.fileName();