The CatDefs singleton did not resolve on the reporter's Linux build, which showed up as "property mood of object CatDefs is not a function". The same lookup failure made CatDefs.aspect undefined, so the cat window's height became NaN and the cat rendered as a moving line. The mug survived because its height used a literal ratio. The singleton is gone rather than repaired, since nothing in it had to be shared. The mood name now comes from C++, derived from the enum key, so there is one source of truth instead of a list in QML that had to match. Window sizes now follow the implicit size of the drawing they contain, so the proportions live in the one file that defines them. Also for X11: TNCat now warns, naming Xfce's compositor setting, when its window comes up without an alpha channel, which is what a missing compositor looks like and why the mug had a black background. Opaque mode no longer hides the chip and the mug. TNCAT_DEBUG=1 logs window geometry. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
293 lines
11 KiB
QML
293 lines
11 KiB
QML
pragma ComponentBehavior: Bound
|
|
import QtQuick
|
|
import TNCat
|
|
|
|
// Plain Qt Quick: no Controls, no Widgets, no Layouts.
|
|
Window {
|
|
id: win
|
|
|
|
required property CatController cat
|
|
required property AppSettings settings
|
|
|
|
readonly property var coats: [
|
|
{ name: qsTr("Apricot"), color: "#f4b183" },
|
|
{ name: qsTr("Ivory"), color: "#f3ede2" },
|
|
{ name: qsTr("Grey"), color: "#a4a6b3" },
|
|
{ name: qsTr("Charcoal"), color: "#3c3b46" },
|
|
{ name: qsTr("Sage"), color: "#a9bfa0" },
|
|
{ name: qsTr("Plum"), color: "#9a7bb0" }
|
|
]
|
|
readonly property real margin: 22
|
|
readonly property real labelWidth: 96
|
|
|
|
width: 440
|
|
// Tall enough for the whole panel, but never taller than the screen; the
|
|
// Flickable takes over when it has to be shorter.
|
|
height: Math.min(830, Screen.desktopAvailableHeight - 60)
|
|
minimumWidth: 380
|
|
minimumHeight: 420
|
|
title: qsTr("TNCat")
|
|
color: "#faf7f2"
|
|
flags: Qt.Dialog
|
|
|
|
Flickable {
|
|
id: flick
|
|
anchors.fill: parent
|
|
contentWidth: width
|
|
contentHeight: content.implicitHeight + win.margin * 2
|
|
boundsBehavior: Flickable.StopAtBounds
|
|
|
|
Column {
|
|
id: content
|
|
x: win.margin
|
|
y: win.margin
|
|
width: flick.width - win.margin * 2
|
|
spacing: 16
|
|
|
|
// header
|
|
Item {
|
|
width: parent.width
|
|
height: Math.max(96, headerText.implicitHeight)
|
|
|
|
Loader {
|
|
id: preview
|
|
width: 106
|
|
height: Math.round(width * 106 / 120)
|
|
anchors.verticalCenter: parent.verticalCenter
|
|
active: win.visible
|
|
sourceComponent: Cat {
|
|
coat: win.settings.coat
|
|
mood: "sitting"
|
|
showCodes: false
|
|
petted: previewHover.hovered
|
|
HoverHandler { id: previewHover }
|
|
}
|
|
}
|
|
|
|
Column {
|
|
id: headerText
|
|
anchors.left: preview.right
|
|
anchors.leftMargin: 14
|
|
anchors.right: parent.right
|
|
anchors.verticalCenter: parent.verticalCenter
|
|
spacing: 4
|
|
|
|
Text {
|
|
text: qsTr("TNCat")
|
|
font.pixelSize: 26
|
|
font.bold: true
|
|
color: "#2f2a36"
|
|
}
|
|
Text {
|
|
width: headerText.width
|
|
wrapMode: Text.WordWrap
|
|
text: qsTr("A little cat that wanders along the bottom of your screen. Click to pet it, drag it somewhere else.")
|
|
color: "#7a7484"
|
|
font.pixelSize: 12
|
|
}
|
|
}
|
|
}
|
|
|
|
SettingsGroup {
|
|
width: parent.width
|
|
title: qsTr("COAT")
|
|
|
|
Flow {
|
|
width: parent.width
|
|
spacing: 12
|
|
|
|
Repeater {
|
|
model: win.coats
|
|
|
|
Column {
|
|
id: swatch
|
|
required property var modelData
|
|
readonly property bool selected: Qt.colorEqual(win.settings.coat, modelData.color)
|
|
spacing: 4
|
|
|
|
Rectangle {
|
|
width: 40
|
|
height: 40
|
|
radius: 20
|
|
color: swatch.modelData.color
|
|
border.width: swatch.selected ? 3 : 1
|
|
border.color: swatch.selected ? "#f25f7a" : "#d8d2ca"
|
|
antialiasing: true
|
|
activeFocusOnTab: true
|
|
|
|
Accessible.role: Accessible.RadioButton
|
|
Accessible.name: swatch.modelData.name
|
|
Accessible.checked: swatch.selected
|
|
Accessible.onPressAction: win.settings.coat = swatch.modelData.color
|
|
|
|
TapHandler { onTapped: win.settings.coat = swatch.modelData.color }
|
|
Keys.onSpacePressed: win.settings.coat = swatch.modelData.color
|
|
}
|
|
|
|
Text {
|
|
anchors.horizontalCenter: parent.horizontalCenter
|
|
text: swatch.modelData.name
|
|
font.pixelSize: 11
|
|
color: "#7a7484"
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
SettingsGroup {
|
|
width: parent.width
|
|
title: qsTr("THE CAT")
|
|
spacing: 12
|
|
|
|
Item {
|
|
width: parent.width
|
|
height: 26
|
|
Text {
|
|
id: sizeLabel
|
|
anchors.verticalCenter: parent.verticalCenter
|
|
width: win.labelWidth
|
|
text: qsTr("Size")
|
|
color: "#2f2a36"
|
|
font.pixelSize: 13
|
|
}
|
|
AppSlider {
|
|
anchors.left: sizeLabel.right
|
|
anchors.right: parent.right
|
|
anchors.verticalCenter: parent.verticalCenter
|
|
from: 72; to: 260; stepSize: 4
|
|
value: win.settings.catSize
|
|
suffix: qsTr("px")
|
|
onMoved: function(v) { win.settings.catSize = v }
|
|
}
|
|
}
|
|
|
|
Item {
|
|
width: parent.width
|
|
height: 26
|
|
Text {
|
|
id: paceLabel
|
|
anchors.verticalCenter: parent.verticalCenter
|
|
width: win.labelWidth
|
|
text: qsTr("Pace")
|
|
color: "#2f2a36"
|
|
font.pixelSize: 13
|
|
}
|
|
AppSlider {
|
|
anchors.left: paceLabel.right
|
|
anchors.right: parent.right
|
|
anchors.verticalCenter: parent.verticalCenter
|
|
from: 10; to: 200; stepSize: 5
|
|
value: win.settings.walkSpeed
|
|
onMoved: function(v) { win.settings.walkSpeed = v }
|
|
}
|
|
}
|
|
|
|
Item {
|
|
width: parent.width
|
|
height: 26
|
|
Text {
|
|
id: groundLabel
|
|
anchors.verticalCenter: parent.verticalCenter
|
|
width: win.labelWidth
|
|
text: qsTr("Ground line")
|
|
color: "#2f2a36"
|
|
font.pixelSize: 13
|
|
}
|
|
AppSlider {
|
|
anchors.left: groundLabel.right
|
|
anchors.right: parent.right
|
|
anchors.verticalCenter: parent.verticalCenter
|
|
from: 0; to: 600; stepSize: 10
|
|
value: win.settings.bottomMargin
|
|
suffix: qsTr("px")
|
|
onMoved: function(v) { win.settings.bottomMargin = v }
|
|
}
|
|
}
|
|
|
|
Text {
|
|
width: parent.width
|
|
wrapMode: Text.WordWrap
|
|
text: qsTr("The ground line lifts the cat off the bottom edge, so it can walk above a taskbar or a row of softkeys.")
|
|
color: "#9b95a3"
|
|
font.pixelSize: 11
|
|
}
|
|
}
|
|
|
|
SettingsGroup {
|
|
width: parent.width
|
|
title: qsTr("HABITS")
|
|
spacing: 12
|
|
|
|
AppToggle {
|
|
width: parent.width
|
|
checked: win.settings.followCursor
|
|
text: qsTr("Follow the mouse with its eyes")
|
|
onToggled: function(v) { win.settings.followCursor = v }
|
|
}
|
|
AppToggle {
|
|
width: parent.width
|
|
checked: win.settings.showCodes
|
|
text: qsTr("Announce what it does in G-code")
|
|
onToggled: function(v) { win.settings.showCodes = v }
|
|
}
|
|
AppToggle {
|
|
width: parent.width
|
|
checked: win.settings.chipsEnabled
|
|
text: qsTr("Chase a chip now and then")
|
|
onToggled: function(v) { win.settings.chipsEnabled = v }
|
|
}
|
|
AppToggle {
|
|
width: parent.width
|
|
checked: win.settings.coffeeEnabled
|
|
text: qsTr("Stop for coffee now and then")
|
|
onToggled: function(v) { win.settings.coffeeEnabled = v }
|
|
}
|
|
AppToggle {
|
|
width: parent.width
|
|
checked: win.cat.paused
|
|
text: win.cat.paused ? qsTr("Napping, nothing will wake it") : qsTr("Awake and on the move")
|
|
onToggled: function(v) { win.cat.paused = v }
|
|
}
|
|
}
|
|
|
|
SettingsGroup {
|
|
width: parent.width
|
|
title: qsTr("TRICKS")
|
|
|
|
Flow {
|
|
width: parent.width
|
|
spacing: 8
|
|
|
|
AppButton { text: qsTr("Sit"); onClicked: win.cat.doTrick(CatController.Sitting) }
|
|
AppButton { text: qsTr("Groom"); onClicked: win.cat.doTrick(CatController.Grooming) }
|
|
AppButton { text: qsTr("Stretch"); onClicked: win.cat.doTrick(CatController.Stretching) }
|
|
AppButton { text: qsTr("Dash"); onClicked: win.cat.doTrick(CatController.Running) }
|
|
AppButton { text: qsTr("Nap"); onClicked: win.cat.doTrick(CatController.Sleeping) }
|
|
AppButton { text: qsTr("Chip"); onClicked: win.cat.tossChip() }
|
|
AppButton { text: qsTr("Coffee"); onClicked: win.cat.coffeeBreak() }
|
|
}
|
|
}
|
|
|
|
Item {
|
|
width: parent.width
|
|
height: 34
|
|
|
|
Text {
|
|
anchors.left: parent.left
|
|
anchors.verticalCenter: parent.verticalCenter
|
|
text: qsTr("%n pet(s) so far.", "", win.settings.petCount)
|
|
color: "#7a7484"
|
|
font.pixelSize: 12
|
|
}
|
|
AppButton {
|
|
anchors.right: parent.right
|
|
anchors.verticalCenter: parent.verticalCenter
|
|
text: qsTr("Quit")
|
|
onClicked: Qt.quit()
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|