File indexing completed on 2024-04-21 04:04:00

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