import QtQuick import Solitare // In solitare, Tableau refers to the part of the board where all of the columns are placed Row { id: tableau required property real cardWidth required property real cardHeight spacing: cardWidth * 0.125 Repeater { id: colRepeater model: GameState.columns.length delegate: Column { required property int index // passed from repeater spacing: -tableau.cardHeight * 0.8 // Overlap Repeater { id: slotRepeater model: GameState.columns[parent.index].length > 0 ? GameState.columns[parent.index].length : 1 // Render an empty slot for an empty column delegate: ColumnSlotModel { required property int index // passed from repeater cardId: index columnId: parent.index // this is actually passed from the Column, not the Repeater width: tableau.cardWidth height: tableau.cardHeight } } } } component ColumnSlotModel: Item { required property int columnId required property int cardId property ColumnSlot colSlot: GameState.columns[columnId].length > 0 ? GameState.columns[columnId][cardId] : null CardModel { id: colCard anchors.fill: parent visible: parent.colSlot !== null card: parent.colSlot ? parent.colSlot.card : null isFaceDown: parent.colSlot ? !parent.colSlot.revealed : false onClicked: { if (parent.colSlot && parent.colSlot.revealed) { if (GameState.autoMoveColumnCard(parent.columnId, parent.cardId)) { if (GameState.isWinnable()) { console.log("Still winnable"); } else { console.log("Game is lost"); } } } } } Rectangle { id: emptySlotRect anchors.fill: parent visible: parent.colSlot === null color: "gray" border.color: "white" border.width: width * 0.025 opacity: 0.2 radius: width * 0.05 } } }