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"
29 #include "GameMatrix.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"
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)
54 _actualPlayerIndex
= -1;
55 _isStandAloneGame
= false;
56 _isOnlineGame
= false;
57 _isServerGame
= false;
58 _isDedicatedServer
= false;
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()
110 set
.setGeometry(this->saveGeometry());
111 //set.setDockState(this->saveState());
119 if (_suggester
!= 0) {
121 _suggester
->deleteLater();
126 _loop
->deleteLater();
133 //TODO c'e' altro da fare?
136 void MainWindow::drawMove(Move move
)
138 if (_playersInfo
.isEmpty()) {
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();
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?
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);
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,
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
) {
201 void MainWindow::newStandAloneGame()
203 if (_loop
!= 0 && !askUserConfirmation()) {
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);
215 if (dialog
.result() == QDialog::Rejected
) {
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();
230 Q_ASSERT(numPlayers
!= 0);
231 GameMatrix::create(d1
, d2
, numPlayers
);
232 Q_ASSERT(GameMatrix::instance() != 0);
234 _render
->init(d1
* d2
);
237 QList
<Player
*> players
;
238 if (dialog
.human_0
->isChecked()) {
240 players
.append(new HumanPlayer(0, _render
));
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()) {
250 players
.append(new HumanPlayer(1, _render
));
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()) {
261 players
.append(new HumanPlayer(2, _render
));
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
);
274 _history
= new HistoryModel(this, &_playersInfo
);
275 _historyView
->setModel(_history
);
277 qobject_cast
<QDockWidget
*>(_historyView
->parent())->setVisible(true);
280 _loop
= new GameLoop(players
);
281 //move to thread dei player
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>)));
297 void MainWindow::newOnlineGame()
299 if (_loop
!= 0 && !askUserConfirmation()) {
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);
311 if (dialog
.result() == QDialog::Rejected
) {
319 _isOnlineGame
= true;
321 //TODO connette i segnali di errore del net con MW
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
335 QList
<Player
*> players
;
336 if (dialog
.human_0
->isChecked()) {
338 players
.append(new HumanPlayer(0, _render
));
341 players
.append(new RemotePlayer(0, _net
));
342 if (dialog
.ai_0
->isChecked()) {
349 _playersInfo
.append(PlayerInfo(dialog
.playername_0
->text(), dialog
.color_0
->palette().color(QPalette::Button
), type
));
350 if (dialog
.human_1
->isChecked()) {
352 players
.append(new HumanPlayer(1, _render
));
355 players
.append(new RemotePlayer(1, _net
));
356 if (dialog
.ai_1
->isChecked()) {
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()) {
367 players
.append(new HumanPlayer(2, _render
));
370 players
.append(new RemotePlayer(2, _net
));
371 if (dialog
.ai_2
->isChecked()) {
378 _playersInfo
.append(PlayerInfo(dialog
.playername_2
->text(), dialog
.color_2
->palette().color(QPalette::Button
), type
));
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());
395 _loop
= new GameLoop(players
);
396 //move to thread dei player
398 foreach (p
, players
) {
399 p
->moveToThread(_loop
);
402 _net
->setupGameLoop(_loop
);
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>)));
414 void MainWindow::newServerGame()
416 if (_loop
!= 0 && !askUserConfirmation()) {
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);
428 if (dialog
.result() == QDialog::Rejected
) {
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
);
443 QList
<Player
*> players
;
444 if (dialog
.human_0
->isChecked()) {
446 _render
->init(d1
* d2
);
447 actionShow_last_move
->setEnabled(true);
448 players
.append(new HumanPlayer(0, _render
));
451 if (dialog
.ai_0
->isChecked()) {
453 players
.append(new AIPlayer(0));
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()) {
463 _render
->init(d1
* d2
);
464 actionShow_last_move
->setEnabled(true);
465 players
.append(new HumanPlayer(1, _render
));
468 if (dialog
.ai_1
->isChecked()) {
470 players
.append(new AIPlayer(1));
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()) {
481 _render
->init(d1
* d2
);
482 actionShow_last_move
->setEnabled(true);
483 players
.append(new HumanPlayer(2, _render
));
486 if (dialog
.ai_2
->isChecked()) {
488 players
.append(new AIPlayer(2));
492 players
.append(new RemotePlayer(2, _net
));
495 _playersInfo
.append(PlayerInfo(dialog
.playername_2
->text(), dialog
.color_2
->palette().color(QPalette::Button
), type
));
499 _loop
= new GameLoop(players
);
500 //move to thread dei player
502 foreach (p
, players
) {
503 p
->moveToThread(_loop
);
505 connectAISkillSlider(players
);
507 _net
->setupGameLoop(_loop
);
510 for (int i
= 0; i
< _playersInfo
.size(); i
++) {
511 if (_playersInfo
.at(i
).type() == "H") {
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?
524 // modalità giocatore o spettatore
525 _isServerGame
= true;
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);
533 _history
= new HistoryModel(this, &_playersInfo
);
534 _historyView
->setModel(_history
);
537 _playersWidget
->set(&_playersInfo
);
538 _timer
->setDuration(dialog
.timerSpinBox
->value());
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?
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()
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
)
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
)
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);
595 actionSuggest_move
->setEnabled(false);
597 if (_playersInfo
.at(playerId
).type() == "A") {
598 actionForce_Move
->setEnabled(true);
601 actionForce_Move
->setEnabled(false);
606 void MainWindow::resetOnNewGame()
608 //disabilito alcune voci del menù
617 if (_suggester
!= 0) {
619 _suggester
->deleteLater();
625 _loop
->deleteLater();
638 if (_playersWidget
!= 0) {
639 _playersWidget
->reset();
642 if (_settings
!= 0) {
647 _playersInfo
.clear();
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) {
667 _suggester
->deleteLater();
670 _suggester
= new Suggester(_actualPlayerIndex
);
671 connect(_suggester
, SIGNAL(suggestedMoveReady(Point
)), _render
, SLOT(highlightPoint(Point
)));
676 bool MainWindow::isOnlineGame() const
678 return _isOnlineGame
;
681 void MainWindow::connectAISkillSlider(QList
<Player
*> players
)
683 AIPlayer
*ai0
= qobject_cast
<AIPlayer
*>(players
.at(0));
685 connect(_playersWidget
->skill_0
, SIGNAL(valueChanged(int)), ai0
, SLOT(setSkill(int)), Qt::DirectConnection
);
687 AIPlayer
*ai1
= qobject_cast
<AIPlayer
*>(players
.at(1));
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));
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
) {
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());
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);
733 _render
->acceptMove(false);
737 void MainWindow::undoTurn()
739 int ply
= _history
->moveList().size();
740 if (ply
<= _playersInfo
.size()) {
743 QModelIndex end
= _history
->index(ply
- _playersInfo
.size() - 1, 0);
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
) {
754 QList
<Move
> list
= _history
->moveList();
755 if (index
.row() == list
.size() - 1) {
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
);
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()) {
793 if (!f
.open(QIODevice::WriteOnly
)) {
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();
838 xml
.writeTextElement("type", type
);
839 xml
.writeEndElement();
841 xml
.writeEndElement();
842 xml
.writeStartElement("history");
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();