mirror of
https://invent.kde.org/marcoa/a-la-karte.git
synced 2026-03-27 01:03:09 +00:00
fix: restore console UI icon visibility, selection highlight, focus transfer
- Force isMask on header Kirigami.Icon contentItems (Search/Import/Settings) so white color is applied regardless of icon theme - Remove MultiEffect shadow from GameCard (was bleeding far outside card bounds) - Add gridActive prop to GameCard so selection highlight depends on actual flickable focus, not wrapper focus - Two-tier selection: full highlight when grid focused, dim border when grid unfocused (card stays visible) - Focus transfer: gamepad Up from top row emits headerFocusRequested; Down from rail/buttons calls libraryView.restoreFocus() - Gate gamepad navigation guards on grid.flickable.activeFocus (Maui.GridBrowser internal GridView)
This commit is contained in:
parent
b5e03fe856
commit
2df35e9b81
5 changed files with 195 additions and 37 deletions
|
|
@ -16,6 +16,15 @@ Item {
|
|||
signal sourceSelected(string source)
|
||||
signal settingsRequested()
|
||||
signal importRequested()
|
||||
signal focusDownRequested()
|
||||
|
||||
function focusCurrent() {
|
||||
if (tabList.currentItem) {
|
||||
tabList.currentItem.forceActiveFocus()
|
||||
return
|
||||
}
|
||||
tabList.forceActiveFocus()
|
||||
}
|
||||
|
||||
function selectNext() {
|
||||
if (sourceModel.count <= 0) return
|
||||
|
|
@ -136,12 +145,25 @@ Item {
|
|||
height: tabList.height - tabList.topMargin - tabList.bottomMargin
|
||||
|
||||
readonly property bool isActive: model.sourceId === root.currentSource
|
||||
readonly property bool isFocused: tabDelegate.activeFocus || tabDelegate.hovered
|
||||
|
||||
background: Rectangle {
|
||||
hoverEnabled: true
|
||||
scale: tabDelegate.isFocused ? 1.02 : (tabDelegate.isActive ? 1.01 : 1.0)
|
||||
Behavior on scale {
|
||||
NumberAnimation { duration: Kirigami.Units.shortDuration; easing.type: Easing.OutCubic }
|
||||
}
|
||||
|
||||
background: Kirigami.ShadowedRectangle {
|
||||
radius: Kirigami.Units.smallSpacing
|
||||
color: tabDelegate.isActive ? Kirigami.Theme.highlightColor
|
||||
: (tabDelegate.hovered ? Kirigami.Theme.alternateBackgroundColor : "transparent")
|
||||
opacity: tabDelegate.isActive ? 0.22 : (tabDelegate.hovered ? 0.12 : 0.0)
|
||||
: Kirigami.Theme.alternateBackgroundColor
|
||||
opacity: tabDelegate.isActive ? 0.20 : (tabDelegate.isFocused ? 0.10 : 0.0)
|
||||
|
||||
border.width: tabDelegate.isFocused ? 2 : 0
|
||||
border.color: Kirigami.Theme.highlightColor
|
||||
|
||||
shadow.size: tabDelegate.isFocused ? Kirigami.Units.mediumSpacing : 0
|
||||
shadow.color: Qt.rgba(0, 0, 0, 0.28)
|
||||
|
||||
Rectangle {
|
||||
anchors.bottom: parent.bottom
|
||||
|
|
@ -153,7 +175,17 @@ Item {
|
|||
visible: tabDelegate.isActive
|
||||
}
|
||||
|
||||
Behavior on opacity { NumberAnimation { duration: Kirigami.Units.shortDuration } }
|
||||
Behavior on opacity {
|
||||
NumberAnimation { duration: Kirigami.Units.shortDuration; easing.type: Easing.OutCubic }
|
||||
}
|
||||
|
||||
Behavior on shadow.size {
|
||||
NumberAnimation { duration: Kirigami.Units.shortDuration; easing.type: Easing.OutCubic }
|
||||
}
|
||||
|
||||
Behavior on border.width {
|
||||
NumberAnimation { duration: Kirigami.Units.shortDuration; easing.type: Easing.OutCubic }
|
||||
}
|
||||
}
|
||||
|
||||
leftPadding: Kirigami.Units.mediumSpacing
|
||||
|
|
@ -184,6 +216,8 @@ Item {
|
|||
root.currentSource = model.sourceId
|
||||
root.sourceSelected(model.sourceId)
|
||||
}
|
||||
|
||||
Keys.onDownPressed: root.focusDownRequested()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -191,23 +225,89 @@ Item {
|
|||
Kirigami.Separator { Layout.fillHeight: true }
|
||||
|
||||
QQC2.ToolButton {
|
||||
id: importBtn
|
||||
icon.name: "document-import"
|
||||
onClicked: root.importRequested()
|
||||
Layout.fillHeight: true
|
||||
flat: true
|
||||
hoverEnabled: true
|
||||
scale: activeFocus ? 1.02 : (hovered ? 1.01 : 1.0)
|
||||
Behavior on scale {
|
||||
NumberAnimation { duration: Kirigami.Units.shortDuration; easing.type: Easing.OutCubic }
|
||||
}
|
||||
|
||||
contentItem: Kirigami.Icon {
|
||||
source: "document-import"
|
||||
isMask: true
|
||||
implicitWidth: Kirigami.Units.iconSizes.smallMedium
|
||||
implicitHeight: Kirigami.Units.iconSizes.smallMedium
|
||||
width: implicitWidth
|
||||
height: implicitHeight
|
||||
anchors.centerIn: parent
|
||||
color: "white"
|
||||
}
|
||||
|
||||
background: Kirigami.ShadowedRectangle {
|
||||
radius: Kirigami.Units.smallSpacing
|
||||
color: Kirigami.Theme.alternateBackgroundColor
|
||||
opacity: parent.activeFocus ? 0.18 : (parent.hovered ? 0.10 : 0.0)
|
||||
border.width: parent.activeFocus ? 2 : 0
|
||||
border.color: Kirigami.Theme.highlightColor
|
||||
shadow.size: parent.activeFocus ? Kirigami.Units.mediumSpacing : 0
|
||||
shadow.color: Qt.rgba(0, 0, 0, 0.28)
|
||||
|
||||
Behavior on opacity { NumberAnimation { duration: Kirigami.Units.shortDuration; easing.type: Easing.OutCubic } }
|
||||
Behavior on shadow.size { NumberAnimation { duration: Kirigami.Units.shortDuration; easing.type: Easing.OutCubic } }
|
||||
Behavior on border.width { NumberAnimation { duration: Kirigami.Units.shortDuration; easing.type: Easing.OutCubic } }
|
||||
}
|
||||
|
||||
QQC2.ToolTip.text: i18n("Import Games")
|
||||
QQC2.ToolTip.visible: hovered
|
||||
QQC2.ToolTip.delay: Kirigami.Units.toolTipDelay
|
||||
|
||||
Keys.onDownPressed: root.focusDownRequested()
|
||||
}
|
||||
|
||||
QQC2.ToolButton {
|
||||
id: settingsBtn
|
||||
icon.name: "configure"
|
||||
onClicked: root.settingsRequested()
|
||||
Layout.fillHeight: true
|
||||
flat: true
|
||||
hoverEnabled: true
|
||||
scale: activeFocus ? 1.02 : (hovered ? 1.01 : 1.0)
|
||||
Behavior on scale {
|
||||
NumberAnimation { duration: Kirigami.Units.shortDuration; easing.type: Easing.OutCubic }
|
||||
}
|
||||
|
||||
contentItem: Kirigami.Icon {
|
||||
source: "configure"
|
||||
isMask: true
|
||||
implicitWidth: Kirigami.Units.iconSizes.smallMedium
|
||||
implicitHeight: Kirigami.Units.iconSizes.smallMedium
|
||||
width: implicitWidth
|
||||
height: implicitHeight
|
||||
anchors.centerIn: parent
|
||||
color: "white"
|
||||
}
|
||||
|
||||
background: Kirigami.ShadowedRectangle {
|
||||
radius: Kirigami.Units.smallSpacing
|
||||
color: Kirigami.Theme.alternateBackgroundColor
|
||||
opacity: parent.activeFocus ? 0.18 : (parent.hovered ? 0.10 : 0.0)
|
||||
border.width: parent.activeFocus ? 2 : 0
|
||||
border.color: Kirigami.Theme.highlightColor
|
||||
shadow.size: parent.activeFocus ? Kirigami.Units.mediumSpacing : 0
|
||||
shadow.color: Qt.rgba(0, 0, 0, 0.28)
|
||||
|
||||
Behavior on opacity { NumberAnimation { duration: Kirigami.Units.shortDuration; easing.type: Easing.OutCubic } }
|
||||
Behavior on shadow.size { NumberAnimation { duration: Kirigami.Units.shortDuration; easing.type: Easing.OutCubic } }
|
||||
Behavior on border.width { NumberAnimation { duration: Kirigami.Units.shortDuration; easing.type: Easing.OutCubic } }
|
||||
}
|
||||
|
||||
QQC2.ToolTip.text: i18n("Settings")
|
||||
QQC2.ToolTip.visible: hovered
|
||||
QQC2.ToolTip.delay: Kirigami.Units.toolTipDelay
|
||||
|
||||
Keys.onDownPressed: root.focusDownRequested()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -201,6 +201,12 @@ Item {
|
|||
focus: true
|
||||
KeyNavigation.right: favoriteBtn
|
||||
|
||||
hoverEnabled: true
|
||||
scale: activeFocus ? 1.03 : (hovered ? 1.01 : 1.0)
|
||||
Behavior on scale {
|
||||
NumberAnimation { duration: Kirigami.Units.shortDuration; easing.type: Easing.OutCubic }
|
||||
}
|
||||
|
||||
contentItem: RowLayout {
|
||||
spacing: 8
|
||||
Kirigami.Icon {
|
||||
|
|
@ -223,7 +229,7 @@ Item {
|
|||
: (playBtn.hovered ? Qt.rgba(1,1,1,0.22) : Qt.rgba(1,1,1,0.14))
|
||||
border.color: playBtn.activeFocus ? Kirigami.Theme.highlightColor : Qt.rgba(1,1,1,0.28)
|
||||
border.width: playBtn.activeFocus ? 0 : 1
|
||||
Behavior on color { ColorAnimation { duration: 100 } }
|
||||
Behavior on color { ColorAnimation { duration: Kirigami.Units.shortDuration; easing.type: Easing.OutCubic } }
|
||||
}
|
||||
|
||||
implicitWidth: 160
|
||||
|
|
@ -240,6 +246,12 @@ Item {
|
|||
KeyNavigation.left: playBtn
|
||||
KeyNavigation.right: editBtn
|
||||
|
||||
hoverEnabled: true
|
||||
scale: activeFocus ? 1.03 : (hovered ? 1.01 : 1.0)
|
||||
Behavior on scale {
|
||||
NumberAnimation { duration: Kirigami.Units.shortDuration; easing.type: Easing.OutCubic }
|
||||
}
|
||||
|
||||
contentItem: Kirigami.Icon {
|
||||
source: detailRoot.game && detailRoot.game.favorite ? "starred-symbolic" : "non-starred-symbolic"
|
||||
width: 22; height: 22
|
||||
|
|
@ -253,7 +265,7 @@ Item {
|
|||
: (favoriteBtn.hovered ? Qt.rgba(1,1,1,0.18) : Qt.rgba(1,1,1,0.10))
|
||||
border.color: favoriteBtn.activeFocus ? "white" : Qt.rgba(1,1,1,0.25)
|
||||
border.width: 1
|
||||
Behavior on color { ColorAnimation { duration: 100 } }
|
||||
Behavior on color { ColorAnimation { duration: Kirigami.Units.shortDuration; easing.type: Easing.OutCubic } }
|
||||
}
|
||||
|
||||
implicitWidth: 52
|
||||
|
|
@ -272,6 +284,12 @@ Item {
|
|||
KeyNavigation.left: favoriteBtn
|
||||
KeyNavigation.right: closeBtn
|
||||
|
||||
hoverEnabled: true
|
||||
scale: activeFocus ? 1.03 : (hovered ? 1.01 : 1.0)
|
||||
Behavior on scale {
|
||||
NumberAnimation { duration: Kirigami.Units.shortDuration; easing.type: Easing.OutCubic }
|
||||
}
|
||||
|
||||
contentItem: Kirigami.Icon {
|
||||
source: "document-edit"
|
||||
width: 20; height: 20
|
||||
|
|
@ -285,7 +303,7 @@ Item {
|
|||
: (editBtn.hovered ? Qt.rgba(1,1,1,0.18) : Qt.rgba(1,1,1,0.10))
|
||||
border.color: editBtn.activeFocus ? "white" : Qt.rgba(1,1,1,0.25)
|
||||
border.width: 1
|
||||
Behavior on color { ColorAnimation { duration: 100 } }
|
||||
Behavior on color { ColorAnimation { duration: Kirigami.Units.shortDuration; easing.type: Easing.OutCubic } }
|
||||
}
|
||||
|
||||
implicitWidth: 52
|
||||
|
|
@ -302,6 +320,12 @@ Item {
|
|||
icon.name: "window-close"
|
||||
KeyNavigation.left: editBtn
|
||||
|
||||
hoverEnabled: true
|
||||
scale: activeFocus ? 1.03 : (hovered ? 1.01 : 1.0)
|
||||
Behavior on scale {
|
||||
NumberAnimation { duration: Kirigami.Units.shortDuration; easing.type: Easing.OutCubic }
|
||||
}
|
||||
|
||||
contentItem: Kirigami.Icon {
|
||||
source: "window-close"
|
||||
width: 20; height: 20
|
||||
|
|
@ -315,7 +339,7 @@ Item {
|
|||
: (closeBtn.hovered ? Qt.rgba(1,1,1,0.18) : Qt.rgba(1,1,1,0.10))
|
||||
border.color: closeBtn.activeFocus ? "white" : Qt.rgba(1,1,1,0.25)
|
||||
border.width: 1
|
||||
Behavior on color { ColorAnimation { duration: 100 } }
|
||||
Behavior on color { ColorAnimation { duration: Kirigami.Units.shortDuration; easing.type: Easing.OutCubic } }
|
||||
}
|
||||
|
||||
implicitWidth: 52
|
||||
|
|
|
|||
|
|
@ -4,7 +4,6 @@
|
|||
import QtQuick
|
||||
import QtQuick.Controls as QQC2
|
||||
import QtQuick.Layouts
|
||||
import QtQuick.Effects
|
||||
import org.kde.kirigami as Kirigami
|
||||
import org.kde.alakarte
|
||||
|
||||
|
|
@ -12,10 +11,13 @@ Item {
|
|||
id: gameCard
|
||||
|
||||
property var game
|
||||
property bool gridActive: false
|
||||
signal clicked()
|
||||
signal playClicked()
|
||||
|
||||
readonly property bool isCurrent: GridView.isCurrentItem
|
||||
readonly property bool isGridFocused: gridActive
|
||||
readonly property bool isHighlighted: isCurrent && isGridFocused
|
||||
|
||||
readonly property bool useAnimatedCover: App.config.animatedCovers
|
||||
&& game && game.coverUrl
|
||||
|
|
@ -32,21 +34,9 @@ Item {
|
|||
width: parent.width - 16
|
||||
height: parent.height - 16
|
||||
|
||||
scale: gameCard.isCurrent ? 1.08 : (hoverHandler.hovered ? 1.03 : 1.0)
|
||||
scale: gameCard.isHighlighted ? 1.08 : ((gameCard.isCurrent || hoverHandler.hovered) ? 1.03 : 1.0)
|
||||
Behavior on scale {
|
||||
NumberAnimation { duration: 140; easing.type: Easing.OutCubic }
|
||||
}
|
||||
|
||||
layer.enabled: gameCard.isCurrent
|
||||
layer.effect: MultiEffect {
|
||||
shadowEnabled: true
|
||||
shadowColor: Qt.rgba(
|
||||
Kirigami.Theme.highlightColor.r,
|
||||
Kirigami.Theme.highlightColor.g,
|
||||
Kirigami.Theme.highlightColor.b, 0.55)
|
||||
shadowBlur: 0.8
|
||||
shadowHorizontalOffset: 0
|
||||
shadowVerticalOffset: 6
|
||||
NumberAnimation { duration: Kirigami.Units.shortDuration; easing.type: Easing.OutCubic }
|
||||
}
|
||||
|
||||
Rectangle {
|
||||
|
|
@ -73,7 +63,7 @@ Item {
|
|||
source: game ? game.coverUrl : ""
|
||||
fillMode: Image.PreserveAspectCrop
|
||||
asynchronous: true
|
||||
playing: gameCard.isCurrent
|
||||
playing: gameCard.isHighlighted
|
||||
visible: gameCard.useAnimatedCover
|
||||
smooth: true
|
||||
}
|
||||
|
|
@ -150,10 +140,10 @@ Item {
|
|||
radius: 8
|
||||
color: "transparent"
|
||||
border.color: Kirigami.Theme.highlightColor
|
||||
border.width: gameCard.isCurrent ? 3 : 0
|
||||
opacity: gameCard.isCurrent ? 1.0 : 0.0
|
||||
Behavior on opacity { NumberAnimation { duration: 120 } }
|
||||
Behavior on border.width { NumberAnimation { duration: 120 } }
|
||||
border.width: gameCard.isHighlighted ? 3 : (gameCard.isCurrent ? 2 : 0)
|
||||
opacity: gameCard.isHighlighted ? 1.0 : (gameCard.isCurrent ? 0.55 : 0.0)
|
||||
Behavior on opacity { NumberAnimation { duration: Kirigami.Units.shortDuration; easing.type: Easing.OutCubic } }
|
||||
Behavior on border.width { NumberAnimation { duration: Kirigami.Units.shortDuration; easing.type: Easing.OutCubic } }
|
||||
}
|
||||
|
||||
HoverHandler { id: hoverHandler }
|
||||
|
|
|
|||
|
|
@ -17,11 +17,16 @@ FocusScope {
|
|||
signal gameSelected(var game)
|
||||
signal gameFocused(var game)
|
||||
signal gameLaunched(var game)
|
||||
signal headerFocusRequested()
|
||||
|
||||
readonly property int gameCount: proxyModel.count
|
||||
|
||||
function restoreFocus() {
|
||||
grid.forceActiveFocus()
|
||||
if (grid.flickable) {
|
||||
grid.flickable.forceActiveFocus()
|
||||
} else {
|
||||
grid.forceActiveFocus()
|
||||
}
|
||||
}
|
||||
|
||||
function focusedGame() {
|
||||
|
|
@ -85,6 +90,7 @@ FocusScope {
|
|||
|
||||
delegate: GameCard {
|
||||
game: model.gameObject
|
||||
gridActive: grid.flickable ? grid.flickable.activeFocus : grid.activeFocus
|
||||
|
||||
onClicked: {
|
||||
grid.currentIndex = index
|
||||
|
|
@ -109,26 +115,29 @@ FocusScope {
|
|||
Connections {
|
||||
target: GamepadManager
|
||||
function onSelectPressed() {
|
||||
if (!grid.activeFocus) return
|
||||
if (!grid.flickable || !grid.flickable.activeFocus) return
|
||||
libraryRoot.selectFocused()
|
||||
}
|
||||
function onNavigateUp() {
|
||||
if (!grid.activeFocus) return
|
||||
if (grid.currentIndex <= 0) return
|
||||
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.activeFocus) return
|
||||
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.activeFocus) return
|
||||
if (!grid.flickable || !grid.flickable.activeFocus) return
|
||||
grid.currentIndex = Math.max(0, grid.currentIndex - 1)
|
||||
}
|
||||
function onNavigateRight() {
|
||||
if (!grid.activeFocus) return
|
||||
if (!grid.flickable || !grid.flickable.activeFocus) return
|
||||
grid.currentIndex = Math.min(proxyModel.count - 1, grid.currentIndex + 1)
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -6,6 +6,7 @@ import QtQuick.Controls as QQC2
|
|||
import QtQuick.Layouts
|
||||
import QtQuick.Effects
|
||||
import org.mauikit.controls as Maui
|
||||
import org.kde.kirigami as Kirigami
|
||||
import org.kde.alakarte
|
||||
import "components"
|
||||
|
||||
|
|
@ -120,16 +121,48 @@ Maui.ApplicationWindow {
|
|||
onSourceSelected: function(src) { root.currentCategory = src }
|
||||
onSettingsRequested: root.settingsVisible = true
|
||||
onImportRequested: App.importAllGames()
|
||||
onFocusDownRequested: libraryView.restoreFocus()
|
||||
}
|
||||
|
||||
QQC2.ToolButton {
|
||||
id: searchButton
|
||||
icon.name: "edit-find"
|
||||
flat: true
|
||||
Layout.preferredWidth: 40
|
||||
Layout.preferredHeight: 40
|
||||
hoverEnabled: true
|
||||
scale: activeFocus ? 1.02 : (hovered ? 1.01 : 1.0)
|
||||
Behavior on scale {
|
||||
NumberAnimation { duration: Kirigami.Units.shortDuration; easing.type: Easing.OutCubic }
|
||||
}
|
||||
onClicked: root.searchVisible = !root.searchVisible
|
||||
QQC2.ToolTip.text: i18n("Search")
|
||||
QQC2.ToolTip.visible: hovered
|
||||
|
||||
contentItem: Kirigami.Icon {
|
||||
source: "edit-find"
|
||||
isMask: true
|
||||
implicitWidth: Kirigami.Units.iconSizes.smallMedium
|
||||
implicitHeight: Kirigami.Units.iconSizes.smallMedium
|
||||
width: implicitWidth
|
||||
height: implicitHeight
|
||||
anchors.centerIn: parent
|
||||
color: "white"
|
||||
}
|
||||
|
||||
Keys.onDownPressed: libraryView.restoreFocus()
|
||||
|
||||
background: Rectangle {
|
||||
radius: 8
|
||||
color: parent.activeFocus
|
||||
? Qt.rgba(Kirigami.Theme.highlightColor.r, Kirigami.Theme.highlightColor.g, Kirigami.Theme.highlightColor.b, 0.18)
|
||||
: (parent.hovered ? Qt.rgba(1, 1, 1, 0.10) : Qt.rgba(1, 1, 1, 0.0))
|
||||
border.width: parent.activeFocus ? 2 : 0
|
||||
border.color: Kirigami.Theme.highlightColor
|
||||
|
||||
Behavior on color { ColorAnimation { duration: Kirigami.Units.shortDuration; easing.type: Easing.OutCubic } }
|
||||
Behavior on border.width { NumberAnimation { duration: Kirigami.Units.shortDuration; easing.type: Easing.OutCubic } }
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -159,6 +192,8 @@ Maui.ApplicationWindow {
|
|||
filterSource: root.currentCategory
|
||||
filterText: root.searchText
|
||||
|
||||
onHeaderFocusRequested: categoryRail.focusCurrent()
|
||||
|
||||
onGameFocused: function(game) { root.focusedGame = game }
|
||||
onGameSelected: function(game) {
|
||||
root.selectedGame = game
|
||||
|
|
|
|||
Loading…
Reference in a new issue