a-la-karte/src/qml/LibraryView.qml

147 lines
4.8 KiB
QML
Raw Normal View History

// SPDX-License-Identifier: GPL-3.0-or-later
// SPDX-FileCopyrightText: 2026 A-La-Karte Contributors
import QtQuick
import QtQuick.Controls as QQC2
import QtQuick.Layouts
import org.mauikit.controls as Maui
import org.kde.alakarte
import "components"
FocusScope {
id: libraryRoot
property string filterSource: "all"
property string filterText: ""
signal gameSelected(var game)
signal gameFocused(var game)
signal gameLaunched(var game)
signal headerFocusRequested()
readonly property int gameCount: proxyModel.count
function restoreFocus() {
if (grid.flickable) {
grid.flickable.forceActiveFocus()
} else {
grid.forceActiveFocus()
}
}
function focusedGame() {
if (grid.currentIndex < 0) return null
return proxyModel.get(grid.currentIndex)
}
function selectFocused() {
let g = focusedGame()
if (g) libraryRoot.gameSelected(g)
}
function launchFocused() {
let g = focusedGame()
if (g) libraryRoot.gameLaunched(g)
}
GameSortFilterModel {
id: proxyModel
sourceModel: App.gameModel
showHidden: libraryRoot.filterSource === "hidden"
favoritesOnly: libraryRoot.filterSource === "favorites"
filterSource: {
if (libraryRoot.filterSource === "all") return ""
if (libraryRoot.filterSource === "favorites") return ""
if (libraryRoot.filterSource === "hidden") return ""
return libraryRoot.filterSource
}
filterText: libraryRoot.filterText
}
Maui.GridBrowser {
id: grid
anchors.fill: parent
focus: true
model: proxyModel
itemSize: Math.max(160, Math.min(App.config.gridSize, 280))
itemHeight: Math.round(grid.itemSize * 1.5)
adaptContent: true
enableLassoSelection: false
topPadding: 16
bottomPadding: 24
leftPadding: 24
rightPadding: 24
holder.visible: proxyModel.count === 0 && !App.importing
holder.emoji: libraryRoot.filterSource === "favorites" ? "starred-symbolic"
: "applications-games"
holder.title: libraryRoot.filterSource === "favorites"
? i18n("No favorites yet")
: i18n("Your library is empty")
holder.body: libraryRoot.filterSource === "favorites"
? i18n("Mark games as favorites to see them here")
: i18n("Import games to get started")
onCurrentIndexChanged: {
let g = proxyModel.get(currentIndex)
if (g) libraryRoot.gameFocused(g)
}
delegate: GameCard {
game: model.gameObject
gridActive: grid.flickable ? grid.flickable.activeFocus : grid.activeFocus
onClicked: {
grid.currentIndex = index
libraryRoot.gameSelected(model.gameObject)
}
onPlayClicked: {
grid.currentIndex = index
libraryRoot.gameLaunched(model.gameObject)
}
}
Keys.onReturnPressed: libraryRoot.selectFocused()
Keys.onEnterPressed: libraryRoot.selectFocused()
Keys.onSpacePressed: libraryRoot.selectFocused()
QQC2.BusyIndicator {
anchors.centerIn: parent
running: App.importing
visible: App.importing
}
Connections {
target: GamepadManager
function onSelectPressed() {
if (!grid.flickable || !grid.flickable.activeFocus) return
libraryRoot.selectFocused()
}
function onNavigateUp() {
if (!grid.flickable || !grid.flickable.activeFocus) return
let cols = Math.max(1, Math.floor(grid.width / grid.cellWidth))
if (grid.currentIndex < cols) {
libraryRoot.headerFocusRequested()
return
}
grid.currentIndex = Math.max(0, grid.currentIndex - cols)
}
function onNavigateDown() {
if (!grid.flickable || !grid.flickable.activeFocus) return
let cols = Math.max(1, Math.floor(grid.width / grid.cellWidth))
grid.currentIndex = Math.min(proxyModel.count - 1, grid.currentIndex + cols)
}
function onNavigateLeft() {
if (!grid.flickable || !grid.flickable.activeFocus) return
grid.currentIndex = Math.max(0, grid.currentIndex - 1)
}
function onNavigateRight() {
if (!grid.flickable || !grid.flickable.activeFocus) return
grid.currentIndex = Math.min(proxyModel.count - 1, grid.currentIndex + 1)
}
}
}
}