blob: f8e10d94406711c1c5a6cc708130c60ac9d7d3cc (
plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
|
pragma ComponentBehavior: Bound
import ".."
import qs.services
import qs.config
import qs.utils
import Quickshell
import Quickshell.Io
import Quickshell.Widgets
import QtQuick
import Qt.labs.folderlistmodel
GridView {
id: root
required property var dialog
property var mimes: ({})
clip: true
focus: true
Keys.onEscapePressed: root.currentIndex = -1
model: FolderListModel {
folder: {
let url = "file://";
if (root.dialog.cwd[0] === "Home")
url += `${Paths.strip(Paths.home)}/${root.dialog.cwd.slice(1).join("/")}`;
else
url += root.dialog.cwd.join("/");
return url;
}
onFolderChanged: root.currentIndex = -1
}
delegate: StyledRect {
id: item
required property int index
required property string fileName
required property string filePath
required property url fileUrl
required property string fileSuffix
required property bool fileIsDir
readonly property real nonAnimHeight: icon.implicitHeight + name.anchors.topMargin + name.implicitHeight + Appearance.padding.normal * 2
implicitWidth: Sizes.itemWidth
implicitHeight: nonAnimHeight
radius: Appearance.rounding.normal
color: root.currentItem === item ? Colours.palette.m3primary : "transparent"
z: root.currentItem === item || implicitHeight !== nonAnimHeight ? 1 : 0
clip: true
StateLayer {
color: root.currentItem === item ? Colours.palette.m3onPrimary : Colours.palette.m3onSurface
onDoubleClicked: {
if (item.fileIsDir)
root.dialog.cwd.push(item.fileName);
else
root.dialog.accepted(item.filePath);
}
function onClicked(): void {
root.currentIndex = item.index;
}
}
IconImage {
id: icon
anchors.horizontalCenter: parent.horizontalCenter
anchors.top: parent.top
anchors.topMargin: Appearance.spacing.normal
asynchronous: true
implicitSize: Sizes.itemWidth - Appearance.padding.normal * 2
source: {
const mime = root.mimes[item.fileSuffix];
if (mime?.startsWith("image-"))
return item.fileUrl;
return Quickshell.iconPath(item.fileIsDir ? "inode-directory" : root.mimes[item.fileSuffix] ?? "application-x-zerosize", "image-missing");
}
onStatusChanged: {
if (status === Image.Error)
source = Quickshell.iconPath("error");
}
}
StyledText {
id: name
anchors.left: parent.left
anchors.right: parent.right
anchors.top: icon.bottom
anchors.topMargin: Appearance.spacing.small
anchors.margins: Appearance.padding.normal
horizontalAlignment: Text.AlignHCenter
text: item.fileName
color: root.currentItem === item ? Colours.palette.m3onPrimary : Colours.palette.m3onSurface
elide: root.currentItem === item ? Text.ElideNone : Text.ElideRight
wrapMode: root.currentItem === item ? Text.WrapAtWordBoundaryOrAnywhere : Text.NoWrap
}
Behavior on implicitHeight {
NumberAnimation {
duration: Appearance.anim.durations.normal
easing.type: Easing.BezierSpline
easing.bezierCurve: Appearance.anim.curves.standard
}
}
}
FileView {
path: "/etc/mime.types"
onLoaded: {
root.mimes = text().split("\n").filter(l => !l.startsWith("#")).reduce((mimes, line) => {
const [type, ext] = line.split(/\s+/);
if (ext)
mimes[ext] = type.replace("/", "-");
return mimes;
}, {});
}
}
}
|