1/*
2 Copyright 2006-2007 Dmitry Suzdalev <dimsuz@gmail.com>
3 Copyright 2010 Brian Croom <brian.s.croom@gmail.com>
4 Copyright 2013 Denis Kuplyakov <dener.kup@gmail.com>
5
6 This program is free software: you can redistribute it and/or modify
7 it under the terms of the GNU General Public License as published by
8 the Free Software Foundation, either version 2 of the License, or
9 (at your option) any later version.
10
11 This program is distributed in the hope that it will be useful,
12 but WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 GNU General Public License for more details.
15
16 You should have received a copy of the GNU General Public License
17 along with this program. If not, see <http://www.gnu.org/licenses/>.
18*/
19
20#include <kreversiview.h>
21
22#include <KLocalizedString>
23#include <KStandardDirs>
24
25#include <colorscheme.h>
26
27KReversiView::KReversiView(KReversiGame* game, QWidget *parent, KgThemeProvider *provider) :
28 KgDeclarativeView(parent), m_delay(ANIMATION_SPEED_NORMAL), m_game(0),
29 m_showLastMove(false), m_showLegalMoves(false),
30 m_showLabels(false), m_provider(provider)
31{
32 m_provider->setDeclarativeEngine("themeProvider", engine());
33
34 qmlRegisterType<ColorScheme>("ColorScheme", 1, 0, "ColorScheme");
35
36 QString path =
37 KStandardDirs::locate("appdata", QLatin1String("qml/Table.qml"));
38 setSource(QUrl::fromLocalFile(path));
39
40 m_qml_root = (QObject*) rootObject();
41 rootContext()->setContextProperty("container", this);
42
43 connect(m_qml_root, SIGNAL(cellClicked(int,int)),
44 this, SLOT(onPlayerMove(int,int)));
45 setGame(game);
46}
47
48void KReversiView::setGame(KReversiGame *game)
49{
50 // disconnect signals from previous game if they exist,
51 // we are not interested in them anymore
52 if (m_game) {
53 disconnect(m_game, SIGNAL(boardChanged()), this, SLOT(updateBoard()));
54 disconnect(m_game, SIGNAL(moveFinished()), this, SLOT(gameMoveFinished()));
55 disconnect(m_game, SIGNAL(gameOver()), this, SLOT(gameOver()));
56 disconnect(m_game, SIGNAL(whitePlayerCantMove()), this, SLOT(whitePlayerCantMove()));
57 disconnect(m_game, SIGNAL(blackPlayerCantMove()), this, SLOT(blackPlayerCantMove()));
58 delete m_game;
59 }
60
61 m_game = game;
62
63 if (m_game) {
64 connect(m_game, SIGNAL(boardChanged()), this, SLOT(updateBoard()));
65 connect(m_game, SIGNAL(moveFinished()), this, SLOT(gameMoveFinished()));
66 connect(m_game, SIGNAL(gameOver()), this, SLOT(gameOver()));
67 connect(m_game, SIGNAL(whitePlayerCantMove()), this, SLOT(whitePlayerCantMove()));
68 connect(m_game, SIGNAL(blackPlayerCantMove()), this, SLOT(blackPlayerCantMove()));
69
70 m_game->setDelay(m_delay);
71 }
72
73 m_hint = KReversiMove();
74
75 updateBoard();
76}
77
78void KReversiView::setChipsPrefix(ChipsPrefix chipsPrefix)
79{
80 m_qml_root->setProperty("chipsImagePrefix",
81 Utils::chipPrefixToString(chipsPrefix));
82}
83
84void KReversiView::setShowBoardLabels(bool show)
85{
86 m_showLabels = show;
87 updateBoard();
88}
89
90void KReversiView::setAnimationSpeed(int speed)
91{
92 int value = ANIMATION_SPEED_NORMAL;
93 switch (speed) {
94 case 0:
95 value = ANIMATION_SPEED_SLOW;
96 break;
97 default:
98 case 1:
99 value = ANIMATION_SPEED_NORMAL;
100 break;
101 case 2:
102 value = ANIMATION_SPEED_FAST;
103 break;
104 }
105
106 m_delay = value;
107
108 if (m_game)
109 m_game->setDelay(value);
110
111 m_qml_root->setProperty("chipsAnimationTime", value);
112}
113
114KReversiView::~KReversiView()
115{
116 setGame(0);
117}
118
119void KReversiView::updateBoard()
120{
121 for (int i = 0; i < 8; i++) {
122 for (int j = 0; j < 8; j++) {
123 QMetaObject::invokeMethod(m_qml_root, "setPreAnimationTime",
124 Q_ARG(QVariant, i),
125 Q_ARG(QVariant, j),
126 Q_ARG(QVariant, m_game ? m_game->getPreAnimationDelay(KReversiPos(i, j)) : 0));
127 }
128 }
129
130 for (int i = 0; i < 8; i++)
131 for (int j = 0; j < 8; j++) {
132 QString new_state = "";
133 if (m_game) // showing empty board if has no game
134 switch (m_game->chipColorAt(KReversiMove(NoColor, i, j))) {
135 case Black:
136 new_state = "Black";
137 break;
138 case White:
139 new_state = "White";
140 break;
141 case NoColor:
142 new_state = "";
143 break;
144 }
145
146 QMetaObject::invokeMethod(m_qml_root, "setChipState",
147 Q_ARG(QVariant, i),
148 Q_ARG(QVariant, j),
149 Q_ARG(QVariant, new_state));
150
151 // clearing legal markers, hints and lastmove
152 QMetaObject::invokeMethod(m_qml_root, "setLegal",
153 Q_ARG(QVariant, i),
154 Q_ARG(QVariant, j),
155 Q_ARG(QVariant, false));
156 QMetaObject::invokeMethod(m_qml_root, "setHint",
157 Q_ARG(QVariant, i),
158 Q_ARG(QVariant, j),
159 Q_ARG(QVariant, false));
160 QMetaObject::invokeMethod(m_qml_root, "setLastMove",
161 Q_ARG(QVariant, i),
162 Q_ARG(QVariant, j),
163 Q_ARG(QVariant, false));
164 }
165
166 if (m_game && m_showLegalMoves) {
167 MoveList possible_moves = m_game->possibleMoves();
168 for (int i = 0; i < possible_moves.size(); i++) {
169 QMetaObject::invokeMethod(m_qml_root, "setLegal",
170 Q_ARG(QVariant, possible_moves.at(i).row),
171 Q_ARG(QVariant, possible_moves.at(i).col),
172 Q_ARG(QVariant, true));
173 }
174 }
175
176 m_qml_root->setProperty("isBoardShowingLabels", m_showLabels);
177
178 if (m_hint.isValid()) {
179 QMetaObject::invokeMethod(m_qml_root, "setChipState",
180 Q_ARG(QVariant, m_hint.row),
181 Q_ARG(QVariant, m_hint.col),
182 Q_ARG(QVariant, "Black"));
183 QMetaObject::invokeMethod(m_qml_root, "setHint",
184 Q_ARG(QVariant, m_hint.row),
185 Q_ARG(QVariant, m_hint.col),
186 Q_ARG(QVariant, true));
187 }
188
189 if (m_game && m_showLastMove) {
190 KReversiMove lastmove = m_game->getLastMove();
191 if (lastmove.isValid())
192 QMetaObject::invokeMethod(m_qml_root, "setLastMove",
193 Q_ARG(QVariant, lastmove.row),
194 Q_ARG(QVariant, lastmove.col),
195 Q_ARG(QVariant, true));
196 }
197}
198
199void KReversiView::setShowLastMove(bool show)
200{
201 m_showLastMove = show;
202 updateBoard();
203}
204
205void KReversiView::setShowLegalMoves(bool show)
206{
207 m_showLegalMoves = show;
208 updateBoard();
209}
210
211void KReversiView::slotHint()
212{
213 if (!m_game) {
214 m_hint = KReversiMove();
215 return;
216 }
217
218 m_hint = m_game->getHint();
219 updateBoard();
220}
221
222void KReversiView::onPlayerMove(int row, int col)
223{
224 if (!m_game)
225 return;
226
227 emit userMove(KReversiPos(row, col));
228}
229
230
231void KReversiView::gameMoveFinished()
232{
233 m_hint = KReversiMove();
234 updateBoard();
235}
236
237void KReversiView::gameOver()
238{
239}
240
241void KReversiView::whitePlayerCantMove()
242{
243 // TODO: use Computer, You and Opponent instead in message
244 QMetaObject::invokeMethod(m_qml_root, "showPopup",
245 Q_ARG(QVariant,
246 i18n("White can not perform any move. It is black turn again.")));
247 updateBoard();
248}
249
250void KReversiView::blackPlayerCantMove()
251{
252 // TODO: use Computer, You and Opponent instead in message
253 QMetaObject::invokeMethod(m_qml_root, "showPopup",
254 Q_ARG(QVariant,
255 i18n("Black can not perform any move. It is white turn again.")));
256 updateBoard();
257}
258