From e3242b71e922f62c07b05ad17811c78fe901248e Mon Sep 17 00:00:00 2001 From: ItsDrike Date: Sun, 1 Dec 2024 19:43:49 +0100 Subject: [PATCH] Manage playing cards from C++ only --- CMakeLists.txt | 3 +- PlayingCard.qml => CardModel.qml | 16 +++++------ Main.qml | 8 +++--- main.cpp | 8 ++++++ playingcard.cpp | 47 ++++++++++++++++++++++++++++++++ playingcard.h | 37 +++++++++++++++++++++++++ 6 files changed, 106 insertions(+), 13 deletions(-) rename PlayingCard.qml => CardModel.qml (59%) create mode 100644 playingcard.cpp create mode 100644 playingcard.h diff --git a/CMakeLists.txt b/CMakeLists.txt index eea4255..6ebfa76 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -21,7 +21,8 @@ qt_add_qml_module(appSolitare QML_FILES Main.qml QML_FILES ScoreBar.qml - QML_FILES PlayingCard.qml + QML_FILES CardModel.qml + SOURCES playingcard.h playingcard.cpp ) # Qt for iOS sets MACOSX_BUNDLE_GUI_IDENTIFIER automatically since Qt 6.1. diff --git a/PlayingCard.qml b/CardModel.qml similarity index 59% rename from PlayingCard.qml rename to CardModel.qml index 3312245..41ff92d 100644 --- a/PlayingCard.qml +++ b/CardModel.qml @@ -1,24 +1,24 @@ +import Solitare import QtQuick Item { - id: playingCard + id: cardModel width: 100 height: width * 1.4 // Maintian the aspect ratio of a playing card + required property PlayingCard card; + property string backStyle: "red" + // Annoyingly, there is no easy way to make this type-safe, QML does have enums // but they only act as ints, and since we need the string names for the img paths // anyways, typing these as simple strings is the easiest way to do this. - required property string color - required property string value - property string backStyle: "red" - property bool isFaceDown: false Image { id: cardImage anchors.fill: parent - source: playingCard.isFaceDown - ? "qrc:/img/playing_cards/backs/" + playingCard.backStyle + ".svg" - : "qrc:/img/playing_cards/fronts/" + playingCard.color + "_" + playingCard.value + ".svg" + source: cardModel.card.isFaceDown + ? "qrc:/img/playing_cards/backs/" + cardModel.backStyle + ".svg" + : "qrc:/img/playing_cards/fronts/" + cardModel.card.color + "_" + cardModel.card.value + ".svg" fillMode: Image.PreserveAspectFit } } diff --git a/Main.qml b/Main.qml index f258771..1d83025 100644 --- a/Main.qml +++ b/Main.qml @@ -1,3 +1,4 @@ +import Solitare import QtQuick import QtQuick.Controls import QtQuick.Layouts @@ -17,9 +18,8 @@ ApplicationWindow { moves: 64 } - PlayingCard { - color: "clubs" - value: "ace" - isFaceDown: true + CardModel { + anchors.centerIn: parent + card: myCard } } diff --git a/main.cpp b/main.cpp index 700e71a..1bcc9fd 100644 --- a/main.cpp +++ b/main.cpp @@ -1,5 +1,7 @@ #include #include +#include +#include "playingcard.h" int main(int argc, char *argv[]) { @@ -12,6 +14,12 @@ int main(int argc, char *argv[]) &app, []() { QCoreApplication::exit(-1); }, Qt::QueuedConnection); + + qmlRegisterUncreatableType("Solitare", 1, 0, "PlayingCard", "PlayingCard cannot be directly created in QML. Use C++ logic to instantiate."); + + PlayingCard myCard("clubs", "ace"); + engine.rootContext()->setContextProperty("myCard", &myCard); + engine.loadFromModule("Solitare", "Main"); return app.exec(); diff --git a/playingcard.cpp b/playingcard.cpp new file mode 100644 index 0000000..8c500f1 --- /dev/null +++ b/playingcard.cpp @@ -0,0 +1,47 @@ +#include "playingcard.h" + +PlayingCard::PlayingCard(const QString &color, const QString &value, bool isFaceDown, QObject *parent) + : QObject{parent}, m_color{color}, m_value{value}, m_isFaceDown{isFaceDown} +{ } + +QString PlayingCard::color() const +{ + return m_color; +} + +void PlayingCard::setColor(const QString &color) +{ + if (m_color == color) + return; + + m_color = color; + emit onColorChanged(); +} + +QString PlayingCard::value() const +{ + return m_value; +} + +void PlayingCard::setValue(const QString &value) +{ + if (m_value == value) + return; + + m_value = value; + emit onValueChanged(); +} + +bool PlayingCard::isFaceDown() const +{ + return m_isFaceDown; +} + +void PlayingCard::setIsFaceDown(bool faceDown) +{ + if (m_isFaceDown == faceDown) + return; + + m_isFaceDown = faceDown; + emit onIsFaceDownChanged(); +} diff --git a/playingcard.h b/playingcard.h new file mode 100644 index 0000000..ff8f772 --- /dev/null +++ b/playingcard.h @@ -0,0 +1,37 @@ +#ifndef PLAYINGCARD_H +#define PLAYINGCARD_H + +#include + +class PlayingCard : public QObject +{ + Q_OBJECT + Q_PROPERTY(QString color READ color WRITE setColor NOTIFY onColorChanged REQUIRED) + Q_PROPERTY(QString value READ value WRITE setValue NOTIFY onValueChanged REQUIRED) + Q_PROPERTY(bool isFaceDown READ isFaceDown WRITE setIsFaceDown NOTIFY onIsFaceDownChanged) + +public: + explicit PlayingCard(const QString &color = "", const QString &value = "", bool isFaceDown = false, QObject *parent = nullptr); + + QString color() const; + void setColor(const QString &color); + + QString value() const; + void setValue(const QString &value); + + bool isFaceDown() const; + void setIsFaceDown(bool faceDown); + +signals: + void onColorChanged(); + void onValueChanged(); + void onIsFaceDownChanged(); + +private: + QString m_color; + QString m_value; + bool m_isFaceDown; + QString m_imgUrl; +}; + +#endif // PLAYINGCARD_H