Skip to content

Commit 6b42979

Browse files
committed
Update workspace panels
1 parent 5fea2b4 commit 6b42979

File tree

13 files changed

+672
-451
lines changed

13 files changed

+672
-451
lines changed
Lines changed: 284 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,284 @@
1+
import QtQml
2+
import QtQml.Models
3+
import QtQuick
4+
import QtQuick.Controls
5+
import QtQuick.Layouts
6+
import QtQuick.Controls.impl
7+
8+
import SVSCraft
9+
import SVSCraft.UIComponents
10+
import SVSCraft.UIComponents.impl
11+
12+
import DiffScope.UIShell
13+
14+
Item {
15+
id: view
16+
17+
enum DisplayMode {
18+
Grid,
19+
List
20+
}
21+
22+
property string searchText: ""
23+
property var filesModel: null
24+
property int displayMode: FileView.List
25+
property bool newFileActionEnabled: false
26+
property string emptyTip: ""
27+
28+
readonly property var newFilePseudoElement: ({
29+
name: qsTr("New project"),
30+
path: "",
31+
lastModifiedText: "",
32+
thumbnail: "",
33+
icon: "",
34+
})
35+
36+
signal newFileRequested()
37+
signal openFileRequested(int index)
38+
signal contextMenuRequested(int index)
39+
40+
component CellButton: Button {
41+
id: cell
42+
required property int index
43+
required property var modelData
44+
flat: true
45+
padding: 4
46+
Accessible.name: modelData.name + "\n" + modelData.lastModifiedText
47+
Accessible.description: modelData.path
48+
DescriptiveText.toolTip: modelData.path
49+
DescriptiveText.activated: !modelData.newFile && hovered
50+
contentItem: ColumnLayout {
51+
id: cellContent
52+
spacing: 4
53+
Item {
54+
implicitWidth: 160
55+
implicitHeight: 120
56+
Layout.alignment: Qt.AlignHCenter
57+
Rectangle {
58+
anchors.fill: parent
59+
color: Theme.backgroundTertiaryColor
60+
ColorImage {
61+
visible: cell.index === -1
62+
width: 80
63+
height: 80
64+
anchors.centerIn: parent
65+
source: "image://fluent-system-icons/document_add?size=48&style=regular"
66+
sourceSize.width: 80
67+
sourceSize.height: 80
68+
color: Theme.foregroundSecondaryColor
69+
}
70+
// fallback display icon as thumbnail
71+
ColorImage {
72+
width: 80
73+
height: 80
74+
anchors.centerIn: parent
75+
source: cell.modelData.icon
76+
color: cell.modelData.colorize ? Theme.foregroundSecondaryColor : "transparent"
77+
sourceSize.width: 80
78+
sourceSize.height: 80
79+
}
80+
}
81+
Image {
82+
anchors.fill: parent
83+
fillMode: Image.PreserveAspectCrop
84+
source: cell.modelData.thumbnail
85+
cache: false
86+
mipmap: true
87+
}
88+
Rectangle {
89+
anchors.fill: parent
90+
color: "transparent"
91+
border.width: 1
92+
border.color: Theme.borderColor
93+
}
94+
}
95+
Label {
96+
id: nameLabel
97+
Layout.alignment: Qt.AlignHCenter
98+
Layout.maximumWidth: 160
99+
text: cell.modelData.name
100+
elide: Text.ElideMiddle
101+
}
102+
Label {
103+
id: lastModifiedTextLabel
104+
Layout.alignment: Qt.AlignHCenter
105+
Layout.maximumWidth: 160
106+
text: cell.modelData.lastModifiedText
107+
elide: Text.ElideMiddle
108+
ThemedItem.foregroundLevel: SVS.FL_Secondary
109+
}
110+
}
111+
TapHandler {
112+
acceptedButtons: Qt.RightButton
113+
enabled: cell.index !== -1
114+
onSingleTapped: view.contextMenuRequested(filesProxyModel.mapIndexToSource(cell.index))
115+
}
116+
Keys.onMenuPressed: view.contextMenuRequested(filesProxyModel.mapIndexToSource(cell.index))
117+
onClicked: () => {
118+
if (cell.index === -1) {
119+
view.newFileRequested()
120+
} else {
121+
view.openFileRequested(filesProxyModel.mapIndexToSource(cell.index))
122+
}
123+
}
124+
}
125+
component ListItemButton: Button {
126+
id: cell
127+
required property int index
128+
required property var modelData
129+
property bool recovery: false
130+
flat: true
131+
padding: 4
132+
Accessible.name: modelData.name + "\n" + modelData.lastModifiedText
133+
Accessible.description: modelData.path
134+
DescriptiveText.toolTip: modelData.path
135+
DescriptiveText.activated: !modelData.newFile && hovered
136+
contentItem: RowLayout {
137+
id: cellContent
138+
spacing: 4
139+
Item {
140+
implicitWidth: 48
141+
implicitHeight: 48
142+
Layout.alignment: Qt.AlignHCenter
143+
ColorImage {
144+
visible: cell.index === -1
145+
anchors.fill: parent
146+
source: "image://fluent-system-icons/document_add?size=48&style=regular"
147+
color: Theme.foregroundSecondaryColor
148+
sourceSize.width: 48
149+
sourceSize.height: 48
150+
}
151+
ColorImage {
152+
anchors.fill: parent
153+
source: cell.modelData.icon
154+
color: cell.modelData.colorize ? Theme.foregroundSecondaryColor : "transparent"
155+
sourceSize.width: 48
156+
sourceSize.height: 48
157+
}
158+
}
159+
ColumnLayout {
160+
spacing: 4
161+
Layout.fillWidth: true
162+
RowLayout {
163+
spacing: 4
164+
Label {
165+
Layout.fillWidth: true
166+
text: cell.modelData.name
167+
elide: Text.ElideMiddle
168+
}
169+
Label {
170+
text: cell.modelData.lastModifiedText
171+
elide: Text.ElideMiddle
172+
ThemedItem.foregroundLevel: SVS.FL_Secondary
173+
}
174+
}
175+
Label {
176+
visible: cell.modelData.path.length !== 0
177+
text: cell.modelData.path
178+
elide: Text.ElideMiddle
179+
ThemedItem.foregroundLevel: SVS.FL_Secondary
180+
}
181+
}
182+
}
183+
TapHandler {
184+
acceptedButtons: Qt.RightButton
185+
enabled: cell.index !== -1
186+
onSingleTapped: view.contextMenuRequested(filesProxyModel.mapIndexToSource(cell.index))
187+
}
188+
Keys.onMenuPressed: view.contextMenuRequested(filesProxyModel.mapIndexToSource(cell.index))
189+
onClicked: () => {
190+
if (cell.index === -1) {
191+
view.newFileRequested()
192+
} else {
193+
view.openFileRequested(filesProxyModel.mapIndexToSource(cell.index))
194+
}
195+
}
196+
}
197+
198+
RecentFilesProxyModel {
199+
id: filesProxyModel
200+
sourceModel: view.filesModel
201+
filterRole: USDef.RF_NameRole
202+
filterCaseSensitivity: Qt.CaseInsensitive
203+
property string _filterRegularExpression: searchTextField.text
204+
on_FilterRegularExpressionChanged: setFilterRegularExpression(_filterRegularExpression)
205+
}
206+
207+
ColumnLayout {
208+
id: recentFilesLayout
209+
spacing: 16
210+
anchors.fill: parent
211+
Item {
212+
Layout.fillWidth: true
213+
Layout.fillHeight: true
214+
visible: filesProxyModel.count === 0 && !(view.newFileActionEnabled && view.searchText.length === 0)
215+
Label {
216+
text: qsTr("No result found")
217+
ThemedItem.foregroundLevel: SVS.FL_Secondary
218+
anchors.top: parent.top
219+
anchors.left: parent.left
220+
anchors.right: parent.right
221+
horizontalAlignment: Text.AlignHCenter
222+
wrapMode: Text.Wrap
223+
visible: view.searchText.length !== 0
224+
}
225+
Label {
226+
text: view.emptyTip
227+
ThemedItem.foregroundLevel: SVS.FL_Secondary
228+
anchors.top: parent.top
229+
anchors.left: parent.left
230+
anchors.right: parent.right
231+
horizontalAlignment: Text.AlignHCenter
232+
wrapMode: Text.Wrap
233+
visible: view.searchText.length === 0
234+
}
235+
}
236+
ScrollView {
237+
id: fileGridScrollView
238+
visible: view.displayMode === FileView.Grid
239+
Layout.fillWidth: true
240+
Layout.fillHeight: true
241+
GridLayout {
242+
id: fileGridLayout
243+
rowSpacing: 16
244+
columnSpacing: (fileGridScrollView.width - 172 * columns) / (columns - 1)
245+
width: parent.width
246+
columns: Math.floor((fileGridScrollView.width + 8) / (172 + 8))
247+
CellButton {
248+
index: -1
249+
modelData: view.newFilePseudoElement
250+
visible: view.searchText.length === 0 && view.newFileActionEnabled
251+
}
252+
Repeater {
253+
model: filesProxyModel
254+
CellButton {
255+
}
256+
}
257+
}
258+
}
259+
ScrollView {
260+
id: fileListScrollView
261+
visible: view.displayMode === FileView.List
262+
Layout.fillWidth: true
263+
Layout.fillHeight: true
264+
ColumnLayout {
265+
id: fileListLayout
266+
spacing: 4
267+
implicitWidth: fileListScrollView.width
268+
width: fileListScrollView.width
269+
ListItemButton {
270+
Layout.fillWidth: true
271+
index: -1
272+
modelData: view.newFilePseudoElement
273+
visible: view.searchText.length === 0 && view.newFileActionEnabled
274+
}
275+
Repeater {
276+
model: filesProxyModel
277+
ListItemButton {
278+
Layout.fillWidth: true
279+
}
280+
}
281+
}
282+
}
283+
}
284+
}

0 commit comments

Comments
 (0)