[LyX/master] Allow multiple selections in the file open dialog

Jean-Marc Lasgouttes lasgouttes at lyx.org
Mon Jan 9 13:59:27 UTC 2023


commit f6083280596217987accb55538ba8bc57814b302
Author: Daniel Ramoeller <d.lyx at web.de>
Date:   Tue Dec 20 11:55:25 2022 +0100

    Allow multiple selections in the file open dialog
    
    Fix for bug #4315.
---
 src/frontends/qt/FileDialog.cpp     |   38 ++++++++---
 src/frontends/qt/FileDialog.h       |    6 ++
 src/frontends/qt/GuiApplication.cpp |    4 +-
 src/frontends/qt/GuiView.cpp        |  119 ++++++++++++++++++-----------------
 src/frontends/qt/GuiView.h          |    2 +-
 5 files changed, 99 insertions(+), 70 deletions(-)

diff --git a/src/frontends/qt/FileDialog.cpp b/src/frontends/qt/FileDialog.cpp
index 1491939..704c34c 100644
--- a/src/frontends/qt/FileDialog.cpp
+++ b/src/frontends/qt/FileDialog.cpp
@@ -134,20 +134,38 @@ FileDialog::Result FileDialog::save(QString const & path,
 FileDialog::Result FileDialog::open(QString const & path,
 	QStringList const & filters, QString const & suggested)
 {
+	FileDialog::Result result;
+	FileDialog::Results results = openMulti(path, filters, suggested, false);
+	result.first = results.first;
+	result.second = results.second.at(0);
+	return result;
+}
+
+
+FileDialog::Results FileDialog::openMulti(QString const & path,
+	QStringList const & filters, QString const & suggested, bool multi)
+{
 	LYXERR(Debug::GUI, "Select with path \"" << path
 			   << "\", mask \"" << filters.join(";;")
 			   << "\", suggested \"" << suggested << '"');
-	FileDialog::Result result;
-	result.first = FileDialog::Chosen;
+	FileDialog::Results results;
+	results.first = FileDialog::Chosen;
 
 	if (lyxrc.use_native_filedialog) {
 		QString const startsWith = makeAbsPath(suggested, path);
-		QString const file = QFileDialog::getOpenFileName(qApp->focusWidget(),
-				title_, startsWith, filters.join(";;"));
-		if (file.isNull())
-			result.first = FileDialog::Later;
+		QStringList files;
+		if (multi)
+			files = QFileDialog::getOpenFileNames(qApp->focusWidget(),
+					title_, startsWith, filters.join(";;"));
 		else
-			result.second = internalPath(file);
+			files << QFileDialog::getOpenFileName(qApp->focusWidget(),
+					title_, startsWith, filters.join(";;"));
+		if (files.isEmpty())
+			results.first = FileDialog::Later;
+		else {
+			for (const auto& file : files)
+				results.second << internalPath(file);
+		}
 	} else {
 		LyXFileDialog dlg(title_, path, filters, private_->b1, private_->b2);
 
@@ -158,12 +176,12 @@ FileDialog::Result FileDialog::open(QString const & path,
 		int res = dlg.exec();
 		LYXERR(Debug::GUI, "result " << res);
 		if (res == QDialog::Accepted)
-			result.second = internalPath(dlg.selectedFiles()[0]);
+			results.second << internalPath(dlg.selectedFiles()[0]);
 		else
-			result.first = FileDialog::Later;
+			results.first = FileDialog::Later;
 		dlg.hide();
 	}
-	return result;
+	return results;
 }
 
 
diff --git a/src/frontends/qt/FileDialog.h b/src/frontends/qt/FileDialog.h
index fe75b5b..3d6a549 100644
--- a/src/frontends/qt/FileDialog.h
+++ b/src/frontends/qt/FileDialog.h
@@ -41,6 +41,9 @@ public:
 	/// result return
 	typedef std::pair<FileDialog::ResultType, QString> Result;
 
+	/// result return
+	typedef std::pair<FileDialog::ResultType, QStringList> Results;
+
 	/**
 	 * Constructs a file dialog with title \param title.
 	 *
@@ -58,6 +61,9 @@ public:
 	/// Choose a file for opening, starting in directory \c path.
 	Result open(QString const & path, QStringList const & filters,
 			  QString const & suggested = QString());
+	/// Choose several files for opening, starting in directory \c path.
+	Results openMulti(QString const & path, QStringList const & filters,
+			  QString const & suggested = QString(), bool multi = true);
 
 	/// Choose a directory, starting in directory \c path.
 	Result opendir(QString const & path = QString(),
diff --git a/src/frontends/qt/GuiApplication.cpp b/src/frontends/qt/GuiApplication.cpp
index 967f134..25ca4b2 100644
--- a/src/frontends/qt/GuiApplication.cpp
+++ b/src/frontends/qt/GuiApplication.cpp
@@ -1858,7 +1858,7 @@ void GuiApplication::dispatch(FuncRequest const & cmd, DispatchResult & dr)
 			// We want the ui session to be saved per document and not per
 			// window number. The filename crc is a good enough identifier.
 			createView(support::checksum(fname));
-			current_view_->openDocument(fname, cmd.origin());
+			current_view_->openDocuments(fname, cmd.origin());
 			if (!current_view_->documentBufferView())
 				current_view_->close();
 			else if (cmd.origin() == FuncRequest::LYXSERVER) {
@@ -1867,7 +1867,7 @@ void GuiApplication::dispatch(FuncRequest const & cmd, DispatchResult & dr)
 				current_view_->showNormal();
 			}
 		} else {
-			current_view_->openDocument(fname, cmd.origin());
+			current_view_->openDocuments(fname, cmd.origin());
 			if (cmd.origin() == FuncRequest::LYXSERVER) {
 				current_view_->raise();
 				current_view_->activateWindow();
diff --git a/src/frontends/qt/GuiView.cpp b/src/frontends/qt/GuiView.cpp
index e7a3b29..461b09c 100644
--- a/src/frontends/qt/GuiView.cpp
+++ b/src/frontends/qt/GuiView.cpp
@@ -2792,7 +2792,7 @@ Buffer * GuiView::loadDocument(FileName const & filename, bool tolastfiles)
 }
 
 
-void GuiView::openDocument(string const & fname, int origin)
+void GuiView::openDocuments(string const & fname, int origin)
 {
 	string initpath = lyxrc.document_path;
 
@@ -2803,10 +2803,10 @@ void GuiView::openDocument(string const & fname, int origin)
 			initpath = trypath;
 	}
 
-	string filename;
+	QStringList files;
 
 	if (fname.empty()) {
-		FileDialog dlg(qt_("Select document to open"));
+		FileDialog dlg(qt_("Select documents to open"));
 		dlg.setButton1(qt_("D&ocuments"), toqstr(lyxrc.document_path));
 		dlg.setButton2(qt_("&Examples"), toqstr(lyxrc.example_path));
 
@@ -2815,74 +2815,79 @@ void GuiView::openDocument(string const & fname, int origin)
 				qt_("LyX Document Backups (*.lyx~)"),
 				qt_("All Files (*.*)")
 		});
-		FileDialog::Result result =
-			dlg.open(toqstr(initpath), filter);
+		FileDialog::Results results =
+			dlg.openMulti(toqstr(initpath), filter);
 
-		if (result.first == FileDialog::Later)
+		if (results.first == FileDialog::Later)
 			return;
 
-		filename = fromqstr(result.second);
+		files = results.second;
 
 		// check selected filename
-		if (filename.empty()) {
+		if (files.isEmpty()) {
 			message(_("Canceled."));
 			return;
 		}
 	} else
-		filename = fname;
-
-	// get absolute path of file and add ".lyx" to the filename if
-	// necessary.
-	FileName const fullname =
-			fileSearch(string(), filename, "lyx", support::may_not_exist);
-	if (!fullname.empty())
-		filename = fullname.absFileName();
-
-	if (!fullname.onlyPath().isDirectory()) {
-		Alert::warning(_("Invalid filename"),
-				bformat(_("The directory in the given path\n%1$s\ndoes not exist."),
-				from_utf8(fullname.absFileName())));
-		return;
-	}
+		files << toqstr(fname);
+
+	// iterate over all selected files
+	for (auto const & file : files) {
+		string filename = fromqstr(file);
+
+		// get absolute path of file and add ".lyx" to the filename if
+		// necessary.
+		FileName const fullname =
+				fileSearch(string(), filename, "lyx", support::may_not_exist);
+		if (!fullname.empty())
+			filename = fullname.absFileName();
+
+		if (!fullname.onlyPath().isDirectory()) {
+			Alert::warning(_("Invalid filename"),
+					bformat(_("The directory in the given path\n%1$s\ndoes not exist."),
+					from_utf8(fullname.absFileName())));
+			continue;
+		}
 
-	// if the file doesn't exist and isn't already open (bug 6645),
-	// let the user create one
-	if (!fullname.exists() && !theBufferList().exists(fullname) &&
-	    !LyXVC::file_not_found_hook(fullname)) {
-		// see bug #12609
-		if (origin == FuncRequest::MENU) {
-			docstring const & msg =
-				bformat(_("File\n"
-					  "%1$s\n"
-					  "does not exist. Create empty file?"),
-						from_utf8(filename));
-			int ret = Alert::prompt(_("File does not exist"),
-						msg, 0, 1,
-						_("Create &File"),
-						_("&Cancel"));
-			if (ret == 1)
-				return;
+		// if the file doesn't exist and isn't already open (bug 6645),
+		// let the user create one
+		if (!fullname.exists() && !theBufferList().exists(fullname) &&
+			!LyXVC::file_not_found_hook(fullname)) {
+			// see bug #12609
+			if (origin == FuncRequest::MENU) {
+				docstring const & msg =
+					bformat(_("File\n"
+						"%1$s\n"
+						"does not exist. Create empty file?"),
+							from_utf8(filename));
+				int ret = Alert::prompt(_("File does not exist"),
+							msg, 0, 1,
+							_("Create &File"),
+							_("&Cancel"));
+				if (ret == 1)
+					continue;
+			}
+			Buffer * const b = newFile(filename, string(), true);
+			if (b)
+				setBuffer(b);
+			continue;
 		}
-		Buffer * const b = newFile(filename, string(), true);
-		if (b)
-			setBuffer(b);
-		return;
-	}
 
-	docstring const disp_fn = makeDisplayPath(filename);
-	message(bformat(_("Opening document %1$s..."), disp_fn));
+		docstring const disp_fn = makeDisplayPath(filename);
+		message(bformat(_("Opening document %1$s..."), disp_fn));
 
-	docstring str2;
-	Buffer * buf = loadDocument(fullname);
-	if (buf) {
-		str2 = bformat(_("Document %1$s opened."), disp_fn);
-		if (buf->lyxvc().inUse())
-			str2 += " " + from_utf8(buf->lyxvc().versionString()) +
-				" " + _("Version control detected.");
-	} else {
-		str2 = bformat(_("Could not open document %1$s"), disp_fn);
+		docstring str2;
+		Buffer * buf = loadDocument(fullname);
+		if (buf) {
+			str2 = bformat(_("Document %1$s opened."), disp_fn);
+			if (buf->lyxvc().inUse())
+				str2 += " " + from_utf8(buf->lyxvc().versionString()) +
+					" " + _("Version control detected.");
+		} else {
+			str2 = bformat(_("Could not open document %1$s"), disp_fn);
+		}
+		message(str2);
 	}
-	message(str2);
 }
 
 // FIXME: clean that
diff --git a/src/frontends/qt/GuiView.h b/src/frontends/qt/GuiView.h
index 57461d0..29687c3 100644
--- a/src/frontends/qt/GuiView.h
+++ b/src/frontends/qt/GuiView.h
@@ -164,7 +164,7 @@ public:
 	/// closes the buffer
 	bool closeBuffer(Buffer & buf);
 	///
-	void openDocument(std::string const & filename, int origin);
+	void openDocuments(std::string const & filename, int origin);
 	///
 	void importDocument(std::string const &);
 


More information about the lyx-cvs mailing list