mirror of
https://invent.kde.org/marcoa/a-la-karte.git
synced 2026-02-09 21:13:08 +00:00
Merge branch 'feat/couch-mode-diagnostics' into 'master'
Couch Mode: add diagnostics overlay See merge request marcoa/a-la-karte!2
This commit is contained in:
commit
1889f9cf81
7 changed files with 346 additions and 11 deletions
|
|
@ -64,6 +64,7 @@ ecm_add_qml_module(alakarte URI org.kde.alakarte
|
|||
qml/LibraryView.qml
|
||||
qml/GameCard.qml
|
||||
qml/GameDetailsSheet.qml
|
||||
qml/DiagnosticsSheet.qml
|
||||
qml/SettingsPage.qml
|
||||
qml/SidebarView.qml
|
||||
qml/GameEditDialog.qml
|
||||
|
|
|
|||
|
|
@ -132,6 +132,159 @@ bool GameLauncher::hasRunningGames() const
|
|||
return !m_runningGames.isEmpty();
|
||||
}
|
||||
|
||||
QVariantMap GameLauncher::resolveLaunchInfo(Game *game) const
|
||||
{
|
||||
QVariantMap info;
|
||||
info.insert(QStringLiteral("ok"), false);
|
||||
|
||||
if (!game) {
|
||||
info.insert(QStringLiteral("error"), tr("No game selected"));
|
||||
return info;
|
||||
}
|
||||
|
||||
info.insert(QStringLiteral("gameId"), game->id());
|
||||
info.insert(QStringLiteral("gameName"), game->name());
|
||||
info.insert(QStringLiteral("isRunning"), m_runningGames.contains(game->id()));
|
||||
|
||||
const QString command = game->launchCommand();
|
||||
info.insert(QStringLiteral("launchCommand"), command);
|
||||
if (command.isEmpty()) {
|
||||
info.insert(QStringLiteral("error"), tr("No launch command configured"));
|
||||
return info;
|
||||
}
|
||||
|
||||
const QString runner = game->launchRunner().trimmed();
|
||||
const QString runnerPath = game->launchRunnerPath().trimmed();
|
||||
const QString prefixPath = game->launchPrefixPath().trimmed();
|
||||
const QVariantMap launchEnv = game->launchEnv();
|
||||
const bool hasLaunchOverrides = !runner.isEmpty() || !runnerPath.isEmpty() || !prefixPath.isEmpty() || !launchEnv.isEmpty();
|
||||
|
||||
info.insert(QStringLiteral("runner"), runner);
|
||||
info.insert(QStringLiteral("runnerPath"), runnerPath);
|
||||
info.insert(QStringLiteral("prefixPath"), prefixPath);
|
||||
info.insert(QStringLiteral("workingDirectory"), game->workingDirectory());
|
||||
info.insert(QStringLiteral("hasLaunchOverrides"), hasLaunchOverrides);
|
||||
|
||||
QVariantMap envOverrides;
|
||||
for (auto it = launchEnv.constBegin(); it != launchEnv.constEnd(); ++it) {
|
||||
const QString key = it.key();
|
||||
if (key.isEmpty() || key.contains(QLatin1Char('='))) {
|
||||
continue;
|
||||
}
|
||||
envOverrides.insert(key, it.value().toString());
|
||||
}
|
||||
info.insert(QStringLiteral("envOverrides"), envOverrides);
|
||||
|
||||
if (!hasLaunchOverrides && command.startsWith(QLatin1String("steam://"))) {
|
||||
info.insert(QStringLiteral("ok"), true);
|
||||
info.insert(QStringLiteral("launchType"), QStringLiteral("url"));
|
||||
info.insert(QStringLiteral("url"), command);
|
||||
info.insert(QStringLiteral("usesDesktopServices"), true);
|
||||
return info;
|
||||
}
|
||||
|
||||
if (!hasLaunchOverrides && command.startsWith(QLatin1String("lutris "))) {
|
||||
info.insert(QStringLiteral("ok"), true);
|
||||
info.insert(QStringLiteral("launchType"), QStringLiteral("url"));
|
||||
info.insert(QStringLiteral("url"), command.mid(7));
|
||||
info.insert(QStringLiteral("usesDesktopServices"), true);
|
||||
return info;
|
||||
}
|
||||
|
||||
QStringList parts;
|
||||
if (command.startsWith(QLatin1String("steam://"))) {
|
||||
parts = {QStringLiteral("xdg-open"), command};
|
||||
} else if (command.startsWith(QLatin1String("lutris "))) {
|
||||
parts = {QStringLiteral("xdg-open"), command.mid(7)};
|
||||
} else {
|
||||
parts = QProcess::splitCommand(command);
|
||||
}
|
||||
|
||||
if (parts.isEmpty()) {
|
||||
info.insert(QStringLiteral("error"), tr("Invalid launch command"));
|
||||
return info;
|
||||
}
|
||||
|
||||
const QString program = parts.takeFirst();
|
||||
info.insert(QStringLiteral("program"), program);
|
||||
info.insert(QStringLiteral("args"), parts);
|
||||
|
||||
QString finalProgram = program;
|
||||
QStringList finalArgs = parts;
|
||||
|
||||
QVariantMap effectiveEnv = envOverrides;
|
||||
|
||||
if ((runner == QLatin1String("wine") || runner == QLatin1String("proton")) && (program == QLatin1String("xdg-open"))) {
|
||||
info.insert(QStringLiteral("error"), tr("This runner cannot be used with URL-based launch commands"));
|
||||
return info;
|
||||
}
|
||||
|
||||
if (runner == QLatin1String("custom")) {
|
||||
if (runnerPath.isEmpty()) {
|
||||
info.insert(QStringLiteral("error"), tr("Custom runner is enabled but no runner path is configured"));
|
||||
return info;
|
||||
}
|
||||
finalProgram = runnerPath;
|
||||
finalArgs = {program};
|
||||
finalArgs.append(parts);
|
||||
} else if (runner == QLatin1String("wine")) {
|
||||
QString wineExe = runnerPath;
|
||||
if (wineExe.isEmpty()) {
|
||||
wineExe = QStandardPaths::findExecutable(QStringLiteral("wine"));
|
||||
}
|
||||
if (wineExe.isEmpty()) {
|
||||
info.insert(QStringLiteral("error"), tr("Wine runner is enabled but Wine was not found"));
|
||||
return info;
|
||||
}
|
||||
|
||||
QString winePrefix = prefixPath;
|
||||
if (winePrefix.isEmpty()) {
|
||||
winePrefix = QStandardPaths::writableLocation(QStandardPaths::AppDataLocation) + QStringLiteral("/prefixes/") + game->id();
|
||||
}
|
||||
|
||||
effectiveEnv.insert(QStringLiteral("WINEPREFIX"), winePrefix);
|
||||
info.insert(QStringLiteral("resolvedPrefixPath"), winePrefix);
|
||||
|
||||
finalProgram = wineExe;
|
||||
finalArgs = {program};
|
||||
finalArgs.append(parts);
|
||||
} else if (runner == QLatin1String("proton")) {
|
||||
QString protonExe = runnerPath;
|
||||
if (protonExe.isEmpty()) {
|
||||
protonExe = discoverDefaultProtonExecutable();
|
||||
}
|
||||
if (protonExe.isEmpty()) {
|
||||
info.insert(QStringLiteral("error"), tr("Proton runner is enabled but no Proton installation was found"));
|
||||
return info;
|
||||
}
|
||||
|
||||
const QString steamInstallPath = findSteamClientInstallPathFromProton(protonExe);
|
||||
info.insert(QStringLiteral("resolvedSteamInstallPath"), steamInstallPath);
|
||||
|
||||
QString compatDataPath = prefixPath;
|
||||
if (compatDataPath.isEmpty()) {
|
||||
compatDataPath = QStandardPaths::writableLocation(QStandardPaths::AppDataLocation) + QStringLiteral("/prefixes/") + game->id();
|
||||
}
|
||||
|
||||
effectiveEnv.insert(QStringLiteral("STEAM_COMPAT_DATA_PATH"), compatDataPath);
|
||||
info.insert(QStringLiteral("resolvedPrefixPath"), compatDataPath);
|
||||
|
||||
if (!steamInstallPath.isEmpty()) {
|
||||
effectiveEnv.insert(QStringLiteral("STEAM_COMPAT_CLIENT_INSTALL_PATH"), steamInstallPath);
|
||||
}
|
||||
|
||||
finalProgram = protonExe;
|
||||
finalArgs = {QStringLiteral("run"), program};
|
||||
finalArgs.append(parts);
|
||||
}
|
||||
|
||||
info.insert(QStringLiteral("finalProgram"), finalProgram);
|
||||
info.insert(QStringLiteral("finalArgs"), finalArgs);
|
||||
info.insert(QStringLiteral("effectiveEnv"), effectiveEnv);
|
||||
info.insert(QStringLiteral("ok"), true);
|
||||
return info;
|
||||
}
|
||||
|
||||
void GameLauncher::launchGame(Game *game)
|
||||
{
|
||||
if (!game) {
|
||||
|
|
|
|||
|
|
@ -7,6 +7,7 @@
|
|||
#include <QObject>
|
||||
#include <QProcess>
|
||||
#include <QQmlEngine>
|
||||
#include <QVariantMap>
|
||||
|
||||
#include "game.h"
|
||||
|
||||
|
|
@ -24,6 +25,7 @@ public:
|
|||
bool hasRunningGames() const;
|
||||
|
||||
Q_INVOKABLE void launchGame(Game *game);
|
||||
Q_INVOKABLE QVariantMap resolveLaunchInfo(Game *game) const;
|
||||
Q_INVOKABLE void stopGame(Game *game);
|
||||
Q_INVOKABLE bool isGameRunning(Game *game) const;
|
||||
|
||||
|
|
|
|||
126
src/qml/DiagnosticsSheet.qml
Normal file
126
src/qml/DiagnosticsSheet.qml
Normal file
|
|
@ -0,0 +1,126 @@
|
|||
import QtQuick
|
||||
import QtQuick.Controls as QQC2
|
||||
import QtQuick.Layouts
|
||||
import org.kde.kirigami as Kirigami
|
||||
import org.kde.alakarte
|
||||
|
||||
Kirigami.OverlaySheet {
|
||||
id: diagnosticsSheet
|
||||
|
||||
property var game
|
||||
property var launchInfo: ({})
|
||||
|
||||
title: i18n("Diagnostics")
|
||||
parent: applicationWindow().overlay
|
||||
|
||||
closePolicy: QQC2.Popup.CloseOnEscape | QQC2.Popup.CloseOnPressOutside
|
||||
|
||||
implicitWidth: {
|
||||
let w = applicationWindow()
|
||||
if (!w) return Kirigami.Units.gridUnit * 30
|
||||
if (w.isMobile) return w.width
|
||||
if (w.isNarrowScreen) return w.width - Kirigami.Units.largeSpacing * 2
|
||||
return Math.min(w.width - Kirigami.Units.gridUnit * 2, Kirigami.Units.gridUnit * 34)
|
||||
}
|
||||
|
||||
implicitHeight: {
|
||||
let w = applicationWindow()
|
||||
if (!w) return Kirigami.Units.gridUnit * 30
|
||||
if (w.isMobile) return w.height
|
||||
return Math.min(w.height - Kirigami.Units.gridUnit * 2, Kirigami.Units.gridUnit * 42)
|
||||
}
|
||||
|
||||
onOpened: {
|
||||
if (game) {
|
||||
launchInfo = App.launcher.resolveLaunchInfo(game)
|
||||
} else {
|
||||
launchInfo = ({ "ok": false, "error": i18n("No game selected") })
|
||||
}
|
||||
closeButton.forceActiveFocus()
|
||||
}
|
||||
|
||||
header: Kirigami.ShadowedRectangle {
|
||||
implicitHeight: headerRow.implicitHeight + Kirigami.Units.largeSpacing * 2
|
||||
radius: Kirigami.Units.mediumSpacing
|
||||
color: Kirigami.Theme.backgroundColor
|
||||
|
||||
RowLayout {
|
||||
id: headerRow
|
||||
anchors.fill: parent
|
||||
anchors.margins: Kirigami.Units.largeSpacing
|
||||
spacing: Kirigami.Units.mediumSpacing
|
||||
|
||||
Kirigami.Heading {
|
||||
text: diagnosticsSheet.title
|
||||
level: 2
|
||||
Layout.fillWidth: true
|
||||
elide: Text.ElideRight
|
||||
}
|
||||
|
||||
QQC2.ToolButton {
|
||||
id: closeButton
|
||||
text: i18n("Close")
|
||||
icon.name: "dialog-close"
|
||||
display: QQC2.AbstractButton.IconOnly
|
||||
onClicked: diagnosticsSheet.close()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
contentItem: QQC2.ScrollView {
|
||||
id: scroll
|
||||
clip: true
|
||||
|
||||
ColumnLayout {
|
||||
width: scroll.availableWidth
|
||||
spacing: Kirigami.Units.largeSpacing
|
||||
|
||||
Kirigami.InlineMessage {
|
||||
Layout.fillWidth: true
|
||||
visible: launchInfo && launchInfo.ok === false
|
||||
type: Kirigami.MessageType.Error
|
||||
text: launchInfo && launchInfo.error ? launchInfo.error : i18n("Unknown error")
|
||||
}
|
||||
|
||||
Kirigami.FormLayout {
|
||||
Layout.fillWidth: true
|
||||
|
||||
QQC2.Label {
|
||||
Kirigami.FormData.label: i18n("Launch command:")
|
||||
text: launchInfo && launchInfo.launchCommand ? launchInfo.launchCommand : ""
|
||||
wrapMode: Text.WrapAnywhere
|
||||
}
|
||||
|
||||
QQC2.Label {
|
||||
Kirigami.FormData.label: i18n("Runner:")
|
||||
text: launchInfo && launchInfo.runner ? launchInfo.runner : i18n("None")
|
||||
wrapMode: Text.WrapAnywhere
|
||||
}
|
||||
|
||||
QQC2.Label {
|
||||
Kirigami.FormData.label: i18n("Program:")
|
||||
text: launchInfo && launchInfo.finalProgram ? launchInfo.finalProgram : ""
|
||||
wrapMode: Text.WrapAnywhere
|
||||
}
|
||||
|
||||
QQC2.Label {
|
||||
Kirigami.FormData.label: i18n("Args:")
|
||||
text: launchInfo && launchInfo.finalArgs ? launchInfo.finalArgs.join(" ") : ""
|
||||
wrapMode: Text.WrapAnywhere
|
||||
}
|
||||
|
||||
QQC2.Label {
|
||||
Kirigami.FormData.label: i18n("Working directory:")
|
||||
text: launchInfo && launchInfo.workingDirectory ? launchInfo.workingDirectory : i18n("Not specified")
|
||||
wrapMode: Text.WrapAnywhere
|
||||
}
|
||||
|
||||
QQC2.Label {
|
||||
Kirigami.FormData.label: i18n("Prefix:")
|
||||
text: launchInfo && launchInfo.resolvedPrefixPath ? launchInfo.resolvedPrefixPath : (launchInfo && launchInfo.prefixPath ? launchInfo.prefixPath : "")
|
||||
wrapMode: Text.WrapAnywhere
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -48,6 +48,7 @@ Kirigami.OverlaySheet {
|
|||
|
||||
signal launchRequested()
|
||||
signal editRequested()
|
||||
signal diagnosticsRequested()
|
||||
signal removeRequested()
|
||||
|
||||
title: game ? game.name : ""
|
||||
|
|
@ -417,6 +418,14 @@ Kirigami.OverlaySheet {
|
|||
onClicked: detailsSheet.editRequested()
|
||||
}
|
||||
|
||||
QQC2.Button {
|
||||
icon.name: "dialog-information"
|
||||
text: i18n("Diagnostics")
|
||||
display: detailsSheet.useCompactLayout ? QQC2.AbstractButton.TextUnderIcon : QQC2.AbstractButton.TextBesideIcon
|
||||
enabled: !!game
|
||||
onClicked: detailsSheet.diagnosticsRequested()
|
||||
}
|
||||
|
||||
QQC2.Button {
|
||||
icon.name: "edit-delete"
|
||||
text: i18n("Remove")
|
||||
|
|
|
|||
|
|
@ -34,6 +34,7 @@ Kirigami.ApplicationWindow {
|
|||
if (settingsLayerOpen && layerContent && layerContent.anyConfirmOpen) return "confirm"
|
||||
}
|
||||
if (settingsSheet.opened && settingsContent.anyConfirmOpen) return "confirm"
|
||||
if (diagnosticsSheet.opened) return "diagnostics"
|
||||
if (detailsSheet.opened) return "details"
|
||||
if (importSheet.opened) return "import"
|
||||
if (settingsSheet.opened) return "settings"
|
||||
|
|
@ -169,6 +170,10 @@ Kirigami.ApplicationWindow {
|
|||
settingsSheet.close()
|
||||
return true
|
||||
}
|
||||
if (diagnosticsSheet.opened) {
|
||||
diagnosticsSheet.close()
|
||||
return true
|
||||
}
|
||||
if (detailsSheet.opened) {
|
||||
detailsSheet.close()
|
||||
return true
|
||||
|
|
@ -206,6 +211,7 @@ Kirigami.ApplicationWindow {
|
|||
function canOpenSettings() {
|
||||
return !gameEditDialog.visible
|
||||
&& !detailsSheet.opened
|
||||
&& !diagnosticsSheet.opened
|
||||
&& !importSheet.opened
|
||||
&& !aboutSheet.opened
|
||||
&& !settingsSheet.opened
|
||||
|
|
@ -397,7 +403,7 @@ Kirigami.ApplicationWindow {
|
|||
sequence: "Ctrl+F"
|
||||
onActivated: {
|
||||
if (root.currentConfirmDialog()) return
|
||||
if (detailsSheet.opened || gameEditDialog.visible || importSheet.opened || settingsLayerOpen || settingsSheet.opened || aboutSheet.opened) return
|
||||
if (detailsSheet.opened || diagnosticsSheet.opened || gameEditDialog.visible || importSheet.opened || settingsLayerOpen || settingsSheet.opened || aboutSheet.opened) return
|
||||
if (sidebar.modal && sidebar.opened) return
|
||||
searchActive = true
|
||||
Qt.callLater(function() { libraryView.focusSearch() })
|
||||
|
|
@ -433,6 +439,11 @@ Kirigami.ApplicationWindow {
|
|||
root.closeSettings()
|
||||
return
|
||||
}
|
||||
if (diagnosticsSheet.opened) {
|
||||
diagnosticsSheet.close()
|
||||
Qt.callLater(function() { root.openSettings() })
|
||||
return
|
||||
}
|
||||
if (root.canOpenSettings()) {
|
||||
root.openSettings()
|
||||
return
|
||||
|
|
@ -467,7 +478,7 @@ Kirigami.ApplicationWindow {
|
|||
sequence: "Ctrl+H"
|
||||
onActivated: {
|
||||
if (root.currentConfirmDialog()) return
|
||||
if (detailsSheet.opened || gameEditDialog.visible || importSheet.opened || settingsLayerOpen || settingsSheet.opened || aboutSheet.opened) return
|
||||
if (detailsSheet.opened || diagnosticsSheet.opened || gameEditDialog.visible || importSheet.opened || settingsLayerOpen || settingsSheet.opened || aboutSheet.opened) return
|
||||
if (root.hintContext !== "library" && root.hintContext !== "sidebar") return
|
||||
let target = (root.currentSource === "hidden") ? "all" : "hidden"
|
||||
sidebarView.suppressAutoClose = true
|
||||
|
|
@ -480,7 +491,7 @@ Kirigami.ApplicationWindow {
|
|||
sequence: "Ctrl+PgUp"
|
||||
onActivated: {
|
||||
if (root.currentConfirmDialog()) return
|
||||
if (detailsSheet.opened || gameEditDialog.visible || importSheet.opened || settingsLayerOpen || settingsSheet.opened || aboutSheet.opened) return
|
||||
if (detailsSheet.opened || diagnosticsSheet.opened || gameEditDialog.visible || importSheet.opened || settingsLayerOpen || settingsSheet.opened || aboutSheet.opened) return
|
||||
if (root.hintContext !== "library" && root.hintContext !== "sidebar") return
|
||||
sidebarView.cycleSource(-1)
|
||||
}
|
||||
|
|
@ -490,7 +501,7 @@ Kirigami.ApplicationWindow {
|
|||
sequence: "Ctrl+PgDown"
|
||||
onActivated: {
|
||||
if (root.currentConfirmDialog()) return
|
||||
if (detailsSheet.opened || gameEditDialog.visible || importSheet.opened || settingsLayerOpen || settingsSheet.opened || aboutSheet.opened) return
|
||||
if (detailsSheet.opened || diagnosticsSheet.opened || gameEditDialog.visible || importSheet.opened || settingsLayerOpen || settingsSheet.opened || aboutSheet.opened) return
|
||||
if (root.hintContext !== "library" && root.hintContext !== "sidebar") return
|
||||
sidebarView.cycleSource(1)
|
||||
}
|
||||
|
|
@ -500,7 +511,7 @@ Kirigami.ApplicationWindow {
|
|||
sequence: "Ctrl+D"
|
||||
onActivated: {
|
||||
if (root.currentConfirmDialog()) return
|
||||
if (detailsSheet.opened || gameEditDialog.visible || importSheet.opened || settingsLayerOpen || settingsSheet.opened || aboutSheet.opened) return
|
||||
if (detailsSheet.opened || diagnosticsSheet.opened || gameEditDialog.visible || importSheet.opened || settingsLayerOpen || settingsSheet.opened || aboutSheet.opened) return
|
||||
if (sidebar.modal && sidebar.opened) return
|
||||
if (root.selectedGame) {
|
||||
detailsSheet.open()
|
||||
|
|
@ -528,19 +539,19 @@ Kirigami.ApplicationWindow {
|
|||
}
|
||||
function onLeftBumperPressed() {
|
||||
if (root.currentConfirmDialog()) return
|
||||
if (detailsSheet.opened || gameEditDialog.visible || importSheet.opened || settingsLayerOpen || settingsSheet.opened || aboutSheet.opened) return
|
||||
if (detailsSheet.opened || diagnosticsSheet.opened || gameEditDialog.visible || importSheet.opened || settingsLayerOpen || settingsSheet.opened || aboutSheet.opened) return
|
||||
if (root.hintContext !== "library" && root.hintContext !== "sidebar") return
|
||||
sidebarView.cycleSource(-1)
|
||||
}
|
||||
function onRightBumperPressed() {
|
||||
if (root.currentConfirmDialog()) return
|
||||
if (detailsSheet.opened || gameEditDialog.visible || importSheet.opened || settingsLayerOpen || settingsSheet.opened || aboutSheet.opened) return
|
||||
if (detailsSheet.opened || diagnosticsSheet.opened || gameEditDialog.visible || importSheet.opened || settingsLayerOpen || settingsSheet.opened || aboutSheet.opened) return
|
||||
if (root.hintContext !== "library" && root.hintContext !== "sidebar") return
|
||||
sidebarView.cycleSource(1)
|
||||
}
|
||||
function onDetailsPressed() {
|
||||
if (root.currentConfirmDialog()) return
|
||||
if (gameEditDialog.visible || importSheet.opened || settingsLayerOpen || settingsSheet.opened || aboutSheet.opened || (sidebar.modal && sidebar.opened)) return
|
||||
if (gameEditDialog.visible || diagnosticsSheet.opened || importSheet.opened || settingsLayerOpen || settingsSheet.opened || aboutSheet.opened || (sidebar.modal && sidebar.opened)) return
|
||||
if (root.hintContext !== "library" && root.hintContext !== "details") return
|
||||
if (detailsSheet.opened) {
|
||||
if (root.selectedGame) {
|
||||
|
|
@ -610,6 +621,11 @@ Kirigami.ApplicationWindow {
|
|||
aboutSheet.close()
|
||||
return
|
||||
}
|
||||
if (diagnosticsSheet.opened) {
|
||||
root.pendingSidebarOpen = true
|
||||
diagnosticsSheet.close()
|
||||
return
|
||||
}
|
||||
if (detailsSheet.opened) {
|
||||
root.pendingSidebarOpen = true
|
||||
detailsSheet.close()
|
||||
|
|
@ -650,7 +666,7 @@ Kirigami.ApplicationWindow {
|
|||
detailsSheet.editRequested()
|
||||
return
|
||||
}
|
||||
if (gameEditDialog.visible || importSheet.opened || settingsLayerOpen || settingsSheet.opened || aboutSheet.opened || (sidebar.modal && sidebar.opened)) return
|
||||
if (gameEditDialog.visible || diagnosticsSheet.opened || importSheet.opened || settingsLayerOpen || settingsSheet.opened || aboutSheet.opened || (sidebar.modal && sidebar.opened)) return
|
||||
searchActive = true
|
||||
Qt.callLater(function() { libraryView.focusSearch() })
|
||||
}
|
||||
|
|
@ -872,6 +888,11 @@ Kirigami.ApplicationWindow {
|
|||
gameEditDialog.open()
|
||||
}
|
||||
|
||||
onDiagnosticsRequested: {
|
||||
diagnosticsSheet.game = root.selectedGame
|
||||
diagnosticsSheet.open()
|
||||
}
|
||||
|
||||
onRemoveRequested: {
|
||||
if (!root.selectedGame) return
|
||||
root.pendingRemoveGame = root.selectedGame
|
||||
|
|
@ -883,6 +904,19 @@ Kirigami.ApplicationWindow {
|
|||
}
|
||||
}
|
||||
|
||||
DiagnosticsSheet {
|
||||
id: diagnosticsSheet
|
||||
game: root.selectedGame
|
||||
|
||||
onClosed: {
|
||||
if (detailsSheet.opened) {
|
||||
detailsSheet.forceActiveFocus()
|
||||
return
|
||||
}
|
||||
libraryView.restoreFocus()
|
||||
}
|
||||
}
|
||||
|
||||
Kirigami.PromptDialog {
|
||||
id: removeGameConfirmDialog
|
||||
title: i18n("Remove Game")
|
||||
|
|
|
|||
|
|
@ -152,7 +152,7 @@ RowLayout {
|
|||
}
|
||||
}
|
||||
|
||||
if (root.context === "settings" || root.context === "import" || root.context === "sidebar" || root.context === "about") {
|
||||
if (root.context === "settings" || root.context === "import" || root.context === "sidebar" || root.context === "about" || root.context === "diagnostics") {
|
||||
switch (action) {
|
||||
case "navigate": return "Tab"
|
||||
case "confirm": return "Enter"
|
||||
|
|
@ -199,6 +199,16 @@ RowLayout {
|
|||
}
|
||||
}
|
||||
|
||||
if (root.context === "diagnostics") {
|
||||
switch (action) {
|
||||
case "navigate": return (useGamepadHints || keyboardLabel("navigate") !== "") ? i18n("Navigate") : ""
|
||||
case "confirm": return i18n("Select")
|
||||
case "back": return i18n("Back")
|
||||
case "menu": return (useGamepadHints && uiMode === Config.Couch) ? i18n("Menu") : i18n("Close")
|
||||
default: return ""
|
||||
}
|
||||
}
|
||||
|
||||
if (root.context === "edit") {
|
||||
switch (action) {
|
||||
case "navigate": return (useGamepadHints || keyboardLabel("navigate") !== "") ? i18n("Navigate") : ""
|
||||
|
|
@ -364,7 +374,7 @@ RowLayout {
|
|||
label: actionLabel("menu")
|
||||
iconSource: (useGamepadHints && uiMode === Config.Couch)
|
||||
? iconForAux("menu")
|
||||
: ((root.context === "library" || root.context === "details" || root.context === "sidebar" || root.context === "settings") ? iconForAux("menu") : "")
|
||||
: ((root.context === "library" || root.context === "details" || root.context === "sidebar" || root.context === "settings" || root.context === "diagnostics") ? iconForAux("menu") : "")
|
||||
keyLabel: keyboardLabel("menu")
|
||||
}
|
||||
}
|
||||
|
|
|
|||
Loading…
Reference in a new issue