diff --git a/qml/CardModel.qml b/qml/CardModel.qml index 86d9ce0..9815ab5 100644 --- a/qml/CardModel.qml +++ b/qml/CardModel.qml @@ -3,16 +3,19 @@ import Solitare Item { id: cardModel - width: 80 - height: width * 1.4 // Maintian the aspect ratio of a playing card required property PlayingCard card required property bool isFaceDown property string backStyle: "red" + signal clicked + width: 80 + height: width * 1.4 // Maintian the aspect ratio of a playing card + Image { id: cardImage + anchors.fill: parent source: cardModel.isFaceDown ? "qrc:/img/playing_cards/backs/" + cardModel.backStyle + ".svg" : cardModel.card ? "qrc:/img/playing_cards/fronts/" + cardModel.card.suitString + "_" + cardModel.card.valueString + ".svg" : "qrc:/img/playing_cards/backs/blue.svg" fillMode: Image.PreserveAspectFit diff --git a/qml/DrawPile.qml b/qml/DrawPile.qml index 8c3da9f..a03b45a 100644 --- a/qml/DrawPile.qml +++ b/qml/DrawPile.qml @@ -3,7 +3,6 @@ import Solitare // Shows the top card facing down // (or a blank card if the pile is empty) - CardModel { card: GameState.drawPile.length > 0 ? GameState.drawPile[GameState.drawPile.length - 1] : null isFaceDown: GameState.drawPile.length > 0 ? true : false diff --git a/qml/FoundationPiles.qml b/qml/FoundationPiles.qml index 5ad49fd..ffd41c6 100644 --- a/qml/FoundationPiles.qml +++ b/qml/FoundationPiles.qml @@ -6,8 +6,10 @@ Row { Repeater { model: 4 // Each of the 4 suits + CardModel { required property int index // passed from repeater + card: GameState.foundation[index].length > 0 ? GameState.foundation[index][0] : null isFaceDown: false } diff --git a/qml/Main.qml b/qml/Main.qml index 37190b2..45f15e6 100644 --- a/qml/Main.qml +++ b/qml/Main.qml @@ -12,6 +12,7 @@ ApplicationWindow { ScoreBar { id: scoreBar + height: 50 anchors.top: parent.top anchors.left: parent.left @@ -21,6 +22,7 @@ ApplicationWindow { // Show the foundation piles, throwaway pile & the draw stack on the first row Rectangle { id: firstRow + height: 135 anchors.top: scoreBar.bottom anchors.left: parent.left @@ -42,6 +44,7 @@ ApplicationWindow { anchors.right: parent.right ThrowawayPile {} + DrawPile {} } } diff --git a/qml/ScoreBar.qml b/qml/ScoreBar.qml index fb85697..fd716fb 100644 --- a/qml/ScoreBar.qml +++ b/qml/ScoreBar.qml @@ -2,41 +2,19 @@ import QtQuick Rectangle { id: scoreBarRoot - width: parent.width - height: 60 - color: "lightgray" property int score: 0 property int time: 0 property int moves: 0 - property int dynamicFontSize: Math.round(height * 0.35) - component ScoreItem: Column { - anchors.verticalCenter: parent.verticalCenter - spacing: 4 - - required property string title - required property string value - required property int fontPixelSize - - Text { - text: parent.title - font.pixelSize: Math.round(parent.fontPixelSize * 0.4) // 40% of the dynamic font size - font.bold: true - horizontalAlignment: Text.AlignHCenter - anchors.horizontalCenter: parent.horizontalCenter - } - Text { - text: parent.value - font.pixelSize: parent.fontPixelSize // 100% of the dynamic font size - horizontalAlignment: Text.AlignHCenter - anchors.horizontalCenter: parent.horizontalCenter - } - } + width: parent.width + height: 60 + color: "lightgray" Row { id: scoreContainer + anchors.horizontalCenter: parent.horizontalCenter anchors.verticalCenter: parent.verticalCenter spacing: 40 @@ -59,14 +37,12 @@ Rectangle { var hours = Math.floor(seconds / 3600); var minutes = Math.floor((seconds % 3600) / 60); var remainingSeconds = seconds % 60; - // Format with leading zeros var formattedTime = ""; - if (hours > 0) { - formattedTime = (hours < 10 ? "0" : "") + hours + ":"; // include hours if > 0 - } - formattedTime += (minutes < 10 ? "0" : "") + minutes + ":" + (remainingSeconds < 10 ? "0" : "") + remainingSeconds; + if (hours > 0) + formattedTime = (hours < 10 ? "0" : "") + hours + ":"; + formattedTime += (minutes < 10 ? "0" : "") + minutes + ":" + (remainingSeconds < 10 ? "0" : "") + remainingSeconds; return formattedTime; } @@ -81,4 +57,28 @@ Rectangle { fontPixelSize: scoreBarRoot.dynamicFontSize } } + + component ScoreItem: Column { + required property string title + required property string value + required property int fontPixelSize + + anchors.verticalCenter: parent.verticalCenter + spacing: 4 + + Text { + text: parent.title + font.pixelSize: Math.round(parent.fontPixelSize * 0.4) // 40% of the dynamic font size + font.bold: true + horizontalAlignment: Text.AlignHCenter + anchors.horizontalCenter: parent.horizontalCenter + } + + Text { + text: parent.value + font.pixelSize: parent.fontPixelSize // 100% of the dynamic font size + horizontalAlignment: Text.AlignHCenter + anchors.horizontalCenter: parent.horizontalCenter + } + } } diff --git a/qml/Tableau.qml b/qml/Tableau.qml index 3c57050..c76c127 100644 --- a/qml/Tableau.qml +++ b/qml/Tableau.qml @@ -2,7 +2,6 @@ import QtQuick import Solitare // In solitare, Tableau refers to the part of the board where all of the columns are placed - Row { spacing: 10 @@ -11,10 +10,12 @@ Row { delegate: Column { required property int index // passed from repeater + spacing: -80 // Overlap Repeater { model: GameState.columns[parent.index].length > 0 ? GameState.columns[parent.index].length : 1 // Render an empty slot for an empty column + delegate: CardModel { required property int index property ColumnSlot col: GameState.columns[parent.index].length > 0 ? GameState.columns[parent.index][index] : null // empty column (single empty slot) @@ -22,9 +23,8 @@ Row { card: col ? col.card : null isFaceDown: col ? !col.revealed : false onClicked: { - if (col && col.revealed) { + if (col && col.revealed) GameState.autoMoveColumnCard(parent.index, index); - } } } } diff --git a/qml/ThrowawayPile.qml b/qml/ThrowawayPile.qml index edf544e..047a006 100644 --- a/qml/ThrowawayPile.qml +++ b/qml/ThrowawayPile.qml @@ -2,24 +2,24 @@ import QtQuick import Solitare // The throwaway pile (shows last 3 cards) - Row { // This allows makes the cards overlap spacing: -60 Repeater { model: Math.min(GameState.throwawayPile.length, 3) + delegate: CardModel { required property int index // passed from repeater property int reversedIndex: Math.min(GameState.throwawayPile.length, 3) - 1 - index + card: GameState.throwawayPile[GameState.throwawayPile.length - 1 - reversedIndex] isFaceDown: false onClicked: { // Only auto-move the last card in the throwaway pile // cards below it are shown, but shouldn't have a click effect - if (reversedIndex == 0) { + if (reversedIndex == 0) GameState.autoMoveThrownCard(); - } } } }