1
0

feat: make gui?

This commit is contained in:
2026-06-04 19:53:41 +08:00
parent af2d264346
commit 5e652a3207
20 changed files with 836 additions and 2 deletions
@@ -0,0 +1,106 @@
import QtQuick
import QtQuick.Controls
import QtQuick.Layouts
import QtQuick.Effects
import QtQuick.Shapes
import Qt.labs.qmlmodels
import InventoryWars
import Style
Rectangle {
id: root
color: UIStyle.background
required property ListModel rounds
property QtObject selectedRound
signal roundSelected()
ColumnLayout {
anchors.fill: parent
anchors.margins: 20
spacing: 20
Item { Layout.fillHeight: true }
Image {
Layout.alignment: Qt.AlignHCenter
Layout.preferredWidth: 256
source: "images/modules.png"
fillMode: Image.PreserveAspectFit
}
Label {
Layout.alignment: Qt.AlignHCenter
font.pixelSize: UIStyle.fontSizeXL
color: UIStyle.titletextColor
text: "Start a round"
}
ComboBox {
id: roundSelect
Layout.alignment: Qt.AlignHCenter
model: root.rounds
textRole: "name"
}
Button {
Layout.alignment: Qt.AlignHCenter
buttonColor: UIStyle.highlightColor
buttonBorderColor: UIStyle.highlightBorderColor
textColor: UIStyle.textColor
text: "Start"
onClicked: {
root.selectedRound = rounds.get(roundSelect.currentIndex)
roundSelected()
}
}
TableView {
Layout.fillHeight: true
columnSpacing: 1
rowSpacing: 1
delegate: Rectangle {
border.width: 1
implicitHeight: 50
implicitWidth: 100
Text {
anchors.centerIn: parent
text: display
}
}
model: TableModel {
rows: [
{
User: "me",
Score: "1"
}
]
TableModelColumn {
display: "User"
}
TableModelColumn {
display: "Score"
}
}
}
Item { Layout.fillHeight: true }
}
}
@@ -0,0 +1,85 @@
import QtQuick
import QtQuick.Controls
import QtQuick.Layouts
import QtQuick.Effects
import QtQuick.Shapes
import Qt.labs.qmlmodels
import InventoryWars
ApplicationWindow {
height: 480
title: "Inventory Wars"
visible: true
width: 640
ListModel {
id: rounds
ListElement {
name: "Round 1"
mode: GameService.GameScoring.FirstGuess
item_id: 100
item_name: "Item 1"
item_image: ""
clue: "Clue 1"
}
ListElement {
name: "Round 2"
mode: GameService.GameScoring.FirstGuess
item_id: 100
item_name: "Item 2"
item_image: ""
clue: "Clue 2"
}
ListElement {
name: "Round 3"
mode: GameService.GameScoring.FirstGuess
item_id: 100
item_name: "Item 3"
item_image: ""
clue: "Clue 3"
}
ListElement {
name: "Round 4"
mode: GameService.GameScoring.FirstGuess
item_id: 100
item_name: "Item 4"
item_image: ""
clue: "Clue 4"
}
}
IdleView {
id: idleView
anchors.fill: parent
rounds: rounds
selectedRound: rounds.get(0)
onRoundSelected: {
idleView.visible = false
ongoingView.start()
ongoingView.visible = true
}
}
OngoingView {
id: ongoingView
anchors.fill: parent
visible: false
round: idleView.selectedRound
gameService: gameService
onClose: {
idleView.visible = true
ongoingView.visible = false
}
}
GameService {
id: gameService
}
}
@@ -0,0 +1,188 @@
import QtQuick
import QtQuick.Controls
import QtQuick.Layouts
import QtQuick.Effects
import QtQuick.Shapes
import Qt.labs.qmlmodels
import InventoryWars
import Style
Rectangle {
id: root
color: UIStyle.background
required property GameService gameService
required property QtObject round
property QtObject guessed: QtObject {
property string username
property double seconds
}
property QtObject highest: QtObject {
property string username
property int count
}
function start() {
gameService.start(round.item_id, round.mode)
}
signal close()
Connections {
target: root.gameService
function onGuessed(username: str, seconds: double) {
root.guessed.username = username
root.guessed.seconds = seconds
}
function onHighest(username: str, count: int) {
root.highest.username = username
root.highest.count = count
}
}
ColumnLayout {
anchors.fill: parent
anchors.bottomMargin: 10
spacing: 5
ToolBar {
Layout.fillWidth: true
Layout.minimumHeight: 35
RowLayout {
anchors.fill: parent
anchors.leftMargin: 5
anchors.rightMargin: 5
Layout.alignment: Qt.AlignVCenter
Button {
Layout.preferredWidth: 25
Layout.preferredHeight: 25
icon.name: "back"
icon.source: "icons/x.svg"
onClicked: root.close()
}
Item {
Layout.fillWidth: true
}
Text {
Layout.alignment: Qt.AlignVCenter | Qt.AlignLeft
font.pixelSize: UIStyle.fontSizeM
font.bold: true
color: UIStyle.titletextColor
text: root.round.name
}
Item {
Layout.fillWidth: true
}
}
}
Item { Layout.fillHeight: true }
Label {
Layout.alignment: Qt.AlignHCenter
font.pixelSize: UIStyle.fontSizeL
font.bold: true
color: UIStyle.titletextColor
text: "Current Item:"
}
Text {
Layout.alignment: Qt.AlignHCenter
font.pixelSize: UIStyle.fontSizeM
color: UIStyle.textColor
text: root.gameService.state == GameService.Ongoing ? "???" : root.round.item_name
}
Image {
Layout.alignment: Qt.AlignHCenter
Layout.preferredWidth: 256
Layout.preferredHeight: 256
source: root.gameService.state == GameService.Ongoing ? "images/unknown.png" : root.round.item_image
fillMode: Image.PreserveAspectFit
}
Text {
Layout.alignment: Qt.AlignHCenter
font.pixelSize: UIStyle.fontSizeXL
font.bold: true
color: UIStyle.textColor
text: ""
Timer {
id: elapsedTimer
interval: 10
running: root.gameService.state != GameService.Ended
repeat: true
onTriggered: {
parent.text = root.gameService.elapsedSeconds.toFixed(2) + "s"
}
}
}
Text {
Layout.alignment: Qt.AlignHCenter
font.pixelSize: UIStyle.fontSizeM
font.bold: true
color: UIStyle.textColor
visible: root.gameService.state == GameService.GameState.Hidden
text: "Clue: " + root.round.clue
}
Text {
Layout.alignment: Qt.AlignHCenter
font.pixelSize: UIStyle.fontSizeM
font.bold: true
color: UIStyle.textColor
visible: root.gameService.state != GameService.GameState.Hidden
text: "Fastest guess: " + root.guessed.seconds + "s (by " + root.guessed.username + ")"
}
Text {
Layout.alignment: Qt.AlignHCenter
font.pixelSize: UIStyle.fontSizeM
font.bold: true
color: UIStyle.textColor
visible: root.gameService.state != GameService.GameState.Hidden && root.round.mode == GameService.GameScoring.FirstGuessThenHighestAmount
text: "Highest count: " + root.highest.count + " (by " + root.highest.username + ")"
}
Item { Layout.fillHeight: true }
Button {
Layout.alignment: Qt.AlignHCenter
visible: root.gameService.state != GameService.GameState.Ended
text: "End"
onClicked: root.gameService.end()
}
}
}
@@ -0,0 +1 @@
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 640 640"><!--!Font Awesome Free v7.2.0 by @fontawesome - https://fontawesome.com License - https://fontawesome.com/license/free Copyright 2026 Fonticons, Inc.--><path d="M504.6 148.5C515.9 134.9 514.1 114.7 500.5 103.4C486.9 92.1 466.7 93.9 455.4 107.5L320 270L184.6 107.5C173.3 93.9 153.1 92.1 139.5 103.4C125.9 114.7 124.1 134.9 135.4 148.5L278.3 320L135.4 491.5C124.1 505.1 125.9 525.3 139.5 536.6C153.1 547.9 173.3 546.1 184.6 532.5L320 370L455.4 532.5C466.7 546.1 486.9 547.9 500.5 536.6C514.1 525.3 515.9 505.1 504.6 491.5L361.7 320L504.6 148.5z"/></svg>

After

Width:  |  Height:  |  Size: 613 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 102 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 40 KiB

@@ -0,0 +1,4 @@
module InventoryWars
Main 1.0 Main.qml
IdleView 1.0 IdleView.qml
OngoingView 1.0 OngoingView.qml