Allow multiple selections in the file open dialog

Fix for bug #4315.
This commit is contained in:
Daniel Ramoeller 2022-12-20 11:55:25 +01:00 committed by Jean-Marc Lasgouttes
parent 3324793b8b
commit f608328059
5 changed files with 97 additions and 68 deletions

View File

@ -133,21 +133,39 @@ 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;
}

View File

@ -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(),

View File

@ -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();

View File

@ -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;
files << toqstr(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();
// iterate over all selected files
for (auto const & file : files) {
string filename = fromqstr(file);
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;
}
// 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 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 (!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;
}
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));
// 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;
}
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 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);
}
message(str2);
}
message(str2);
}
// FIXME: clean that

View File

@ -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 &);