File indexing completed on 2022-09-30 10:19:26

0001 /*
0002     SPDX-FileCopyrightText: 2006-2007 Dmitry Suzdalev <dimsuz@gmail.com>
0003     SPDX-FileCopyrightText: 2010 Brian Croom <brian.s.croom@gmail.com>
0004     SPDX-FileCopyrightText: 2013 Denis Kuplyakov <dener.kup@gmail.com>
0005 
0006     SPDX-License-Identifier: GPL-2.0-or-later
0007 */
0008 
0009 #include "kreversiview.h"
0010 
0011 // game
0012 #include "colorscheme.h"
0013 // KF
0014 #include <KLocalizedString>
0015 #include <KLocalizedContext>
0016 // Qt
0017 #include <QQmlContext>
0018 #include <QStandardPaths>
0019 
0020 KReversiView::KReversiView(KReversiGame* game, QWidget *parent, KgThemeProvider *provider)
0021     : QQuickWidget(parent),
0022     m_provider(provider),
0023     m_delay(ANIMATION_SPEED_NORMAL),
0024     m_game(nullptr),
0025     m_showLastMove(false),
0026     m_showLegalMoves(false),
0027     m_showLabels(false)
0028 {
0029     QQmlEngine *engine = this->engine();
0030 
0031     auto *localizedContextObject = new KLocalizedContext(engine);
0032     engine->rootContext()->setContextObject(localizedContextObject);
0033 
0034     setResizeMode(SizeRootObjectToView);
0035 
0036     m_provider->setDeclarativeEngine(QStringLiteral("themeProvider"), engine);
0037 
0038     qmlRegisterType<ColorScheme>("ColorScheme", 1, 0, "ColorScheme");
0039 
0040     QString path = QStandardPaths::locate(QStandardPaths::AppDataLocation, QStringLiteral("qml/Table.qml"));
0041     setSource(QUrl::fromLocalFile(path));
0042 
0043     m_qml_root = (QObject*) rootObject();
0044     rootContext()->setContextProperty(QStringLiteral("container"), this);
0045 
0046     connect(m_qml_root, SIGNAL(cellClicked(int,int)),
0047             this, SLOT(onPlayerMove(int,int)));
0048 
0049     setGame(game);
0050 }
0051 
0052 void KReversiView::setGame(KReversiGame *game)
0053 {
0054     // disconnect signals from previous game if they exist,
0055     // we are not interested in them anymore
0056     if (m_game) {
0057         disconnect(m_game, &KReversiGame::boardChanged, this, &KReversiView::updateBoard);
0058         disconnect(m_game, &KReversiGame::moveFinished, this, &KReversiView::gameMoveFinished);
0059         disconnect(m_game, &KReversiGame::gameOver, this, &KReversiView::gameOver);
0060         disconnect(m_game, &KReversiGame::whitePlayerCantMove, this, &KReversiView::whitePlayerCantMove);
0061         disconnect(m_game, &KReversiGame::blackPlayerCantMove, this, &KReversiView::blackPlayerCantMove);
0062         delete m_game;
0063     }
0064 
0065     m_game = game;
0066 
0067     if (m_game) {
0068         connect(m_game, &KReversiGame::boardChanged, this, &KReversiView::updateBoard);
0069         connect(m_game, &KReversiGame::moveFinished, this, &KReversiView::gameMoveFinished);
0070         connect(m_game, &KReversiGame::gameOver, this, &KReversiView::gameOver);
0071         connect(m_game, &KReversiGame::whitePlayerCantMove, this, &KReversiView::whitePlayerCantMove);
0072         connect(m_game, &KReversiGame::blackPlayerCantMove, this, &KReversiView::blackPlayerCantMove);
0073 
0074         m_game->setDelay(m_delay);
0075     }
0076 
0077     m_hint = KReversiMove();
0078 
0079     updateBoard();
0080 }
0081 
0082 void KReversiView::setChipsPrefix(ChipsPrefix chipsPrefix)
0083 {
0084     m_ColouredChips = chipsPrefix;
0085     m_qml_root->setProperty("chipsImagePrefix",
0086                             Utils::chipPrefixToString(chipsPrefix));
0087 }
0088 
0089 void KReversiView::setShowBoardLabels(bool show)
0090 {
0091     m_showLabels = show;
0092     updateBoard();
0093 }
0094 
0095 void KReversiView::setAnimationSpeed(int speed)
0096 {
0097     int value = ANIMATION_SPEED_NORMAL;
0098     switch (speed) {
0099     case 0:
0100         value = ANIMATION_SPEED_SLOW;
0101         break;
0102     default:
0103     case 1:
0104         value = ANIMATION_SPEED_NORMAL;
0105         break;
0106     case 2:
0107         value = ANIMATION_SPEED_FAST;
0108         break;
0109     }
0110 
0111     m_delay = value;
0112 
0113     if (m_game)
0114         m_game->setDelay(value);
0115 
0116     m_qml_root->setProperty("chipsAnimationTime", value);
0117 }
0118 
0119 KReversiView::~KReversiView()
0120 {
0121     setGame(nullptr);
0122 }
0123 
0124 void KReversiView::updateBoard()
0125 {
0126     for (int i = 0; i < 8; i++) {
0127         for (int j = 0; j < 8; j++) {
0128             QMetaObject::invokeMethod(m_qml_root, "setPreAnimationTime",
0129                                       Q_ARG(QVariant, i),
0130                                       Q_ARG(QVariant, j),
0131                                       Q_ARG(QVariant, m_game ? m_game->getPreAnimationDelay(KReversiPos(i, j)) : 0));
0132         }
0133     }
0134 
0135     for (int i = 0; i < 8; i++)
0136         for (int j = 0; j < 8; j++) {
0137             QString new_state;
0138             if (m_game) // showing empty board if has no game
0139                 switch (m_game->chipColorAt(KReversiMove(NoColor, i, j))) {
0140                 case Black:
0141                     new_state = QStringLiteral("Black");
0142                     break;
0143                 case White:
0144                     new_state = QStringLiteral("White");
0145                     break;
0146                 case NoColor:
0147                     new_state = QString();
0148                     break;
0149                 }
0150 
0151             QMetaObject::invokeMethod(m_qml_root, "setChipState",
0152                                       Q_ARG(QVariant, i),
0153                                       Q_ARG(QVariant, j),
0154                                       Q_ARG(QVariant, new_state));
0155 
0156             // clearing legal markers, hints and lastmove
0157             QMetaObject::invokeMethod(m_qml_root, "setLegal",
0158                                       Q_ARG(QVariant, i),
0159                                       Q_ARG(QVariant, j),
0160                                       Q_ARG(QVariant, false));
0161             QMetaObject::invokeMethod(m_qml_root, "setHint",
0162                                       Q_ARG(QVariant, i),
0163                                       Q_ARG(QVariant, j),
0164                                       Q_ARG(QVariant, false));
0165             QMetaObject::invokeMethod(m_qml_root, "setLastMove",
0166                                       Q_ARG(QVariant, i),
0167                                       Q_ARG(QVariant, j),
0168                                       Q_ARG(QVariant, false));
0169         }
0170 
0171     if (m_game && m_showLegalMoves) {
0172         MoveList possible_moves = m_game->possibleMoves();
0173         for (int i = 0; i < possible_moves.size(); i++) {
0174             QMetaObject::invokeMethod(m_qml_root, "setLegal",
0175                                       Q_ARG(QVariant, possible_moves.at(i).row),
0176                                       Q_ARG(QVariant, possible_moves.at(i).col),
0177                                       Q_ARG(QVariant, true));
0178         }
0179     }
0180 
0181     m_qml_root->setProperty("isBoardShowingLabels", m_showLabels);
0182 
0183     if (m_hint.isValid()) {
0184         QMetaObject::invokeMethod(m_qml_root, "setChipState",
0185                                   Q_ARG(QVariant, m_hint.row),
0186                                   Q_ARG(QVariant, m_hint.col),
0187                                   Q_ARG(QVariant, QLatin1String("Black")));
0188         QMetaObject::invokeMethod(m_qml_root, "setHint",
0189                                   Q_ARG(QVariant, m_hint.row),
0190                                   Q_ARG(QVariant, m_hint.col),
0191                                   Q_ARG(QVariant, true));
0192     }
0193 
0194     if (m_game && m_showLastMove) {
0195         KReversiMove lastmove = m_game->getLastMove();
0196         if (lastmove.isValid())
0197             QMetaObject::invokeMethod(m_qml_root, "setLastMove",
0198                                       Q_ARG(QVariant, lastmove.row),
0199                                       Q_ARG(QVariant, lastmove.col),
0200                                       Q_ARG(QVariant, true));
0201     }
0202 }
0203 
0204 void KReversiView::setShowLastMove(bool show)
0205 {
0206     m_showLastMove = show;
0207     updateBoard();
0208 }
0209 
0210 void KReversiView::setShowLegalMoves(bool show)
0211 {
0212     m_showLegalMoves = show;
0213     updateBoard();
0214 }
0215 
0216 void KReversiView::slotHint()
0217 {
0218     if (!m_game) {
0219         m_hint = KReversiMove();
0220         return;
0221     }
0222 
0223     m_hint = m_game->getHint();
0224     updateBoard();
0225 }
0226 
0227 void KReversiView::onPlayerMove(int row, int col)
0228 {
0229     if (!m_game)
0230         return;
0231 
0232     Q_EMIT userMove(KReversiPos(row, col));
0233 }
0234 
0235 
0236 void KReversiView::gameMoveFinished()
0237 {
0238     m_hint = KReversiMove();
0239     updateBoard();
0240 }
0241 
0242 void KReversiView::gameOver()
0243 {
0244 }
0245 
0246 void KReversiView::whitePlayerCantMove()
0247 {
0248     // TODO: use Computer, You and Opponent instead in message
0249     QMetaObject::invokeMethod(m_qml_root, "showPopup",
0250                               Q_ARG(QVariant, m_ColouredChips ?
0251                                     i18n("Red can not perform any move. It is blue turn again.") :
0252                                     i18n("White can not perform any move. It is black turn again.")));
0253     updateBoard();
0254 }
0255 
0256 void KReversiView::blackPlayerCantMove()
0257 {
0258     // TODO: use Computer, You and Opponent instead in message
0259     QMetaObject::invokeMethod(m_qml_root, "showPopup",
0260                               Q_ARG(QVariant, m_ColouredChips ?
0261                                     i18n("Blue can not perform any move. It is red turn again.") :
0262                                     i18n("Black can not perform any move. It is white turn again.")));
0263     updateBoard();
0264 }