mirror of
https://invent.kde.org/marcoa/a-la-karte.git
synced 2026-02-09 21:13:08 +00:00
Merge branch 'fix/couch-mode-focus' into 'master'
Fix/couch mode focus See merge request marcoa/a-la-karte!1
This commit is contained in:
commit
8ecc1e3a74
14 changed files with 1306 additions and 123 deletions
|
|
@ -8,6 +8,7 @@ add_executable(alakarte
|
|||
gamesortfiltermodel.cpp
|
||||
game.cpp
|
||||
gamepadmanager.cpp
|
||||
inputmanager.cpp
|
||||
mediamanager.cpp
|
||||
screenshotmodel.cpp
|
||||
platformimporter.cpp
|
||||
|
|
@ -118,6 +119,7 @@ ecm_add_qml_module(alakarte URI org.kde.alakarte
|
|||
gamesortfiltermodel.h
|
||||
game.h
|
||||
gamepadmanager.h
|
||||
inputmanager.h
|
||||
platformimporter.h
|
||||
steamimporter.h
|
||||
lutrisimporter.h
|
||||
|
|
|
|||
|
|
@ -42,7 +42,7 @@ public:
|
|||
enum UiMode {
|
||||
Auto,
|
||||
Desktop,
|
||||
Handheld
|
||||
Couch
|
||||
};
|
||||
Q_ENUM(UiMode)
|
||||
|
||||
|
|
|
|||
104
src/inputmanager.cpp
Normal file
104
src/inputmanager.cpp
Normal file
|
|
@ -0,0 +1,104 @@
|
|||
// SPDX-License-Identifier: GPL-3.0-or-later
|
||||
// SPDX-FileCopyrightText: 2026 A-La-Karte Contributors
|
||||
|
||||
#include "inputmanager.h"
|
||||
|
||||
#include "gamepadmanager.h"
|
||||
|
||||
#include <QCoreApplication>
|
||||
#include <QEvent>
|
||||
#include <QGuiApplication>
|
||||
|
||||
InputManager *InputManager::s_instance = nullptr;
|
||||
|
||||
InputManager::InputManager(QObject *parent)
|
||||
: QObject(parent)
|
||||
{
|
||||
if (QCoreApplication::instance()) {
|
||||
QCoreApplication::instance()->installEventFilter(this);
|
||||
}
|
||||
|
||||
auto *pad = GamepadManager::instance();
|
||||
connect(pad, &GamepadManager::activeChanged, this, [this, pad]() {
|
||||
if (pad->active()) {
|
||||
if (!m_hasSeenGamepad) {
|
||||
m_hasSeenGamepad = true;
|
||||
Q_EMIT inputHistoryChanged();
|
||||
}
|
||||
setActiveInput(Gamepad);
|
||||
}
|
||||
});
|
||||
|
||||
connect(pad, &GamepadManager::connectedChanged, this, [this, pad]() {
|
||||
if (!pad->connected() && m_activeInput == Gamepad) {
|
||||
setActiveInput(KeyboardMouse);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
InputManager *InputManager::instance()
|
||||
{
|
||||
if (!s_instance) {
|
||||
s_instance = new InputManager();
|
||||
}
|
||||
return s_instance;
|
||||
}
|
||||
|
||||
InputManager *InputManager::create(QQmlEngine *engine, QJSEngine *scriptEngine)
|
||||
{
|
||||
Q_UNUSED(engine)
|
||||
Q_UNUSED(scriptEngine)
|
||||
return instance();
|
||||
}
|
||||
|
||||
InputManager::ActiveInput InputManager::activeInput() const
|
||||
{
|
||||
return m_activeInput;
|
||||
}
|
||||
|
||||
bool InputManager::hasSeenKeyboardMouse() const
|
||||
{
|
||||
return m_hasSeenKeyboardMouse;
|
||||
}
|
||||
|
||||
bool InputManager::hasSeenGamepad() const
|
||||
{
|
||||
return m_hasSeenGamepad;
|
||||
}
|
||||
|
||||
void InputManager::setActiveInput(ActiveInput input)
|
||||
{
|
||||
if (m_activeInput == input) {
|
||||
return;
|
||||
}
|
||||
|
||||
m_activeInput = input;
|
||||
Q_EMIT activeInputChanged();
|
||||
}
|
||||
|
||||
bool InputManager::eventFilter(QObject *watched, QEvent *event)
|
||||
{
|
||||
Q_UNUSED(watched)
|
||||
|
||||
if (!event) {
|
||||
return false;
|
||||
}
|
||||
|
||||
switch (event->type()) {
|
||||
case QEvent::KeyPress:
|
||||
case QEvent::KeyRelease:
|
||||
case QEvent::MouseButtonPress:
|
||||
case QEvent::MouseButtonRelease:
|
||||
case QEvent::Wheel:
|
||||
if (!m_hasSeenKeyboardMouse) {
|
||||
m_hasSeenKeyboardMouse = true;
|
||||
Q_EMIT inputHistoryChanged();
|
||||
}
|
||||
setActiveInput(KeyboardMouse);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
54
src/inputmanager.h
Normal file
54
src/inputmanager.h
Normal file
|
|
@ -0,0 +1,54 @@
|
|||
// SPDX-License-Identifier: GPL-3.0-or-later
|
||||
// SPDX-FileCopyrightText: 2026 A-La-Karte Contributors
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <QObject>
|
||||
#include <QQmlEngine>
|
||||
|
||||
class QEvent;
|
||||
class QJSEngine;
|
||||
|
||||
class InputManager : public QObject
|
||||
{
|
||||
Q_OBJECT
|
||||
QML_ELEMENT
|
||||
QML_SINGLETON
|
||||
|
||||
Q_PROPERTY(ActiveInput activeInput READ activeInput NOTIFY activeInputChanged)
|
||||
Q_PROPERTY(bool hasSeenKeyboardMouse READ hasSeenKeyboardMouse NOTIFY inputHistoryChanged)
|
||||
Q_PROPERTY(bool hasSeenGamepad READ hasSeenGamepad NOTIFY inputHistoryChanged)
|
||||
|
||||
public:
|
||||
enum ActiveInput {
|
||||
KeyboardMouse = 0,
|
||||
Gamepad = 1,
|
||||
};
|
||||
Q_ENUM(ActiveInput)
|
||||
|
||||
static InputManager *instance();
|
||||
static InputManager *create(QQmlEngine *engine, QJSEngine *scriptEngine);
|
||||
|
||||
ActiveInput activeInput() const;
|
||||
|
||||
bool hasSeenKeyboardMouse() const;
|
||||
bool hasSeenGamepad() const;
|
||||
|
||||
Q_SIGNALS:
|
||||
void activeInputChanged();
|
||||
void inputHistoryChanged();
|
||||
|
||||
protected:
|
||||
bool eventFilter(QObject *watched, QEvent *event) override;
|
||||
|
||||
private:
|
||||
explicit InputManager(QObject *parent = nullptr);
|
||||
|
||||
static InputManager *s_instance;
|
||||
|
||||
ActiveInput m_activeInput = KeyboardMouse;
|
||||
bool m_hasSeenKeyboardMouse = false;
|
||||
bool m_hasSeenGamepad = false;
|
||||
|
||||
void setActiveInput(ActiveInput input);
|
||||
};
|
||||
|
|
@ -1,6 +1,7 @@
|
|||
// SPDX-License-Identifier: GPL-3.0-or-later
|
||||
// SPDX-FileCopyrightText: 2026 A-La-Karte Contributors
|
||||
|
||||
#include <QByteArray>
|
||||
#include <QCommandLineParser>
|
||||
#include <QGuiApplication>
|
||||
#include <QIcon>
|
||||
|
|
@ -18,6 +19,7 @@
|
|||
|
||||
int main(int argc, char *argv[])
|
||||
{
|
||||
qputenv("QT_DESKTOP_FILE_NAME", QByteArray("org.kde.alakarte"));
|
||||
QGuiApplication app(argc, argv);
|
||||
QGuiApplication::setDesktopFileName(QStringLiteral("org.kde.alakarte"));
|
||||
|
||||
|
|
|
|||
|
|
@ -54,10 +54,37 @@ Kirigami.OverlaySheet {
|
|||
|
||||
onOpened: playButton.forceActiveFocus()
|
||||
|
||||
Shortcut {
|
||||
enabled: detailsSheet.opened
|
||||
sequence: "E"
|
||||
onActivated: {
|
||||
let app = applicationWindow()
|
||||
if (app && app.currentConfirmDialog && app.currentConfirmDialog()) return
|
||||
detailsSheet.editRequested()
|
||||
}
|
||||
}
|
||||
|
||||
Shortcut {
|
||||
enabled: detailsSheet.opened
|
||||
sequence: "F"
|
||||
onActivated: {
|
||||
let app = applicationWindow()
|
||||
if (app && app.currentConfirmDialog && app.currentConfirmDialog()) return
|
||||
if (game) game.favorite = !game.favorite
|
||||
}
|
||||
}
|
||||
|
||||
function isDescendant(item, ancestor) {
|
||||
let p = item
|
||||
while (p) {
|
||||
if (p === ancestor) return true
|
||||
if (ancestor.contentItem && p === ancestor.contentItem) return true
|
||||
if (ancestor.header && p === ancestor.header) return true
|
||||
if (p.visualParent !== undefined && p.visualParent !== null) {
|
||||
if (detailsSheet.isDescendant(p.visualParent, ancestor)) return true
|
||||
} else if (p.popup !== undefined && p.popup !== null && p.popup.visualParent !== undefined && p.popup.visualParent !== null) {
|
||||
if (detailsSheet.isDescendant(p.popup.visualParent, ancestor)) return true
|
||||
}
|
||||
p = p.parent
|
||||
}
|
||||
return false
|
||||
|
|
@ -81,6 +108,8 @@ Kirigami.OverlaySheet {
|
|||
Connections {
|
||||
target: GamepadManager
|
||||
function onNavigateLeft() {
|
||||
let app = applicationWindow()
|
||||
if (app && app.currentConfirmDialog && app.currentConfirmDialog()) return
|
||||
if (!detailsSheet.opened) return
|
||||
let w = applicationWindow()
|
||||
if (!w || !w.activeFocusItem) return
|
||||
|
|
@ -88,6 +117,8 @@ Kirigami.OverlaySheet {
|
|||
detailsSheet.focusNextInChain(false)
|
||||
}
|
||||
function onNavigateRight() {
|
||||
let app = applicationWindow()
|
||||
if (app && app.currentConfirmDialog && app.currentConfirmDialog()) return
|
||||
if (!detailsSheet.opened) return
|
||||
let w = applicationWindow()
|
||||
if (!w || !w.activeFocusItem) return
|
||||
|
|
@ -95,6 +126,8 @@ Kirigami.OverlaySheet {
|
|||
detailsSheet.focusNextInChain(true)
|
||||
}
|
||||
function onNavigateUp() {
|
||||
let app = applicationWindow()
|
||||
if (app && app.currentConfirmDialog && app.currentConfirmDialog()) return
|
||||
if (!detailsSheet.opened) return
|
||||
let w = applicationWindow()
|
||||
if (!w || !w.activeFocusItem) return
|
||||
|
|
@ -102,6 +135,8 @@ Kirigami.OverlaySheet {
|
|||
detailsSheet.focusNextInChain(false)
|
||||
}
|
||||
function onNavigateDown() {
|
||||
let app = applicationWindow()
|
||||
if (app && app.currentConfirmDialog && app.currentConfirmDialog()) return
|
||||
if (!detailsSheet.opened) return
|
||||
let w = applicationWindow()
|
||||
if (!w || !w.activeFocusItem) return
|
||||
|
|
@ -109,6 +144,8 @@ Kirigami.OverlaySheet {
|
|||
detailsSheet.focusNextInChain(true)
|
||||
}
|
||||
function onSelectPressed() {
|
||||
let app = applicationWindow()
|
||||
if (app && app.currentConfirmDialog && app.currentConfirmDialog()) return
|
||||
if (!detailsSheet.opened) return
|
||||
let w = applicationWindow()
|
||||
if (!w || !w.activeFocusItem) return
|
||||
|
|
|
|||
|
|
@ -86,10 +86,23 @@ Kirigami.Dialog {
|
|||
|
||||
property string selectedCoverPath: ""
|
||||
|
||||
readonly property bool anyMenuOpen: runnerCombo && runnerCombo.popup && runnerCombo.popup.visible
|
||||
|
||||
function closeCurrentMenu() {
|
||||
if (runnerCombo && runnerCombo.popup && runnerCombo.popup.visible) {
|
||||
runnerCombo.popup.close()
|
||||
}
|
||||
}
|
||||
|
||||
function isDescendant(item, ancestor) {
|
||||
let p = item
|
||||
while (p) {
|
||||
if (p === ancestor || (ancestor.contentItem && p === ancestor.contentItem)) return true
|
||||
if (p.visualParent !== undefined && p.visualParent !== null) {
|
||||
if (dialog.isDescendant(p.visualParent, ancestor)) return true
|
||||
} else if (p.popup !== undefined && p.popup !== null && p.popup.visualParent !== undefined && p.popup.visualParent !== null) {
|
||||
if (dialog.isDescendant(p.popup.visualParent, ancestor)) return true
|
||||
}
|
||||
p = p.parent
|
||||
}
|
||||
return false
|
||||
|
|
@ -118,7 +131,7 @@ Kirigami.Dialog {
|
|||
item.toggle()
|
||||
return
|
||||
}
|
||||
if (item.hasOwnProperty("checked")) {
|
||||
if (item.checkable !== undefined && item.checkable && item.checked !== undefined) {
|
||||
item.checked = !item.checked
|
||||
return
|
||||
}
|
||||
|
|
@ -203,6 +216,8 @@ Kirigami.Dialog {
|
|||
Connections {
|
||||
target: GamepadManager
|
||||
function onNavigateUp() {
|
||||
let app = applicationWindow()
|
||||
if (app && app.currentConfirmDialog && app.currentConfirmDialog()) return
|
||||
if (!dialog.opened) return
|
||||
let w = applicationWindow()
|
||||
if (!w || !w.activeFocusItem) return
|
||||
|
|
@ -210,6 +225,8 @@ Kirigami.Dialog {
|
|||
dialog.focusNextInChain(false)
|
||||
}
|
||||
function onNavigateDown() {
|
||||
let app = applicationWindow()
|
||||
if (app && app.currentConfirmDialog && app.currentConfirmDialog()) return
|
||||
if (!dialog.opened) return
|
||||
let w = applicationWindow()
|
||||
if (!w || !w.activeFocusItem) return
|
||||
|
|
@ -217,6 +234,8 @@ Kirigami.Dialog {
|
|||
dialog.focusNextInChain(true)
|
||||
}
|
||||
function onNavigateLeft() {
|
||||
let app = applicationWindow()
|
||||
if (app && app.currentConfirmDialog && app.currentConfirmDialog()) return
|
||||
if (!dialog.opened) return
|
||||
let w = applicationWindow()
|
||||
if (!w || !w.activeFocusItem) return
|
||||
|
|
@ -224,6 +243,8 @@ Kirigami.Dialog {
|
|||
dialog.focusNextInChain(false)
|
||||
}
|
||||
function onNavigateRight() {
|
||||
let app = applicationWindow()
|
||||
if (app && app.currentConfirmDialog && app.currentConfirmDialog()) return
|
||||
if (!dialog.opened) return
|
||||
let w = applicationWindow()
|
||||
if (!w || !w.activeFocusItem) return
|
||||
|
|
@ -231,6 +252,8 @@ Kirigami.Dialog {
|
|||
dialog.focusNextInChain(true)
|
||||
}
|
||||
function onSelectPressed() {
|
||||
let app = applicationWindow()
|
||||
if (app && app.currentConfirmDialog && app.currentConfirmDialog()) return
|
||||
if (!dialog.opened) return
|
||||
let w = applicationWindow()
|
||||
if (!w || !w.activeFocusItem) return
|
||||
|
|
|
|||
|
|
@ -25,6 +25,12 @@ FocusScope {
|
|||
readonly property int gameCount: proxyModel.count
|
||||
property url focusedCoverUrl: ""
|
||||
|
||||
readonly property bool anyMenuOpen: searchHeader.anyMenuOpen
|
||||
|
||||
function closeCurrentMenu() {
|
||||
searchHeader.closeCurrentMenu()
|
||||
}
|
||||
|
||||
function focusSearch() {
|
||||
searchField.forceActiveFocus()
|
||||
}
|
||||
|
|
@ -35,6 +41,14 @@ FocusScope {
|
|||
}
|
||||
|
||||
function restoreFocus() {
|
||||
let w = applicationWindow()
|
||||
if (w && w.hasOwnProperty("pendingSidebarOpen") && w.pendingSidebarOpen) {
|
||||
w.pendingSidebarOpen = false
|
||||
if (w.globalDrawer && typeof w.globalDrawer.open === "function") {
|
||||
w.globalDrawer.open()
|
||||
return
|
||||
}
|
||||
}
|
||||
if (libraryRoot.searchActive) {
|
||||
libraryRoot.focusSearch()
|
||||
} else {
|
||||
|
|
@ -176,6 +190,16 @@ FocusScope {
|
|||
}
|
||||
|
||||
Keys.onDownPressed: gameGrid.forceActiveFocus()
|
||||
|
||||
Connections {
|
||||
target: GamepadManager
|
||||
function onNavigateDown() {
|
||||
let w = applicationWindow()
|
||||
if (w && w.currentConfirmDialog && w.currentConfirmDialog()) return
|
||||
if (!searchField.activeFocus) return
|
||||
gameGrid.forceActiveFocus()
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
739
src/qml/Main.qml
739
src/qml/Main.qml
File diff suppressed because it is too large
Load diff
|
|
@ -20,6 +20,96 @@ ColumnLayout {
|
|||
property var pendingDisableImportApply: null
|
||||
property string pendingDisableImportName: ""
|
||||
|
||||
readonly property bool anyConfirmOpen: disableImportConfirmDialog.opened
|
||||
|| fetchAllCoversConfirmDialog.opened
|
||||
|| removeMissingConfirmDialog.opened
|
||||
|| clearConfirmDialog.opened
|
||||
|| resetConfirmDialog.opened
|
||||
|
||||
readonly property bool anyMenuOpen: uiModeMenu.visible
|
||||
|
||||
function currentConfirmDialog() {
|
||||
if (disableImportConfirmDialog.opened) return disableImportConfirmDialog
|
||||
if (fetchAllCoversConfirmDialog.opened) return fetchAllCoversConfirmDialog
|
||||
if (removeMissingConfirmDialog.opened) return removeMissingConfirmDialog
|
||||
if (clearConfirmDialog.opened) return clearConfirmDialog
|
||||
if (resetConfirmDialog.opened) return resetConfirmDialog
|
||||
return null
|
||||
}
|
||||
|
||||
function closeCurrentConfirmDialog() {
|
||||
let d = currentConfirmDialog()
|
||||
if (!d) return
|
||||
if (typeof d.reject === "function") {
|
||||
d.reject()
|
||||
} else {
|
||||
d.close()
|
||||
}
|
||||
}
|
||||
|
||||
function closeCurrentMenu() {
|
||||
if (uiModeMenu.visible) {
|
||||
uiModeMenu.close()
|
||||
}
|
||||
}
|
||||
|
||||
function isDescendant(item, ancestor) {
|
||||
let p = item
|
||||
while (p) {
|
||||
if (p === ancestor) return true
|
||||
if (ancestor.contentItem && p === ancestor.contentItem) return true
|
||||
if (p.visualParent !== undefined && p.visualParent !== null) {
|
||||
if (settingsPage.isDescendant(p.visualParent, ancestor)) return true
|
||||
} else if (p.popup !== undefined && p.popup !== null && p.popup.visualParent !== undefined && p.popup.visualParent !== null) {
|
||||
if (settingsPage.isDescendant(p.popup.visualParent, ancestor)) return true
|
||||
}
|
||||
p = p.parent
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
function focusNextInMenu(forward) {
|
||||
let w = applicationWindow()
|
||||
if (!w || !w.activeFocusItem) return
|
||||
let next = w.activeFocusItem
|
||||
for (let i = 0; i < 50; i++) {
|
||||
next = next.nextItemInFocusChain(forward)
|
||||
if (!next) return
|
||||
if (settingsPage.isDescendant(next, uiModeMenu)) {
|
||||
next.forceActiveFocus()
|
||||
return
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function activateFocusedInMenu() {
|
||||
let w = applicationWindow()
|
||||
if (!w || !w.activeFocusItem) return
|
||||
let item = w.activeFocusItem
|
||||
if (typeof item.triggered === "function") {
|
||||
item.triggered()
|
||||
return
|
||||
}
|
||||
if (typeof item.clicked === "function") {
|
||||
item.clicked()
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
function focusNoButton(dialog) {
|
||||
Qt.callLater(function() {
|
||||
if (!dialog) return
|
||||
if (typeof dialog.standardButton === "function") {
|
||||
let noButton = dialog.standardButton(Kirigami.Dialog.No)
|
||||
if (noButton) {
|
||||
noButton.forceActiveFocus()
|
||||
return
|
||||
}
|
||||
}
|
||||
dialog.forceActiveFocus()
|
||||
})
|
||||
}
|
||||
|
||||
function requestDisableImport(sourceName, applyFn) {
|
||||
pendingDisableImportName = sourceName
|
||||
pendingDisableImportApply = applyFn
|
||||
|
|
@ -48,7 +138,7 @@ ColumnLayout {
|
|||
text: i18n("UI mode")
|
||||
description: {
|
||||
if (App.config.uiMode === Config.Desktop) return i18n("Desktop")
|
||||
if (App.config.uiMode === Config.Handheld) return i18n("Handheld")
|
||||
if (App.config.uiMode === Config.Couch) return i18n("Couch")
|
||||
return i18n("Automatic")
|
||||
}
|
||||
icon.name: "view-fullscreen"
|
||||
|
|
@ -56,8 +146,12 @@ ColumnLayout {
|
|||
|
||||
QQC2.Menu {
|
||||
id: uiModeMenu
|
||||
focus: true
|
||||
|
||||
onOpened: Qt.callLater(function() { uiModeAuto.forceActiveFocus() })
|
||||
|
||||
QQC2.MenuItem {
|
||||
id: uiModeAuto
|
||||
text: i18n("Automatic")
|
||||
checkable: true
|
||||
checked: App.config.uiMode === Config.Auto
|
||||
|
|
@ -65,6 +159,7 @@ ColumnLayout {
|
|||
}
|
||||
|
||||
QQC2.MenuItem {
|
||||
id: uiModeDesktop
|
||||
text: i18n("Desktop")
|
||||
checkable: true
|
||||
checked: App.config.uiMode === Config.Desktop
|
||||
|
|
@ -72,15 +167,55 @@ ColumnLayout {
|
|||
}
|
||||
|
||||
QQC2.MenuItem {
|
||||
text: i18n("Handheld")
|
||||
id: uiModeCouch
|
||||
text: i18n("Couch")
|
||||
checkable: true
|
||||
checked: App.config.uiMode === Config.Handheld
|
||||
onTriggered: App.config.uiMode = Config.Handheld
|
||||
checked: App.config.uiMode === Config.Couch
|
||||
onTriggered: App.config.uiMode = Config.Couch
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Connections {
|
||||
target: GamepadManager
|
||||
function onNavigateUp() {
|
||||
if (!uiModeMenu.visible) return
|
||||
let w = applicationWindow()
|
||||
if (!w || !w.activeFocusItem) return
|
||||
if (!settingsPage.isDescendant(w.activeFocusItem, uiModeMenu)) return
|
||||
settingsPage.focusNextInMenu(false)
|
||||
}
|
||||
function onNavigateDown() {
|
||||
if (!uiModeMenu.visible) return
|
||||
let w = applicationWindow()
|
||||
if (!w || !w.activeFocusItem) return
|
||||
if (!settingsPage.isDescendant(w.activeFocusItem, uiModeMenu)) return
|
||||
settingsPage.focusNextInMenu(true)
|
||||
}
|
||||
function onNavigateLeft() {
|
||||
if (!uiModeMenu.visible) return
|
||||
let w = applicationWindow()
|
||||
if (!w || !w.activeFocusItem) return
|
||||
if (!settingsPage.isDescendant(w.activeFocusItem, uiModeMenu)) return
|
||||
settingsPage.focusNextInMenu(false)
|
||||
}
|
||||
function onNavigateRight() {
|
||||
if (!uiModeMenu.visible) return
|
||||
let w = applicationWindow()
|
||||
if (!w || !w.activeFocusItem) return
|
||||
if (!settingsPage.isDescendant(w.activeFocusItem, uiModeMenu)) return
|
||||
settingsPage.focusNextInMenu(true)
|
||||
}
|
||||
function onSelectPressed() {
|
||||
if (!uiModeMenu.visible) return
|
||||
let w = applicationWindow()
|
||||
if (!w || !w.activeFocusItem) return
|
||||
if (!settingsPage.isDescendant(w.activeFocusItem, uiModeMenu)) return
|
||||
settingsPage.activateFocusedInMenu()
|
||||
}
|
||||
}
|
||||
|
||||
FormCard.FormHeader {
|
||||
Layout.topMargin: Kirigami.Units.mediumSpacing
|
||||
Layout.fillWidth: true
|
||||
|
|
@ -553,6 +688,7 @@ FormCard.FormHeader {
|
|||
title: i18n("Disable Import Source")
|
||||
subtitle: i18n("Disabling %1 will remove all games imported from that source. Are you sure?", settingsPage.pendingDisableImportName)
|
||||
standardButtons: Kirigami.Dialog.Yes | Kirigami.Dialog.No
|
||||
onOpened: settingsPage.focusNoButton(disableImportConfirmDialog)
|
||||
onAccepted: {
|
||||
if (settingsPage.pendingDisableImportApply) {
|
||||
settingsPage.pendingDisableImportApply()
|
||||
|
|
@ -573,6 +709,7 @@ FormCard.FormHeader {
|
|||
? i18n("This will download cover art for all games and may replace existing covers. Continue?")
|
||||
: i18n("This will download cover art for games that are missing covers. Continue?")
|
||||
standardButtons: Kirigami.Dialog.Yes | Kirigami.Dialog.No
|
||||
onOpened: settingsPage.focusNoButton(fetchAllCoversConfirmDialog)
|
||||
onAccepted: App.steamGridDB.fetchAllCovers()
|
||||
}
|
||||
|
||||
|
|
@ -581,6 +718,7 @@ FormCard.FormHeader {
|
|||
title: i18n("Remove Missing Games")
|
||||
subtitle: i18n("This will remove games whose executables cannot be found. This cannot be undone. Continue?")
|
||||
standardButtons: Kirigami.Dialog.Yes | Kirigami.Dialog.No
|
||||
onOpened: settingsPage.focusNoButton(removeMissingConfirmDialog)
|
||||
onAccepted: App.removeMissingGames()
|
||||
}
|
||||
|
||||
|
|
@ -589,6 +727,7 @@ FormCard.FormHeader {
|
|||
title: i18n("Clear Library")
|
||||
subtitle: i18n("Are you sure you want to remove all games?")
|
||||
standardButtons: Kirigami.Dialog.Yes | Kirigami.Dialog.No
|
||||
onOpened: settingsPage.focusNoButton(clearConfirmDialog)
|
||||
onAccepted: App.clearLibrary()
|
||||
}
|
||||
|
||||
|
|
@ -597,6 +736,7 @@ FormCard.FormHeader {
|
|||
title: i18n("Reset Application")
|
||||
subtitle: i18n("This will remove all games and reset all settings to defaults. Are you sure?")
|
||||
standardButtons: Kirigami.Dialog.Yes | Kirigami.Dialog.No
|
||||
onOpened: settingsPage.focusNoButton(resetConfirmDialog)
|
||||
onAccepted: {
|
||||
App.clearLibrary()
|
||||
App.config.resetToDefaults()
|
||||
|
|
|
|||
|
|
@ -16,6 +16,8 @@ ColumnLayout {
|
|||
property string currentSourceName: i18n("All Games")
|
||||
property bool suppressAutoClose: false
|
||||
|
||||
readonly property bool hasSidebarFocus: sourceList.activeFocus || importAction.activeFocus || settingsAction.activeFocus || aboutAction.activeFocus
|
||||
|
||||
readonly property int adaptiveFocusRingWidth: 1
|
||||
|
||||
signal sourceSelected(string source)
|
||||
|
|
@ -45,6 +47,17 @@ ColumnLayout {
|
|||
sourceList.positionViewAtIndex(i, ListView.Contain)
|
||||
}
|
||||
|
||||
function applySourceById(sourceId) {
|
||||
for (let i = 0; i < sourceModel.count; i++) {
|
||||
let item = sourceModel.get(i)
|
||||
if (item && item.sourceId === sourceId) {
|
||||
applySourceAtIndex(i)
|
||||
return
|
||||
}
|
||||
}
|
||||
applySourceAtIndex(0)
|
||||
}
|
||||
|
||||
function cycleSource(delta) {
|
||||
if (sourceModel.count <= 0) return
|
||||
let i = sourceList.currentIndex
|
||||
|
|
@ -97,9 +110,31 @@ ColumnLayout {
|
|||
|
||||
Connections {
|
||||
target: GamepadManager
|
||||
function onNavigateUp() { if (sourceList.activeFocus) sourceList.decrementCurrentIndex() }
|
||||
function onNavigateDown() { if (sourceList.activeFocus) sourceList.incrementCurrentIndex() }
|
||||
function onSelectPressed() { if (sourceList.activeFocus) sidebarRoot.activateCurrentItem() }
|
||||
function onNavigateUp() {
|
||||
let w = applicationWindow()
|
||||
if (w && w.currentConfirmDialog && w.currentConfirmDialog()) return
|
||||
if (!sourceList.activeFocus) return
|
||||
if (sourceList.count > 0 && sourceList.currentIndex <= 0) {
|
||||
aboutAction.forceActiveFocus()
|
||||
} else {
|
||||
sourceList.decrementCurrentIndex()
|
||||
}
|
||||
}
|
||||
function onNavigateDown() {
|
||||
let w = applicationWindow()
|
||||
if (w && w.currentConfirmDialog && w.currentConfirmDialog()) return
|
||||
if (!sourceList.activeFocus) return
|
||||
if (sourceList.count > 0 && sourceList.currentIndex >= sourceList.count - 1) {
|
||||
importAction.forceActiveFocus()
|
||||
} else {
|
||||
sourceList.incrementCurrentIndex()
|
||||
}
|
||||
}
|
||||
function onSelectPressed() {
|
||||
let w = applicationWindow()
|
||||
if (w && w.currentConfirmDialog && w.currentConfirmDialog()) return
|
||||
if (sourceList.activeFocus) sidebarRoot.activateCurrentItem()
|
||||
}
|
||||
}
|
||||
|
||||
delegate: QQC2.ItemDelegate {
|
||||
|
|
@ -294,6 +329,8 @@ ColumnLayout {
|
|||
Connections {
|
||||
target: GamepadManager
|
||||
function onNavigateUp() {
|
||||
let w = applicationWindow()
|
||||
if (w && w.currentConfirmDialog && w.currentConfirmDialog()) return
|
||||
if (aboutAction.activeFocus) {
|
||||
settingsAction.forceActiveFocus()
|
||||
} else if (settingsAction.activeFocus) {
|
||||
|
|
@ -304,13 +341,20 @@ ColumnLayout {
|
|||
}
|
||||
}
|
||||
function onNavigateDown() {
|
||||
let w = applicationWindow()
|
||||
if (w && w.currentConfirmDialog && w.currentConfirmDialog()) return
|
||||
if (importAction.activeFocus) {
|
||||
settingsAction.forceActiveFocus()
|
||||
} else if (settingsAction.activeFocus) {
|
||||
aboutAction.forceActiveFocus()
|
||||
} else if (aboutAction.activeFocus) {
|
||||
sourceList.forceActiveFocus()
|
||||
sourceList.currentIndex = 0
|
||||
}
|
||||
}
|
||||
function onSelectPressed() {
|
||||
let w = applicationWindow()
|
||||
if (w && w.currentConfirmDialog && w.currentConfirmDialog()) return
|
||||
if (importAction.activeFocus) {
|
||||
importAction.clicked()
|
||||
} else if (settingsAction.activeFocus) {
|
||||
|
|
|
|||
|
|
@ -7,9 +7,19 @@ import org.kde.alakarte
|
|||
RowLayout {
|
||||
id: root
|
||||
|
||||
spacing: Kirigami.Units.largeSpacing
|
||||
spacing: uiMode === Config.Couch ? Kirigami.Units.largeSpacing * 1.25 : Kirigami.Units.largeSpacing
|
||||
|
||||
readonly property bool useGamepadHints: GamepadManager.connected
|
||||
property int uiMode: Config.Auto
|
||||
property int activeInput: InputManager.KeyboardMouse
|
||||
|
||||
readonly property bool useGamepadHints: {
|
||||
if (!GamepadManager.connected) return false
|
||||
if (uiMode === Config.Couch) {
|
||||
if (activeInput === InputManager.KeyboardMouse && InputManager.hasSeenKeyboardMouse) return false
|
||||
return true
|
||||
}
|
||||
return activeInput === InputManager.Gamepad
|
||||
}
|
||||
readonly property int style: GamepadManager.controllerStyle
|
||||
property string context: "library"
|
||||
|
||||
|
|
@ -49,6 +59,9 @@ RowLayout {
|
|||
function iconForAux(action) {
|
||||
if (!useGamepadHints) return ""
|
||||
|
||||
if (action === "dpad") {
|
||||
return "qrc:/qt/qml/org/kde/alakarte/qml/icons/gamepad/generic/dpad.svg"
|
||||
}
|
||||
if (action === "lb") {
|
||||
return "qrc:/qt/qml/org/kde/alakarte/qml/icons/gamepad/generic/lb.svg"
|
||||
}
|
||||
|
|
@ -72,12 +85,25 @@ RowLayout {
|
|||
}
|
||||
|
||||
function keyboardLabel(action) {
|
||||
if (root.context === "confirm" || root.context === "confirm_remove") {
|
||||
switch (action) {
|
||||
case "navigate": return "Tab"
|
||||
case "confirm": return "Enter"
|
||||
case "back": return "Esc"
|
||||
case "menu": return ""
|
||||
default: return ""
|
||||
}
|
||||
}
|
||||
|
||||
if (root.context === "library") {
|
||||
switch (action) {
|
||||
case "navigate": return i18n("Arrows")
|
||||
case "confirm": return "Space"
|
||||
case "back": return "Esc"
|
||||
case "back": return ""
|
||||
case "details": return "Enter"
|
||||
case "search": return "Ctrl+F"
|
||||
case "lb": return "Ctrl+PgUp"
|
||||
case "rb": return "Ctrl+PgDown"
|
||||
case "menu": return "Ctrl+,"
|
||||
default: return ""
|
||||
}
|
||||
|
|
@ -85,6 +111,7 @@ RowLayout {
|
|||
|
||||
if (root.context === "edit") {
|
||||
switch (action) {
|
||||
case "navigate": return "Tab"
|
||||
case "confirm": return "Enter"
|
||||
case "back": return "Esc"
|
||||
default: return ""
|
||||
|
|
@ -93,8 +120,11 @@ RowLayout {
|
|||
|
||||
if (root.context === "details") {
|
||||
switch (action) {
|
||||
case "navigate": return "Tab"
|
||||
case "confirm": return "Enter"
|
||||
case "back": return "Esc"
|
||||
case "details": return "F"
|
||||
case "search": return "E"
|
||||
case "menu": return "Ctrl+,"
|
||||
default: return ""
|
||||
}
|
||||
|
|
@ -102,6 +132,19 @@ RowLayout {
|
|||
|
||||
if (root.context === "sidebar") {
|
||||
switch (action) {
|
||||
case "navigate": return i18n("Arrows/Tab")
|
||||
case "confirm": return "Enter"
|
||||
case "back": return "Esc"
|
||||
case "lb": return "Ctrl+PgUp"
|
||||
case "rb": return "Ctrl+PgDown"
|
||||
case "menu": return "Ctrl+,"
|
||||
default: return ""
|
||||
}
|
||||
}
|
||||
|
||||
if (root.context === "settings") {
|
||||
switch (action) {
|
||||
case "navigate": return "Tab"
|
||||
case "confirm": return "Enter"
|
||||
case "back": return "Esc"
|
||||
case "menu": return "Ctrl+,"
|
||||
|
|
@ -109,8 +152,9 @@ RowLayout {
|
|||
}
|
||||
}
|
||||
|
||||
if (root.context === "settings" || root.context === "import" || root.context === "sidebar") {
|
||||
if (root.context === "settings" || root.context === "import" || root.context === "sidebar" || root.context === "about") {
|
||||
switch (action) {
|
||||
case "navigate": return "Tab"
|
||||
case "confirm": return "Enter"
|
||||
case "back": return "Esc"
|
||||
default: return ""
|
||||
|
|
@ -121,53 +165,90 @@ RowLayout {
|
|||
}
|
||||
|
||||
function actionLabel(action) {
|
||||
if (root.context === "confirm" || root.context === "confirm_remove") {
|
||||
switch (action) {
|
||||
case "navigate": return (useGamepadHints || keyboardLabel("navigate") !== "") ? i18n("Navigate") : ""
|
||||
case "confirm": return i18n("Select")
|
||||
case "back": return i18n("Cancel")
|
||||
case "menu": return (useGamepadHints && uiMode === Config.Couch) ? i18n("Menu") : ""
|
||||
default: return ""
|
||||
}
|
||||
}
|
||||
|
||||
if (root.context === "library") {
|
||||
switch (action) {
|
||||
case "navigate": return (useGamepadHints || keyboardLabel("navigate") !== "") ? i18n("Navigate") : ""
|
||||
case "confirm": return i18n("Play")
|
||||
case "back": return i18n("Back")
|
||||
case "back": return ""
|
||||
case "details": return i18n("Details")
|
||||
case "search": return i18n("Search")
|
||||
case "lb": return i18n("Prev Source")
|
||||
case "rb": return i18n("Next Source")
|
||||
case "menu": return i18n("Settings")
|
||||
case "menu": return (useGamepadHints && uiMode === Config.Couch) ? i18n("Menu") : i18n("Settings")
|
||||
default: return ""
|
||||
}
|
||||
}
|
||||
|
||||
if (root.context === "settings") {
|
||||
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") : ""
|
||||
case "confirm": return i18n("Select")
|
||||
case "back": return i18n("Back")
|
||||
case "menu": return (useGamepadHints && uiMode === Config.Couch) ? i18n("Menu") : ""
|
||||
default: return ""
|
||||
}
|
||||
}
|
||||
|
||||
if (root.context === "details") {
|
||||
switch (action) {
|
||||
case "confirm": return i18n("Play")
|
||||
case "navigate": return (useGamepadHints || keyboardLabel("navigate") !== "") ? i18n("Navigate") : ""
|
||||
case "confirm": return i18n("Select")
|
||||
case "back": return i18n("Back")
|
||||
case "details": return i18n("Favorite")
|
||||
case "search": return i18n("Edit")
|
||||
case "menu": return i18n("Settings")
|
||||
case "menu": return (useGamepadHints && uiMode === Config.Couch) ? i18n("Menu") : i18n("Settings")
|
||||
default: return ""
|
||||
}
|
||||
}
|
||||
|
||||
if (root.context === "sidebar") {
|
||||
switch (action) {
|
||||
case "navigate": return (useGamepadHints || keyboardLabel("navigate") !== "") ? i18n("Navigate") : ""
|
||||
case "confirm": return i18n("Select")
|
||||
case "back": return i18n("Back")
|
||||
case "lb": return i18n("Prev Source")
|
||||
case "rb": return i18n("Next Source")
|
||||
case "menu": return i18n("Settings")
|
||||
case "menu": return (useGamepadHints && uiMode === Config.Couch) ? i18n("Close") : i18n("Settings")
|
||||
default: return ""
|
||||
}
|
||||
}
|
||||
|
||||
if (root.context === "settings" || root.context === "import" || root.context === "sidebar") {
|
||||
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") : ""
|
||||
default: return ""
|
||||
}
|
||||
}
|
||||
|
||||
if (root.context === "about") {
|
||||
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") : ""
|
||||
default: return ""
|
||||
}
|
||||
}
|
||||
|
|
@ -195,7 +276,7 @@ RowLayout {
|
|||
border.width: 1
|
||||
border.color: Qt.rgba(Kirigami.Theme.textColor.r, Kirigami.Theme.textColor.g, Kirigami.Theme.textColor.b, 0.2)
|
||||
|
||||
Layout.preferredHeight: Kirigami.Units.gridUnit * 1.4
|
||||
Layout.preferredHeight: uiMode === Config.Couch ? Kirigami.Units.gridUnit * 1.8 : Kirigami.Units.gridUnit * 1.4
|
||||
Layout.preferredWidth: useGamepadHints
|
||||
? Layout.preferredHeight
|
||||
: Math.max(keyText.implicitWidth + Kirigami.Units.mediumSpacing * 2, Layout.preferredHeight)
|
||||
|
|
@ -215,7 +296,7 @@ RowLayout {
|
|||
anchors.centerIn: parent
|
||||
text: parent.parent.keyLabel
|
||||
font.bold: true
|
||||
font.pointSize: Kirigami.Theme.smallFont.pointSize
|
||||
font.pointSize: uiMode === Config.Couch ? Kirigami.Theme.defaultFont.pointSize : Kirigami.Theme.smallFont.pointSize
|
||||
color: Kirigami.Theme.textColor
|
||||
visible: !useGamepadHints
|
||||
}
|
||||
|
|
@ -224,11 +305,18 @@ RowLayout {
|
|||
QQC2.Label {
|
||||
text: parent.label
|
||||
color: Kirigami.Theme.textColor
|
||||
font.pointSize: Kirigami.Theme.smallFont.pointSize
|
||||
font.pointSize: uiMode === Config.Couch ? Kirigami.Theme.defaultFont.pointSize : Kirigami.Theme.smallFont.pointSize
|
||||
Layout.alignment: Qt.AlignVCenter
|
||||
}
|
||||
}
|
||||
|
||||
HintItem {
|
||||
action: "navigate"
|
||||
label: actionLabel("navigate")
|
||||
iconSource: iconForAux("dpad")
|
||||
keyLabel: keyboardLabel("navigate")
|
||||
}
|
||||
|
||||
HintItem {
|
||||
action: "confirm"
|
||||
label: actionLabel("confirm")
|
||||
|
|
@ -261,20 +349,22 @@ RowLayout {
|
|||
action: "lb"
|
||||
label: actionLabel("lb")
|
||||
iconSource: (root.context === "library" || root.context === "sidebar") ? iconForAux("lb") : ""
|
||||
keyLabel: ""
|
||||
keyLabel: keyboardLabel("lb")
|
||||
}
|
||||
|
||||
HintItem {
|
||||
action: "rb"
|
||||
label: actionLabel("rb")
|
||||
iconSource: (root.context === "library" || root.context === "sidebar") ? iconForAux("rb") : ""
|
||||
keyLabel: ""
|
||||
keyLabel: keyboardLabel("rb")
|
||||
}
|
||||
|
||||
HintItem {
|
||||
action: "menu"
|
||||
label: actionLabel("menu")
|
||||
iconSource: (root.context === "library" || root.context === "details" || root.context === "sidebar") ? iconForAux("menu") : ""
|
||||
iconSource: (useGamepadHints && uiMode === Config.Couch)
|
||||
? iconForAux("menu")
|
||||
: ((root.context === "library" || root.context === "details" || root.context === "sidebar" || root.context === "settings") ? iconForAux("menu") : "")
|
||||
keyLabel: keyboardLabel("menu")
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -74,11 +74,29 @@ GridView {
|
|||
|
||||
Connections {
|
||||
target: GamepadManager
|
||||
function onNavigateUp() { if (gridView.activeFocus) gridView.navigateUp() }
|
||||
function onNavigateDown() { if (gridView.activeFocus) gridView.navigateDown() }
|
||||
function onNavigateLeft() { if (gridView.activeFocus) gridView.navigateLeft() }
|
||||
function onNavigateRight() { if (gridView.activeFocus) gridView.navigateRight() }
|
||||
function onNavigateUp() {
|
||||
let w = applicationWindow()
|
||||
if (w && w.currentConfirmDialog && w.currentConfirmDialog()) return
|
||||
if (gridView.activeFocus) gridView.navigateUp()
|
||||
}
|
||||
function onNavigateDown() {
|
||||
let w = applicationWindow()
|
||||
if (w && w.currentConfirmDialog && w.currentConfirmDialog()) return
|
||||
if (gridView.activeFocus) gridView.navigateDown()
|
||||
}
|
||||
function onNavigateLeft() {
|
||||
let w = applicationWindow()
|
||||
if (w && w.currentConfirmDialog && w.currentConfirmDialog()) return
|
||||
if (gridView.activeFocus) gridView.navigateLeft()
|
||||
}
|
||||
function onNavigateRight() {
|
||||
let w = applicationWindow()
|
||||
if (w && w.currentConfirmDialog && w.currentConfirmDialog()) return
|
||||
if (gridView.activeFocus) gridView.navigateRight()
|
||||
}
|
||||
function onSelectPressed() {
|
||||
let w = applicationWindow()
|
||||
if (w && w.currentConfirmDialog && w.currentConfirmDialog()) return
|
||||
if (!gridView.activeFocus) {
|
||||
return
|
||||
}
|
||||
|
|
|
|||
|
|
@ -13,6 +13,57 @@ QQC2.ToolBar {
|
|||
property alias searchField: searchFieldContainer.data
|
||||
property int currentSortMode: 0
|
||||
|
||||
readonly property bool anyMenuOpen: sortMenu.visible
|
||||
|
||||
function closeCurrentMenu() {
|
||||
if (sortMenu.visible) {
|
||||
sortMenu.close()
|
||||
}
|
||||
}
|
||||
|
||||
function isDescendant(item, ancestor) {
|
||||
let p = item
|
||||
while (p) {
|
||||
if (p === ancestor) return true
|
||||
if (ancestor.contentItem && p === ancestor.contentItem) return true
|
||||
if (p.visualParent !== undefined && p.visualParent !== null) {
|
||||
if (searchHeader.isDescendant(p.visualParent, ancestor)) return true
|
||||
} else if (p.popup !== undefined && p.popup !== null && p.popup.visualParent !== undefined && p.popup.visualParent !== null) {
|
||||
if (searchHeader.isDescendant(p.popup.visualParent, ancestor)) return true
|
||||
}
|
||||
p = p.parent
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
function focusNextInMenu(forward) {
|
||||
let w = applicationWindow()
|
||||
if (!w || !w.activeFocusItem) return
|
||||
let next = w.activeFocusItem
|
||||
for (let i = 0; i < 50; i++) {
|
||||
next = next.nextItemInFocusChain(forward)
|
||||
if (!next) return
|
||||
if (searchHeader.isDescendant(next, sortMenu)) {
|
||||
next.forceActiveFocus()
|
||||
return
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function activateFocusedInMenu() {
|
||||
let w = applicationWindow()
|
||||
if (!w || !w.activeFocusItem) return
|
||||
let item = w.activeFocusItem
|
||||
if (typeof item.triggered === "function") {
|
||||
item.triggered()
|
||||
return
|
||||
}
|
||||
if (typeof item.clicked === "function") {
|
||||
item.clicked()
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
signal searchChanged(string text)
|
||||
signal sortChanged(int mode)
|
||||
|
||||
|
|
@ -47,8 +98,12 @@ QQC2.ToolBar {
|
|||
|
||||
QQC2.Menu {
|
||||
id: sortMenu
|
||||
focus: true
|
||||
|
||||
onOpened: Qt.callLater(function() { sortModeLastPlayed.forceActiveFocus() })
|
||||
|
||||
QQC2.MenuItem {
|
||||
id: sortModeLastPlayed
|
||||
text: i18n("Last Played")
|
||||
checkable: true
|
||||
checked: searchHeader.currentSortMode === 0
|
||||
|
|
@ -59,6 +114,7 @@ QQC2.ToolBar {
|
|||
}
|
||||
|
||||
QQC2.MenuItem {
|
||||
id: sortModeName
|
||||
text: i18n("Name")
|
||||
checkable: true
|
||||
checked: searchHeader.currentSortMode === 1
|
||||
|
|
@ -69,6 +125,7 @@ QQC2.ToolBar {
|
|||
}
|
||||
|
||||
QQC2.MenuItem {
|
||||
id: sortModePlayTime
|
||||
text: i18n("Play Time")
|
||||
checkable: true
|
||||
checked: searchHeader.currentSortMode === 2
|
||||
|
|
@ -80,4 +137,43 @@ QQC2.ToolBar {
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
Connections {
|
||||
target: GamepadManager
|
||||
function onNavigateUp() {
|
||||
if (!sortMenu.visible) return
|
||||
let w = applicationWindow()
|
||||
if (!w || !w.activeFocusItem) return
|
||||
if (!searchHeader.isDescendant(w.activeFocusItem, sortMenu)) return
|
||||
searchHeader.focusNextInMenu(false)
|
||||
}
|
||||
function onNavigateDown() {
|
||||
if (!sortMenu.visible) return
|
||||
let w = applicationWindow()
|
||||
if (!w || !w.activeFocusItem) return
|
||||
if (!searchHeader.isDescendant(w.activeFocusItem, sortMenu)) return
|
||||
searchHeader.focusNextInMenu(true)
|
||||
}
|
||||
function onNavigateLeft() {
|
||||
if (!sortMenu.visible) return
|
||||
let w = applicationWindow()
|
||||
if (!w || !w.activeFocusItem) return
|
||||
if (!searchHeader.isDescendant(w.activeFocusItem, sortMenu)) return
|
||||
searchHeader.focusNextInMenu(false)
|
||||
}
|
||||
function onNavigateRight() {
|
||||
if (!sortMenu.visible) return
|
||||
let w = applicationWindow()
|
||||
if (!w || !w.activeFocusItem) return
|
||||
if (!searchHeader.isDescendant(w.activeFocusItem, sortMenu)) return
|
||||
searchHeader.focusNextInMenu(true)
|
||||
}
|
||||
function onSelectPressed() {
|
||||
if (!sortMenu.visible) return
|
||||
let w = applicationWindow()
|
||||
if (!w || !w.activeFocusItem) return
|
||||
if (!searchHeader.isDescendant(w.activeFocusItem, sortMenu)) return
|
||||
searchHeader.activateFocusedInMenu()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
Loading…
Reference in a new issue