From 9936374d4c29dc575492f420463e0600162dce2b Mon Sep 17 00:00:00 2001 From: Marco Allegretti Date: Mon, 23 Mar 2026 12:38:20 +0100 Subject: [PATCH] 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. --- src/CMakeLists.txt | 1 + src/qml/DesktopMain.qml | 132 ++++++++++++++++++++++++++++++++++++++++ src/qml/Main.qml | 37 ++++++++++- 3 files changed, 168 insertions(+), 2 deletions(-) create mode 100644 src/qml/DesktopMain.qml diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index c5c45de..92dcf91 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -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 diff --git a/src/qml/DesktopMain.qml b/src/qml/DesktopMain.qml new file mode 100644 index 0000000..4d4615c --- /dev/null +++ b/src/qml/DesktopMain.qml @@ -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() + } +} diff --git a/src/qml/Main.qml b/src/qml/Main.qml index 061b157..73bff33 100644 --- a/src/qml/Main.qml +++ b/src/qml/Main.qml @@ -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: { - libraryView.restoreFocus() + 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 }