mirror of
https://invent.kde.org/marcoa/shift-shell.git
synced 2026-06-11 00:47:22 +00:00
Add trash button to convergence dock
Show a trash icon to the left of the Overview button in convergence
mode. The icon toggles between user-trash and user-trash-full by
watching ~/.local/share/Trash/files via FolderListModel.
Left-click opens the trash in the default file manager via
Qt.openUrlExternally("trash:/"), making the feature file-manager-
agnostic. Right-click offers "Open Trash" and "Empty Trash"; the
latter shows a confirmation dialog before invoking KIO.Trash via
D-Bus.
The right wing of the virtual-desktop pager shifts left to make
room for the trash button.
This commit is contained in:
parent
a0bad0507f
commit
6d79f8ed05
3 changed files with 130 additions and 2 deletions
|
|
@ -108,4 +108,13 @@ void HomeScreen::activateVirtualDesktop(const QVariant &desktop) const
|
|||
virtualDesktopInfo.requestActivate(desktop);
|
||||
}
|
||||
|
||||
void HomeScreen::emptyTrash() const
|
||||
{
|
||||
QDBusMessage message = QDBusMessage::createMethodCall(QStringLiteral("org.kde.kio.trash"),
|
||||
QStringLiteral("/trash"),
|
||||
QStringLiteral("org.kde.KIO.Trash"),
|
||||
QStringLiteral("emptyTrash"));
|
||||
QDBusConnection::sessionBus().send(message);
|
||||
}
|
||||
|
||||
#include "homescreen.moc"
|
||||
|
|
|
|||
|
|
@ -51,6 +51,7 @@ public:
|
|||
|
||||
Q_INVOKABLE void triggerOverview() const;
|
||||
Q_INVOKABLE void activateVirtualDesktop(const QVariant &desktop) const;
|
||||
Q_INVOKABLE void emptyTrash() const;
|
||||
|
||||
FolioSettings *folioSettings();
|
||||
HomeScreenState *homeScreenState();
|
||||
|
|
|
|||
|
|
@ -4,6 +4,8 @@
|
|||
import QtQuick 2.12
|
||||
import QtQuick.Window 2.12
|
||||
import QtQuick.Layouts 1.1
|
||||
import QtCore
|
||||
import Qt.labs.folderlistmodel
|
||||
|
||||
import org.kde.plasma.components 3.0 as PC3
|
||||
import org.kde.plasma.private.mobileshell.state as MobileShellState
|
||||
|
|
@ -91,6 +93,7 @@ MouseArea {
|
|||
readonly property real pagerButtonWidth: showPager ? Math.min(root.height, Kirigami.Units.gridUnit * 2.5) : 0
|
||||
readonly property int pagerLeftCount: showPager ? Math.ceil(virtualDesktopInfo.numberOfDesktops / 2) : 0
|
||||
readonly property int pagerRightCount: showPager ? virtualDesktopInfo.numberOfDesktops - pagerLeftCount : 0
|
||||
readonly property real trashButtonWidth: convergenceMode ? root.height : 0
|
||||
|
||||
function pagerDesktopName(index) {
|
||||
let names = virtualDesktopInfo.desktopNames
|
||||
|
|
@ -109,7 +112,7 @@ MouseArea {
|
|||
return (ids && i < ids.length) ? String(ids[i]) : ""
|
||||
}
|
||||
for (let i = 0; i < pagerRightCount; ++i) {
|
||||
let bx = root.width - navButtonWidth - (pagerRightCount - i) * pagerButtonWidth
|
||||
let bx = root.width - navButtonWidth - root.trashButtonWidth - (pagerRightCount - i) * pagerButtonWidth
|
||||
if (x >= bx && x < bx + pagerButtonWidth) {
|
||||
let di = pagerLeftCount + i
|
||||
return (ids && di < ids.length) ? String(ids[di]) : ""
|
||||
|
|
@ -371,7 +374,7 @@ MouseArea {
|
|||
return root.pagerButtonDesktopAt(cx) === desktopId
|
||||
}
|
||||
|
||||
x: root.width - root.navButtonWidth - (root.pagerRightCount - index) * root.pagerButtonWidth
|
||||
x: root.width - root.navButtonWidth - root.trashButtonWidth - (root.pagerRightCount - index) * root.pagerButtonWidth
|
||||
y: 0
|
||||
width: root.pagerButtonWidth
|
||||
height: root.height
|
||||
|
|
@ -413,6 +416,121 @@ MouseArea {
|
|||
}
|
||||
}
|
||||
|
||||
// ---- Trash button (convergence mode, sits between the right pager wing and the Overview button) ----
|
||||
|
||||
// Watches ~/.local/share/Trash/files to detect empty/full state.
|
||||
// FolderListModel reacts to directory changes automatically.
|
||||
FolderListModel {
|
||||
id: trashFilesModel
|
||||
folder: StandardPaths.writableLocation(StandardPaths.HomeLocation) + "/.local/share/Trash/files"
|
||||
showFiles: true
|
||||
showDirs: true
|
||||
showDotAndDotDot: false
|
||||
}
|
||||
|
||||
// Confirmation dialog for "Empty Trash" — parented to the homescreen so it
|
||||
// is sized correctly and floats above all dock content.
|
||||
Loader {
|
||||
id: emptyTrashDialogLoader
|
||||
parent: root.homeScreen
|
||||
anchors.fill: parent
|
||||
active: false
|
||||
|
||||
function open() {
|
||||
active = true;
|
||||
item.open();
|
||||
}
|
||||
|
||||
sourceComponent: Kirigami.PromptDialog {
|
||||
title: i18n("Empty Trash")
|
||||
subtitle: i18n("Permanently delete all items in the trash? This action cannot be undone.")
|
||||
standardButtons: Kirigami.Dialog.Yes | Kirigami.Dialog.Cancel
|
||||
onAccepted: root.folio.emptyTrash()
|
||||
onClosed: emptyTrashDialogLoader.active = false
|
||||
}
|
||||
}
|
||||
|
||||
Rectangle {
|
||||
id: trashButton
|
||||
visible: root.convergenceMode
|
||||
activeFocusOnTab: root.convergenceMode
|
||||
x: root.width - root.navButtonWidth - root.trashButtonWidth
|
||||
y: 0
|
||||
width: root.trashButtonWidth
|
||||
height: root.height
|
||||
color: "transparent"
|
||||
|
||||
Accessible.role: Accessible.Button
|
||||
Accessible.name: i18n("Trash")
|
||||
Accessible.onPressAction: Qt.openUrlExternally("trash:/")
|
||||
|
||||
Keys.onReturnPressed: Qt.openUrlExternally("trash:/")
|
||||
Keys.onEnterPressed: Qt.openUrlExternally("trash:/")
|
||||
Keys.onSpacePressed: Qt.openUrlExternally("trash:/")
|
||||
|
||||
KeyboardHighlight {
|
||||
anchors.fill: parent
|
||||
visible: trashButton.activeFocus
|
||||
}
|
||||
|
||||
Rectangle {
|
||||
anchors.fill: parent
|
||||
anchors.margins: root.dockItemInset
|
||||
radius: Kirigami.Units.cornerRadius
|
||||
color: root.dockItemColor(trashMouseArea.containsPress, trashMouseArea.containsMouse, false)
|
||||
Behavior on color {
|
||||
ColorAnimation { duration: Kirigami.Units.shortDuration; easing.type: Easing.OutCubic }
|
||||
}
|
||||
}
|
||||
|
||||
Kirigami.Icon {
|
||||
anchors.centerIn: parent
|
||||
width: root.dockIconSize
|
||||
height: width
|
||||
source: trashFilesModel.count > 0 ? "user-trash-full" : "user-trash"
|
||||
active: trashMouseArea.containsMouse
|
||||
}
|
||||
|
||||
PC3.ToolTip {
|
||||
visible: trashMouseArea.containsMouse
|
||||
text: trashFilesModel.count > 0
|
||||
? i18np("Trash — 1 item", "Trash — %1 items", trashFilesModel.count)
|
||||
: i18n("Trash")
|
||||
}
|
||||
|
||||
MouseArea {
|
||||
id: trashMouseArea
|
||||
anchors.fill: parent
|
||||
hoverEnabled: true
|
||||
cursorShape: Qt.PointingHandCursor
|
||||
acceptedButtons: Qt.LeftButton | Qt.RightButton
|
||||
onClicked: (mouse) => {
|
||||
if (mouse.button === Qt.RightButton) {
|
||||
trashContextMenu.open()
|
||||
} else {
|
||||
Qt.openUrlExternally("trash:/")
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
PC3.Menu {
|
||||
id: trashContextMenu
|
||||
popupType: T.Popup.Window
|
||||
|
||||
PC3.MenuItem {
|
||||
icon.name: "folder-open"
|
||||
text: i18n("Open Trash")
|
||||
onTriggered: Qt.openUrlExternally("trash:/")
|
||||
}
|
||||
PC3.MenuItem {
|
||||
icon.name: "trash-empty"
|
||||
text: i18n("Empty Trash")
|
||||
enabled: trashFilesModel.count > 0
|
||||
onTriggered: emptyTrashDialogLoader.open()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
TaskManager.VirtualDesktopInfo {
|
||||
id: virtualDesktopInfo
|
||||
}
|
||||
|
|
|
|||
Loading…
Reference in a new issue