Merge pull request #1864 from alicevision/dev/saveImportImagesFolder

[ui] Use the location of the most recently imported images as the base folder for the "Import Images" dialog
This commit is contained in:
Fabien Castan 2023-01-22 18:07:56 +00:00 committed by GitHub
commit 40b182efc5
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
4 changed files with 119 additions and 8 deletions

View file

@ -250,12 +250,12 @@ class MeshroomApp(QApplication):
# add the new value in the first place # add the new value in the first place
projects.insert(0, projectFileNorm) projects.insert(0, projectFileNorm)
# keep only the 10 first elements # keep only the 20 first elements
projects = projects[0:20] projects = projects[0:20]
settings = QSettings() settings = QSettings()
settings.beginGroup("RecentFiles") settings.beginGroup("RecentFiles")
size = settings.beginWriteArray("Projects") settings.beginWriteArray("Projects")
for i, p in enumerate(projects): for i, p in enumerate(projects):
settings.setArrayIndex(i) settings.setArrayIndex(i)
settings.setValue("filepath", p) settings.setValue("filepath", p)
@ -292,7 +292,7 @@ class MeshroomApp(QApplication):
settings = QSettings() settings = QSettings()
settings.beginGroup("RecentFiles") settings.beginGroup("RecentFiles")
size = settings.beginWriteArray("Projects") settings.beginWriteArray("Projects")
for i, p in enumerate(projects): for i, p in enumerate(projects):
settings.setArrayIndex(i) settings.setArrayIndex(i)
settings.setValue("filepath", p) settings.setValue("filepath", p)
@ -301,6 +301,86 @@ class MeshroomApp(QApplication):
self.recentProjectFilesChanged.emit() self.recentProjectFilesChanged.emit()
def _recentImportedImagesFolders(self):
folders = []
settings = QSettings()
settings.beginGroup("RecentFiles")
size = settings.beginReadArray("ImagesFolders")
for i in range(size):
settings.setArrayIndex(i)
f = settings.value("path")
if f:
folders.append(f)
settings.endArray()
return folders
@Slot(QUrl)
def addRecentImportedImagesFolder(self, imagesFolder):
if isinstance(imagesFolder, QUrl):
folderPath = imagesFolder.toLocalFile()
if not folderPath:
folderPath = imagesFolder.toString()
else:
raise TypeError("Unexpected data type: {}".format(imagesFolder.__class__))
folders = self._recentImportedImagesFolders()
# remove duplicates while preserving order
from collections import OrderedDict
uniqueFolders = OrderedDict.fromkeys(folders)
folders = list(uniqueFolders)
# remove previous usage of the value
if folderPath in uniqueFolders:
folders.remove(folderPath)
# add the new value in the first place
folders.insert(0, folderPath)
# keep only the first three elements to have a backup if one of the folders goes missing
folders = folders[0:3]
settings = QSettings()
settings.beginGroup("RecentFiles")
settings.beginWriteArray("ImagesFolders")
for i, p in enumerate(folders):
settings.setArrayIndex(i)
settings.setValue("path", p)
settings.endArray()
settings.sync()
self.recentImportedImagesFoldersChanged.emit()
@Slot(QUrl)
def removeRecentImportedImagesFolder(self, imagesFolder):
if isinstance(imagesFolder, QUrl):
folderPath = imagesFolder.toLocalFile()
if not folderPath:
folderPath = imagesFolder.toString()
else:
raise TypeError("Unexpected data type: {}".format(imagesFolder.__class__))
folders = self._recentImportedImagesFolders()
# remove duplicates while preserving order
from collections import OrderedDict
uniqueFolders = OrderedDict.fromkeys(folders)
folders = list(uniqueFolders)
# remove previous usage of the value
if folderPath not in uniqueFolders:
return
folders.remove(folderPath)
settings = QSettings()
settings.beginGroup("RecentFiles")
settings.beginWriteArray("ImagesFolders")
for i, f in enumerate(folders):
settings.setArrayIndex(i)
settings.setValue("path", f)
settings.endArray()
settings.sync()
self.recentImportedImagesFoldersChanged.emit()
@Slot(str, result=str) @Slot(str, result=str)
def markdownToHtml(self, md): def markdownToHtml(self, md):
""" """
@ -358,7 +438,9 @@ class MeshroomApp(QApplication):
licensesModel = Property("QVariantList", _licensesModel, constant=True) licensesModel = Property("QVariantList", _licensesModel, constant=True)
pipelineTemplateFilesChanged = Signal() pipelineTemplateFilesChanged = Signal()
recentProjectFilesChanged = Signal() recentProjectFilesChanged = Signal()
recentImportedImagesFoldersChanged = Signal()
pipelineTemplateFiles = Property("QVariantList", _pipelineTemplateFiles, notify=pipelineTemplateFilesChanged) pipelineTemplateFiles = Property("QVariantList", _pipelineTemplateFiles, notify=pipelineTemplateFilesChanged)
pipelineTemplateNames = Property("QVariantList", _pipelineTemplateNames, notify=pipelineTemplateFilesChanged) pipelineTemplateNames = Property("QVariantList", _pipelineTemplateNames, notify=pipelineTemplateFilesChanged)
recentProjectFiles = Property("QVariantList", _recentProjectFiles, notify=recentProjectFilesChanged) recentProjectFiles = Property("QVariantList", _recentProjectFiles, notify=recentProjectFilesChanged)
recentImportedImagesFolders = Property("QVariantList", _recentImportedImagesFolders, notify=recentImportedImagesFoldersChanged)
default8bitViewerEnabled = Property(bool, _default8bitViewerEnabled, constant=True) default8bitViewerEnabled = Property(bool, _default8bitViewerEnabled, constant=True)

View file

@ -23,6 +23,7 @@ Panel {
readonly property string currentItemSource: grid.currentItem ? grid.currentItem.source : "" readonly property string currentItemSource: grid.currentItem ? grid.currentItem.source : ""
readonly property var currentItemMetadata: grid.currentItem ? grid.currentItem.metadata : undefined readonly property var currentItemMetadata: grid.currentItem ? grid.currentItem.metadata : undefined
readonly property int centerViewId: (_reconstruction && _reconstruction.sfmTransform) ? parseInt(_reconstruction.sfmTransform.attribute("transformation").value) : 0 readonly property int centerViewId: (_reconstruction && _reconstruction.sfmTransform) ? parseInt(_reconstruction.sfmTransform.attribute("transformation").value) : 0
readonly property alias galleryGrid: grid
property int defaultCellSize: 160 property int defaultCellSize: 160
property bool readOnly: false property bool readOnly: false

View file

@ -24,6 +24,7 @@ Item {
property bool readOnly: false property bool readOnly: false
property alias panel3dViewer: panel3dViewerLoader.item property alias panel3dViewer: panel3dViewerLoader.item
readonly property Viewer2D viewer2D: viewer2D readonly property Viewer2D viewer2D: viewer2D
readonly property alias imageGallery: imageGallery
implicitWidth: 300 implicitWidth: 300
implicitHeight: 400 implicitHeight: 400

View file

@ -46,6 +46,19 @@ ApplicationWindow {
SystemPalette { id: activePalette } SystemPalette { id: activePalette }
SystemPalette { id: disabledPalette; colorGroup: SystemPalette.Disabled } SystemPalette { id: disabledPalette; colorGroup: SystemPalette.Disabled }
property url imagesFolder: {
var recentImportedImagesFolders = MeshroomApp.recentImportedImagesFolders
if (recentImportedImagesFolders.length > 0) {
for (var i = 0; i < recentImportedImagesFolders.length; i++) {
if (Filepath.exists(recentImportedImagesFolders[i]))
return Filepath.stringToUrl(recentImportedImagesFolders[i])
else
MeshroomApp.removeRecentImportedImagesFolder(Filepath.stringToUrl(recentImportedImagesFolders[i]))
}
}
return ""
}
Settings { Settings {
id: settings_General id: settings_General
category: 'General' category: 'General'
@ -328,6 +341,8 @@ ApplicationWindow {
nameFilters: [] nameFilters: []
onAccepted: { onAccepted: {
_reconstruction.importImagesUrls(importImagesDialog.fileUrls) _reconstruction.importImagesUrls(importImagesDialog.fileUrls)
imagesFolder = Filepath.dirname(importImagesDialog.fileUrls[0])
MeshroomApp.addRecentImportedImagesFolder(imagesFolder)
} }
} }
@ -475,15 +490,27 @@ ApplicationWindow {
// Utility functions for elements in the menubar // Utility functions for elements in the menubar
function initFileDialogFolder(dialog) { function initFileDialogFolder(dialog, importImages = false) {
if(_reconstruction.graph && _reconstruction.graph.filepath) { let folder = "";
dialog.folder = Filepath.stringToUrl(Filepath.dirname(_reconstruction.graph.filepath));
if (imagesFolder.toString() === "" && workspaceView.imageGallery.galleryGrid.itemAtIndex(0) !== null) {
imagesFolder = Filepath.stringToUrl(Filepath.dirname(workspaceView.imageGallery.galleryGrid.itemAtIndex(0).source));
}
if (_reconstruction.graph && _reconstruction.graph.filepath) {
folder = Filepath.stringToUrl(Filepath.dirname(_reconstruction.graph.filepath));
} else { } else {
var projects = MeshroomApp.recentProjectFiles; var projects = MeshroomApp.recentProjectFiles;
if (projects.length > 0 && Filepath.exists(projects[0])) { if (projects.length > 0 && Filepath.exists(projects[0])) {
dialog.folder = Filepath.stringToUrl(Filepath.dirname(projects[0])); folder = Filepath.stringToUrl(Filepath.dirname(projects[0]));
} }
} }
if (importImages && imagesFolder.toString() !== "" && Filepath.exists(imagesFolder)) {
folder = imagesFolder;
}
dialog.folder = folder;
} }
header: MenuBar { header: MenuBar {
@ -606,7 +633,7 @@ ApplicationWindow {
text: "Import Images" text: "Import Images"
shortcut: "Ctrl+I" shortcut: "Ctrl+I"
onTriggered: { onTriggered: {
initFileDialogFolder(importImagesDialog); initFileDialogFolder(importImagesDialog, true);
importImagesDialog.open(); importImagesDialog.open();
} }
} }