feat: add DesktopMain.qml; make Main.qml mode-aware

Main.qml reads App.config.uiMode at startup:
- Config.Desktop: load DesktopMain.qml via Loader, normal window,
  save/restore window geometry from Config
- anything else (Couch/Auto): existing full-screen couch UI

DesktopMain.qml: SidebarView + LibraryView + GameDetailsSheet +
GameEditDialog + settings overlay.
This commit is contained in:
Marco Allegretti 2026-03-23 12:38:20 +01:00
parent a1e9ce73cd
commit 9936374d4c
3 changed files with 168 additions and 2 deletions

View file

@ -104,6 +104,7 @@ ecm_add_qml_module(alakarte URI org.kde.alakarte
VERSION 1.0
QML_FILES
qml/Main.qml
qml/DesktopMain.qml
qml/LibraryView.qml
qml/GameCard.qml
qml/ConsoleGameDetail.qml

132
src/qml/DesktopMain.qml Normal file
View file

@ -0,0 +1,132 @@
// 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.kde.kirigami as Kirigami
import org.kde.alakarte
import "components"
Item {
id: desktopRoot
property string currentCategory: "all"
property string searchText: ""
property var selectedGame: null
RowLayout {
anchors.fill: parent
spacing: 0
ColumnLayout {
Layout.preferredWidth: 240
Layout.minimumWidth: 180
Layout.maximumWidth: 320
Layout.fillHeight: true
spacing: 0
SidebarView {
id: sidebar
Layout.fillWidth: true
Layout.fillHeight: true
currentSource: desktopRoot.currentCategory
onSourceSelected: function(src) { desktopRoot.currentCategory = src }
onSettingsRequested: settingsLoader.active = true
onImportRequested: App.importAllGames()
onHiddenGamesRequested: applySourceById("hidden")
}
}
Kirigami.Separator {
Layout.fillHeight: true
}
ColumnLayout {
Layout.fillWidth: true
Layout.fillHeight: true
spacing: 0
QQC2.ToolBar {
Layout.fillWidth: true
contentItem: RowLayout {
spacing: Kirigami.Units.mediumSpacing
QQC2.TextField {
id: searchField
Layout.fillWidth: true
placeholderText: i18n("Search games…")
onTextChanged: desktopRoot.searchText = text
Keys.onEscapePressed: { text = ""; desktopRoot.searchText = "" }
}
}
}
LibraryView {
id: libraryView
Layout.fillWidth: true
Layout.fillHeight: true
filterSource: desktopRoot.currentCategory
filterText: desktopRoot.searchText
onHeaderFocusRequested: sidebar.focusList()
onGameFocused: function(game) {}
onGameSelected: function(game) {
desktopRoot.selectedGame = game
gameDetailsSheet.open()
}
onGameLaunched: function(game) {
App.launcher.launchGame(game)
}
}
}
}
GameDetailsSheet {
id: gameDetailsSheet
game: desktopRoot.selectedGame
onLaunchRequested: {
if (desktopRoot.selectedGame) App.launcher.launchGame(desktopRoot.selectedGame)
close()
}
onEditRequested: {
gameEditDialog.game = desktopRoot.selectedGame
gameEditDialog.isEditing = true
close()
gameEditDialog.open()
}
onRemoveRequested: {
if (desktopRoot.selectedGame) App.removeGame(desktopRoot.selectedGame)
desktopRoot.selectedGame = null
close()
}
}
GameEditDialog {
id: gameEditDialog
}
Loader {
id: settingsLoader
anchors.fill: parent
z: 20
active: false
sourceComponent: Item {
Rectangle {
anchors.fill: parent
color: Qt.rgba(0, 0, 0, 0.72)
TapHandler { onTapped: settingsLoader.active = false }
}
SettingsPage {
anchors.centerIn: parent
width: Math.min(parent.width - 48, 760)
height: Math.min(parent.height - 48, 680)
}
Keys.onEscapePressed: settingsLoader.active = false
}
onLoaded: item.forceActiveFocus()
}
}

View file

@ -17,6 +17,8 @@ Maui.ApplicationWindow {
minimumWidth: 800
minimumHeight: 500
readonly property bool isCouchMode: App.config.uiMode !== Config.Desktop
property var focusedGame: null
property var selectedGame: null
property string currentCategory: "all"
@ -25,16 +27,37 @@ Maui.ApplicationWindow {
property bool settingsVisible: false
property string searchText: ""
color: "#0d0d14"
color: isCouchMode ? "#0d0d14" : "transparent"
visibility: isCouchMode ? Window.FullScreen : Window.AutomaticVisibility
Component.onCompleted: {
if (isCouchMode) {
libraryView.restoreFocus()
} else {
if (App.config.windowWidth > 0) width = App.config.windowWidth
if (App.config.windowHeight > 0) height = App.config.windowHeight
if (App.config.windowMaximized) showMaximized()
}
}
onWidthChanged: {
if (!isCouchMode && visibility !== Window.Maximized && visibility !== Window.FullScreen)
App.config.setWindowSize(width, height)
}
onHeightChanged: {
if (!isCouchMode && visibility !== Window.Maximized && visibility !== Window.FullScreen)
App.config.setWindowSize(width, height)
}
onVisibilityChanged: {
if (!isCouchMode)
App.config.windowMaximized = (visibility === Window.Maximized)
}
Item {
id: backdrop
anchors.fill: parent
z: 0
visible: isCouchMode
Image {
id: backdropImg
@ -74,6 +97,7 @@ Maui.ApplicationWindow {
anchors.fill: parent
spacing: 0
z: 1
visible: isCouchMode
Rectangle {
Layout.fillWidth: true
@ -277,8 +301,17 @@ Maui.ApplicationWindow {
id: gameEditDialog
}
Loader {
id: desktopLoader
anchors.fill: parent
z: 1
active: !isCouchMode
source: "DesktopMain.qml"
}
Connections {
target: GamepadManager
enabled: isCouchMode
function onBackPressed() {
if (root.settingsVisible) { root.settingsVisible = false; return }