File indexing completed on 2024-04-14 03:59:28

0001 /*
0002     SPDX-FileCopyrightText: 2012 Viranch Mehta <viranch.mehta@gmail.com>
0003 
0004     SPDX-License-Identifier: GPL-2.0-or-later
0005 */
0006 
0007 #include "canvaswidget.h"
0008 
0009 // own
0010 #include "globals.h"
0011 #include "kbreakout_debug.h"
0012 #include "settings.h"
0013 // KDEGames
0014 #include <KGameThemeProvider>
0015 // KF
0016 #include <KLocalizedContext>
0017 // Qt
0018 #include <QAction>
0019 #include <QCursor>
0020 #include <QGraphicsObject>
0021 #include <QQmlContext>
0022 #include <QQuickItem>
0023 #include <QStandardPaths>
0024 
0025 CanvasWidget::CanvasWidget(QWidget *parent) :
0026     QQuickWidget(parent),
0027     m_provider(new KGameThemeProvider)
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->discoverThemes(QStringLiteral("themes"));
0037     m_provider->setDeclarativeEngine(QStringLiteral("themeProvider"), engine);
0038     QString path = QStandardPaths::locate(QStandardPaths::AppDataLocation, QStringLiteral("qml/main.qml"));
0039 
0040     qCDebug(KBREAKOUT_General) << "QtQuick QML file: " << path;
0041 
0042     setSource(QUrl::fromLocalFile(path));
0043 
0044     // forward signals from QML
0045     connect(rootObject(), SIGNAL(levelComplete()), this, SIGNAL(levelComplete()));
0046     connect(rootObject(), SIGNAL(gameEnded(int,int,int)), this, SIGNAL(gameEnded(int,int,int)));
0047     connect(rootObject(), SIGNAL(mousePressed()), this, SIGNAL(mousePressed()));
0048 
0049     // for handling mouse cursor
0050     connect(rootObject(), SIGNAL(ballMovingChanged()), this, SLOT(updateCursor()));
0051 }
0052 
0053 CanvasWidget::~CanvasWidget()
0054 {
0055     delete m_provider;
0056 }
0057 
0058 void CanvasWidget::updateFireShortcut()
0059 {
0060     QAction *fireAction = qobject_cast<QAction *>(sender());
0061     QString shortcut = fireAction->shortcut().toString(QKeySequence::NativeText);
0062     rootObject()->setProperty("fireShortcut", shortcut);
0063 }
0064 
0065 void CanvasWidget::resizeEvent(QResizeEvent *event)
0066 {
0067     QQuickWidget::resizeEvent(event);
0068     QMetaObject::invokeMethod(rootObject(), "updateGeometry");
0069 }
0070 
0071 bool CanvasWidget::event(QEvent *event)
0072 {
0073     if (event->type() == QEvent::Leave) {
0074         updateCursor();
0075     }
0076     return QQuickWidget::event(event);
0077 }
0078 
0079 void CanvasWidget::newGame()
0080 {
0081     QMetaObject::invokeMethod(rootObject(), "reset");
0082 }
0083 
0084 void CanvasWidget::showLine(const QString &line, int lineNumber)
0085 {
0086     QMetaObject::invokeMethod(rootObject(), "loadLine",
0087                               Q_ARG(QVariant, line),
0088                               Q_ARG(QVariant, lineNumber));
0089 }
0090 
0091 void CanvasWidget::putGift(const QString &gift, int times, const QString &pos)
0092 {
0093     QMetaObject::invokeMethod(rootObject(), "loadGift",
0094                               Q_ARG(QVariant, gift),
0095                               Q_ARG(QVariant, times),
0096                               Q_ARG(QVariant, pos));
0097 }
0098 
0099 void CanvasWidget::startGame()
0100 {
0101     QMetaObject::invokeMethod(rootObject(), "startGame");
0102 }
0103 
0104 void CanvasWidget::fire()
0105 {
0106     QMetaObject::invokeMethod(rootObject(), "fire");
0107 }
0108 
0109 void CanvasWidget::cheatSkipLevel()
0110 {
0111     QMetaObject::invokeMethod(rootObject(), "cheatSkipLevel");
0112 }
0113 
0114 void CanvasWidget::cheatAddLife()
0115 {
0116     QMetaObject::invokeMethod(rootObject(), "cheatAddLife");
0117 }
0118 
0119 void CanvasWidget::setGamePaused(bool paused)
0120 {
0121     QMetaObject::invokeMethod(rootObject(), "setGamePaused",
0122                               Q_ARG(QVariant, paused));
0123 }
0124 
0125 void CanvasWidget::updateBarDirection()
0126 {
0127     QMetaObject::invokeMethod(rootObject(), "updateBarDirection",
0128                               Q_ARG(QVariant, m_barDirection));
0129 }
0130 
0131 void CanvasWidget::updateCursor()
0132 {
0133     const bool ballMoving = rootObject()->property("ballMoving").toBool();
0134 
0135     if (ballMoving) {
0136         resetMousePosition();
0137         setCursor(Qt::BlankCursor);
0138     } else {
0139         setCursor(Qt::ArrowCursor);
0140     }
0141 }
0142 
0143 void CanvasWidget::resetMousePosition()
0144 {
0145     const QQuickItem *jailItem = rootObject()->property("jailItem").value<QQuickItem*>();
0146     const QPoint jailItemTopLeft = mapToGlobal(QPoint(jailItem->x(), jailItem->y()));
0147     QPoint p = QCursor::pos();
0148     if (p.x() < jailItemTopLeft.x()) {
0149         QCursor::setPos(jailItemTopLeft.x(), p.y());
0150     } else if (p.x() > jailItemTopLeft.x() + jailItem->width()) {
0151         QCursor::setPos(jailItemTopLeft.x() + jailItem->width(), p.y());
0152     }
0153 
0154     if (p.y() < jailItemTopLeft.y()) {
0155         QCursor::setPos(p.x(), jailItemTopLeft.y());
0156     } else if (p.y() > jailItemTopLeft.y() + jailItem->height()) {
0157         QCursor::setPos(p.x(), jailItemTopLeft.y() + jailItem->height());
0158     }
0159 }
0160 
0161 void CanvasWidget::focusOutEvent(QFocusEvent *event)
0162 {
0163     Q_EMIT focusLost();
0164     QQuickWidget::focusOutEvent(event);
0165 }
0166 
0167 #include "moc_canvaswidget.cpp"