From e9918e72aba349ed733a4e1b1a7f42fd5e9d85cf Mon Sep 17 00:00:00 2001
From: Aurore LAFAURIE <aurore.lafaurie.pro@gmail.com>
Date: Fri, 12 Jul 2024 11:39:57 +0200
Subject: [PATCH] [ui] Shortcut to make widgets in fullscreen mode

---
 meshroom/ui/qml/ImageGallery/ImageGallery.qml |  6 +-
 meshroom/ui/qml/Viewer/Viewer2D.qml           |  4 +
 .../qml/Viewer3D/DefaultCameraController.qml  |  1 +
 meshroom/ui/qml/Viewer3D/Viewer3D.qml         |  1 +
 meshroom/ui/qml/WorkspaceView.qml             | 35 +++++---
 meshroom/ui/qml/main.qml                      | 81 ++++++++++++++++++-
 6 files changed, 116 insertions(+), 12 deletions(-)

diff --git a/meshroom/ui/qml/ImageGallery/ImageGallery.qml b/meshroom/ui/qml/ImageGallery/ImageGallery.qml
index 977759114a..af1788999d 100644
--- a/meshroom/ui/qml/ImageGallery/ImageGallery.qml
+++ b/meshroom/ui/qml/ImageGallery/ImageGallery.qml
@@ -14,6 +14,7 @@ import Utils 1.0
  */
 Panel {
     id: root
+    visible: settings_UILayout.showImageGallery
 
     property variant cameraInits
     property variant cameraInit
@@ -32,12 +33,13 @@ Panel {
     property int nbMeshroomScenes: 0
     property int nbDraggedFiles: 0
 
+    property alias mouseArea: mouseArea
+
     signal removeImageRequest(var attribute)
     signal allViewpointsCleared()
     signal filesDropped(var drop, var augmentSfm)
 
     title: "Image Gallery"
-    implicitWidth: (root.defaultCellSize + 2) * 2
 
     Connections {
         target: _reconstruction
@@ -530,7 +532,9 @@ Panel {
             }
 
             MouseArea {
+                id: mouseArea
                 anchors.fill: parent
+                hoverEnabled: true
                 onPressed: {
                     if (mouse.button == Qt.LeftButton)
                         grid.forceActiveFocus()
diff --git a/meshroom/ui/qml/Viewer/Viewer2D.qml b/meshroom/ui/qml/Viewer/Viewer2D.qml
index de87d6cfd7..2bd53b41c1 100644
--- a/meshroom/ui/qml/Viewer/Viewer2D.qml
+++ b/meshroom/ui/qml/Viewer/Viewer2D.qml
@@ -36,6 +36,8 @@ FocusScope {
     property alias currentFrame: sequencePlayer.frameId
     property alias frameRange: sequencePlayer.frameRange
 
+    property alias mouseArea: mouseArea
+
     QtObject {
         id: m
         property variant viewpointMetadata: {
@@ -114,9 +116,11 @@ FocusScope {
 
     // mouse area
     MouseArea {
+        id: mouseArea
         anchors.fill: parent
         property double factor: 1.2
         acceptedButtons: Qt.LeftButton | Qt.RightButton | Qt.MiddleButton
+        hoverEnabled: true
         onPressed: {
             imgContainer.forceActiveFocus()
             if (mouse.button & Qt.MiddleButton || (mouse.button & Qt.LeftButton && mouse.modifiers & Qt.ShiftModifier))
diff --git a/meshroom/ui/qml/Viewer3D/DefaultCameraController.qml b/meshroom/ui/qml/Viewer3D/DefaultCameraController.qml
index 1466b54544..0fa2d7a9bd 100644
--- a/meshroom/ui/qml/Viewer3D/DefaultCameraController.qml
+++ b/meshroom/ui/qml/Viewer3D/DefaultCameraController.qml
@@ -22,6 +22,7 @@ Entity {
     property alias rotationSpeed: trackball.rotationSpeed
     property alias windowSize: trackball.windowSize
     property alias trackballSize: trackball.trackballSize
+    property alias mouseHandler: mouseHandler
 
     property bool loseMouseFocus: false // Must be changed by other entities when they want to take mouse focus
 
diff --git a/meshroom/ui/qml/Viewer3D/Viewer3D.qml b/meshroom/ui/qml/Viewer3D/Viewer3D.qml
index 76ba1108b9..cf34cbbaa3 100644
--- a/meshroom/ui/qml/Viewer3D/Viewer3D.qml
+++ b/meshroom/ui/qml/Viewer3D/Viewer3D.qml
@@ -28,6 +28,7 @@ FocusScope {
 
     readonly property var viewpoint: _reconstruction ? _reconstruction.selectedViewpoint : null
     readonly property bool doSyncViewpointCamera: Viewer3DSettings.syncViewpointCamera && (viewpoint && viewpoint.isReconstructed)
+    property alias mouseArea: cameraController
 
     // functions
     function resetCameraPosition() {
diff --git a/meshroom/ui/qml/WorkspaceView.qml b/meshroom/ui/qml/WorkspaceView.qml
index ba01f0e7e7..50bb32d1f4 100644
--- a/meshroom/ui/qml/WorkspaceView.qml
+++ b/meshroom/ui/qml/WorkspaceView.qml
@@ -23,6 +23,7 @@ Item {
     readonly property variant cameraInits: _reconstruction ? _reconstruction.cameraInits : null
     property bool readOnly: false
     property alias panel3dViewer: panel3dViewerLoader.item
+    property alias viewer3DContainer: panel3dViewerContainer
     readonly property Viewer2D viewer2D: viewer2D
     readonly property alias imageGallery: imageGallery
 
@@ -66,12 +67,20 @@ Item {
 
         Controls1.SplitView {
             orientation: Qt.Vertical
-            Layout.fillHeight: true
-            implicitWidth: Math.round(parent.width * 0.2)
+            SplitView.fillHeight: true
+
             Layout.minimumWidth: imageGallery.defaultCellSize
+            implicitWidth: (imageGallery.defaultCellSize + 2) * 2
+            Layout.fillWidth: imageGallery.isFullScreen
+            Layout.maximumWidth: imageGallery.isFullScreen ? parent.width : (imageGallery.defaultCellSize + 2) * 4
+
+            visible: settings_UILayout.showImageGallery || settings_UILayout.showLiveReconstruction
 
             ImageGallery {
                 id: imageGallery
+                property bool isFullScreen: settings_UILayout.showImageGallery && !settings_UILayout.showLiveReconstruction && !settings_UILayout.showImageViewer && !settings_UILayout.showViewer3D && !settings_UILayout.showGraphEditor
+                Layout.fillWidth: isFullScreen
+                anchors.fill: parent
                 Layout.fillHeight: true
                 readOnly: root.readOnly
                 cameraInits: root.cameraInits
@@ -93,8 +102,7 @@ Item {
             LiveSfmView {
                 visible: settings_UILayout.showLiveReconstruction
                 reconstruction: root.reconstruction
-                Layout.fillWidth: true
-                Layout.preferredHeight: childrenRect.height
+                SplitView.preferredHeight: childrenRect.height
             }
         }
 
@@ -103,8 +111,12 @@ Item {
             visible: settings_UILayout.showImageViewer
             implicitWidth: Math.round(parent.width * 0.35)
             Layout.fillHeight: true
-            Layout.fillWidth: true
-            Layout.minimumWidth: 50
+
+            property bool isFullScreen: !settings_UILayout.showImageGallery && !settings_UILayout.showLiveReconstruction && settings_UILayout.showImageViewer && !settings_UILayout.showViewer3D && !settings_UILayout.showGraphEditor
+
+            Layout.fillWidth: isFullScreen
+
+            Layout.minimumWidth: visible ? 50 : 0
             loading: viewer2D.loadingModules.length > 0
             loadingText: loading ? "Loading " + viewer2D.loadingModules : ""
 
@@ -184,13 +196,18 @@ Item {
             }
         }
 
-        Item {
+        Page {
+            id: panel3dViewerContainer
             visible: settings_UILayout.showViewer3D
-            Layout.minimumWidth: 20
-            Layout.minimumHeight: 80
+            Layout.minimumWidth: visible ? 200 : 0
+            Layout.minimumHeight: visible ? 80 : 0
             Layout.fillHeight: true
             implicitWidth: Math.round(parent.width * 0.45)
 
+            property bool isFullScreen: !settings_UILayout.showImageGallery && !settings_UILayout.showLiveReconstruction && !settings_UILayout.showImageViewer && settings_UILayout.showViewer3D && !settings_UILayout.showGraphEditor
+
+            Layout.fillWidth: isFullScreen
+
             Loader {
                 id: panel3dViewerLoader
                 active: settings_UILayout.showViewer3D
diff --git a/meshroom/ui/qml/main.qml b/meshroom/ui/qml/main.qml
index 9590bae3cc..9184a8db26 100644
--- a/meshroom/ui/qml/main.qml
+++ b/meshroom/ui/qml/main.qml
@@ -97,6 +97,7 @@ ApplicationWindow {
         property alias showGraphEditor: graphEditorVisibilityCB.checked
         property alias showImageViewer: imageViewerVisibilityCB.checked
         property alias showViewer3D: viewer3DVisibilityCB.checked
+        property alias showImageGallery: imageGalleryVisibilityCB.checked
     }
 
     Component.onDestruction: {
@@ -112,6 +113,67 @@ ApplicationWindow {
         onActivated: ensureSaved(function() { _reconstruction.new() })
     }
 
+    // Action to put component with mouse focus in fullscreen
+    Action {
+        id: showFullScreenAction
+
+        property bool isFullScreen: false
+        property Settings settingsBeforeFullScreen: Settings {
+            property bool showLiveReconstruction: false
+            property bool showImageViewer: false
+            property bool showViewer3D: false
+            property bool showGraphEditor: false
+            property bool showImageGallery: false
+        }
+
+        function setSettingsBeforeFullScreen(setting) {
+            settingsBeforeFullScreen.showLiveReconstruction = settings_UILayout.showLiveReconstruction
+            settingsBeforeFullScreen.showImageViewer = settings_UILayout.showImageViewer
+            settingsBeforeFullScreen.showViewer3D = settings_UILayout.showViewer3D
+            settingsBeforeFullScreen.showGraphEditor = settings_UILayout.showGraphEditor
+            settingsBeforeFullScreen.showImageGallery = settings_UILayout.showImageGallery
+
+            // set all to false except the one that triggered the fullscreen
+            for (var name in settings_UILayout) {
+                if (name !== setting && !settings_UILayout[name].readOnly && typeof settings_UILayout[name] === "boolean")
+                    settings_UILayout[name] = false
+            }
+
+            isFullScreen = true
+        }
+
+        function setSettingsAfterFullScreen() {
+            settings_UILayout.showLiveReconstruction = settingsBeforeFullScreen.showLiveReconstruction
+            settings_UILayout.showImageViewer = settingsBeforeFullScreen.showImageViewer
+            settings_UILayout.showViewer3D = settingsBeforeFullScreen.showViewer3D
+            settings_UILayout.showGraphEditor = settingsBeforeFullScreen.showGraphEditor
+            settings_UILayout.showImageGallery = settingsBeforeFullScreen.showImageGallery
+        }
+
+        shortcut: "Shift+F"
+        onTriggered: {
+            if (isFullScreen) {
+                setSettingsAfterFullScreen()
+                if (settings_UILayout.showGraphEditor)
+                    graphEditor.fit()
+
+                isFullScreen = false
+                return
+            } else {
+                if (workspaceView.viewer2D.mouseArea.containsMouse) {
+                    setSettingsBeforeFullScreen("showImageViewer")
+                } else if (workspaceView.imageGallery.mouseArea.containsMouse) {
+                    setSettingsBeforeFullScreen("showImageGallery")
+                } else if (workspaceView.viewer3DContainer.hovered) {
+                    setSettingsBeforeFullScreen("showViewer3D")
+                } else if (graphEditorPanel.hovered) {
+                    setSettingsBeforeFullScreen("showGraphEditor")
+                    graphEditor.fit()
+                }
+            }
+        }
+    }
+
     MessageDialog {
         id: unsavedDialog
 
@@ -896,6 +958,12 @@ ApplicationWindow {
                 checkable: true
                 checked: true
             }
+            MenuItem {
+                id: imageGalleryVisibilityCB
+                text: "Image Gallery"
+                checkable: true
+                checked: true
+            }
             MenuSeparator {}
             Action {
                 text: "Fullscreen"
@@ -1045,7 +1113,7 @@ ApplicationWindow {
                 id: workspaceView
                 Layout.fillWidth: true
                 Layout.fillHeight: true
-                Layout.minimumHeight: 50
+                Layout.minimumHeight: graphEditorPanel.parent.isFullScreen ? 50 : 0
                 reconstruction: _reconstruction
                 readOnly: _reconstruction ? _reconstruction.computing : false
 
@@ -1081,14 +1149,21 @@ ApplicationWindow {
         Controls1.SplitView {
             orientation: Qt.Horizontal
             width: parent.width
-            height: Math.round(parent.height * 0.3)
+
+            Layout.minimumHeight: graphEditorPanel.isFullScreen ? _window.height : 50
+            Layout.maximumHeight: graphEditorPanel.isFullScreen ? _window.height : Math.round(_window.height * 0.4)
             visible: settings_UILayout.showGraphEditor
 
             TabPanel {
                 id: graphEditorPanel
                 Layout.fillWidth: true
+
+                property bool isFullScreen: !settings_UILayout.showImageGallery && !settings_UILayout.showLiveReconstruction && !settings_UILayout.showImageViewer && !settings_UILayout.showViewer3D && settings_UILayout.showGraphEditor
+
+                implicitHeight: Math.round(_window.height * 0.3)
                 padding: 4
                 tabs: ["Graph Editor", "Task Manager", "Script Editor"]
+                hoverEnabled: true
 
                 headerBar: RowLayout {
                     MaterialToolButton {
@@ -1261,6 +1336,8 @@ ApplicationWindow {
                             _reconstruction.handleFilesUrl(filesByType, null, mousePosition)
                         }
                     }
+
+                    
                 }
 
                 TaskManager {