Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[ui] Use the location of the most recently imported images as the base folder for the "Import Images" dialog #1864

Merged
merged 6 commits into from
Jan 22, 2023
Merged
88 changes: 85 additions & 3 deletions meshroom/ui/app.py
Original file line number Diff line number Diff line change
Expand Up @@ -247,12 +247,12 @@ def addRecentProjectFile(self, projectFile):
# add the new value in the first place
projects.insert(0, projectFileNorm)

# keep only the 10 first elements
# keep only the 20 first elements
projects = projects[0:20]

settings = QSettings()
settings.beginGroup("RecentFiles")
size = settings.beginWriteArray("Projects")
settings.beginWriteArray("Projects")
for i, p in enumerate(projects):
settings.setArrayIndex(i)
settings.setValue("filepath", p)
Expand Down Expand Up @@ -289,7 +289,7 @@ def removeRecentProjectFile(self, projectFile):

settings = QSettings()
settings.beginGroup("RecentFiles")
size = settings.beginWriteArray("Projects")
settings.beginWriteArray("Projects")
for i, p in enumerate(projects):
settings.setArrayIndex(i)
settings.setValue("filepath", p)
Expand All @@ -298,6 +298,86 @@ def removeRecentProjectFile(self, projectFile):

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)
def markdownToHtml(self, md):
"""
Expand Down Expand Up @@ -355,7 +435,9 @@ def _default8bitViewerEnabled(self):
licensesModel = Property("QVariantList", _licensesModel, constant=True)
pipelineTemplateFilesChanged = Signal()
recentProjectFilesChanged = Signal()
recentImportedImagesFoldersChanged = Signal()
pipelineTemplateFiles = Property("QVariantList", _pipelineTemplateFiles, notify=pipelineTemplateFilesChanged)
pipelineTemplateNames = Property("QVariantList", _pipelineTemplateNames, notify=pipelineTemplateFilesChanged)
recentProjectFiles = Property("QVariantList", _recentProjectFiles, notify=recentProjectFilesChanged)
recentImportedImagesFolders = Property("QVariantList", _recentImportedImagesFolders, notify=recentImportedImagesFoldersChanged)
default8bitViewerEnabled = Property(bool, _default8bitViewerEnabled, constant=True)
1 change: 1 addition & 0 deletions meshroom/ui/qml/ImageGallery/ImageGallery.qml
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@ Panel {
readonly property string currentItemSource: grid.currentItem ? grid.currentItem.source : ""
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 alias galleryGrid: grid

property int defaultCellSize: 160
property bool readOnly: false
Expand Down
1 change: 1 addition & 0 deletions meshroom/ui/qml/WorkspaceView.qml
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@ Item {
property bool readOnly: false
property alias panel3dViewer: panel3dViewerLoader.item
readonly property Viewer2D viewer2D: viewer2D
readonly property alias imageGallery: imageGallery

implicitWidth: 300
implicitHeight: 400
Expand Down
37 changes: 32 additions & 5 deletions meshroom/ui/qml/main.qml
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,19 @@ ApplicationWindow {
SystemPalette { id: activePalette }
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 {
id: settings_General
category: 'General'
Expand Down Expand Up @@ -328,6 +341,8 @@ ApplicationWindow {
nameFilters: []
onAccepted: {
_reconstruction.importImagesUrls(importImagesDialog.fileUrls)
imagesFolder = Filepath.dirname(importImagesDialog.fileUrls[0])
MeshroomApp.addRecentImportedImagesFolder(imagesFolder)
}
}

Expand Down Expand Up @@ -475,15 +490,27 @@ ApplicationWindow {

// Utility functions for elements in the menubar

function initFileDialogFolder(dialog) {
if(_reconstruction.graph && _reconstruction.graph.filepath) {
dialog.folder = Filepath.stringToUrl(Filepath.dirname(_reconstruction.graph.filepath));
function initFileDialogFolder(dialog, importImages = false) {
let folder = "";

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 {
var projects = MeshroomApp.recentProjectFiles;
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 {
Expand Down Expand Up @@ -606,7 +633,7 @@ ApplicationWindow {
text: "Import Images"
shortcut: "Ctrl+I"
onTriggered: {
initFileDialogFolder(importImagesDialog);
initFileDialogFolder(importImagesDialog, true);
importImagesDialog.open();
}
}
Expand Down