mirror of
https://invent.kde.org/marcoa/shift-shell.git
synced 2026-06-11 16:57:43 +00:00
Let the shared drawer surface provide the background and stop\nthe Folio subpanels from painting their own opaque rectangles on\ntop of it.
738 lines
32 KiB
QML
738 lines
32 KiB
QML
// SPDX-FileCopyrightText: 2026 Marco Allegretti
|
|
// SPDX-License-Identifier: EUPL-1.2
|
|
|
|
import QtQuick
|
|
import QtQuick.Layouts
|
|
|
|
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.shellsettingsplugin as ShellSettings
|
|
import org.kde.taskmanager as TaskManager
|
|
|
|
import plasma.applet.org.kde.plasma.mobile.homescreen.folio as Folio
|
|
|
|
Item {
|
|
id: root
|
|
|
|
required property var folio
|
|
|
|
readonly property bool hasTasks: allTasksModel.count > 0
|
|
readonly property int shortAnimationDuration: MobileShell.Motion.duration(MobileShell.Motion.EffectsFast)
|
|
property bool sortByName: false
|
|
property int dragTargetDesktopIndex: -1
|
|
property string pendingMoveTaskKey: ""
|
|
property string pendingMoveTargetName: ""
|
|
|
|
signal taskActivated()
|
|
|
|
function taskStorageId(taskModel) {
|
|
var id = taskModel ? taskModel.AppId || "" : ""
|
|
if (id && !id.endsWith(".desktop")) {
|
|
id += ".desktop"
|
|
}
|
|
return id
|
|
}
|
|
|
|
function taskKey(taskModel) {
|
|
const winIds = taskModel && taskModel.WinIdList ? taskModel.WinIdList : []
|
|
if (winIds.length > 0) {
|
|
var key = ""
|
|
for (var i = 0; i < winIds.length; ++i) {
|
|
key += String(winIds[i]) + "|"
|
|
}
|
|
return key
|
|
}
|
|
|
|
return String(taskModel ? taskModel.AppId || "" : "") + "|" + String(taskModel ? taskModel.display || "" : "")
|
|
}
|
|
|
|
function taskWindowId(taskModel) {
|
|
const winIds = taskModel && taskModel.WinIdList ? taskModel.WinIdList : []
|
|
return winIds.length === 1 ? String(winIds[0]) : ""
|
|
}
|
|
|
|
function dynamicTilingMoveToDesktopAction(desktopId, desktopIndex) {
|
|
if (String(desktopId).length === 0 || desktopIndex < 0) {
|
|
return ""
|
|
}
|
|
return "move-to-desktop:" + String(desktopId) + "|" + String(desktopIndex + 1)
|
|
}
|
|
|
|
function markTaskMove(taskKey, desktopIndex) {
|
|
pendingMoveTaskKey = taskKey
|
|
pendingMoveTargetName = desktopName(desktopIndex)
|
|
pendingMoveResetTimer.restart()
|
|
}
|
|
|
|
function mixColor(base, overlay, ratio) {
|
|
return Qt.rgba(
|
|
base.r + (overlay.r - base.r) * ratio,
|
|
base.g + (overlay.g - base.g) * ratio,
|
|
base.b + (overlay.b - base.b) * ratio,
|
|
base.a + (overlay.a - base.a) * ratio)
|
|
}
|
|
|
|
function desktopName(index) {
|
|
const names = virtualDesktopInfo.desktopNames
|
|
if (names && names.length > index && String(names[index]).length > 0) {
|
|
return String(names[index])
|
|
}
|
|
return "Desktop " + (index + 1)
|
|
}
|
|
|
|
function isCurrentDesktop(desktopId) {
|
|
return String(desktopId) === String(virtualDesktopInfo.currentDesktop)
|
|
}
|
|
|
|
Timer {
|
|
id: pendingMoveResetTimer
|
|
interval: 1200
|
|
onTriggered: {
|
|
root.pendingMoveTaskKey = ""
|
|
root.pendingMoveTargetName = ""
|
|
}
|
|
}
|
|
|
|
TaskManager.VirtualDesktopInfo { id: virtualDesktopInfo }
|
|
TaskManager.ActivityInfo { id: activityInfo }
|
|
|
|
TaskManager.TasksModel {
|
|
id: allTasksModel
|
|
filterByVirtualDesktop: false
|
|
filterByActivity: true
|
|
filterNotMaximized: false
|
|
filterByScreen: true
|
|
filterHidden: false
|
|
activity: activityInfo.currentActivity
|
|
groupMode: TaskManager.TasksModel.GroupDisabled
|
|
}
|
|
|
|
TaskManager.TasksModel {
|
|
id: tasksModel
|
|
filterByVirtualDesktop: true
|
|
filterByActivity: true
|
|
filterNotMaximized: false
|
|
filterByScreen: true
|
|
filterHidden: false
|
|
virtualDesktop: virtualDesktopInfo.currentDesktop
|
|
activity: activityInfo.currentActivity
|
|
groupMode: TaskManager.TasksModel.GroupDisabled
|
|
sortMode: root.sortByName ? TaskManager.TasksModel.SortAlpha : TaskManager.TasksModel.SortLastActivated
|
|
}
|
|
|
|
Rectangle {
|
|
id: panelBackground
|
|
anchors.fill: parent
|
|
radius: 0
|
|
color: "transparent"
|
|
}
|
|
|
|
MouseArea {
|
|
anchors.fill: parent
|
|
}
|
|
|
|
ColumnLayout {
|
|
anchors.fill: parent
|
|
anchors.margins: Kirigami.Units.smallSpacing
|
|
spacing: Kirigami.Units.smallSpacing
|
|
|
|
RowLayout {
|
|
Layout.fillWidth: true
|
|
spacing: Kirigami.Units.smallSpacing
|
|
|
|
PC3.Label {
|
|
Layout.fillWidth: true
|
|
text: i18n("Running")
|
|
font.weight: Font.Medium
|
|
elide: Text.ElideRight
|
|
}
|
|
|
|
Row {
|
|
spacing: 1
|
|
|
|
Repeater {
|
|
model: [
|
|
{ label: i18n("Recent"), byName: false },
|
|
{ label: i18n("Name"), byName: true }
|
|
]
|
|
|
|
delegate: MouseArea {
|
|
id: sortButton
|
|
|
|
required property var modelData
|
|
readonly property bool checked: root.sortByName === modelData.byName
|
|
|
|
width: Math.max(Kirigami.Units.gridUnit * 3.5, label.implicitWidth + Kirigami.Units.smallSpacing * 3)
|
|
height: Kirigami.Units.gridUnit * 1.6
|
|
hoverEnabled: true
|
|
cursorShape: Qt.PointingHandCursor
|
|
onClicked: root.sortByName = modelData.byName
|
|
|
|
Rectangle {
|
|
anchors.fill: parent
|
|
radius: Kirigami.Units.cornerRadius
|
|
color: sortButton.checked
|
|
? root.mixColor(Kirigami.Theme.backgroundColor, Kirigami.Theme.highlightColor, sortButton.containsMouse ? 0.28 : 0.2)
|
|
: sortButton.containsMouse
|
|
? root.mixColor(Kirigami.Theme.backgroundColor, Kirigami.Theme.textColor, 0.08)
|
|
: "transparent"
|
|
}
|
|
|
|
PC3.Label {
|
|
id: label
|
|
anchors.centerIn: parent
|
|
text: sortButton.modelData.label
|
|
font.pointSize: Kirigami.Theme.defaultFont.pointSize * 0.85
|
|
color: sortButton.checked ? Kirigami.Theme.highlightColor : Kirigami.Theme.textColor
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
RowLayout {
|
|
id: desktopStrip
|
|
|
|
Layout.fillWidth: true
|
|
visible: virtualDesktopInfo.numberOfDesktops > 1
|
|
spacing: Kirigami.Units.smallSpacing
|
|
|
|
PC3.Label {
|
|
text: i18n("Desktops")
|
|
opacity: 0.7
|
|
font.pointSize: Kirigami.Theme.defaultFont.pointSize * 0.85
|
|
}
|
|
|
|
Item {
|
|
id: desktopDropSurface
|
|
|
|
Layout.fillWidth: true
|
|
Layout.preferredHeight: Kirigami.Units.gridUnit * 2.4
|
|
|
|
function desktopIndexAt(x) {
|
|
if (virtualDesktopInfo.numberOfDesktops <= 0) {
|
|
return -1
|
|
}
|
|
|
|
const localX = desktopRow.mapFromItem(desktopDropSurface, x, 0).x
|
|
var nearestIndex = -1
|
|
var nearestDistance = Number.MAX_VALUE
|
|
for (var i = 0; i < virtualDesktopInfo.numberOfDesktops; ++i) {
|
|
const item = desktopRepeater.itemAt(i)
|
|
if (!item) {
|
|
continue
|
|
}
|
|
|
|
if (localX >= item.x && localX <= item.x + item.width) {
|
|
return i
|
|
}
|
|
|
|
const center = item.x + item.width / 2
|
|
const distance = Math.abs(localX - center)
|
|
if (distance < nearestDistance) {
|
|
nearestIndex = i
|
|
nearestDistance = distance
|
|
}
|
|
}
|
|
return nearestIndex
|
|
}
|
|
|
|
Row {
|
|
id: desktopRow
|
|
|
|
anchors.fill: parent
|
|
spacing: Kirigami.Units.smallSpacing
|
|
|
|
Repeater {
|
|
id: desktopRepeater
|
|
|
|
model: virtualDesktopInfo.desktopIds
|
|
|
|
delegate: MouseArea {
|
|
id: desktopButton
|
|
|
|
required property int index
|
|
required property var modelData
|
|
|
|
readonly property bool checked: root.isCurrentDesktop(modelData)
|
|
readonly property string desktopLabel: root.desktopName(index)
|
|
readonly property bool dragHovered: desktopDropArea.containsDrag && root.dragTargetDesktopIndex === index
|
|
|
|
width: Math.max(Kirigami.Units.gridUnit * 5.5, (desktopRow.width / Math.max(1, virtualDesktopInfo.numberOfDesktops)) - Kirigami.Units.smallSpacing)
|
|
height: desktopRow.height
|
|
hoverEnabled: true
|
|
cursorShape: Qt.PointingHandCursor
|
|
|
|
onClicked: root.folio.activateVirtualDesktop(modelData)
|
|
|
|
Rectangle {
|
|
anchors.fill: parent
|
|
radius: Kirigami.Units.cornerRadius
|
|
scale: desktopButton.dragHovered ? 1.03 : 1
|
|
color: desktopButton.checked
|
|
? root.mixColor(Kirigami.Theme.backgroundColor, Kirigami.Theme.highlightColor, desktopButton.containsMouse || desktopButton.dragHovered ? 0.32 : 0.24)
|
|
: desktopButton.dragHovered
|
|
? root.mixColor(Kirigami.Theme.backgroundColor, Kirigami.Theme.highlightColor, 0.18)
|
|
: desktopButton.containsMouse
|
|
? root.mixColor(Kirigami.Theme.backgroundColor, Kirigami.Theme.textColor, 0.08)
|
|
: root.mixColor(Kirigami.Theme.backgroundColor, Kirigami.Theme.textColor, 0.045)
|
|
border.width: 1
|
|
border.pixelAligned: false
|
|
border.color: desktopButton.checked || desktopButton.dragHovered
|
|
? root.mixColor(Kirigami.Theme.backgroundColor, Kirigami.Theme.highlightColor, 0.55)
|
|
: root.mixColor(Kirigami.Theme.backgroundColor, Kirigami.Theme.textColor, 0.14)
|
|
|
|
Behavior on color {
|
|
MobileShell.MotionColorAnimation { type: MobileShell.Motion.EffectsFast; duration: root.shortAnimationDuration }
|
|
}
|
|
Behavior on scale {
|
|
MobileShell.MotionNumberAnimation { type: MobileShell.Motion.EffectsFast; duration: root.shortAnimationDuration }
|
|
}
|
|
}
|
|
|
|
Rectangle {
|
|
anchors.left: parent.left
|
|
anchors.right: parent.right
|
|
anchors.bottom: parent.bottom
|
|
anchors.margins: Kirigami.Units.smallSpacing / 2
|
|
height: Math.max(2, Math.round(Kirigami.Units.devicePixelRatio))
|
|
radius: height / 2
|
|
visible: desktopButton.checked
|
|
color: Kirigami.Theme.highlightColor
|
|
}
|
|
|
|
PC3.Label {
|
|
anchors.centerIn: parent
|
|
width: parent.width - Kirigami.Units.smallSpacing * 2
|
|
text: desktopButton.desktopLabel
|
|
elide: Text.ElideRight
|
|
horizontalAlignment: Text.AlignHCenter
|
|
font.weight: desktopButton.checked || desktopButton.dragHovered ? Font.Medium : Font.Normal
|
|
font.pixelSize: Math.min(Kirigami.Theme.defaultFont.pixelSize, parent.height * 0.42)
|
|
color: desktopButton.checked || desktopButton.dragHovered ? Kirigami.Theme.highlightColor : Kirigami.Theme.textColor
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
DropArea {
|
|
id: desktopDropArea
|
|
|
|
anchors.fill: parent
|
|
keys: ["folio-running-task"]
|
|
|
|
onEntered: (drag) => {
|
|
root.dragTargetDesktopIndex = desktopDropSurface.desktopIndexAt(drag.x)
|
|
drag.accept(Qt.MoveAction)
|
|
}
|
|
onPositionChanged: (drag) => {
|
|
root.dragTargetDesktopIndex = desktopDropSurface.desktopIndexAt(drag.x)
|
|
drag.accept(Qt.MoveAction)
|
|
}
|
|
onExited: root.dragTargetDesktopIndex = -1
|
|
onDropped: (drop) => {
|
|
const desktopIndex = desktopDropSurface.desktopIndexAt(drop.x)
|
|
const desktopId = desktopIndex >= 0 ? virtualDesktopInfo.desktopIds[desktopIndex] : ""
|
|
if (!drop.source || !drop.source.moveToDesktop || String(desktopId).length === 0) {
|
|
root.dragTargetDesktopIndex = -1
|
|
return
|
|
}
|
|
|
|
drop.source.moveToDesktop(desktopId, desktopIndex)
|
|
root.dragTargetDesktopIndex = -1
|
|
drop.accept(Qt.MoveAction)
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
GridView {
|
|
id: taskGrid
|
|
|
|
Layout.fillWidth: true
|
|
Layout.fillHeight: true
|
|
clip: true
|
|
model: tasksModel
|
|
boundsBehavior: Flickable.StopAtBounds
|
|
interactive: contentHeight > height
|
|
|
|
readonly property int columns: Math.max(1, Math.floor(width / (Kirigami.Units.gridUnit * 14)))
|
|
cellWidth: Math.floor(width / columns)
|
|
cellHeight: Kirigami.Units.gridUnit * 10
|
|
|
|
delegate: Item {
|
|
id: taskCard
|
|
|
|
required property int index
|
|
required property var model
|
|
|
|
width: taskGrid.cellWidth - Kirigami.Units.smallSpacing
|
|
height: taskGrid.cellHeight - Kirigami.Units.smallSpacing
|
|
|
|
readonly property var modelIndex: tasksModel.makeModelIndex(index)
|
|
readonly property var winIds: model.WinIdList ? model.WinIdList : []
|
|
readonly property int previewCount: Math.max(1, Math.min(2, winIds.length))
|
|
readonly property bool activeTask: model.IsActive === true
|
|
readonly property bool minimizedTask: model.IsMinimized === true
|
|
readonly property bool groupTask: model.IsGroupParent === true
|
|
readonly property bool desktopsChangeable: model.IsVirtualDesktopsChangeable === true
|
|
readonly property string storageId: root.taskStorageId(model)
|
|
readonly property string taskKey: root.taskKey(model)
|
|
readonly property string windowId: root.taskWindowId(model)
|
|
readonly property bool dynamicTilingActive: ShellSettings.Settings.convergenceModeEnabled && ShellSettings.Settings.dynamicTilingEnabled
|
|
readonly property bool canRequestDynamicTiling: dynamicTilingActive && !groupTask && windowId !== ""
|
|
readonly property int dynamicTilingWindowStateSerial: ShellSettings.Settings.dynamicTilingWindowStateSerial
|
|
readonly property bool dynamicTilingMaximized: canRequestDynamicTiling
|
|
&& dynamicTilingWindowStateSerial >= 0
|
|
&& ShellSettings.Settings.isDynamicTilingWindowMaximized(windowId)
|
|
readonly property bool maximizedTask: model.IsMaximized === true || dynamicTilingMaximized
|
|
readonly property bool pinned: storageId !== "" && root.folio.FavouritesModel.containsApplication(storageId)
|
|
readonly property bool pendingMove: root.pendingMoveTaskKey === taskKey
|
|
|
|
function taskIndexForPreview(previewIndex) {
|
|
return taskCard.groupTask
|
|
? tasksModel.makeModelIndex(taskCard.index, previewIndex)
|
|
: taskCard.modelIndex
|
|
}
|
|
|
|
function titleForPreview(previewIndex) {
|
|
if (!taskCard.groupTask) {
|
|
return taskCard.model.display || ""
|
|
}
|
|
return tasksModel.data(tasksModel.makeModelIndex(taskCard.index, previewIndex), 0) || taskCard.model.display || ""
|
|
}
|
|
|
|
function activate(previewIndex) {
|
|
tasksModel.requestActivate(taskIndexForPreview(previewIndex || 0))
|
|
root.taskActivated()
|
|
}
|
|
|
|
function moveToDesktop(desktopId, desktopIndex) {
|
|
if (!taskCard.desktopsChangeable || String(desktopId).length === 0) {
|
|
return
|
|
}
|
|
|
|
root.markTaskMove(taskCard.taskKey, desktopIndex)
|
|
if (taskCard.canRequestDynamicTiling) {
|
|
const action = root.dynamicTilingMoveToDesktopAction(desktopId, desktopIndex)
|
|
if (action !== "") {
|
|
ShellSettings.Settings.requestDynamicTilingWindowAction(taskCard.windowId, action)
|
|
}
|
|
}
|
|
tasksModel.requestVirtualDesktops(taskCard.modelIndex, [desktopId])
|
|
}
|
|
|
|
Item {
|
|
id: dragProxy
|
|
|
|
parent: root
|
|
width: taskCard.width
|
|
height: taskCard.height
|
|
z: 1000
|
|
visible: cardArea.drag.active
|
|
opacity: 0.9
|
|
|
|
Drag.active: cardArea.drag.active
|
|
Drag.hotSpot.x: cardArea.pressX
|
|
Drag.hotSpot.y: cardArea.pressY
|
|
Drag.keys: ["folio-running-task"]
|
|
Drag.proposedAction: Qt.MoveAction
|
|
Drag.source: taskCard
|
|
Drag.supportedActions: Qt.MoveAction
|
|
|
|
Rectangle {
|
|
anchors.fill: parent
|
|
radius: Kirigami.Units.cornerRadius
|
|
color: root.mixColor(Kirigami.Theme.backgroundColor, Kirigami.Theme.highlightColor, 0.2)
|
|
border.width: 1
|
|
border.pixelAligned: false
|
|
border.color: root.mixColor(Kirigami.Theme.backgroundColor, Kirigami.Theme.highlightColor, 0.6)
|
|
}
|
|
|
|
RowLayout {
|
|
anchors.fill: parent
|
|
anchors.margins: Kirigami.Units.smallSpacing
|
|
spacing: Kirigami.Units.smallSpacing
|
|
|
|
Kirigami.Icon {
|
|
Layout.preferredWidth: Kirigami.Units.iconSizes.smallMedium
|
|
Layout.preferredHeight: Layout.preferredWidth
|
|
source: taskCard.model.decoration
|
|
}
|
|
|
|
PC3.Label {
|
|
Layout.fillWidth: true
|
|
text: taskCard.model.display || ""
|
|
elide: Text.ElideRight
|
|
maximumLineCount: 1
|
|
}
|
|
}
|
|
}
|
|
|
|
MouseArea {
|
|
id: cardArea
|
|
anchors.fill: parent
|
|
hoverEnabled: true
|
|
cursorShape: taskCard.desktopsChangeable ? Qt.OpenHandCursor : Qt.PointingHandCursor
|
|
enabled: !taskCard.pendingMove
|
|
property real pressX: width / 2
|
|
property real pressY: height / 2
|
|
property bool wasDragged: false
|
|
drag.target: taskCard.desktopsChangeable ? dragProxy : undefined
|
|
drag.threshold: Math.max(4, Kirigami.Units.smallSpacing)
|
|
drag.smoothed: false
|
|
|
|
onPressed: (mouse) => {
|
|
wasDragged = false
|
|
pressX = mouse.x
|
|
pressY = mouse.y
|
|
const pos = taskCard.mapToItem(root, 0, 0)
|
|
dragProxy.x = pos.x
|
|
dragProxy.y = pos.y
|
|
}
|
|
|
|
onPositionChanged: {
|
|
if (drag.active) {
|
|
wasDragged = true
|
|
}
|
|
}
|
|
|
|
onReleased: {
|
|
if (wasDragged) {
|
|
dragProxy.Drag.drop()
|
|
}
|
|
}
|
|
|
|
onClicked: {
|
|
if (!wasDragged) {
|
|
taskCard.activate(0)
|
|
}
|
|
}
|
|
}
|
|
|
|
Rectangle {
|
|
anchors.fill: parent
|
|
radius: Kirigami.Units.cornerRadius
|
|
color: taskCard.activeTask
|
|
? root.mixColor(Kirigami.Theme.backgroundColor, Kirigami.Theme.highlightColor, cardArea.containsMouse ? 0.18 : 0.12)
|
|
: cardArea.containsMouse
|
|
? root.mixColor(Kirigami.Theme.backgroundColor, Kirigami.Theme.textColor, 0.08)
|
|
: root.mixColor(Kirigami.Theme.backgroundColor, Kirigami.Theme.textColor, 0.04)
|
|
border.width: 1
|
|
border.pixelAligned: false
|
|
border.color: taskCard.activeTask
|
|
? root.mixColor(Kirigami.Theme.backgroundColor, Kirigami.Theme.highlightColor, 0.5)
|
|
: root.mixColor(Kirigami.Theme.backgroundColor, Kirigami.Theme.textColor, 0.12)
|
|
|
|
Behavior on color {
|
|
MobileShell.MotionColorAnimation { type: MobileShell.Motion.EffectsFast; duration: root.shortAnimationDuration }
|
|
}
|
|
}
|
|
|
|
ColumnLayout {
|
|
anchors.fill: parent
|
|
anchors.margins: Kirigami.Units.smallSpacing
|
|
spacing: Kirigami.Units.smallSpacing
|
|
|
|
Row {
|
|
id: previewRow
|
|
Layout.fillWidth: true
|
|
Layout.preferredHeight: Kirigami.Units.gridUnit * 5
|
|
spacing: Kirigami.Units.smallSpacing
|
|
|
|
Repeater {
|
|
model: taskCard.previewCount
|
|
|
|
delegate: MouseArea {
|
|
id: previewArea
|
|
|
|
required property int index
|
|
readonly property string childUuid: taskCard.winIds.length > index ? taskCard.winIds[index] : ""
|
|
|
|
width: (previewRow.width - previewRow.spacing * (taskCard.previewCount - 1)) / taskCard.previewCount
|
|
height: previewRow.height
|
|
hoverEnabled: true
|
|
cursorShape: Qt.PointingHandCursor
|
|
onClicked: taskCard.activate(index)
|
|
|
|
Rectangle {
|
|
anchors.fill: parent
|
|
radius: Kirigami.Units.cornerRadius
|
|
color: root.mixColor(Kirigami.Theme.backgroundColor, Kirigami.Theme.textColor, previewArea.containsMouse ? 0.1 : 0.06)
|
|
border.width: 1
|
|
border.pixelAligned: false
|
|
border.color: root.mixColor(Kirigami.Theme.backgroundColor, Kirigami.Theme.textColor, 0.14)
|
|
}
|
|
|
|
Loader {
|
|
id: thumbnailLoader
|
|
anchors.fill: parent
|
|
anchors.margins: 1
|
|
active: previewArea.childUuid !== "" && root.visible
|
|
sourceComponent: PipeWireThumbnail {
|
|
windowUuid: previewArea.childUuid
|
|
}
|
|
}
|
|
|
|
Kirigami.Icon {
|
|
anchors.centerIn: parent
|
|
width: Kirigami.Units.iconSizes.large
|
|
height: width
|
|
source: taskCard.model.decoration
|
|
visible: !thumbnailLoader.item || !thumbnailLoader.item.hasThumbnail
|
|
}
|
|
|
|
Rectangle {
|
|
anchors.left: parent.left
|
|
anchors.right: parent.right
|
|
anchors.bottom: parent.bottom
|
|
height: titleLabel.implicitHeight + Kirigami.Units.smallSpacing
|
|
radius: Kirigami.Units.cornerRadius
|
|
color: Qt.rgba(0, 0, 0, 0.48)
|
|
visible: taskCard.previewCount > 1
|
|
|
|
PC3.Label {
|
|
id: titleLabel
|
|
anchors.left: parent.left
|
|
anchors.right: parent.right
|
|
anchors.verticalCenter: parent.verticalCenter
|
|
anchors.margins: Kirigami.Units.smallSpacing
|
|
text: taskCard.titleForPreview(previewArea.index)
|
|
elide: Text.ElideRight
|
|
maximumLineCount: 1
|
|
font.pointSize: Kirigami.Theme.defaultFont.pointSize * 0.75
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
RowLayout {
|
|
Layout.fillWidth: true
|
|
spacing: Kirigami.Units.smallSpacing
|
|
|
|
Kirigami.Icon {
|
|
Layout.preferredWidth: Kirigami.Units.iconSizes.smallMedium
|
|
Layout.preferredHeight: Layout.preferredWidth
|
|
source: taskCard.model.decoration
|
|
}
|
|
|
|
ColumnLayout {
|
|
Layout.fillWidth: true
|
|
spacing: 0
|
|
|
|
PC3.Label {
|
|
Layout.fillWidth: true
|
|
text: taskCard.model.display || ""
|
|
font.weight: taskCard.activeTask ? Font.Medium : Font.Normal
|
|
elide: Text.ElideRight
|
|
maximumLineCount: 1
|
|
}
|
|
|
|
Row {
|
|
spacing: Kirigami.Units.smallSpacing
|
|
|
|
PC3.Label {
|
|
text: taskCard.activeTask ? i18n("Active") : taskCard.minimizedTask ? i18n("Minimized") : i18n("Open")
|
|
opacity: 0.65
|
|
font.pointSize: Kirigami.Theme.defaultFont.pointSize * 0.75
|
|
}
|
|
|
|
PC3.Label {
|
|
visible: taskCard.maximizedTask
|
|
text: i18n("Maximized")
|
|
opacity: 0.65
|
|
font.pointSize: Kirigami.Theme.defaultFont.pointSize * 0.75
|
|
}
|
|
|
|
PC3.Label {
|
|
visible: taskCard.winIds.length > 1
|
|
text: i18np("%1 window", "%1 windows", taskCard.winIds.length)
|
|
opacity: 0.65
|
|
font.pointSize: Kirigami.Theme.defaultFont.pointSize * 0.75
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
RowLayout {
|
|
Layout.fillWidth: true
|
|
spacing: Kirigami.Units.smallSpacing
|
|
|
|
Item { Layout.fillWidth: true }
|
|
|
|
RunningAppsPanelButton {
|
|
iconName: taskCard.pinned ? "emblem-favorite" : "window-pin"
|
|
toolTipText: taskCard.pinned ? i18n("Pinned") : i18n("Pin to Dock")
|
|
checked: taskCard.pinned
|
|
enabled: taskCard.storageId !== "" && !taskCard.pinned && !root.folio.FolioSettings.lockLayout
|
|
onTriggered: root.folio.FavouritesModel.addApplication(taskCard.storageId)
|
|
}
|
|
|
|
RunningAppsPanelButton {
|
|
iconName: taskCard.minimizedTask ? "window-restore" : "window-minimize"
|
|
toolTipText: taskCard.minimizedTask ? i18n("Restore") : i18n("Minimize")
|
|
onTriggered: tasksModel.requestToggleMinimized(taskCard.modelIndex)
|
|
}
|
|
|
|
RunningAppsPanelButton {
|
|
iconName: taskCard.maximizedTask ? "window-restore" : "window-maximize"
|
|
toolTipText: taskCard.maximizedTask ? i18n("Restore") : i18n("Maximize")
|
|
enabled: !taskCard.groupTask
|
|
onTriggered: {
|
|
if (taskCard.canRequestDynamicTiling) {
|
|
ShellSettings.Settings.requestDynamicTilingWindowAction(taskCard.windowId, "maximize-toggle")
|
|
return
|
|
}
|
|
tasksModel.requestToggleMaximized(taskCard.modelIndex)
|
|
}
|
|
}
|
|
|
|
RunningAppsPanelButton {
|
|
iconName: "window-close"
|
|
toolTipText: taskCard.winIds.length > 1 ? i18n("Close All") : i18n("Close")
|
|
onTriggered: tasksModel.requestClose(taskCard.modelIndex)
|
|
}
|
|
}
|
|
}
|
|
|
|
Rectangle {
|
|
anchors.fill: parent
|
|
radius: Kirigami.Units.cornerRadius
|
|
visible: taskCard.pendingMove
|
|
color: root.mixColor(Kirigami.Theme.backgroundColor, Kirigami.Theme.highlightColor, 0.18)
|
|
border.width: 1
|
|
border.pixelAligned: false
|
|
border.color: root.mixColor(Kirigami.Theme.backgroundColor, Kirigami.Theme.highlightColor, 0.55)
|
|
|
|
PC3.Label {
|
|
anchors.centerIn: parent
|
|
width: parent.width - Kirigami.Units.gridUnit
|
|
text: i18n("Moving to %1", root.pendingMoveTargetName)
|
|
horizontalAlignment: Text.AlignHCenter
|
|
elide: Text.ElideRight
|
|
font.weight: Font.Medium
|
|
color: Kirigami.Theme.highlightColor
|
|
}
|
|
}
|
|
}
|
|
|
|
PC3.ScrollBar.vertical: PC3.ScrollBar {
|
|
interactive: true
|
|
enabled: taskGrid.contentHeight > taskGrid.height
|
|
implicitWidth: Kirigami.Units.smallSpacing
|
|
}
|
|
|
|
PC3.Label {
|
|
anchors.centerIn: parent
|
|
width: parent.width - Kirigami.Units.gridUnit * 2
|
|
visible: taskGrid.count === 0
|
|
text: i18n("No windows on this desktop")
|
|
horizontalAlignment: Text.AlignHCenter
|
|
opacity: 0.65
|
|
wrapMode: Text.WordWrap
|
|
}
|
|
}
|
|
}
|
|
}
|