Skip to content

Commit 88d094c

Browse files
Merge pull request #3080 from alicevision/dev/highlightProject
[ui] Homepage: Highlight the pipeline or project that is being loaded
2 parents 0ee8481 + c394ebd commit 88d094c

1 file changed

Lines changed: 91 additions & 21 deletions

File tree

meshroom/ui/qml/Homepage.qml

Lines changed: 91 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -9,10 +9,41 @@ import Controls 1.0
99
Page {
1010
id: root
1111

12+
property bool isLoading: false
13+
14+
// Schedule an action to run after the current frame has been rendered and
15+
// displayed, so that visual feedback (highlight, spinner) is visible before
16+
// the UI thread is blocked by a heavy synchronous operation.
17+
// Uses _window (the ApplicationWindow id from main.qml) since root.window
18+
// is not reliably available for Page items inside a StackView.
19+
function executeAfterFrameRendered(action, params = undefined) {
20+
function onFrame() {
21+
_window.frameSwapped.disconnect(onFrame)
22+
if (params === undefined)
23+
action()
24+
else
25+
action(params)
26+
}
27+
_window.frameSwapped.connect(onFrame)
28+
}
29+
30+
function openProject(path) {
31+
mainStack.push("Application.qml")
32+
if (_currentScene.load(path)) {
33+
MeshroomApp.addRecentProjectFile(path)
34+
} else {
35+
root.isLoading = false
36+
homepageGridView.loadingIndex = -1
37+
}
38+
}
39+
1240
onVisibleChanged: {
1341
logo.playing = false
1442
if (visible) {
1543
logo.playing = true
44+
isLoading = false
45+
homepageGridView.loadingIndex = -1
46+
pipelinesListView.loadingIndex = -1
1647
}
1748
}
1849

@@ -242,6 +273,8 @@ Page {
242273
id: pipelinesListView
243274
visible: tabPanel.currentTab === 0
244275

276+
property int loadingIndex: -1
277+
245278
anchors.fill: parent
246279
anchors.margins: 10
247280

@@ -251,20 +284,44 @@ Page {
251284
id: pipelineDelegate
252285
padding: 10
253286
width: pipelinesListView.width
287+
enabled: !root.isLoading || index === pipelinesListView.loadingIndex
288+
opacity: (!root.isLoading || index === pipelinesListView.loadingIndex) ? 1.0 : 0.4
289+
290+
contentItem: RowLayout {
291+
Label {
292+
id: pipeline
293+
Layout.fillWidth: true
294+
horizontalAlignment: Text.AlignLeft
295+
verticalAlignment: Text.AlignVCenter
296+
text: modelData["name"]
297+
}
298+
BusyIndicator {
299+
Layout.preferredWidth: 24
300+
Layout.preferredHeight: 24
301+
running: index === pipelinesListView.loadingIndex && root.isLoading
302+
visible: running
303+
}
304+
}
254305

255-
contentItem: Label {
256-
id: pipeline
257-
horizontalAlignment: Text.AlignLeft
258-
verticalAlignment: Text.AlignVCenter
259-
text: modelData["name"]
306+
// Highlight overlay shown when this pipeline is being loaded
307+
Rectangle {
308+
anchors.fill: parent
309+
color: "transparent"
310+
border.color: palette.highlight
311+
border.width: 2
312+
visible: root.isLoading && index === pipelinesListView.loadingIndex
260313
}
261314

262315
Connections {
263316
target: pipelineDelegate
264317
function onClicked() {
265-
// Open pipeline
266-
mainStack.push("Application.qml")
267-
_currentScene.new(modelData["path"])
318+
root.isLoading = true
319+
pipelinesListView.loadingIndex = index
320+
let path = modelData["path"]
321+
root.executeAfterFrameRendered(function() {
322+
mainStack.push("Application.qml")
323+
_currentScene.new(path)
324+
})
268325
}
269326
}
270327
}
@@ -276,6 +333,8 @@ Page {
276333
anchors.fill: parent
277334
anchors.topMargin: cellHeight * 0.1
278335

336+
property int loadingIndex: -1
337+
279338
cellWidth: 195
280339
cellHeight: cellWidth
281340
anchors.margins: 10
@@ -311,6 +370,7 @@ Page {
311370

312371
width: homepageGridView.cellWidth
313372
height: homepageGridView.cellHeight
373+
opacity: (!root.isLoading || index === homepageGridView.loadingIndex) ? 1.0 : 0.4
314374

315375
property var source: modelData["thumbnail"] ? Filepath.stringToUrl(modelData["thumbnail"]) : ""
316376
property int retryCount: 0
@@ -387,6 +447,8 @@ Page {
387447

388448
onClicked: function(mouse) {
389449

450+
if (root.isLoading) return
451+
390452
if (mouse.button === Qt.RightButton) {
391453

392454
if (!modelData["path"]) { return }
@@ -403,11 +465,10 @@ Page {
403465
}
404466

405467
else {
406-
// Open project
407-
mainStack.push("Application.qml")
408-
if (_currentScene.load(modelData["path"])) {
409-
MeshroomApp.addRecentProjectFile(modelData["path"])
410-
}
468+
root.isLoading = true
469+
homepageGridView.loadingIndex = index
470+
let path = modelData["path"]
471+
root.executeAfterFrameRendered(openProject, path)
411472
}
412473
}
413474
}
@@ -416,13 +477,13 @@ Page {
416477
id: projectContextMenu
417478

418479
MenuItem {
419-
enabled: projectDelegate.fileExists
480+
enabled: projectDelegate.fileExists && !root.isLoading
420481
text: "Open"
421-
onTriggered: {
422-
if (_currentScene.load(modelData["path"])) {
423-
mainStack.push("Application.qml")
424-
MeshroomApp.addRecentProjectFile(modelData["path"])
425-
}
482+
onTriggered: {
483+
root.isLoading = true
484+
homepageGridView.loadingIndex = index
485+
let path = modelData["path"]
486+
root.executeAfterFrameRendered(openProject, path)
426487
}
427488
}
428489

@@ -462,8 +523,17 @@ Page {
462523

463524
BusyIndicator {
464525
anchors.centerIn: parent
465-
running: homepageGridView.visible && projectContent.thumbnailBusy
466-
visible: homepageGridView.visible && projectContent.thumbnailBusy
526+
running: (homepageGridView.visible && projectContent.thumbnailBusy) || (root.isLoading && index === homepageGridView.loadingIndex)
527+
visible: running
528+
}
529+
530+
// Highlight overlay shown when this project is being loaded
531+
Rectangle {
532+
anchors.fill: parent
533+
color: "transparent"
534+
border.color: palette.highlight
535+
border.width: 2
536+
visible: root.isLoading && index === homepageGridView.loadingIndex
467537
}
468538
}
469539
Label {

0 commit comments

Comments
 (0)