diff --git a/src/layui/layui/gsiDeclLayDialogs.cc b/src/layui/layui/gsiDeclLayDialogs.cc index e6e4bad67..c08a774fe 100644 --- a/src/layui/layui/gsiDeclLayDialogs.cc +++ b/src/layui/layui/gsiDeclLayDialogs.cc @@ -26,6 +26,7 @@ #include "gsiDeclBasic.h" #include "layBrowserDialog.h" #include "layBrowserPanel.h" +#include "layFileDialog.h" #include #include @@ -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 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" diff --git a/src/layui/layui/layFileDialog.cc b/src/layui/layui/layFileDialog.cc index 2a9ad2615..4e7280bcd 100644 --- a/src/layui/layui/layFileDialog.cc +++ b/src/layui/layui/layFileDialog.cc @@ -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 &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 &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::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 diff --git a/src/layui/layui/layFileDialog.h b/src/layui/layui/layFileDialog.h index b1cd0d626..823d23b27 100644 --- a/src/layui/layui/layFileDialog.h +++ b/src/layui/layui/layFileDialog.h @@ -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 &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; diff --git a/src/plugins/streamers/cif/db_plugin/dbCIF.cc b/src/plugins/streamers/cif/db_plugin/dbCIF.cc index f56600e25..abf5f4edc 100644 --- a/src/plugins/streamers/cif/db_plugin/dbCIF.cc +++ b/src/plugins/streamers/cif/db_plugin/dbCIF.cc @@ -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) { diff --git a/src/plugins/streamers/dxf/db_plugin/dbDXF.cc b/src/plugins/streamers/dxf/db_plugin/dbDXF.cc index 18b0a7525..3954d4916 100644 --- a/src/plugins/streamers/dxf/db_plugin/dbDXF.cc +++ b/src/plugins/streamers/dxf/db_plugin/dbDXF.cc @@ -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 { diff --git a/src/plugins/streamers/gds2/db_plugin/dbGDS2.cc b/src/plugins/streamers/gds2/db_plugin/dbGDS2.cc index f5ee8efc7..3ed9e49e5 100644 --- a/src/plugins/streamers/gds2/db_plugin/dbGDS2.cc +++ b/src/plugins/streamers/gds2/db_plugin/dbGDS2.cc @@ -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 { diff --git a/src/plugins/streamers/magic/db_plugin/dbMAG.cc b/src/plugins/streamers/magic/db_plugin/dbMAG.cc index 521d89673..7a30a6222 100644 --- a/src/plugins/streamers/magic/db_plugin/dbMAG.cc +++ b/src/plugins/streamers/magic/db_plugin/dbMAG.cc @@ -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 { diff --git a/src/plugins/streamers/oasis/db_plugin/dbOASIS.cc b/src/plugins/streamers/oasis/db_plugin/dbOASIS.cc index fd015e448..a89456ef1 100644 --- a/src/plugins/streamers/oasis/db_plugin/dbOASIS.cc +++ b/src/plugins/streamers/oasis/db_plugin/dbOASIS.cc @@ -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 { diff --git a/src/plugins/streamers/pcb/db_plugin/dbGerberImporter.cc b/src/plugins/streamers/pcb/db_plugin/dbGerberImporter.cc index 8b8982d24..69e79f597 100644 --- a/src/plugins/streamers/pcb/db_plugin/dbGerberImporter.cc +++ b/src/plugins/streamers/pcb/db_plugin/dbGerberImporter.cc @@ -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 {