diff --git a/meshroom/ui/app.py b/meshroom/ui/app.py index fb50f9f958..1a2bc5c981 100644 --- a/meshroom/ui/app.py +++ b/meshroom/ui/app.py @@ -3,6 +3,7 @@ import re import argparse import json +from enum import Enum from PySide6 import __version__ as PySideVersion from PySide6 import QtCore @@ -34,6 +35,12 @@ from meshroom.ui import commands +class FileStatus(Enum): + MISSING=0 + EXISTS=1 + ERROR=2 # If the file exists but have errors like missing nodes, file content corruption... + + class MessageHandler: """ MessageHandler that translates Qt logs to Python logging system. @@ -422,7 +429,8 @@ def _getRecentProjectFilesFromSettings(self) -> list[dict[str, str]]: settings.setArrayIndex(i) path = settings.value("filepath") if path: - p = {"path": path, "thumbnail": self._retrieveThumbnailPath(path)} + fileStatus = FileStatus.EXISTS if os.path.isfile(path) else FileStatus.MISSING + p = {"path": path, "thumbnail": self._retrieveThumbnailPath(path), "status": fileStatus.value} projects.append(p) settings.endArray() settings.endGroup() @@ -443,6 +451,7 @@ def _updateRecentProjectFilesThumbnails(self) -> None: for project in self._recentProjectFiles: path = project["path"] project["thumbnail"] = self._retrieveThumbnailPath(path) + project["status"] = os.path.isfile(path) @Slot(str) @Slot(QUrl) @@ -479,7 +488,7 @@ def addRecentProjectFile(self, projectFile) -> None: del projects[idx] # If so, delete its entry # Insert the newest entry at the top of the list - projects.insert(0, {"path": projectFileNorm, "thumbnail": ""}) + projects.insert(0, {"path": projectFileNorm, "thumbnail": "", "status": FileStatus.EXISTS}) # Only keep the first 40 projects maxNbProjects = 40 diff --git a/meshroom/ui/qml/Application.qml b/meshroom/ui/qml/Application.qml index d7fb41380a..d9ba6b515b 100644 --- a/meshroom/ui/qml/Application.qml +++ b/meshroom/ui/qml/Application.qml @@ -725,12 +725,12 @@ Page { id: recentFilesMenuItems model: MeshroomApp.recentProjectFiles MenuItem { + enabled: modelData["status"] != 0 + onTriggered: ensureSaved(function() { openRecentMenu.dismiss() if (_reconstruction.load(modelData["path"])) { MeshroomApp.addRecentProjectFile(modelData["path"]) - } else { - MeshroomApp.removeRecentProjectFile(modelData["path"]) } }) diff --git a/meshroom/ui/qml/Homepage.qml b/meshroom/ui/qml/Homepage.qml index 78baac6115..6a354444d5 100644 --- a/meshroom/ui/qml/Homepage.qml +++ b/meshroom/ui/qml/Homepage.qml @@ -284,7 +284,7 @@ Page { // Request latest thumbnail paths if (mainStack.currentItem instanceof Homepage) MeshroomApp.updateRecentProjectFilesThumbnails() - return [{"path": null, "thumbnail": null}].concat(MeshroomApp.recentProjectFiles) + return [{"path": null, "thumbnail": null, "status": null}].concat(MeshroomApp.recentProjectFiles) } // Update grid item when corresponding thumbnail is computed @@ -325,6 +325,10 @@ Page { height: gridView.cellHeight * 0.95 - project.height width: gridView.cellWidth * 0.9 + // Handle case where the file is missing + property bool fileExists: modelData["status"] != 0 + opacity: fileExists ? 1.0 : 0.3 + ToolTip.visible: hovered ToolTip.text: modelData["path"] ? modelData["path"] : "Open browser to select a project file" @@ -361,8 +365,6 @@ Page { mainStack.push("Application.qml") if (_reconstruction.load(modelData["path"])) { MeshroomApp.addRecentProjectFile(modelData["path"]) - } else { - MeshroomApp.removeRecentProjectFile(modelData["path"]) } } @@ -374,6 +376,7 @@ Page { id: projectContextMenu MenuItem { + enabled: projectDelegate.fileExists text: "Open" onTriggered: { if (_reconstruction.load(modelData["path"])) {