mirror of
https://invent.kde.org/marcoa/shift-shell.git
synced 2026-07-28 15:24:45 +00:00
Add Game Center overlay
Full-screen layer-shell overlay containing a game library grid (XDG Game category, filtered via ApplicationListSearchModel) and a panel of running tasks built on TaskManager.TasksModel. Keyboard-navigable with directional focus between the running tasks row and the game grid. A persistent HUD button lets the user return after launching a game. Exiting gaming mode requires an explicit confirmation dialog. The overlay is a Window with LayerShell.LayerTop so it sits above running application windows without covering system notifications.
This commit is contained in:
parent
b0739dd9a7
commit
6ac9c58d93
5 changed files with 525 additions and 0 deletions
|
|
@ -76,6 +76,14 @@ ecm_target_qml_sources(org.kde.plasma.mobile.homescreen.folio SOURCES
|
||||||
PATH settings
|
PATH settings
|
||||||
)
|
)
|
||||||
|
|
||||||
|
ecm_target_qml_sources(org.kde.plasma.mobile.homescreen.folio SOURCES
|
||||||
|
qml/gaming/GameCenterOverlay.qml
|
||||||
|
qml/gaming/GameTile.qml
|
||||||
|
qml/gaming/GamingHUD.qml
|
||||||
|
qml/gaming/RunningGamesView.qml
|
||||||
|
PATH gaming
|
||||||
|
)
|
||||||
|
|
||||||
target_link_libraries(org.kde.plasma.mobile.homescreen.folio PRIVATE
|
target_link_libraries(org.kde.plasma.mobile.homescreen.folio PRIVATE
|
||||||
Qt::Gui
|
Qt::Gui
|
||||||
Qt::Qml
|
Qt::Qml
|
||||||
|
|
|
||||||
183
containments/homescreens/folio/qml/gaming/GameCenterOverlay.qml
Normal file
183
containments/homescreens/folio/qml/gaming/GameCenterOverlay.qml
Normal file
|
|
@ -0,0 +1,183 @@
|
||||||
|
// SPDX-FileCopyrightText: 2026 Marco Allegretti
|
||||||
|
// SPDX-License-Identifier: EUPL-1.2
|
||||||
|
|
||||||
|
import QtQuick
|
||||||
|
import QtQuick.Layouts
|
||||||
|
import QtQuick.Controls as QQC2
|
||||||
|
import QtQuick.Window
|
||||||
|
|
||||||
|
import org.kde.kirigami as Kirigami
|
||||||
|
import org.kde.plasma.components 3.0 as PC3
|
||||||
|
import org.kde.plasma.private.mobileshell as MobileShell
|
||||||
|
import org.kde.plasma.private.mobileshell.state as MobileShellState
|
||||||
|
import org.kde.plasma.private.mobileshell.shellsettingsplugin as ShellSettings
|
||||||
|
import org.kde.layershell 1.0 as LayerShell
|
||||||
|
|
||||||
|
import plasma.applet.org.kde.plasma.mobile.homescreen.folio as Folio
|
||||||
|
|
||||||
|
Window {
|
||||||
|
id: root
|
||||||
|
|
||||||
|
required property var folio
|
||||||
|
|
||||||
|
signal gameStarted()
|
||||||
|
signal dismissRequested()
|
||||||
|
|
||||||
|
function requestExitGamingMode() {
|
||||||
|
exitGamingDialog.active = true
|
||||||
|
exitGamingDialog.item.open()
|
||||||
|
}
|
||||||
|
|
||||||
|
width: Screen.width
|
||||||
|
height: Screen.height
|
||||||
|
color: "transparent"
|
||||||
|
flags: Qt.FramelessWindowHint
|
||||||
|
|
||||||
|
LayerShell.Window.scope: "gaming-overlay"
|
||||||
|
LayerShell.Window.layer: LayerShell.Window.LayerTop
|
||||||
|
LayerShell.Window.anchors: LayerShell.Window.AnchorTop | LayerShell.Window.AnchorBottom
|
||||||
|
| LayerShell.Window.AnchorLeft | LayerShell.Window.AnchorRight
|
||||||
|
LayerShell.Window.exclusionZone: -1
|
||||||
|
LayerShell.Window.keyboardInteractivity: LayerShell.Window.KeyboardInteractivityOnDemand
|
||||||
|
|
||||||
|
// Animate opacity on show/hide
|
||||||
|
opacity: visible ? 1 : 0
|
||||||
|
Behavior on opacity {
|
||||||
|
NumberAnimation { duration: Kirigami.Units.longDuration; easing.type: Easing.InOutQuad }
|
||||||
|
}
|
||||||
|
|
||||||
|
onVisibleChanged: {
|
||||||
|
if (visible) {
|
||||||
|
root.folio.ApplicationListSearchModel.categoryFilter = "Game"
|
||||||
|
if (runningGames.hasTasks) {
|
||||||
|
runningGames.focusFirstTask()
|
||||||
|
} else {
|
||||||
|
grid.forceActiveFocus()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Rectangle {
|
||||||
|
anchors.fill: parent
|
||||||
|
Kirigami.Theme.inherit: false
|
||||||
|
Kirigami.Theme.colorSet: Kirigami.Theme.Window
|
||||||
|
color: Qt.rgba(Kirigami.Theme.backgroundColor.r,
|
||||||
|
Kirigami.Theme.backgroundColor.g,
|
||||||
|
Kirigami.Theme.backgroundColor.b, 0.92)
|
||||||
|
}
|
||||||
|
|
||||||
|
FocusScope {
|
||||||
|
id: contentRoot
|
||||||
|
anchors.fill: parent
|
||||||
|
focus: root.visible
|
||||||
|
|
||||||
|
// Escape only dismisses the overlay; exiting gaming mode is explicit.
|
||||||
|
Keys.onEscapePressed: root.dismissRequested()
|
||||||
|
|
||||||
|
ColumnLayout {
|
||||||
|
anchors.fill: parent
|
||||||
|
anchors.margins: Kirigami.Units.largeSpacing * 2
|
||||||
|
spacing: Kirigami.Units.largeSpacing
|
||||||
|
|
||||||
|
// ---- header ----
|
||||||
|
RowLayout {
|
||||||
|
Layout.fillWidth: true
|
||||||
|
|
||||||
|
Kirigami.Heading {
|
||||||
|
Layout.fillWidth: true
|
||||||
|
text: i18n("Game Center")
|
||||||
|
level: 1
|
||||||
|
}
|
||||||
|
|
||||||
|
QQC2.ToolButton {
|
||||||
|
icon.name: "window-close"
|
||||||
|
text: i18n("Exit Gaming Mode")
|
||||||
|
display: QQC2.AbstractButton.TextBesideIcon
|
||||||
|
Keys.onReturnPressed: clicked()
|
||||||
|
onClicked: root.requestExitGamingMode()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// ---- running games ----
|
||||||
|
RunningGamesView {
|
||||||
|
id: runningGames
|
||||||
|
Layout.fillWidth: true
|
||||||
|
onTaskActivated: root.gameStarted()
|
||||||
|
onMoveDownRequested: grid.forceActiveFocus()
|
||||||
|
}
|
||||||
|
|
||||||
|
// ---- game grid ----
|
||||||
|
Kirigami.Heading {
|
||||||
|
level: 2
|
||||||
|
text: i18n("Library")
|
||||||
|
}
|
||||||
|
|
||||||
|
GridView {
|
||||||
|
id: grid
|
||||||
|
|
||||||
|
Layout.fillWidth: true
|
||||||
|
Layout.fillHeight: true
|
||||||
|
|
||||||
|
// Filter the app list to the Games XDG category.
|
||||||
|
// ApplicationListSearchModel.categoryFilter is declared in
|
||||||
|
// applicationlistmodel.h and filters on the CategoriesRole of
|
||||||
|
// ApplicationListModel.
|
||||||
|
model: root.folio.ApplicationListSearchModel
|
||||||
|
|
||||||
|
readonly property real minCellSize: Kirigami.Units.gridUnit * 7
|
||||||
|
readonly property int columns: Math.max(2, Math.floor(width / minCellSize))
|
||||||
|
|
||||||
|
cellWidth: Math.floor(width / columns)
|
||||||
|
cellHeight: cellWidth + Kirigami.Units.gridUnit * 2
|
||||||
|
|
||||||
|
keyNavigationEnabled: true
|
||||||
|
highlightMoveDuration: 0
|
||||||
|
highlight: null
|
||||||
|
|
||||||
|
onActiveFocusChanged: {
|
||||||
|
if (activeFocus && count > 0 && currentIndex < 0) {
|
||||||
|
currentIndex = 0
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Keys.onUpPressed: {
|
||||||
|
if (runningGames.hasTasks) {
|
||||||
|
runningGames.focusFirstTask()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Keys.onReturnPressed: currentItem && currentItem.launch()
|
||||||
|
Keys.onEnterPressed: currentItem && currentItem.launch()
|
||||||
|
Keys.onEscapePressed: root.dismissRequested()
|
||||||
|
|
||||||
|
delegate: Item {
|
||||||
|
width: grid.cellWidth
|
||||||
|
height: grid.cellHeight
|
||||||
|
|
||||||
|
GameTile {
|
||||||
|
anchors.fill: parent
|
||||||
|
folio: root.folio
|
||||||
|
application: model.delegate ? model.delegate.application : null
|
||||||
|
isCurrent: GridView.isCurrentItem && grid.activeFocus
|
||||||
|
onLaunchRequested: root.gameStarted()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Loader {
|
||||||
|
id: exitGamingDialog
|
||||||
|
active: false
|
||||||
|
anchors.fill: parent
|
||||||
|
|
||||||
|
sourceComponent: Kirigami.PromptDialog {
|
||||||
|
title: i18n("Exit Gaming Mode")
|
||||||
|
subtitle: i18n("Keep gaming mode enabled, or switch back to the normal shell layout?")
|
||||||
|
standardButtons: Kirigami.Dialog.Yes | Kirigami.Dialog.Cancel
|
||||||
|
|
||||||
|
onAccepted: ShellSettings.Settings.gamingModeEnabled = false
|
||||||
|
onClosed: exitGamingDialog.active = false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
92
containments/homescreens/folio/qml/gaming/GameTile.qml
Normal file
92
containments/homescreens/folio/qml/gaming/GameTile.qml
Normal file
|
|
@ -0,0 +1,92 @@
|
||||||
|
// SPDX-FileCopyrightText: 2026 Marco Allegretti
|
||||||
|
// SPDX-License-Identifier: EUPL-1.2
|
||||||
|
|
||||||
|
import QtQuick
|
||||||
|
import QtQuick.Layouts
|
||||||
|
import QtQuick.Controls as QQC2
|
||||||
|
|
||||||
|
import org.kde.kirigami as Kirigami
|
||||||
|
import org.kde.plasma.private.mobileshell as MobileShell
|
||||||
|
import org.kde.plasma.private.mobileshell.state as MobileShellState
|
||||||
|
import org.kde.plasma.plasmoid
|
||||||
|
|
||||||
|
import plasma.applet.org.kde.plasma.mobile.homescreen.folio as Folio
|
||||||
|
import org.kde.plasma.components 3.0 as PC3
|
||||||
|
|
||||||
|
QQC2.ItemDelegate {
|
||||||
|
id: root
|
||||||
|
|
||||||
|
required property var folio
|
||||||
|
required property Folio.FolioApplication application
|
||||||
|
required property bool isCurrent
|
||||||
|
|
||||||
|
signal launchRequested()
|
||||||
|
|
||||||
|
Keys.onReturnPressed: clicked()
|
||||||
|
Keys.onEnterPressed: clicked()
|
||||||
|
|
||||||
|
onClicked: {
|
||||||
|
if (!application) return
|
||||||
|
if (application.icon !== "" && !application.running) {
|
||||||
|
MobileShellState.ShellDBusClient.openAppLaunchAnimationWithPosition(
|
||||||
|
Plasmoid.screen,
|
||||||
|
application.icon,
|
||||||
|
application.name,
|
||||||
|
application.storageId,
|
||||||
|
iconItem.Kirigami.ScenePosition.x + iconItem.width / 2,
|
||||||
|
iconItem.Kirigami.ScenePosition.y + iconItem.height / 2,
|
||||||
|
Math.min(iconItem.width, iconItem.height))
|
||||||
|
}
|
||||||
|
MobileShell.AppLaunch.launchOrActivateApp(application.storageId)
|
||||||
|
launchRequested()
|
||||||
|
}
|
||||||
|
|
||||||
|
function launch() {
|
||||||
|
clicked()
|
||||||
|
}
|
||||||
|
|
||||||
|
background: Rectangle {
|
||||||
|
Kirigami.Theme.colorSet: Kirigami.Theme.Button
|
||||||
|
color: root.isCurrent
|
||||||
|
? Kirigami.Theme.highlightColor
|
||||||
|
: (root.hovered ? Kirigami.Theme.hoverColor : "transparent")
|
||||||
|
radius: Kirigami.Units.cornerRadius
|
||||||
|
|
||||||
|
Behavior on color {
|
||||||
|
ColorAnimation { duration: Kirigami.Units.shortDuration }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
contentItem: ColumnLayout {
|
||||||
|
spacing: Kirigami.Units.smallSpacing
|
||||||
|
|
||||||
|
Kirigami.Icon {
|
||||||
|
id: iconItem
|
||||||
|
Layout.alignment: Qt.AlignHCenter
|
||||||
|
implicitWidth: Kirigami.Units.iconSizes.huge
|
||||||
|
implicitHeight: Kirigami.Units.iconSizes.huge
|
||||||
|
source: root.application ? root.application.icon : ""
|
||||||
|
|
||||||
|
scale: root.isCurrent ? 1.08 : 1.0
|
||||||
|
Behavior on scale {
|
||||||
|
NumberAnimation { duration: Kirigami.Units.shortDuration; easing.type: Easing.InOutQuad }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
PC3.Label {
|
||||||
|
id: nameLabel
|
||||||
|
Layout.alignment: Qt.AlignHCenter
|
||||||
|
Layout.fillWidth: true
|
||||||
|
text: root.application ? root.application.name : ""
|
||||||
|
maximumLineCount: 2
|
||||||
|
wrapMode: Text.Wrap
|
||||||
|
horizontalAlignment: Text.AlignHCenter
|
||||||
|
elide: Text.ElideRight
|
||||||
|
color: root.isCurrent ? Kirigami.Theme.highlightedTextColor : Kirigami.Theme.textColor
|
||||||
|
|
||||||
|
Behavior on color {
|
||||||
|
ColorAnimation { duration: Kirigami.Units.shortDuration }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
49
containments/homescreens/folio/qml/gaming/GamingHUD.qml
Normal file
49
containments/homescreens/folio/qml/gaming/GamingHUD.qml
Normal file
|
|
@ -0,0 +1,49 @@
|
||||||
|
// SPDX-FileCopyrightText: 2026 Marco Allegretti
|
||||||
|
// SPDX-License-Identifier: EUPL-1.2
|
||||||
|
|
||||||
|
import QtQuick
|
||||||
|
import QtQuick.Controls as QQC2
|
||||||
|
import QtQuick.Window
|
||||||
|
|
||||||
|
import org.kde.kirigami as Kirigami
|
||||||
|
import org.kde.plasma.private.mobileshell.shellsettingsplugin as ShellSettings
|
||||||
|
import org.kde.layershell 1.0 as LayerShell
|
||||||
|
|
||||||
|
Window {
|
||||||
|
id: root
|
||||||
|
|
||||||
|
signal openRequested()
|
||||||
|
|
||||||
|
width: Kirigami.Units.gridUnit * 4
|
||||||
|
height: Kirigami.Units.gridUnit * 2
|
||||||
|
color: "transparent"
|
||||||
|
flags: Qt.FramelessWindowHint
|
||||||
|
|
||||||
|
LayerShell.Window.scope: "gaming-hud"
|
||||||
|
LayerShell.Window.layer: LayerShell.Window.LayerOverlay
|
||||||
|
LayerShell.Window.anchors: LayerShell.Window.AnchorTop | LayerShell.Window.AnchorRight
|
||||||
|
LayerShell.Window.exclusionZone: 0
|
||||||
|
LayerShell.Window.keyboardInteractivity: LayerShell.Window.KeyboardInteractivityNone
|
||||||
|
|
||||||
|
opacity: visible ? 1 : 0
|
||||||
|
Behavior on opacity {
|
||||||
|
NumberAnimation { duration: Kirigami.Units.longDuration; easing.type: Easing.InOutQuad }
|
||||||
|
}
|
||||||
|
|
||||||
|
Rectangle {
|
||||||
|
anchors.fill: parent
|
||||||
|
anchors.margins: Kirigami.Units.smallSpacing
|
||||||
|
radius: height / 2
|
||||||
|
color: Qt.rgba(0, 0, 0, 0.55)
|
||||||
|
|
||||||
|
QQC2.ToolButton {
|
||||||
|
anchors.centerIn: parent
|
||||||
|
icon.name: "input-gaming"
|
||||||
|
icon.color: "white"
|
||||||
|
display: QQC2.AbstractButton.IconOnly
|
||||||
|
QQC2.ToolTip.visible: hovered
|
||||||
|
QQC2.ToolTip.text: i18n("Game Center")
|
||||||
|
onClicked: root.openRequested()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
193
containments/homescreens/folio/qml/gaming/RunningGamesView.qml
Normal file
193
containments/homescreens/folio/qml/gaming/RunningGamesView.qml
Normal file
|
|
@ -0,0 +1,193 @@
|
||||||
|
// SPDX-FileCopyrightText: 2026 Marco Allegretti
|
||||||
|
// SPDX-License-Identifier: EUPL-1.2
|
||||||
|
|
||||||
|
import QtQuick
|
||||||
|
import QtQuick.Layouts
|
||||||
|
import QtQuick.Controls as QQC2
|
||||||
|
|
||||||
|
import org.kde.kirigami as Kirigami
|
||||||
|
import org.kde.plasma.components 3.0 as PC3
|
||||||
|
import org.kde.taskmanager as TaskManager
|
||||||
|
|
||||||
|
import plasma.applet.org.kde.plasma.mobile.homescreen.folio as Folio
|
||||||
|
|
||||||
|
Item {
|
||||||
|
id: root
|
||||||
|
|
||||||
|
implicitHeight: taskList.count > 0 ? column.implicitHeight : 0
|
||||||
|
readonly property bool hasTasks: taskList.count > 0
|
||||||
|
|
||||||
|
signal taskActivated()
|
||||||
|
signal moveDownRequested()
|
||||||
|
|
||||||
|
function focusFirstTask() {
|
||||||
|
if (!hasTasks) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
taskList.currentIndex = Math.max(0, taskList.currentIndex)
|
||||||
|
taskList.positionViewAtIndex(taskList.currentIndex, ListView.Visible)
|
||||||
|
taskList.forceActiveFocus()
|
||||||
|
}
|
||||||
|
|
||||||
|
TaskManager.VirtualDesktopInfo { id: vdInfo }
|
||||||
|
TaskManager.ActivityInfo { id: actInfo }
|
||||||
|
|
||||||
|
TaskManager.TasksModel {
|
||||||
|
id: tasks
|
||||||
|
filterByVirtualDesktop: true
|
||||||
|
filterByActivity: true
|
||||||
|
filterNotMaximized: false
|
||||||
|
filterByScreen: true
|
||||||
|
filterHidden: false
|
||||||
|
virtualDesktop: vdInfo.currentDesktop
|
||||||
|
activity: actInfo.currentActivity
|
||||||
|
groupMode: TaskManager.TasksModel.GroupApplications
|
||||||
|
}
|
||||||
|
|
||||||
|
Behavior on implicitHeight {
|
||||||
|
NumberAnimation { duration: Kirigami.Units.longDuration; easing.type: Easing.InOutQuad }
|
||||||
|
}
|
||||||
|
|
||||||
|
ColumnLayout {
|
||||||
|
id: column
|
||||||
|
anchors.left: parent.left
|
||||||
|
anchors.right: parent.right
|
||||||
|
spacing: Kirigami.Units.smallSpacing
|
||||||
|
visible: taskList.count > 0
|
||||||
|
|
||||||
|
Kirigami.Heading {
|
||||||
|
level: 2
|
||||||
|
text: i18n("Running")
|
||||||
|
}
|
||||||
|
|
||||||
|
ListView {
|
||||||
|
id: taskList
|
||||||
|
Layout.fillWidth: true
|
||||||
|
implicitHeight: contentHeight
|
||||||
|
model: tasks
|
||||||
|
orientation: ListView.Horizontal
|
||||||
|
spacing: Kirigami.Units.largeSpacing
|
||||||
|
clip: true
|
||||||
|
keyNavigationEnabled: true
|
||||||
|
currentIndex: 0
|
||||||
|
|
||||||
|
onActiveFocusChanged: {
|
||||||
|
if (activeFocus && count > 0 && currentIndex < 0) {
|
||||||
|
currentIndex = 0
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Keys.onLeftPressed: {
|
||||||
|
if (count <= 0) {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
currentIndex = Math.max(0, currentIndex - 1)
|
||||||
|
positionViewAtIndex(currentIndex, ListView.Contain)
|
||||||
|
}
|
||||||
|
|
||||||
|
Keys.onRightPressed: {
|
||||||
|
if (count <= 0) {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
currentIndex = Math.min(count - 1, currentIndex + 1)
|
||||||
|
positionViewAtIndex(currentIndex, ListView.Contain)
|
||||||
|
}
|
||||||
|
|
||||||
|
Keys.onDownPressed: root.moveDownRequested()
|
||||||
|
Keys.onReturnPressed: currentItem && currentItem.activate()
|
||||||
|
Keys.onEnterPressed: currentItem && currentItem.activate()
|
||||||
|
|
||||||
|
delegate: QQC2.ItemDelegate {
|
||||||
|
id: taskItem
|
||||||
|
|
||||||
|
required property var decoration
|
||||||
|
required property var winIdList
|
||||||
|
|
||||||
|
width: Kirigami.Units.gridUnit * 8
|
||||||
|
height: Kirigami.Units.gridUnit * 5
|
||||||
|
|
||||||
|
readonly property var modelIndex: tasks.makeModelIndex(index)
|
||||||
|
readonly property bool isCurrent: ListView.isCurrentItem && taskList.activeFocus
|
||||||
|
readonly property string titleText: typeof model !== "undefined" && model.display ? model.display : ""
|
||||||
|
|
||||||
|
function activate() {
|
||||||
|
tasks.requestActivate(taskItem.modelIndex)
|
||||||
|
root.taskActivated()
|
||||||
|
}
|
||||||
|
|
||||||
|
onClicked: {
|
||||||
|
taskList.currentIndex = index
|
||||||
|
activate()
|
||||||
|
}
|
||||||
|
|
||||||
|
Keys.onReturnPressed: activate()
|
||||||
|
Keys.onEnterPressed: activate()
|
||||||
|
|
||||||
|
Rectangle {
|
||||||
|
anchors.fill: parent
|
||||||
|
radius: Kirigami.Units.cornerRadius
|
||||||
|
color: taskItem.isCurrent
|
||||||
|
? Qt.rgba(Kirigami.Theme.highlightColor.r, Kirigami.Theme.highlightColor.g,
|
||||||
|
Kirigami.Theme.highlightColor.b, 0.25)
|
||||||
|
: resumeArea.containsPress
|
||||||
|
? Qt.rgba(Kirigami.Theme.highlightColor.r, Kirigami.Theme.highlightColor.g,
|
||||||
|
Kirigami.Theme.highlightColor.b, 0.3)
|
||||||
|
: resumeArea.containsMouse
|
||||||
|
? Qt.rgba(Kirigami.Theme.textColor.r, Kirigami.Theme.textColor.g,
|
||||||
|
Kirigami.Theme.textColor.b, 0.1)
|
||||||
|
: Qt.rgba(Kirigami.Theme.textColor.r, Kirigami.Theme.textColor.g,
|
||||||
|
Kirigami.Theme.textColor.b, 0.06)
|
||||||
|
|
||||||
|
Behavior on color { ColorAnimation { duration: Kirigami.Units.shortDuration } }
|
||||||
|
}
|
||||||
|
|
||||||
|
ColumnLayout {
|
||||||
|
anchors.fill: parent
|
||||||
|
anchors.margins: Kirigami.Units.smallSpacing
|
||||||
|
spacing: Kirigami.Units.smallSpacing
|
||||||
|
|
||||||
|
Kirigami.Icon {
|
||||||
|
Layout.alignment: Qt.AlignHCenter
|
||||||
|
implicitWidth: Kirigami.Units.iconSizes.large
|
||||||
|
implicitHeight: Kirigami.Units.iconSizes.large
|
||||||
|
source: taskItem.decoration
|
||||||
|
}
|
||||||
|
|
||||||
|
PC3.Label {
|
||||||
|
Layout.fillWidth: true
|
||||||
|
text: taskItem.titleText
|
||||||
|
maximumLineCount: 1
|
||||||
|
elide: Text.ElideRight
|
||||||
|
horizontalAlignment: Text.AlignHCenter
|
||||||
|
font.pointSize: Kirigami.Theme.defaultFont.pointSize * 0.85
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Close button (top-right corner)
|
||||||
|
QQC2.ToolButton {
|
||||||
|
anchors.top: parent.top
|
||||||
|
anchors.right: parent.right
|
||||||
|
anchors.margins: Kirigami.Units.smallSpacing / 2
|
||||||
|
width: Kirigami.Units.iconSizes.small
|
||||||
|
height: width
|
||||||
|
icon.name: "window-close-symbolic"
|
||||||
|
icon.width: Kirigami.Units.iconSizes.small
|
||||||
|
icon.height: Kirigami.Units.iconSizes.small
|
||||||
|
display: QQC2.AbstractButton.IconOnly
|
||||||
|
onClicked: tasks.requestClose(taskItem.modelIndex)
|
||||||
|
}
|
||||||
|
|
||||||
|
MouseArea {
|
||||||
|
id: resumeArea
|
||||||
|
anchors.fill: parent
|
||||||
|
hoverEnabled: true
|
||||||
|
// Leave room for the close button
|
||||||
|
onClicked: {
|
||||||
|
taskList.currentIndex = index
|
||||||
|
taskItem.activate()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
Loading…
Reference in a new issue