mirror of
https://github.com/AvengeMedia/DankMaterialShell.git
synced 2026-10-21 18:54:01 -04:00
160 lines
5.3 KiB
QML
160 lines
5.3 KiB
QML
pragma Singleton
|
|
pragma ComponentBehavior: Bound
|
|
|
|
import QtQuick
|
|
import Qt.labs.folderlistmodel
|
|
import Quickshell
|
|
import Quickshell.Io
|
|
import qs.Common
|
|
|
|
Singleton {
|
|
id: root
|
|
|
|
readonly property string _homeDir: Quickshell.env("HOME") || ""
|
|
readonly property string _xdgDataHome: Quickshell.env("XDG_DATA_HOME") || (_homeDir + "/.local/share")
|
|
readonly property string trashFilesDir: _xdgDataHome + "/Trash/files"
|
|
|
|
readonly property bool monitoring: SettingsData.dockConfigs.some(config => config.showTrash && (config.enabled || config.openOnOverview))
|
|
|
|
property int count: 0
|
|
readonly property bool isEmpty: count === 0
|
|
|
|
property var availableFileManagers: ["default"]
|
|
property bool _fileManagersDetected: false
|
|
property var _pendingOpenOptions: null
|
|
property string defaultFileManagerLabel: "default (xdg-open)"
|
|
|
|
signal emptyTrashConfirmRequested(int itemCount)
|
|
|
|
onMonitoringChanged: {
|
|
if (!monitoring) {
|
|
count = 0;
|
|
return;
|
|
}
|
|
refreshCount();
|
|
}
|
|
|
|
Loader {
|
|
id: homeTrashWatch
|
|
active: root.monitoring
|
|
sourceComponent: FolderListModel {
|
|
folder: "file://" + root.trashFilesDir
|
|
showDirs: true
|
|
showFiles: true
|
|
showHidden: true
|
|
showDotAndDotDot: false
|
|
sortField: FolderListModel.Name
|
|
nameFilters: ["*"]
|
|
onCountChanged: root.refreshCount()
|
|
}
|
|
}
|
|
|
|
Process {
|
|
id: detectProc
|
|
running: false
|
|
command: ["sh", "-c", "for fm in nautilus thunar dolphin nemo caja pcmanfm pcmanfm-qt krusader; do command -v $fm >/dev/null 2>&1 && echo $fm; done"]
|
|
stdout: StdioCollector {
|
|
onStreamFinished: {
|
|
const detected = (text || "").split("\n").map(s => s.trim()).filter(s => s.length > 0);
|
|
root.availableFileManagers = ["default"].concat(detected).concat(["custom"]);
|
|
if (!root._pendingOpenOptions)
|
|
return;
|
|
const options = root._pendingOpenOptions;
|
|
root._pendingOpenOptions = null;
|
|
root.openTrash(options);
|
|
}
|
|
}
|
|
}
|
|
|
|
Component.onCompleted: {
|
|
Paths.trashHandler = (path, callback) => trashPath(path, callback);
|
|
refreshCount();
|
|
}
|
|
|
|
function detectFileManagers() {
|
|
if (_fileManagersDetected)
|
|
return;
|
|
_fileManagersDetected = true;
|
|
detectProc.running = true;
|
|
}
|
|
|
|
function refreshCount() {
|
|
if (!monitoring)
|
|
return;
|
|
Proc.runCommand("trash-count", [Proc.dmsBin, "trash", "count"], (output, exitCode) => {
|
|
const homeCount = homeTrashWatch.item?.count ?? 0;
|
|
if (exitCode !== 0) {
|
|
root.count = homeCount;
|
|
return;
|
|
}
|
|
const n = parseInt((output || "").trim(), 10);
|
|
root.count = isNaN(n) ? homeCount : n;
|
|
});
|
|
}
|
|
|
|
function trashPath(path, callback) {
|
|
if (!path) {
|
|
if (callback)
|
|
callback(false, "empty path");
|
|
return;
|
|
}
|
|
Proc.runCommand(null, [Proc.dmsBin, "trash", "put", path], (output, exitCode) => {
|
|
const ok = exitCode === 0;
|
|
if (!ok)
|
|
ToastService.showError(I18n.tr("Failed to move to trash"), path);
|
|
refreshCount();
|
|
if (callback)
|
|
callback(ok, output);
|
|
});
|
|
}
|
|
|
|
function openTrash(options) {
|
|
const choice = options?.trashFileManager || "default";
|
|
switch (choice) {
|
|
case "default":
|
|
Quickshell.execDetached(["xdg-open", "trash:///"]);
|
|
return;
|
|
case "custom":
|
|
openCustom(options);
|
|
return;
|
|
}
|
|
if (!_fileManagersDetected) {
|
|
_pendingOpenOptions = options;
|
|
detectFileManagers();
|
|
return;
|
|
}
|
|
if (availableFileManagers.indexOf(choice) < 0) {
|
|
ToastService.showInfo(I18n.tr("Cannot open trash: '%1' is not installed", "dock trash toast, %1 is the file manager name").arg(choice), I18n.tr("Pick a different file manager in Settings → Dock → Trash."));
|
|
return;
|
|
}
|
|
Quickshell.execDetached([choice, "trash:///"]);
|
|
}
|
|
|
|
function openCustom(options) {
|
|
const cmd = (options?.trashCustomCommand || "").trim();
|
|
if (!cmd) {
|
|
ToastService.showInfo(I18n.tr("Cannot open trash: no custom command set"), I18n.tr("Configure one in Settings → Dock → Trash."));
|
|
return;
|
|
}
|
|
Proc.runCommand(null, ["sh", "-c", cmd], (output, exitCode) => {
|
|
if (exitCode !== 0) {
|
|
ToastService.showError(I18n.tr("Trash command failed (exit %1)", "dock trash error toast, %1 is the exit code").arg(exitCode), I18n.tr("Check your custom command in Settings → Dock → Trash."));
|
|
}
|
|
}, 0, Proc.noTimeout);
|
|
}
|
|
|
|
function requestEmptyTrash() {
|
|
if (isEmpty)
|
|
return;
|
|
emptyTrashConfirmRequested(count);
|
|
}
|
|
|
|
function emptyTrash() {
|
|
Proc.runCommand("trash-empty", [Proc.dmsBin, "trash", "empty"], (output, exitCode) => {
|
|
if (exitCode !== 0)
|
|
ToastService.showError(I18n.tr("Failed to empty trash"), output || "");
|
|
refreshCount();
|
|
});
|
|
}
|
|
}
|