Add default extension to file names unless one is given

This commit is contained in:
Matthias Koefferlein 2023-07-14 22:04:38 +02:00
parent 2ed27ff937
commit 67436d81a5
9 changed files with 102 additions and 171 deletions

View File

@ -26,6 +26,7 @@
#include "gsiDeclBasic.h"
#include "layBrowserDialog.h"
#include "layBrowserPanel.h"
#include "layFileDialog.h"
#include <QMessageBox>
#include <QInputDialog>
@ -926,11 +927,30 @@ static tl::Variant ask_open_file_name (const std::string &title, const std::stri
static tl::Variant ask_save_file_name (const std::string &title, const std::string &dir, const std::string &filter)
{
QString f = QFileDialog::getSaveFileName (QApplication::activeWindow (), tl::to_qstring (title), tl::to_qstring (dir), tl::to_qstring (filter));
QString selected_filter;
QString f = QFileDialog::getSaveFileName (QApplication::activeWindow (), tl::to_qstring (title), tl::to_qstring (dir), tl::to_qstring (filter), &selected_filter);
if (f.isEmpty ()) {
return tl::Variant ();
} else {
return tl::Variant (tl::to_string (f));
return tl::Variant (lay::FileDialog::add_default_extension (tl::to_string (f), selected_filter));
}
}
static tl::Variant ask_save_file_name2 (const std::string &title, const std::string &dir, const std::string &filter)
{
QString selected_filter;
QString qfilter = tl::to_qstring (filter);
QString f = QFileDialog::getSaveFileName (QApplication::activeWindow (), tl::to_qstring (title), tl::to_qstring (dir), qfilter, &selected_filter);
if (f.isEmpty ()) {
return tl::Variant ();
} else {
tl::Variant v;
v.set_list ();
v.push (lay::FileDialog::add_default_extension (tl::to_string (f), selected_filter));
v.push (lay::FileDialog::find_selected_filter (qfilter, selected_filter));
return v;
}
}
@ -1012,6 +1032,16 @@ Class<FileDialog> decl_FileDialog ("lay", "FileDialog",
"@return The path of the file chosen or \"nil\" if \"Cancel\" was pressed\n"
"\n"
"This method has been introduced in version 0.23. It is somewhat easier to use than the get_... equivalent.\n"
) +
gsi::method ("ask_save_file_name_with_filter", &ask_save_file_name2, gsi::arg ("title"), gsi::arg ("dir"), gsi::arg ("filter"),
"@brief Select one file for writing\n"
"\n"
"@param title The title of the dialog\n"
"@param dir The directory selected initially\n"
"@param filter The filters available, for example \"Images (*.png *.xpm *.jpg);;Text files (*.txt);;XML files (*.xml)\"\n"
"@return \"nil\" if \"Cancel\" was pressed, otherwise a pair: The path of the file chosen and the index selected file type (-1 if no specific type was selected)\n"
"\n"
"This method has been introduced in version 0.28.11.\n"
),
"@brief Various methods to request a file name\n"
"\n"

View File

@ -32,6 +32,8 @@
#include "layFileDialog.h"
#include "tlInternational.h"
#include "tlString.h"
#include "tlFileUtils.h"
namespace lay
{
@ -60,32 +62,53 @@ FileDialog::~FileDialog ()
// .. nothing yet ..
}
// not used if standard dialogs are used (disabled to avoid compiler warning):
#if 0
static void
split_filters (const QString &filters, QStringList &slist)
int
FileDialog::find_selected_filter (const QString &fs, const QString &selected_filter)
{
QString s;
for (const char *cp = filters.ascii (); *cp; ++cp) {
if (cp[0] == ';' && cp[1] == ';') {
slist << s;
++cp;
s = "";
} else {
s += *cp;
QStringList filters = fs.split (tl::to_qstring (";;"));
for (auto f = filters.begin (); f != filters.end (); ++f) {
if (*f == selected_filter) {
return int (f - filters.begin ());
}
}
if (s != "") {
slist << s;
}
return -1;
}
std::string
FileDialog::add_default_extension (const std::string &path, const QString &selected_filter)
{
if (tl::extension (path).empty ()) {
std::string sf = tl::to_string (selected_filter);
auto star = sf.find ("*.");
if (star != std::string::npos) {
tl::Extractor ex (sf.c_str () + star + 2);
std::string ext;
if (ex.try_read_word (ext)) {
return path + "." + ext;
}
}
}
return path;
}
int
FileDialog::selected_filter () const
{
return find_selected_filter (m_filters, m_sel_filter);
}
#endif
bool
FileDialog::get_open (std::string &fp, const std::string &title)
{
#if 1
// Use the standard (system) dialogs:
QString file_name;
@ -107,54 +130,11 @@ FileDialog::get_open (std::string &fp, const std::string &title)
} else {
return false;
}
#else
QString file_name;
if (! fp.empty ()) {
QFileInfo fi (fp.c_str ());
m_dir = fi.absoluteDir ();
file_name = fi.fileName ();
}
QFileDialog fdia (QApplication::activeWindow ());
fdia.setDirectory (m_dir);
if (m_def_suffix != "") {
fdia.setDefaultSuffix (m_def_suffix);
}
QStringList types;
split_filters (m_filters, types);
fdia.setFilters (types);
fdia.setReadOnly (true);
fdia.setViewMode (QFileDialog::Detail);
fdia.setFileMode (QFileDialog::ExistingFile);
fdia.setAcceptMode (QFileDialog::AcceptOpen);
fdia.setConfirmOverwrite (true);
fdia.setCaption (QString (tl::to_string (QObject::tr ("Open ")).c_str ()) + (title.empty () ? m_title : tl::to_qstring (title)));
if (! file_name.isEmpty ()) {
fdia.selectFile (file_name);
}
QStringList files;
if (fdia.exec ()) {
files = fdia.selectedFiles();
if (files.size () > 0) {
fp = tl::to_string (files [0]);
QFileInfo fi (files [0]);
m_dir = fi.absoluteDir ();
return true;
}
}
return false;
#endif
}
bool
FileDialog::get_open (std::vector<std::string> &fp, const std::string &dir, const std::string &title)
{
#if 1
// Use the standard (system) dialogs:
if (! dir.empty ()) {
@ -175,68 +155,11 @@ FileDialog::get_open (std::vector<std::string> &fp, const std::string &dir, cons
} else {
return false;
}
#else
if (! dir.empty ()) {
QDir fi (dir.c_str ());
m_dir = fi.absolutePath ();
}
QStringList file_names;
for (std::vector<std::string>::const_iterator f = fp.begin (); f != fp.end (); ++f) {
QFileInfo fi (f->c_str ());
m_dir = fi.absoluteDir ();
file_names << QString (f->c_str ());
}
QFileDialog fdia (QApplication::activeWindow ());
fdia.setDirectory (m_dir);
if (m_def_suffix != "") {
fdia.setDefaultSuffix (m_def_suffix);
}
QStringList types;
split_filters (m_filters, types);
fdia.setFilters (types);
fdia.setReadOnly (true);
fdia.setViewMode (QFileDialog::Detail);
fdia.setFileMode (QFileDialog::ExistingFiles);
fdia.setAcceptMode (QFileDialog::AcceptOpen);
fdia.setConfirmOverwrite (true);
fdia.setCaption (QString (tl::to_string (QObject::tr ("Open ")).c_str ()) + (title.empty () ? m_title : tl::to_qstring (title)));
for (QStringList::iterator f = file_names.begin (); f != file_names.end (); ++f) {
fdia.selectFile (*f);
}
QStringList files;
if (fdia.exec ()) {
files = fdia.selectedFiles();
if (! files.isEmpty ()) {
fp.clear ();
for (QStringList::iterator f = files.begin (); f != files.end (); ++f) {
fp.push_back (tl::to_string (*f));
QFileInfo fi (*f);
m_dir = fi.absoluteDir ();
}
return true;
}
}
return false;
#endif
}
bool
FileDialog::get_save (std::string &fp, const std::string &title)
{
#if 1
// Use the standard (system) dialogs:
QString file_name;
@ -251,55 +174,16 @@ FileDialog::get_save (std::string &fp, const std::string &title)
QString f = QFileDialog::getSaveFileName (QApplication::activeWindow (), (title.empty () ? m_title : tl::to_qstring (title)), file_name, m_filters, &m_sel_filter);
if (! f.isEmpty ()) {
fp = tl::to_string (f);
fp = add_default_extension (tl::to_string (f), m_sel_filter);
QFileInfo fi (f);
m_dir = fi.absoluteDir ();
return true;
} else {
return false;
}
#else
QString file_name;
if (! fp.empty ()) {
QFileInfo fi (fp.c_str ());
m_dir = fi.absoluteDir ();
file_name = fi.fileName ();
}
QFileDialog fdia (QApplication::activeWindow ());
fdia.setDirectory (m_dir);
if (m_def_suffix != "") {
fdia.setDefaultSuffix (m_def_suffix);
}
QStringList types;
split_filters (m_filters, types);
fdia.setFilters (types);
fdia.setReadOnly (false);
fdia.setViewMode (QFileDialog::Detail);
fdia.setFileMode (QFileDialog::AnyFile);
fdia.setAcceptMode (QFileDialog::AcceptSave);
fdia.setConfirmOverwrite (true);
fdia.setCaption (QString (tl::to_string (QObject::tr ("Save ")).c_str ()) + (title.empty () ? m_title : tl::to_qstring (title)));
if (! file_name.isEmpty ()) {
fdia.selectFile (file_name);
}
QStringList files;
if (fdia.exec ()) {
files = fdia.selectedFiles();
if (files.size () > 0) {
fp = tl::to_string (files [0]);
QFileInfo fi (files [0]);
m_dir = fi.absoluteDir ();
return true;
}
}
return false;
#endif
}
} // namespace lay

View File

@ -65,20 +65,27 @@ public:
~FileDialog ();
/**
* @brief Get a file name to read
* @brief Gets a file name to read
*/
bool get_open (std::string &file_name, const std::string &title = std::string ());
/**
* @brief Read multiple files names
* @brief Reads multiple files names
*/
bool get_open (std::vector<std::string> &file_names, const std::string &dir = std::string (), const std::string &title = std::string ());
/**
* @brief Get a file name to save
* @brief Gets a file name to save
*/
bool get_save (std::string &file_name, const std::string &title = std::string ());
/**
* @brief Gets the selected filter or -1 if no specific filter was selected
*
* This value is only set after get_open or get_save returned true
*/
int selected_filter () const;
/**
* @brief Make the file names use UTF8 encoding
*
@ -87,6 +94,16 @@ public:
*/
static void set_utf8 (bool utf);
/**
* @brief Gets the index of the selected filter from the filter list
*/
static int find_selected_filter (const QString &filters, const QString &selected_filter);
/**
* @brief Adds the default extension unless there is one already
*/
static std::string add_default_extension (const std::string &path, const QString &selected_filter);
private:
QDir m_dir;
QString m_title;

View File

@ -54,7 +54,7 @@ public:
virtual std::string format_name () const { return "CIF"; }
virtual std::string format_desc () const { return "CIF"; }
virtual std::string format_title () const { return "CIF (Caltech interchange format)"; }
virtual std::string file_format () const { return "CIF files (*.CIF *.cif *.cif.gz *.CIF.gz)"; }
virtual std::string file_format () const { return "CIF files (*.cif *.CIF *.cif.gz *.CIF.gz)"; }
static tl::Extractor &skip_blanks (tl::Extractor &ex)
{

View File

@ -54,7 +54,7 @@ public:
virtual std::string format_name () const { return "DXF"; }
virtual std::string format_desc () const { return "DXF"; }
virtual std::string format_title () const { return "DXF (AutoCAD)"; }
virtual std::string file_format () const { return "DXF files (*.DXF *.dxf *.dxf.gz *.DXF.gz)"; }
virtual std::string file_format () const { return "DXF files (*.dxf *.DXF *.dxf.gz *.DXF.gz)"; }
virtual bool detect (tl::InputStream &s) const
{

View File

@ -38,7 +38,7 @@ class GDS2FormatDeclaration
virtual std::string format_name () const { return "GDS2"; }
virtual std::string format_desc () const { return "GDS2"; }
virtual std::string format_title () const { return "GDS2"; }
virtual std::string file_format () const { return "GDS2 files (*.GDS *.gds *.gds.gz *.GDS.gz *.GDS2 *.gds2 *.gds2.gz *.GDS2.gz)"; }
virtual std::string file_format () const { return "GDS2 files (*.gds *.GDS *.gds.gz *.GDS.gz *.GDS2 *.gds2 *.gds2.gz *.GDS2.gz)"; }
virtual bool detect (tl::InputStream &stream) const
{

View File

@ -54,7 +54,7 @@ public:
virtual std::string format_name () const { return "MAG"; }
virtual std::string format_desc () const { return "Magic"; }
virtual std::string format_title () const { return "MAG (Magic layout format)"; }
virtual std::string file_format () const { return "Magic files (*.MAG *.mag *.mag.gz *.MAG.gz)"; }
virtual std::string file_format () const { return "Magic files (*.mag *.MAG *.mag.gz *.MAG.gz)"; }
virtual bool detect (tl::InputStream &s) const
{

View File

@ -436,7 +436,7 @@ public:
virtual std::string format_name () const { return "OASIS"; }
virtual std::string format_desc () const { return "OASIS"; }
virtual std::string format_title () const { return "OASIS"; }
virtual std::string file_format () const { return "OASIS files (*.OAS *.oas *.oas.gz *.OAS.gz)"; }
virtual std::string file_format () const { return "OASIS files (*.oas *.OAS *.oas.gz *.OAS.gz)"; }
virtual bool detect (tl::InputStream &stream) const
{

View File

@ -1168,7 +1168,7 @@ class GerberFormatDeclaration
virtual std::string format_name () const { return "GerberPCB"; }
virtual std::string format_desc () const { return "Gerber PCB"; }
virtual std::string format_title () const { return "Gerber PCB (project files)"; }
virtual std::string file_format () const { return "Gerber PCB project files (*.pcb)"; }
virtual std::string file_format () const { return "Gerber PCB project files (*.pcb *.PCB)"; }
virtual bool detect (tl::InputStream &stream) const
{