[LyX/master] #12576 improved file name chooser implementation for GUI dialogs

Stephan Witt switt at lyx.org
Sat Aug 5 05:42:09 UTC 2023


commit 65ec100f6a13c0ee9b6edecd2b81552373fa70a0
Author: Stephan Witt <switt at lyx.org>
Date:   Sat Aug 5 08:56:35 2023 +0200

    #12576 improved file name chooser implementation for GUI dialogs
    
    - code reorganization to move the file name chooser methods in GuiDialog class
    - on Mac add explicit raise of the current dialog window on close of the file browser to work around the bug 12576
---
 src/frontends/qt/GuiBibtex.cpp   |    4 +-
 src/frontends/qt/GuiBibtex.h     |    4 +-
 src/frontends/qt/GuiCompare.cpp  |    2 +-
 src/frontends/qt/GuiCompare.h    |    2 +-
 src/frontends/qt/GuiDialog.cpp   |  128 ++++++++++++++++++++++++++++++++++-
 src/frontends/qt/GuiDialog.h     |   66 ++++++++++++++++++
 src/frontends/qt/GuiExternal.cpp |    2 +-
 src/frontends/qt/GuiExternal.h   |    2 +-
 src/frontends/qt/GuiGraphics.cpp |    2 +-
 src/frontends/qt/GuiGraphics.h   |    2 +-
 src/frontends/qt/GuiInclude.cpp  |    2 +-
 src/frontends/qt/GuiInclude.h    |    2 +-
 src/frontends/qt/GuiPrefs.cpp    |  140 ++++----------------------------------
 src/frontends/qt/GuiPrefs.h      |    2 +-
 src/frontends/qt/qt_helpers.h    |   41 -----------
 15 files changed, 220 insertions(+), 181 deletions(-)

diff --git a/src/frontends/qt/GuiBibtex.cpp b/src/frontends/qt/GuiBibtex.cpp
index b9c928a..757c2c9 100644
--- a/src/frontends/qt/GuiBibtex.cpp
+++ b/src/frontends/qt/GuiBibtex.cpp
@@ -491,7 +491,7 @@ void GuiBibtex::applyView()
 }
 
 
-QString GuiBibtex::browseBib(QString const & in_name) const
+QString GuiBibtex::browseBib(QString const & in_name)
 {
 	QString const label1 = qt_("D&ocuments");
 	QString const dir1 = toqstr(lyxrc.document_path);
@@ -501,7 +501,7 @@ QString GuiBibtex::browseBib(QString const & in_name) const
 }
 
 
-QString GuiBibtex::browseBst(QString const & in_name) const
+QString GuiBibtex::browseBst(QString const & in_name)
 {
 	QString const label1 = qt_("D&ocuments");
 	QString const dir1 = toqstr(lyxrc.document_path);
diff --git a/src/frontends/qt/GuiBibtex.h b/src/frontends/qt/GuiBibtex.h
index 5d54be7..bd0a0ea 100644
--- a/src/frontends/qt/GuiBibtex.h
+++ b/src/frontends/qt/GuiBibtex.h
@@ -56,9 +56,9 @@ private:
 	void updateContents() override;
 
 	/// Browse for a .bib file
-	QString browseBib(QString const & in_name) const;
+	QString browseBib(QString const & in_name);
 	/// Browse for a .bst file
-	QString browseBst(QString const & in_name) const;
+	QString browseBst(QString const & in_name);
 	/// get the list of bst files
 	QStringList bibStyles() const;
 	/// get the list of bib files
diff --git a/src/frontends/qt/GuiCompare.cpp b/src/frontends/qt/GuiCompare.cpp
index e485ec0..7a58c7a 100644
--- a/src/frontends/qt/GuiCompare.cpp
+++ b/src/frontends/qt/GuiCompare.cpp
@@ -153,7 +153,7 @@ void GuiCompare::selectOldFile()
 }
 
 
-QString GuiCompare::browse(QString const & in_name) const
+QString GuiCompare::browse(QString const & in_name)
 {
 	QString const title = qt_("Select document");
 
diff --git a/src/frontends/qt/GuiCompare.h b/src/frontends/qt/GuiCompare.h
index e71a131..9538083 100644
--- a/src/frontends/qt/GuiCompare.h
+++ b/src/frontends/qt/GuiCompare.h
@@ -80,7 +80,7 @@ private:
 	void enableControls(bool enable);
 
 	/// browse for a file
-	QString browse(QString const & in_name) const;
+	QString browse(QString const & in_name);
 	/// retrieve the buffer from the specified filename
 	Buffer const * bufferFromFileName(std::string const & file) const;
 
diff --git a/src/frontends/qt/GuiDialog.cpp b/src/frontends/qt/GuiDialog.cpp
index 70d086c..67793df 100644
--- a/src/frontends/qt/GuiDialog.cpp
+++ b/src/frontends/qt/GuiDialog.cpp
@@ -10,12 +10,14 @@
 
 #include <config.h>
 
+#include "FileDialog.h"
+#include "GuiApplication.h"
 #include "GuiDialog.h"
-
 #include "GuiView.h"
 #include "qt_helpers.h"
 
 #include "support/debug.h"
+#include "support/filetools.h"
 
 #include <QCloseEvent>
 #include <QDialogButtonBox>
@@ -156,6 +158,130 @@ void GuiDialog::updateView()
 	setUpdatesEnabled(true);
 }
 
+QString GuiDialog::browseFile(QString const & filename,
+	QString const & title,
+	QStringList const & filters,
+	bool save,
+	QString const & label1,
+	QString const & dir1,
+	QString const & label2,
+	QString const & dir2,
+	QString const & fallback_dir)
+{
+	QString lastPath = ".";
+	if (!filename.isEmpty())
+		lastPath = onlyPath(filename);
+	else if(!fallback_dir.isEmpty())
+		lastPath = fallback_dir;
+
+	FileDialog dlg(title);
+	dlg.setButton1(label1, dir1);
+	dlg.setButton2(label2, dir2);
+
+	FileDialog::Result result;
+
+	if (save)
+		result = dlg.save(lastPath, filters, onlyFileName(filename));
+	else
+		result = dlg.open(lastPath, filters, onlyFileName(filename));
+
+	if (guiApp->platformName() == "cocoa") {
+		QWidget * dialog = asQWidget();
+		dialog->raise();
+		dialog->activateWindow();
+	}
+
+	return result.second;
+}
+
+
+/** Launch a file dialog and return the chosen directory.
+	pathname: a suggested pathname.
+	title: the title of the dialog.
+	dir1 = (name, dir), dir2 = (name, dir): extra buttons on the dialog.
+*/
+QString GuiDialog::browseDir(QString const & pathname,
+	QString const & title,
+	QString const & label1,
+	QString const & dir1,
+	QString const & label2,
+	QString const & dir2)
+{
+	QString lastPath = ".";
+	if (!pathname.isEmpty())
+		lastPath = onlyPath(pathname);
+
+	FileDialog dlg(title);
+	dlg.setButton1(label1, dir1);
+	dlg.setButton2(label2, dir2);
+
+	FileDialog::Result const result =
+		dlg.opendir(lastPath, onlyFileName(pathname));
+	
+	if (guiApp->platformName() == "cocoa") {
+		QWidget * dialog = asQWidget();
+		dialog->raise();
+		dialog->activateWindow();
+	}
+
+	return result.second;
+}
+
+QString GuiDialog::browseRelToParent(
+	QString const & filename,
+	QString const & relpath,
+	QString const & title,
+	QStringList const & filters,
+	bool save,
+	QString const & label1,
+	QString const & dir1,
+	QString const & label2,
+	QString const & dir2)
+{
+	QString const fname = makeAbsPath(filename, relpath);
+
+	QString const outname =
+		browseFile(fname, title, filters, save, label1, dir1, label2, dir2);
+
+	QString const reloutname =
+		toqstr(support::makeRelPath(qstring_to_ucs4(outname), qstring_to_ucs4(relpath)));
+
+	if (reloutname.startsWith("../"))
+		return outname;
+	else
+		return reloutname;
+}
+
+
+QString GuiDialog::browseRelToSub(
+	QString const & filename,
+	QString const & relpath,
+	QString const & title,
+	QStringList const & filters,
+	bool save,
+	QString const & label1,
+	QString const & dir1,
+	QString const & label2,
+	QString const & dir2)
+{
+	QString const fname = makeAbsPath(filename, relpath);
+
+	QString const outname =
+		browseFile(fname, title, filters, save, label1, dir1, label2, dir2);
+
+	QString const reloutname =
+		toqstr(support::makeRelPath(qstring_to_ucs4(outname), qstring_to_ucs4(relpath)));
+
+	QString testname = reloutname;
+	testname.remove(QRegularExpression("^(\\.\\./)+"));
+
+	if (testname.contains("/"))
+		return outname;
+	else
+		return reloutname;
+}
+
+
 } // namespace frontend
 } // namespace lyx
 
diff --git a/src/frontends/qt/GuiDialog.h b/src/frontends/qt/GuiDialog.h
index 160357d..50910f4 100644
--- a/src/frontends/qt/GuiDialog.h
+++ b/src/frontends/qt/GuiDialog.h
@@ -112,6 +112,72 @@ public:
 	/// Update the display of the dialog whilst it is still visible.
 	void updateView() override;
 
+
+	/** Launch a file dialog and return the chosen file.
+		filename: a suggested filename.
+		title: the title of the dialog.
+		filters: *.ps etc.
+		dir1 = (name, dir), dir2 = (name, dir): extra buttons on the dialog.
+	 */
+	QString browseFile(QString const & filename,
+		QString const & title,
+		QStringList const & filters,
+		bool save = false,
+		QString const & label1 = QString(),
+		QString const & dir1 = QString(),
+		QString const & label2 = QString(),
+		QString const & dir2 = QString(),
+		QString const & fallback_dir = QString());
+	/** Launch a file dialog and return the chosen directory.
+		pathname: a suggested pathname.
+		title: the title of the dialog.
+		dir1 = (name, dir), dir2 = (name, dir): extra buttons on the dialog.
+	*/
+	QString browseDir(QString const & pathname,
+		QString const & title,
+		QString const & label1 = QString(),
+		QString const & dir1 = QString(),
+		QString const & label2 = QString(),
+		QString const & dir2 = QString());
+	/** Wrappers around browseFile which try to provide a filename relative to relpath.
+
+	\param title: title for dialog
+
+	\param filters: *.ps, etc
+
+	\param save: whether to save dialog info (current path, etc) for next use.
+
+	The \param labelN and \param dirN arguments provide for extra buttons
+	in the dialog (e.g., "Templates" and a path to that directory).
+
+	The difference between the functions concerns when we think we have a
+	relative path.
+
+	In \c browseRelToParent, we return a relative path only if it IS NOT of
+		the form "../../foo.txt".
+
+	In \c browseRelToSub, we return a relative path only if it IS of the
+	 form "../../foo.txt".
+	 */
+	QString browseRelToParent(QString const & filename,
+		QString const & relpath,
+		QString const & title,
+		QStringList const & filters,
+		bool save = false,
+		QString const & label1 = QString(),
+		QString const & dir1 = QString(),
+		QString const & label2 = QString(),
+		QString const & dir2 = QString());
+	QString browseRelToSub(QString const & filename,
+		QString const & relpath,
+		QString const & title,
+		QStringList const & filters,
+		bool save = false,
+		QString const & label1 = QString(),
+		QString const & dir1 = QString(),
+		QString const & label2 = QString(),
+		QString const & dir2 = QString());
+
 private:
 	ButtonController bc_;
 	/// are we updating ?
diff --git a/src/frontends/qt/GuiExternal.cpp b/src/frontends/qt/GuiExternal.cpp
index 372053a..c88be8c 100644
--- a/src/frontends/qt/GuiExternal.cpp
+++ b/src/frontends/qt/GuiExternal.cpp
@@ -682,7 +682,7 @@ static QStringList templateFilters(QString const & template_name)
 
 
 QString GuiExternal::browse(QString const & input,
-				     QString const & template_name) const
+				     QString const & template_name)
 {
 	QString const title = qt_("Select external file");
 	QString const bufpath = bufferFilePath();
diff --git a/src/frontends/qt/GuiExternal.h b/src/frontends/qt/GuiExternal.h
index d83b113..dfb6c5f 100644
--- a/src/frontends/qt/GuiExternal.h
+++ b/src/frontends/qt/GuiExternal.h
@@ -68,7 +68,7 @@ private:
 
 	///
 	QString browse(QString const & input_file,
-				 QString const & template_name) const;
+				 QString const & template_name);
 
 	///
 	MapType extra_;
diff --git a/src/frontends/qt/GuiGraphics.cpp b/src/frontends/qt/GuiGraphics.cpp
index 6801f4c..7ba70fb 100644
--- a/src/frontends/qt/GuiGraphics.cpp
+++ b/src/frontends/qt/GuiGraphics.cpp
@@ -823,7 +823,7 @@ void GuiGraphics::dispatchParams()
 }
 
 
-QString GuiGraphics::browse(QString const & in_name) const
+QString GuiGraphics::browse(QString const & in_name)
 {
 	QString const title = qt_("Select graphics file");
 
diff --git a/src/frontends/qt/GuiGraphics.h b/src/frontends/qt/GuiGraphics.h
index 2687c08..68ef7dd 100644
--- a/src/frontends/qt/GuiGraphics.h
+++ b/src/frontends/qt/GuiGraphics.h
@@ -71,7 +71,7 @@ private:
 	/// does the bounding box differ from the file?
 	bool isChangedBB();
 	/// Browse for a file
-	QString browse(QString const &) const;
+	QString browse(QString const &);
 	/// Read the Bounding Box from a eps or ps-file
 	std::string readBoundingBox(std::string const & file);
 	/// test if file exist
diff --git a/src/frontends/qt/GuiInclude.cpp b/src/frontends/qt/GuiInclude.cpp
index 6120d66..73d4690 100644
--- a/src/frontends/qt/GuiInclude.cpp
+++ b/src/frontends/qt/GuiInclude.cpp
@@ -359,7 +359,7 @@ void GuiInclude::browse()
 }
 
 
-QString GuiInclude::browse(QString const & in_name, Type in_type) const
+QString GuiInclude::browse(QString const & in_name, Type in_type)
 {
 	QString const title = qt_("Select document to include");
 
diff --git a/src/frontends/qt/GuiInclude.h b/src/frontends/qt/GuiInclude.h
index 1c94692..da3972f 100644
--- a/src/frontends/qt/GuiInclude.h
+++ b/src/frontends/qt/GuiInclude.h
@@ -79,7 +79,7 @@ private:
 	/// update
 	void updateContents() override {}
 	/// Browse for a file
-	QString browse(QString const &, Type) const;
+	QString browse(QString const &, Type);
 
 private:
 	///
diff --git a/src/frontends/qt/GuiPrefs.cpp b/src/frontends/qt/GuiPrefs.cpp
index a5f4014..a74d97f 100644
--- a/src/frontends/qt/GuiPrefs.cpp
+++ b/src/frontends/qt/GuiPrefs.cpp
@@ -80,124 +80,6 @@ using namespace lyx::support;
 using namespace lyx::support::os;
 
 namespace lyx {
-namespace frontend {
-
-/////////////////////////////////////////////////////////////////////
-//
-// Browser Helpers
-//
-/////////////////////////////////////////////////////////////////////
-
-/** Launch a file dialog and return the chosen file.
-	filename: a suggested filename.
-	title: the title of the dialog.
-	filters: *.ps etc.
-	dir1 = (name, dir), dir2 = (name, dir): extra buttons on the dialog.
-*/
-QString browseFile(QString const & filename,
-	QString const & title,
-	QStringList const & filters,
-	bool save = false,
-	QString const & label1 = QString(),
-	QString const & dir1 = QString(),
-	QString const & label2 = QString(),
-	QString const & dir2 = QString(),
-	QString const & fallback_dir = QString())
-{
-	QString lastPath = ".";
-	if (!filename.isEmpty())
-		lastPath = onlyPath(filename);
-	else if(!fallback_dir.isEmpty())
-		lastPath = fallback_dir;
-
-	FileDialog dlg(title);
-	dlg.setButton1(label1, dir1);
-	dlg.setButton2(label2, dir2);
-
-	FileDialog::Result result;
-
-	if (save)
-		result = dlg.save(lastPath, filters, onlyFileName(filename));
-	else
-		result = dlg.open(lastPath, filters, onlyFileName(filename));
-
-	return result.second;
-}
-
-
-/** Launch a file dialog and return the chosen directory.
-	pathname: a suggested pathname.
-	title: the title of the dialog.
-	dir1 = (name, dir), dir2 = (name, dir): extra buttons on the dialog.
-*/
-QString browseDir(QString const & pathname,
-	QString const & title,
-	QString const & label1 = QString(),
-	QString const & dir1 = QString(),
-	QString const & label2 = QString(),
-	QString const & dir2 = QString())
-{
-	QString lastPath = ".";
-	if (!pathname.isEmpty())
-		lastPath = onlyPath(pathname);
-
-	FileDialog dlg(title);
-	dlg.setButton1(label1, dir1);
-	dlg.setButton2(label2, dir2);
-
-	FileDialog::Result const result =
-		dlg.opendir(lastPath, onlyFileName(pathname));
-
-	return result.second;
-}
-
-
-} // namespace frontend
-
-
-QString browseRelToParent(QString const & filename, QString const & relpath,
-	QString const & title, QStringList const & filters, bool save,
-	QString const & label1, QString const & dir1,
-	QString const & label2, QString const & dir2)
-{
-	QString const fname = makeAbsPath(filename, relpath);
-
-	QString const outname =
-		frontend::browseFile(fname, title, filters, save, label1, dir1, label2, dir2);
-
-	QString const reloutname =
-		toqstr(makeRelPath(qstring_to_ucs4(outname), qstring_to_ucs4(relpath)));
-
-	if (reloutname.startsWith("../"))
-		return outname;
-	else
-		return reloutname;
-}
-
-
-QString browseRelToSub(QString const & filename, QString const & relpath,
-	QString const & title, QStringList const & filters, bool save,
-	QString const & label1, QString const & dir1,
-	QString const & label2, QString const & dir2)
-{
-	QString const fname = makeAbsPath(filename, relpath);
-
-	QString const outname =
-		frontend::browseFile(fname, title, filters, save, label1, dir1, label2, dir2);
-
-	QString const reloutname =
-		toqstr(makeRelPath(qstring_to_ucs4(outname), qstring_to_ucs4(relpath)));
-
-	QString testname = reloutname;
-	testname.remove(QRegularExpression("^(\\.\\./)+"));
-
-	if (testname.contains("/"))
-		return outname;
-	else
-		return reloutname;
-}
-
-
 
 /////////////////////////////////////////////////////////////////////
 //
@@ -1478,7 +1360,7 @@ void PrefPaths::updateRC(LyXRC const & rc)
 
 void PrefPaths::selectExampledir()
 {
-	QString file = browseDir(internalPath(exampleDirED->text()),
+	QString file = form_->browseDir(internalPath(exampleDirED->text()),
 		qt_("Select directory for example files"));
 	if (!file.isEmpty())
 		exampleDirED->setText(file);
@@ -1487,7 +1369,7 @@ void PrefPaths::selectExampledir()
 
 void PrefPaths::selectTemplatedir()
 {
-	QString file = browseDir(internalPath(templateDirED->text()),
+	QString file = form_->browseDir(internalPath(templateDirED->text()),
 		qt_("Select a document templates directory"));
 	if (!file.isEmpty())
 		templateDirED->setText(file);
@@ -1496,7 +1378,7 @@ void PrefPaths::selectTemplatedir()
 
 void PrefPaths::selectTempdir()
 {
-	QString file = browseDir(internalPath(tempDirED->text()),
+	QString file = form_->browseDir(internalPath(tempDirED->text()),
 		qt_("Select a temporary directory"));
 	if (!file.isEmpty())
 		tempDirED->setText(file);
@@ -1505,7 +1387,7 @@ void PrefPaths::selectTempdir()
 
 void PrefPaths::selectBackupdir()
 {
-	QString file = browseDir(internalPath(backupDirED->text()),
+	QString file = form_->browseDir(internalPath(backupDirED->text()),
 		qt_("Select a backups directory"));
 	if (!file.isEmpty())
 		backupDirED->setText(file);
@@ -1514,7 +1396,7 @@ void PrefPaths::selectBackupdir()
 
 void PrefPaths::selectWorkingdir()
 {
-	QString file = browseDir(internalPath(workingDirED->text()),
+	QString file = form_->browseDir(internalPath(workingDirED->text()),
 		qt_("Select a document directory"));
 	if (!file.isEmpty())
 		workingDirED->setText(file);
@@ -1523,7 +1405,7 @@ void PrefPaths::selectWorkingdir()
 
 void PrefPaths::selectThesaurusdir()
 {
-	QString file = browseDir(internalPath(thesaurusDirED->text()),
+	QString file = form_->browseDir(internalPath(thesaurusDirED->text()),
 		qt_("Set the path to the thesaurus dictionaries"));
 	if (!file.isEmpty())
 		thesaurusDirED->setText(file);
@@ -1532,7 +1414,7 @@ void PrefPaths::selectThesaurusdir()
 
 void PrefPaths::selectHunspelldir()
 {
-	QString file = browseDir(internalPath(hunspellDirED->text()),
+	QString file = form_->browseDir(internalPath(hunspellDirED->text()),
 		qt_("Set the path to the Hunspell dictionaries"));
 	if (!file.isEmpty())
 		hunspellDirED->setText(file);
@@ -3718,6 +3600,12 @@ QString GuiPreferences::browseLibFile(QString const & dir,
 	guilyxfiles_->passParams(fromqstr(dir));
 	guilyxfiles_->selectItem(name);
 	guilyxfiles_->exec();
+	
+	if (frontend::guiApp->platformName() == "cocoa") {
+		QWidget * dialog_ = asQWidget();
+		dialog_->raise();
+		dialog_->activateWindow();
+	}
 
 	QString const result = uifile_;
 
@@ -3756,7 +3644,7 @@ QString GuiPreferences::browsekbmap(QString const & file)
 
 
 QString GuiPreferences::browse(QString const & file,
-	QString const & title) const
+	QString const & title)
 {
 	return browseFile(file, title, QStringList(), true);
 }
diff --git a/src/frontends/qt/GuiPrefs.h b/src/frontends/qt/GuiPrefs.h
index d237590..9c25793 100644
--- a/src/frontends/qt/GuiPrefs.h
+++ b/src/frontends/qt/GuiPrefs.h
@@ -92,7 +92,7 @@ public:
 	QString browsekbmap(QString const & file);
 
 	/// general browse
-	QString browse(QString const & file, QString const & title) const;
+	QString browse(QString const & file, QString const & title);
 
 	/// set a color
 	void setColor(ColorCode col, QString const & hex);
diff --git a/src/frontends/qt/qt_helpers.h b/src/frontends/qt/qt_helpers.h
index 6cad775..f3230b2 100644
--- a/src/frontends/qt/qt_helpers.h
+++ b/src/frontends/qt/qt_helpers.h
@@ -120,47 +120,6 @@ support::FileName imageLibFileSearch(QString & dir, QString const & name,
 				QString const & ext = QString(),
 				support::search_mode mode = support::must_exist);
 
-/** Wrappers around browseFile which try to provide a filename
-	relative to relpath.
-
-\param title: title for dialog
-
-\param filters: *.ps, etc
-
-\param save: whether to save dialog info (current path, etc) for next use.
-
-The \param labelN and \param dirN arguments provide for extra buttons
-in the dialog (e.g., "Templates" and a path to that directory).
-
-The difference between the functions concerns when we think we have a
-relative path.
-
-In \c browseRelToParent, we return a relative path only if it IS NOT of
-	the form "../../foo.txt".
-
-In \c browseRelToSub, we return a relative path only if it IS of the
- form "../../foo.txt".
-*/
-QString browseRelToParent(QString const & filename,
-	QString const & relpath,
-	QString const & title,
-	QStringList const & filters,
-	bool save = false,
-	QString const & label1 = QString(),
-	QString const & dir1 = QString(),
-	QString const & label2 = QString(),
-	QString const & dir2 = QString());
-
-QString browseRelToSub(QString const & filename,
-	QString const & relpath,
-	QString const & title,
-	QStringList const & filters,
-	bool save = false,
-	QString const & label1 = QString(),
-	QString const & dir1 = QString(),
-	QString const & label2 = QString(),
-	QString const & dir2 = QString());
-
 /** Build filelists of all available bst/cls/sty-files. Done through
 *  kpsewhich and an external script, saved in *Files.lst.
 *  \param arg: cls, sty, bst, or bib, as required by TeXFiles.py.


More information about the lyx-cvs mailing list