Skip to content

Commit 5371f9e

Browse files
authored
Merge pull request #2975 from alicevision/dev/gallery_list_view
[ui] Add list view in gallery
2 parents 377305b + 6a3fc60 commit 5371f9e

File tree

8 files changed

+821
-382
lines changed

8 files changed

+821
-382
lines changed

meshroom/ui/qml/Controls/SearchBar.qml

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,7 @@ FocusScope {
3131
Keys.forwardTo: [field]
3232

3333
function forceActiveFocus() {
34+
root.isVisible = true
3435
field.forceActiveFocus()
3536
}
3637

@@ -46,7 +47,7 @@ FocusScope {
4647
text: MaterialIcons.search
4748

4849
onClicked: {
49-
isVisible = !root.isVisible
50+
root.isVisible = !root.isVisible
5051
// Set Focus on the Text Field
5152
field.focus = field.visible
5253
}
@@ -73,6 +74,9 @@ FocusScope {
7374
if ((event.key == Qt.Key_Return || event.key == Qt.Key_Enter)) {
7475
event.accepted = true
7576
root.accepted()
77+
} else if (event.key == Qt.Key_Escape) {
78+
root.isVisible = false
79+
field.focus = false
7680
}
7781
}
7882

meshroom/ui/qml/Homepage.qml

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -271,7 +271,7 @@ Page {
271271
}
272272

273273
GridView {
274-
id: gridView
274+
id: homepageGridView
275275
visible: tabPanel.currentTab === 1
276276
anchors.fill: parent
277277
anchors.topMargin: cellHeight * 0.1
@@ -309,21 +309,21 @@ Page {
309309
delegate: Column {
310310
id: projectContent
311311

312-
width: gridView.cellWidth
313-
height: gridView.cellHeight
312+
width: homepageGridView.cellWidth
313+
height: homepageGridView.cellHeight
314314

315315
property var source: modelData["thumbnail"] ? Filepath.stringToUrl(modelData["thumbnail"]) : ""
316316

317317
function updateThumbnail() {
318-
thumbnail.source = ThumbnailCache.thumbnail(source, gridView.currentIndex)
318+
thumbnail.source = ThumbnailCache.thumbnail(source, homepageGridView.currentIndex)
319319
}
320320

321321
onSourceChanged: updateThumbnail()
322322

323323
Button {
324324
id: projectDelegate
325-
height: gridView.cellHeight * 0.95 - project.height
326-
width: gridView.cellWidth * 0.9
325+
height: homepageGridView.cellHeight * 0.95 - project.height
326+
width: homepageGridView.cellWidth * 0.9
327327

328328
// Handle case where the file is missing
329329
property bool fileExists: modelData["status"] != 0
@@ -408,7 +408,7 @@ Page {
408408

409409
BusyIndicator {
410410
anchors.centerIn: parent
411-
running: gridView.visible && modelData["thumbnail"] && thumbnail.status != Image.Ready
411+
running: homepageGridView.visible && modelData["thumbnail"] && thumbnail.status != Image.Ready
412412
visible: running
413413
}
414414

meshroom/ui/qml/ImageGallery/ImageDelegate.qml

Lines changed: 147 additions & 52 deletions
Original file line numberDiff line numberDiff line change
@@ -13,18 +13,26 @@ Item {
1313

1414
property variant viewpoint
1515
property int cellID: -1
16-
property bool isCurrentItem: false
1716
property alias source: _viewpoint.source
1817
property alias metadata: _viewpoint.metadata
1918
property bool readOnly: false
2019
property bool displayViewId: false
20+
property int layoutMode: 0 // 0: grid, 1: list
21+
22+
property variant parentModel
23+
property int selectedIndex: parentModel ? parentModel.selectedIndex : -1
24+
property bool isCurrentItem: cellID >= 0 && cellID === selectedIndex
2125

2226
signal pressed(var mouse)
2327
signal removeRequest()
2428
signal removeAllImagesRequest()
2529

2630
default property alias children: imageMA.children
2731

32+
// Internal properties to hold thumbnail source & loading status
33+
property url thumbnailSource: ""
34+
property int thumbnailStatus: Image.Null
35+
2836
// Retrieve viewpoints inner data
2937
QtObject {
3038
id: _viewpoint
@@ -37,7 +45,7 @@ Item {
3745
// Update thumbnail location
3846
// Can be called from the GridView when a new thumbnail has been written on disk
3947
function updateThumbnail() {
40-
thumbnail.source = ThumbnailCache.thumbnail(root.source, root.cellID)
48+
root.thumbnailSource = ThumbnailCache.thumbnail(root.source, root.cellID)
4149
}
4250
onSourceChanged: {
4351
updateThumbnail()
@@ -49,7 +57,7 @@ Item {
4957
interval: 5000
5058
running: true
5159
onTriggered: {
52-
if (thumbnail.status == Image.Null) {
60+
if (root.thumbnailStatus == Image.Null) {
5361
updateThumbnail()
5462
}
5563
}
@@ -109,64 +117,151 @@ Item {
109117
}
110118
}
111119

112-
ColumnLayout {
120+
// Switch from the grid component (column layout) to the list component (row layout)
121+
Loader {
122+
id: itemDelegate
113123
anchors.fill: parent
114-
spacing: 0
115-
116-
// Image thumbnail and background
117-
Rectangle {
118-
id: imageBackground
119-
color: Qt.darker(imageLabel.palette.base, 1.15)
120-
Layout.fillHeight: true
121-
Layout.fillWidth: true
122-
border.color: isCurrentItem ? imageLabel.palette.highlight : Qt.darker(imageLabel.palette.highlight)
123-
border.width: imageMA.containsMouse || root.isCurrentItem ? 2 : 0
124-
Image {
125-
id: thumbnail
126-
anchors.fill: parent
127-
anchors.margins: 4
128-
asynchronous: true
129-
autoTransform: true
130-
fillMode: Image.PreserveAspectFit
131-
smooth: false
132-
cache: false
124+
sourceComponent: root.layoutMode === 0 ? gridDelegate : listDelegate
125+
}
126+
127+
Component {
128+
id: gridDelegate
129+
ColumnLayout {
130+
anchors.fill: parent
131+
spacing: 0
132+
133+
// Image thumbnail and background
134+
Rectangle {
135+
color: Qt.darker(grid_imageLabel.palette.base, 1.15)
136+
Layout.fillHeight: true
137+
Layout.fillWidth: true
138+
border.color: isCurrentItem ? grid_imageLabel.palette.highlight : Qt.darker(grid_imageLabel.palette.highlight)
139+
border.width: imageMA.containsMouse || root.isCurrentItem ? 2 : 0
140+
Image {
141+
id: grid_thumbnail
142+
anchors.fill: parent
143+
anchors.margins: 4
144+
source: root.thumbnailSource
145+
asynchronous: true
146+
autoTransform: true
147+
fillMode: Image.PreserveAspectFit
148+
smooth: false
149+
cache: false
150+
onStatusChanged: root.thumbnailStatus = status
151+
}
152+
BusyIndicator {
153+
anchors.centerIn: parent
154+
running: grid_thumbnail.status != Image.Ready
155+
}
133156
}
134-
BusyIndicator {
135-
anchors.centerIn: parent
136-
running: thumbnail.status != Image.Ready
157+
158+
// Image basename
159+
Label {
160+
id: grid_imageLabel
161+
Layout.fillWidth: true
162+
padding: 2
163+
font.pointSize: 8
164+
elide: Text.ElideMiddle
165+
horizontalAlignment: Text.AlignHCenter
166+
text: Filepath.basename(root.source)
167+
background: Rectangle {
168+
color: root.isCurrentItem ? parent.palette.highlight : "transparent"
169+
}
137170
}
138-
}
139171

140-
// Image basename
141-
Label {
142-
id: imageLabel
143-
Layout.fillWidth: true
144-
padding: 2
145-
font.pointSize: 8
146-
elide: Text.ElideMiddle
147-
horizontalAlignment: Text.AlignHCenter
148-
text: Filepath.basename(root.source)
149-
background: Rectangle {
150-
color: root.isCurrentItem ? parent.palette.highlight : "transparent"
172+
// Image viewId
173+
Loader {
174+
active: displayViewId
175+
Layout.fillWidth: true
176+
visible: active
177+
sourceComponent: Label {
178+
padding: grid_imageLabel.padding
179+
font.pointSize: grid_imageLabel.font.pointSize
180+
elide: grid_imageLabel.elide
181+
horizontalAlignment: grid_imageLabel.horizontalAlignment
182+
text: _viewpoint.viewId
183+
background: Rectangle {
184+
color: grid_imageLabel.background.color
185+
}
186+
}
151187
}
152188
}
189+
}
153190

154-
// Image viewId
155-
Loader {
156-
active: displayViewId
157-
Layout.fillWidth: true
158-
visible: active
159-
sourceComponent: Label {
160-
padding: imageLabel.padding
161-
font.pointSize: imageLabel.font.pointSize
162-
elide: imageLabel.elide
163-
horizontalAlignment: imageLabel.horizontalAlignment
164-
text: _viewpoint.viewId
165-
background: Rectangle {
166-
color: imageLabel.background.color
191+
Component {
192+
id: listDelegate
193+
RowLayout {
194+
anchors.fill: parent
195+
spacing: 4
196+
197+
// Image thumbnail and background
198+
Rectangle {
199+
color: Qt.darker(list_imageLabel.palette.base, 1.15)
200+
Layout.fillHeight: true
201+
Layout.preferredWidth: 100
202+
203+
border.color: isCurrentItem ? list_imageLabel.palette.highlight : Qt.darker(list_imageLabel.palette.highlight)
204+
border.width: imageMA.containsMouse || root.isCurrentItem ? 2 : 0
205+
206+
Image {
207+
id: list_thumbnail
208+
anchors.fill: parent
209+
anchors.margins: 4
210+
source: root.thumbnailSource
211+
asynchronous: true
212+
autoTransform: true
213+
fillMode: Image.PreserveAspectFit
214+
smooth: false
215+
cache: false
216+
onStatusChanged: root.thumbnailStatus = status
217+
}
218+
BusyIndicator {
219+
anchors.centerIn: parent
220+
running: list_thumbnail.status != Image.Ready
221+
}
222+
}
223+
224+
ColumnLayout {
225+
Layout.fillWidth: true
226+
Layout.fillHeight: true
227+
spacing: 0
228+
229+
// Image basename
230+
Label {
231+
id: list_imageLabel
232+
Layout.fillWidth: true
233+
Layout.fillHeight: true
234+
padding: 4
235+
font.pointSize: 8
236+
elide: Text.ElideMiddle
237+
horizontalAlignment: Text.AlignLeft
238+
verticalAlignment: Text.AlignVCenter
239+
text: Filepath.basename(root.source)
240+
background: Rectangle {
241+
color: root.isCurrentItem ? parent.palette.highlight : "transparent"
242+
}
243+
}
244+
245+
// Image viewId
246+
Loader {
247+
active: root.displayViewId
248+
Layout.fillWidth: true
249+
Layout.fillHeight: active
250+
visible: active
251+
sourceComponent: Label {
252+
padding: list_imageLabel.padding
253+
font.pointSize: list_imageLabel.font.pointSize
254+
elide: list_imageLabel.elide
255+
horizontalAlignment: list_imageLabel.horizontalAlignment
256+
verticalAlignment: list_imageLabel.verticalAlignment
257+
text: _viewpoint.viewId
258+
background: Rectangle {
259+
color: list_imageLabel.background.color
260+
}
261+
}
167262
}
168263
}
169264
}
170265
}
171266
}
172-
}
267+
}

0 commit comments

Comments
 (0)