Connect more signals on the server side.
[GoMoku3D.git] / src / gui / MainWindow.cpp
blob4557356f92c8ee7f4984443d95f9e6d894a49f57
1 /********************************************************************
3 * Copyright (C) 2008 Davide Pesavento and Daniele Battaglia
5 * This file is part of GoMoku3D.
7 * GoMoku3D is free software; you can redistribute it and/or
8 * modify it under the terms of the GNU General Public License
9 * as published by the Free Software Foundation; either version 2
10 * of the License, or (at your option) any later version.
12 * GoMoku3D is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 * GNU General Public License for more details.
17 * You should have received a copy of the GNU General Public License
18 * along with GoMoku3D. If not, see <http://www.gnu.org/licenses/>.
20 *******************************************************************/
22 #include <QMessageBox>
23 #include <QFileDialog>
24 #include <QXmlStreamReader>
25 #include <QXmlStreamWriter>
27 #include "MainWindow.h"
28 #include "GameLoop.h"
29 #include "GameMatrix.h"
30 #include "AIPlayer.h"
31 #include "RemotePlayer.h"
32 #include "HumanPlayer.h"
33 #include "RenderWidget.h"
34 #include "HistoryModel.h"
35 #include "ChatWidget.h"
36 #include "TimerWidget.h"
37 #include "Network.h"
38 #include "OnlineDialog.h"
39 #include "Suggester.h"
40 #include "SettingsManager.h"
41 #include "GUISettings.h"
42 #include "Preferences.h"
43 #include "PlayersWidget.h"
44 #include "StandAloneDialog.h"
45 #include "ServerSettingsDialog.h"
47 MainWindow::MainWindow() : QMainWindow(), Ui_MainWindow(*this)
49 _loop = 0;
50 _net = 0;
51 _settings = 0;
52 _suggester = 0;
53 _history = 0;
54 _actualPlayerIndex = -1;
55 _isStandAloneGame = false;
56 _isOnlineGame = false;
57 _isServerGame = false;
58 _isDedicatedServer = false;
60 setupUi(this);
62 _render = new RenderWidget(this);
63 setCentralWidget(_render);
65 QDockWidget *playersDock = new QDockWidget(this);
66 QDockWidget *historyDock = new QDockWidget(this);
67 QDockWidget *timerDock = new QDockWidget(this);
68 QDockWidget *chatDock = new QDockWidget(this);
69 playersDock->setWindowTitle(tr("Players' Info"));
70 historyDock->setWindowTitle(tr("History"));
71 timerDock->setWindowTitle(tr("Timer"));
72 chatDock->setWindowTitle(tr("Chat"));
73 playersDock->setFeatures(QDockWidget::DockWidgetMovable | QDockWidget::DockWidgetFloatable);
74 historyDock->setFeatures(QDockWidget::DockWidgetMovable | QDockWidget::DockWidgetFloatable);
75 timerDock->setFeatures(QDockWidget::DockWidgetMovable | QDockWidget::DockWidgetFloatable);
76 chatDock->setFeatures(QDockWidget::DockWidgetMovable | QDockWidget::DockWidgetFloatable);
77 historyDock->setAllowedAreas(Qt::LeftDockWidgetArea | Qt::RightDockWidgetArea);
78 timerDock->setAllowedAreas(Qt::LeftDockWidgetArea | Qt::RightDockWidgetArea);
79 chatDock->setAllowedAreas(Qt::LeftDockWidgetArea | Qt::RightDockWidgetArea);
80 _playersWidget = new PlayersWidget(playersDock);
81 _historyView = new QTableView(historyDock);
82 _timer = new TimerWidget(timerDock);
83 _chat = new ChatWidget(chatDock);
84 playersDock->setWidget(_playersWidget);
85 historyDock->setWidget(_historyView);
86 timerDock->setWidget(_timer);
87 chatDock->setWidget(_chat);
88 addDockWidget(Qt::LeftDockWidgetArea, playersDock);
89 addDockWidget(Qt::LeftDockWidgetArea, historyDock);
90 addDockWidget(Qt::RightDockWidgetArea, timerDock);
91 addDockWidget(Qt::RightDockWidgetArea, chatDock);
93 connect(_historyView, SIGNAL(doubleClicked(QModelIndex)), this, SLOT(undoMoves(QModelIndex)));
94 connect(_historyView, SIGNAL(clicked(QModelIndex)), this, SLOT(showPastGameStatus(QModelIndex)));
95 connect(actionShow_last_move, SIGNAL(triggered()), this, SLOT(showLastMove()));
96 connect(actionSuggest_move, SIGNAL(triggered()), this, SLOT(suggestMove()));
97 connect(actionTake_back_move, SIGNAL(triggered()), this, SLOT(undoTurn()));
98 connect(actionHost_Game, SIGNAL(triggered()), this, SLOT(newServerGame()));
99 connect(actionConnect_To_Server, SIGNAL(triggered()), this, SLOT(newOnlineGame()));
100 connect(actionNew_local_game,SIGNAL(triggered()), this, SLOT(newStandAloneGame()));
101 connect(actionAbout_Qt, SIGNAL(triggered()), qApp, SLOT(aboutQt()));
102 connect(actionPreferences, SIGNAL(triggered()), this, SLOT(showPreferences()));
103 connect(actionQuit, SIGNAL(triggered()), this, SLOT(close()));
104 connect(actionSave_game, SIGNAL(triggered()), this, SLOT(saveGame()));
107 MainWindow::~MainWindow()
109 GUISettings set;
110 set.setGeometry(this->saveGeometry());
111 //set.setDockState(this->saveState());
113 if (_loop != 0) {
114 _loop->stop();
117 delete _render;
119 if (_suggester != 0) {
120 _suggester->wait();
121 _suggester->deleteLater();
124 if (_loop != 0) {
125 _loop->wait();
126 _loop->deleteLater();
129 if (_net != 0) {
130 delete _net;
133 //TODO c'e' altro da fare?
136 void MainWindow::drawMove(Move move)
138 if (_playersInfo.isEmpty()) {
139 return;
142 QColor color;
143 if (move.playerId() == 0) {
144 color = _playersInfo.at(0).color();
146 if (move.playerId() == 1) {
147 color = _playersInfo.at(1).color();
149 if (move.playerId() == 2) {
150 color = _playersInfo.at(2).color();
153 if (!_isDedicatedServer) {
154 bool ok = move.isValid();
155 if (ok) {
156 _history->append(move);
157 if (!_actualViewIndex.isValid() || (_actualViewIndex.row() == _history->moveList().size() - 2)) {
158 _render->drawMove(move.point(), color);
159 _actualViewIndex = _history->index(_history->moveList().size() - 1, 0);
161 actionShow_last_move->setEnabled(true);
162 if (_isStandAloneGame) {
163 actionTake_back_move->setEnabled(true);
165 // TODO c'e' altro da fare?
167 else {
168 // TODO messaggio di errore
169 // se alla drawMove arriva un point nullo cosa vuol dire?
170 // - dal network: scaduto il timer del giocatore
171 // - quando viene rilasciato il lock in fase di distruzione ma non dovrebbe succedere niente
172 QMessageBox::information(this, tr("Game Ended"), tr("Timer expired:\n%1 lost the game.").arg(_playersInfo.at(move.playerId()).name()), QMessageBox::Ok);
173 _render->acceptMove(false);
174 disableOnEndGame();
176 } else {
177 actionShow_last_move->setEnabled(false);
178 actionTake_back_move->setEnabled(false);
182 QModelIndex MainWindow::actualViewIndex() const
184 return _actualViewIndex;
187 bool MainWindow::askUserConfirmation()
189 QMessageBox::StandardButton result = QMessageBox::question(this,
190 tr("Abandon Game?"),
191 tr("If you continue, the current\ngame will be lost.\n\nAre you sure you want to continue?"),
192 QMessageBox::Yes | QMessageBox::No);
194 if (result == QMessageBox::Yes) {
195 return true;
196 } else {
197 return false;
201 void MainWindow::newStandAloneGame()
203 if (_loop != 0 && !askUserConfirmation()) {
204 return;
207 resetOnNewGame();
209 qobject_cast<QDockWidget*>(_timer->parent())->setVisible(false);
210 qobject_cast<QDockWidget*>(_chat->parent())->setVisible(false);
211 qobject_cast<QDockWidget*>(_playersWidget->parent())->setVisible(true);
213 StandAloneDialog dialog(this);
214 dialog.exec();
215 if (dialog.result() == QDialog::Rejected) {
216 return;
219 _isStandAloneGame = true;
221 // abilito alcune voci del menu
222 actionLoad_game->setEnabled(true);
223 actionSave_game->setEnabled(true);
225 int d1 = dialog.d1Box->currentText().toInt();
226 int d2 = dialog.d2Box->currentText().toInt();
227 int numPlayers = dialog.numPlayersBox->currentText().toInt();
228 Q_ASSERT(d1 != 0);
229 Q_ASSERT(d2 != 0);
230 Q_ASSERT(numPlayers != 0);
231 GameMatrix::create(d1, d2, numPlayers);
232 Q_ASSERT(GameMatrix::instance() != 0);
234 _render->init(d1 * d2);
236 QString type;
237 QList<Player*> players;
238 if (dialog.human_0->isChecked()) {
239 type = "H";
240 players.append(new HumanPlayer(0, _render));
242 else {
243 type = "A";
244 players.append(new AIPlayer(0));
246 _playersInfo.append(PlayerInfo(dialog.playername_0->text(), dialog.color_0->palette().color(QPalette::Button), type));
248 if (dialog.human_1->isChecked()) {
249 type = "H";
250 players.append(new HumanPlayer(1, _render));
252 else {
253 type = "A";
254 players.append(new AIPlayer(1));
256 _playersInfo.append(PlayerInfo(dialog.playername_1->text(), dialog.color_1->palette().color(QPalette::Button), type));
258 if (numPlayers == 3) {
259 if (dialog.human_2->isChecked()) {
260 type = "H";
261 players.append(new HumanPlayer(2, _render));
263 else {
264 type = "A";
265 players.append(new AIPlayer(2));
267 _playersInfo.append(PlayerInfo(dialog.playername_2->text(), dialog.color_2->palette().color(QPalette::Button), type));
270 _playersWidget->set(&_playersInfo);
271 connectAISkillSlider(players);
273 if (_history == 0) {
274 _history = new HistoryModel(this, &_playersInfo);
275 _historyView->setModel(_history);
277 qobject_cast<QDockWidget*>(_historyView->parent())->setVisible(true);
279 //costruisco GL
280 _loop = new GameLoop(players);
281 //move to thread dei player
282 Player *p;
283 foreach (p, players) {
284 p->moveToThread(_loop);
287 connect(actionForce_Move, SIGNAL(triggered()), _loop, SLOT(forceMove()));
288 connect(_loop, SIGNAL(turn(int)), this, SLOT(turn(int)));
289 connect(_loop, SIGNAL(turn(int)), _playersWidget, SLOT(updateTurn(int)));
290 connect(_loop, SIGNAL(moved(Move)), this, SLOT(drawMove(Move)));
291 connect(_loop, SIGNAL(win(int)), this, SLOT(playerWin(int)));
292 connect(_loop, SIGNAL(draw(QList<int>)), this, SLOT(playersDraw(QList<int>)));
294 _loop->start();
297 void MainWindow::newOnlineGame()
299 if (_loop != 0 && !askUserConfirmation()) {
300 return;
303 resetOnNewGame();
305 qobject_cast<QDockWidget*>(_timer->parent())->setVisible(true);
306 qobject_cast<QDockWidget*>(_chat->parent())->setVisible(true);
307 qobject_cast<QDockWidget*>(_playersWidget->parent())->setVisible(true);
309 OnlineDialog dialog(this);
310 dialog.exec();
311 if (dialog.result() == QDialog::Rejected) {
312 if (_net != 0) {
313 delete _net;
314 _net = 0;
316 return;
319 _isOnlineGame = true;
321 //TODO connette i segnali di errore del net con MW
323 //estraggo i dati
324 int d1 = dialog.d1Label->text().toInt();
325 int d2 = dialog.d2Label->text().toInt();
326 int numPlayers = dialog.numPlayersLabel->text().toInt();
327 GameMatrix::create(d1, d2, numPlayers);
329 _render->init(d1 * d2);
331 actionShow_last_move->setEnabled(true);
332 //estraggo e costruisco la lista di playersInfo
333 //costruisco i player
334 QString type;
335 QList<Player*> players;
336 if (dialog.human_0->isChecked()) {
337 type = "H";
338 players.append(new HumanPlayer(0, _render));
340 else {
341 players.append(new RemotePlayer(0, _net));
342 if (dialog.ai_0->isChecked()) {
343 type = "A";
345 else {
346 type = "R";
349 _playersInfo.append(PlayerInfo(dialog.playername_0->text(), dialog.color_0->palette().color(QPalette::Button), type));
350 if (dialog.human_1->isChecked()) {
351 type = "H";
352 players.append(new HumanPlayer(1, _render));
354 else {
355 players.append(new RemotePlayer(1, _net));
356 if (dialog.ai_1->isChecked()) {
357 type = "A";
359 else {
360 type = "R";
363 _playersInfo.append(PlayerInfo(dialog.playername_1->text(), dialog.color_1->palette().color(QPalette::Button), type));
364 if (numPlayers == 3) {
365 if (dialog.human_2->isChecked()) {
366 type = "H";
367 players.append(new HumanPlayer(2, _render));
369 else {
370 players.append(new RemotePlayer(2, _net));
371 if (dialog.ai_2->isChecked()) {
372 type = "A";
374 else {
375 type = "R";
378 _playersInfo.append(PlayerInfo(dialog.playername_2->text(), dialog.color_2->palette().color(QPalette::Button), type));
381 if (_history == 0) {
382 _history = new HistoryModel(this, &_playersInfo);
383 _historyView->setModel(_history);
386 qobject_cast<QDockWidget*>(_historyView->parent())->setVisible(true);
388 _playersWidget->set(&_playersInfo);
390 _net->setupChat(_chat);
392 _timer->setDuration(dialog.timerLabel->text().toInt());
394 //costruisco GL
395 _loop = new GameLoop(players);
396 //move to thread dei player
397 Player *p;
398 foreach (p, players) {
399 p->moveToThread(_loop);
402 _net->setupGameLoop(_loop);
404 //connetto
405 connect(_loop, SIGNAL(turn(int)), this, SLOT(turn(int)));
406 connect(_loop, SIGNAL(turn(int)), _playersWidget, SLOT(updateTurn(int)));
407 connect(_loop, SIGNAL(moved(Move)), this, SLOT(drawMove(Move)));
408 connect(_loop, SIGNAL(win(int)), this, SLOT(playerWin(int)));
409 connect(_loop, SIGNAL(draw(QList<int>)), this, SLOT(playersDraw(QList<int>)));
411 _loop->start();
414 void MainWindow::newServerGame()
416 if (_loop != 0 && !askUserConfirmation()) {
417 return;
420 resetOnNewGame();
421 qobject_cast<QDockWidget*>(_timer->parent())->setVisible(false);
422 qobject_cast<QDockWidget*>(_chat->parent())->setVisible(false);
423 qobject_cast<QDockWidget*>(_playersWidget->parent())->setVisible(false);
424 qobject_cast<QDockWidget*>(_historyView->parent())->setVisible(false);
426 ServerSettingsDialog dialog(this);
427 dialog.exec();
428 if (dialog.result() == QDialog::Rejected) {
429 if (_net != 0) {
430 delete _net;
431 _net = 0;
433 return;
436 int d1 = dialog.d1Box->currentText().toInt();
437 int d2 = dialog.d2Box->currentText().toInt();
438 int numPlayers = dialog.numPlayersBox->currentText().toInt();
440 GameMatrix::create(d1, d2, numPlayers);
442 QString type;
443 QList<Player*> players;
444 if (dialog.human_0->isChecked()) {
445 type = "H";
446 _render->init(d1 * d2);
447 actionShow_last_move->setEnabled(true);
448 players.append(new HumanPlayer(0, _render));
450 else {
451 if (dialog.ai_0->isChecked()) {
452 type = "A";
453 players.append(new AIPlayer(0));
455 else {
456 type = "R";
457 players.append(new RemotePlayer(0, _net));
460 _playersInfo.append(PlayerInfo(dialog.playername_0->text(), dialog.color_0->palette().color(QPalette::Button), type));
461 if (dialog.human_1->isChecked()) {
462 type = "H";
463 _render->init(d1 * d2);
464 actionShow_last_move->setEnabled(true);
465 players.append(new HumanPlayer(1, _render));
467 else {
468 if (dialog.ai_1->isChecked()) {
469 type = "A";
470 players.append(new AIPlayer(1));
472 else {
473 type = "R";
474 players.append(new RemotePlayer(1, _net));
477 _playersInfo.append(PlayerInfo(dialog.playername_1->text(), dialog.color_1->palette().color(QPalette::Button), type));
478 if (numPlayers == 3) {
479 if (dialog.human_2->isChecked()) {
480 type = "H";
481 _render->init(d1 * d2);
482 actionShow_last_move->setEnabled(true);
483 players.append(new HumanPlayer(2, _render));
485 else {
486 if (dialog.ai_2->isChecked()) {
487 type = "A";
488 players.append(new AIPlayer(2));
490 else {
491 type = "R";
492 players.append(new RemotePlayer(2, _net));
495 _playersInfo.append(PlayerInfo(dialog.playername_2->text(), dialog.color_2->palette().color(QPalette::Button), type));
498 //costruisco GL
499 _loop = new GameLoop(players);
500 //move to thread dei player
501 Player *p;
502 foreach (p, players) {
503 p->moveToThread(_loop);
505 connectAISkillSlider(players);
507 _net->setupGameLoop(_loop);
509 bool noHuman = true;
510 for (int i = 0; i < _playersInfo.size(); i++) {
511 if (_playersInfo.at(i).type() == "H") {
512 noHuman = false;
516 //TODO connette i segnali di errore del net con MW
518 if (noHuman && dialog.dedicatedserver->isChecked()) {
519 // modalità server dedicato
520 _isDedicatedServer = true;
521 qobject_cast<QDockWidget*>(_playersWidget->parent())->setVisible(true);
522 // TODO: bisogna connettere qualcosa?
523 } else {
524 // modalità giocatore o spettatore
525 _isServerGame = true;
526 //TODO
527 _net->setupChat(_chat);
528 qobject_cast<QDockWidget*>(_timer->parent())->setVisible(true);
529 qobject_cast<QDockWidget*>(_chat->parent())->setVisible(true);
530 qobject_cast<QDockWidget*>(_playersWidget->parent())->setVisible(true);
531 qobject_cast<QDockWidget*>(_historyView->parent())->setVisible(true);
532 if (_history == 0) {
533 _history = new HistoryModel(this, &_playersInfo);
534 _historyView->setModel(_history);
537 _playersWidget->set(&_playersInfo);
538 _timer->setDuration(dialog.timerSpinBox->value());
540 //connetto
541 connect(_loop, SIGNAL(turn(int)), this, SLOT(turn(int)));
542 connect(_loop, SIGNAL(moved(Move)), this, SLOT(drawMove(Move)));
543 connect(_loop, SIGNAL(win(int)), this, SLOT(playerWin(int)));
544 connect(_loop, SIGNAL(draw(QList<int>)), this, SLOT(playersDraw(QList<int>)));
547 connect(_loop, SIGNAL(turn(int)), _playersWidget, SLOT(updateTurn(int))); //FIXME: perché qui?
549 _loop->start();
552 void MainWindow::showPreferences()
554 Preferences pref(this);
555 int result = pref.exec();
556 if (result == QDialog::Accepted) {
557 _render->updateBackground();
561 void MainWindow::disableOnEndGame()
563 //disabilita menu
564 actionTake_back_move->setEnabled(false);
565 actionSuggest_move->setEnabled(false);
566 actionForce_Move->setEnabled(false);
567 actionSave_game->setEnabled(false);
568 actionShow_last_move->setEnabled(false);
571 void MainWindow::playerWin(int playerId)
573 disableOnEndGame();
574 QMessageBox::information(this, tr("Game Ended"), tr("And the winner is ...\n") + _playersInfo.at(playerId).name() + "!", QMessageBox::Ok);
577 void MainWindow::playersDraw(QList<int> playersIds)
579 disableOnEndGame();
580 QString result;
581 int id;
582 foreach (id, playersIds) {
583 result += "\n - " + _playersInfo.at(id).name();
585 QMessageBox::information(this, tr("Game Ended"), tr("Game ended in a draw:") + result, QMessageBox::Ok);
588 void MainWindow::turn(int playerId)
590 _actualPlayerIndex = playerId;
591 if (_playersInfo.at(playerId).type() == "H") {
592 actionSuggest_move->setEnabled(true);
594 else {
595 actionSuggest_move->setEnabled(false);
597 if (_playersInfo.at(playerId).type() == "A") {
598 actionForce_Move->setEnabled(true);
600 else {
601 actionForce_Move->setEnabled(false);
603 //TODO ?
606 void MainWindow::resetOnNewGame()
608 //disabilito alcune voci del menù
609 disableOnEndGame();
611 if (_loop != 0) {
612 _loop->stop();
615 _render->reset();
617 if (_suggester != 0) {
618 _suggester->wait();
619 _suggester->deleteLater();
620 _suggester = 0;
623 if (_loop != 0) {
624 _loop->wait();
625 _loop->deleteLater();
626 _loop = 0;
629 if (_chat != 0) {
630 _chat->reset();
633 if (_net != 0) {
634 delete _net;
635 _net = 0;
638 if (_playersWidget != 0) {
639 _playersWidget->reset();
642 if (_settings != 0) {
643 delete _settings;
644 _settings = 0;
647 _playersInfo.clear();
649 if (_history != 0) {
650 _history->reset();
653 _isStandAloneGame = false;
654 _isOnlineGame = false;
655 _isServerGame = false;
656 _isDedicatedServer = false;
657 _actualViewIndex = QModelIndex();
658 _actualPlayerIndex = 0;
662 void MainWindow::suggestMove()
664 if (_isStandAloneGame) {
665 if (_suggester != 0) {
666 _suggester->wait();
667 _suggester->deleteLater();
668 _suggester = 0;
670 _suggester = new Suggester(_actualPlayerIndex);
671 connect(_suggester, SIGNAL(suggestedMoveReady(Point)), _render, SLOT(highlightPoint(Point)));
672 _suggester->start();
676 bool MainWindow::isOnlineGame() const
678 return _isOnlineGame;
681 void MainWindow::connectAISkillSlider(QList<Player*> players)
683 AIPlayer *ai0 = qobject_cast<AIPlayer*>(players.at(0));
684 if (ai0 != 0) {
685 connect(_playersWidget->skill_0, SIGNAL(valueChanged(int)), ai0, SLOT(setSkill(int)), Qt::DirectConnection);
687 AIPlayer *ai1 = qobject_cast<AIPlayer*>(players.at(1));
688 if (ai1 != 0) {
689 connect(_playersWidget->skill_1, SIGNAL(valueChanged(int)), ai1, SLOT(setSkill(int)), Qt::DirectConnection);
691 if (players.size() == 3) {
692 AIPlayer *ai2 = qobject_cast<AIPlayer*>(players.at(2));
693 if (ai2 != 0) {
694 connect(_playersWidget->skill_2, SIGNAL(valueChanged(int)), ai2, SLOT(setSkill(int)), Qt::DirectConnection);
699 void MainWindow::showLastMove()
701 if (_history && !_isDedicatedServer && !_history->moveList().isEmpty()) {
702 _render->highlightPoint(_history->moveList().last().point());
706 void MainWindow::showPastGameStatus(QModelIndex index)
708 if (index == _actualViewIndex) {
709 return;
711 QList<Point> pointList;
712 QList<QColor> colorList;
713 if (_actualViewIndex < index) {
714 QList<Move> list = _history->moveList();
715 for (int i = _actualViewIndex.row() + 1; i <= index.row(); i++) {
716 pointList.append(list.at(i).point());
717 int id = list.at(i).playerId();
718 colorList.append(_playersInfo.at(id).color());
721 else {
722 QList<Move> list = _history->moveList();
723 for (int i = index.row() + 1; i <= _actualViewIndex.row(); i++) {
724 pointList.append(list.at(i).point());
727 _render->uncheckedDraw(pointList, colorList);
728 _actualViewIndex = index;
729 if (index.row() == _history->moveList().size() - 1 && _playersInfo.at(_actualPlayerIndex).type() == "H") {
730 _render->acceptMove(true);
732 else {
733 _render->acceptMove(false);
737 void MainWindow::undoTurn()
739 int ply = _history->moveList().size();
740 if (ply <= _playersInfo.size()) {
741 return;
743 QModelIndex end = _history->index(ply - _playersInfo.size() - 1, 0);
744 undoMoves(end);
747 void MainWindow::undoMoves(QModelIndex index)
749 QMessageBox::StandardButton result = QMessageBox::question(this, tr("Are you sure?"), tr("Do you really want to bring the game in a past situation?"), QMessageBox::Yes | QMessageBox::No);
750 if (result == QMessageBox::No) {
751 return;
754 QList<Move> list = _history->moveList();
755 if (index.row() == list.size() - 1) {
756 return;
759 Q_ASSERT(_isStandAloneGame);
761 showPastGameStatus(index);
763 GameMatrix *mat = GameMatrix::instance();
764 QList<Point> lastRound;
765 for (int i = index.row(); i > index.row() - _playersInfo.size() && i >= 0; i--) {
766 lastRound.append(list.at(i).point());
768 while (lastRound.size() < _playersInfo.size()) {
769 lastRound.append(Point());
771 mat->setLastRound(lastRound);
772 for (int i = index.row() + 1; i < list.size(); i++) {
773 mat->clear(list.at(i).point());
775 int ply = list.size() - index.row() - 1;
776 _history->remove(ply);
777 _loop->setTurn(ply);
778 SyncSharedCondition::instance()->notifyMove(Point());
781 void MainWindow::saveGame()
783 //FIXME aggiungere altri controlli?
784 Q_ASSERT(_isStandAloneGame);
785 QString fileName = QFileDialog::getSaveFileName(this, tr("Save Game"));
786 if (fileName.isEmpty()) {
787 return;
790 GUISettings set;
792 QFile f(fileName);
793 if (!f.open(QIODevice::WriteOnly)) {
794 //FIXME
795 return;
797 QXmlStreamWriter xml(&f);
798 xml.writeStartDocument();
799 xml.writeDefaultNamespace("http://www.itworks.org/GoMoku3D/SavedGame");
800 xml.writeStartElement("game");
801 xml.writeStartElement("settings");
802 xml.writeTextElement("difficultyOne", QString::number(GameMatrix::instance()->d1()));
803 xml.writeTextElement("difficultyTwo", QString::number(GameMatrix::instance()->d2()));
804 xml.writeStartElement("cubeColor");
805 xml.writeTextElement("r", QString::number(set.defaultCubeColor().red()));
806 xml.writeTextElement("g", QString::number(set.defaultCubeColor().green()));
807 xml.writeTextElement("b", QString::number(set.defaultCubeColor().blue()));
808 xml.writeTextElement("a", QString::number(set.defaultCubeColor().alpha()));
809 xml.writeEndElement();
810 xml.writeStartElement("backgroundColor");
811 xml.writeTextElement("r", QString::number(set.backgroundColor().red()));
812 xml.writeTextElement("g", QString::number(set.backgroundColor().green()));
813 xml.writeTextElement("b", QString::number(set.backgroundColor().blue()));
814 xml.writeTextElement("a", QString::number(set.backgroundColor().alpha()));
815 xml.writeEndElement();
816 xml.writeEndElement();
817 xml.writeStartElement("players");
818 for (int i = 0; i < _playersInfo.size(); i++) {
819 xml.writeStartElement("player");
820 xml.writeAttribute("id", QString::number(i));
821 xml.writeTextElement("name", _playersInfo.at(i).name());
822 xml.writeStartElement("color");
823 xml.writeTextElement("r", QString::number(_playersInfo.at(i).color().red()));
824 xml.writeTextElement("g", QString::number(_playersInfo.at(i).color().green()));
825 xml.writeTextElement("b", QString::number(_playersInfo.at(i).color().blue()));
826 xml.writeTextElement("a", QString::number(_playersInfo.at(i).color().alpha()));
827 xml.writeEndElement();
828 QString type = _playersInfo.at(i).type();
829 if (type == "H") {
830 type = "human";
832 if (type == "R") {
833 type = "remote";
835 if (type == "A") {
836 type = "ai";
838 xml.writeTextElement("type", type);
839 xml.writeEndElement();
841 xml.writeEndElement();
842 xml.writeStartElement("history");
843 Move m;
844 foreach (m, _history->moveList()) {
845 xml.writeStartElement("move");
846 xml.writeTextElement("player", QString::number(m.playerId()));
847 xml.writeStartElement("point");
848 xml.writeTextElement("x", QString::number(m.point().x()));
849 xml.writeTextElement("y", QString::number(m.point().y()));
850 xml.writeTextElement("z", QString::number(m.point().z()));
851 xml.writeEndElement();
852 xml.writeEndElement();
854 xml.writeEndElement();
855 xml.writeEndElement();
856 xml.writeEndDocument();
857 f.close();