diff --git a/po/POTFILES.in b/po/POTFILES.in index 116aadee28..98c98ecb2a 100644 --- a/po/POTFILES.in +++ b/po/POTFILES.in @@ -91,7 +91,6 @@ src/frontends/qt2/floatplacement.C src/frontends/xforms/Alert_pimpl.C src/frontends/xforms/ColorHandler.C src/frontends/xforms/Dialogs.C -src/frontends/xforms/FileDialog.C src/frontends/xforms/FormAboutlyx.C src/frontends/xforms/FormBase.C src/frontends/xforms/FormBibitem.C diff --git a/src/BufferView_pimpl.C b/src/BufferView_pimpl.C index 90c07060ba..d478551551 100644 --- a/src/BufferView_pimpl.C +++ b/src/BufferView_pimpl.C @@ -62,6 +62,7 @@ #include "mathed/formulabase.h" #include "support/filetools.h" +#include "support/globbing.h" #include "support/path_defines.h" #include "support/tostr.h" @@ -73,6 +74,7 @@ using lyx::pos_type; using lyx::support::AddPath; using lyx::support::bformat; +using lyx::support::FileFilterList; using lyx::support::FileSearch; using lyx::support::IsDirWriteable; using lyx::support::MakeDisplayPath; @@ -806,7 +808,8 @@ void BufferView::Pimpl::MenuInsertLyXFile(string const & filen) FileDialog::Result result = fileDlg.open(initpath, - _("*.lyx| LyX Documents (*.lyx)")); + FileFilterList(_("LyX Documents (*.lyx)")), + string()); if (result.first == FileDialog::Later) return; diff --git a/src/ChangeLog b/src/ChangeLog index dcbafa8f0a..4e77f32c3b 100644 --- a/src/ChangeLog +++ b/src/ChangeLog @@ -1,3 +1,10 @@ +2004-01-08 Angus Leeming + + * BufferView_pimpl.C (MenuInsertLyXFile): + * lyx_cb.C (WriteAs, getContentsOfAsciiFile): + * lyxfunc.C (menuNew, open, doImport): + FileFilterList change to the FileDialog open and save functions. + 2004-01-07 Lars Gullik Bjonnes * ShareContainer.h: make isEqual and isUnique adaptable diff --git a/src/frontends/ChangeLog b/src/frontends/ChangeLog index 8324571171..42e140531a 100644 --- a/src/frontends/ChangeLog +++ b/src/frontends/ChangeLog @@ -1,3 +1,8 @@ +2004-01-08 Angus Leeming + + * FileDialog.h (open, save): the file filter mask is now passed + as a FileFilterList rather than as a string. + 2003-11-13 Alfredo Braunstein * screen.[Ch] (fitCursor): use LCursor::getDim, simplify diff --git a/src/frontends/FileDialog.h b/src/frontends/FileDialog.h index 423e8404e1..47949dba81 100644 --- a/src/frontends/FileDialog.h +++ b/src/frontends/FileDialog.h @@ -19,6 +19,16 @@ #include +namespace lyx { +namespace support { + +class FileFilterList; + +} // namespace support +} // namespace lyx + + + /** * \class FileDialog * \brief GUI-I definition of file dialog interface @@ -57,44 +67,23 @@ public: ~FileDialog(); - /** - * Choose a file for opening, starting in directory \param - * path, with the file selection \param mask. The \param mask - * string is of the form : - * - * | - * - * for example, "*.ps | PostScript files (*.ps)". - * - * FIXME: should support multiple lines of these for different file types. - */ - Result const open(std::string const & path = std::string(), - std::string const & mask = std::string(), - std::string const & suggested = std::string()); + /// Choose a file for opening, starting in directory \c path. + Result const open(std::string const & path, + lyx::support::FileFilterList const & filters, + std::string const & suggested); - /** - * Choose a directory, starting in directory \param - * path. - */ + /// Choose a directory, starting in directory \c path. Result const opendir(std::string const & path = std::string(), - std::string const & suggested = std::string()); + std::string const & suggested = std::string()); - /** - * Choose a file for saving, starting in directory \param - * path, with the file selection \param mask. The \param mask - * string is of the form : - * - * | - * - * for example, "*.ps | PostScript files (*.ps)". - */ - Result const save(std::string const & path = std::string(), - std::string const & mask = std::string(), - std::string const & suggested = std::string()); + /// Choose a file for saving, starting in directory \c path. + Result const save(std::string const & path, + lyx::support::FileFilterList const & filters, + std::string const & suggested); - - /* This *has* to be public because there is no way to specify extern "C" functions - * as friends of Private implementation for the xforms implementation ... grr + /* This *has* to be public because there is no way to specify + * extern "C" functions as friends of Private implementation for + * the xforms implementation ... grr */ class Private; friend class Private; diff --git a/src/frontends/controllers/ChangeLog b/src/frontends/controllers/ChangeLog index fc68a40df0..ffca3b01ec 100644 --- a/src/frontends/controllers/ChangeLog +++ b/src/frontends/controllers/ChangeLog @@ -1,3 +1,17 @@ +2004-01-08 Angus Leeming + + * ControlBibtex.[Ch] (browse): + * ControlExternal.[Ch] (browse): + * ControlGraphics.[Ch] (browse): + * ControlInclude.[Ch] (browse): + * ControlPrefs.[Ch] (browsebind, browseUI, browsekbmap, + browsedict, browse, browsedir): + * ControlPrint.[Ch] (browse): + FileFilterList change to the browseFile, browseRelFile functions. + + * helper_funcs.[Ch] (browseFile, browseRelFile): + FileFilterList change to the FileDialog open and save functions. + 2004-01-07 Lars Gullik Bjonnes * ControlSendto.C (allFormats): use the unique-erase idom and diff --git a/src/frontends/controllers/ControlBibtex.C b/src/frontends/controllers/ControlBibtex.C index d513c37504..79a813faf4 100644 --- a/src/frontends/controllers/ControlBibtex.C +++ b/src/frontends/controllers/ControlBibtex.C @@ -20,7 +20,9 @@ #include "gettext.h" #include "support/filetools.h" +#include "support/globbing.h" +using lyx::support::FileFilterList; using lyx::support::OnlyFilename; using std::pair; @@ -33,14 +35,14 @@ ControlBibtex::ControlBibtex(Dialog & d) {} -string const ControlBibtex::Browse(string const & in_name, +string const ControlBibtex::browse(string const & in_name, string const & title, - string const & pattern) + FileFilterList const & filters) const { pair dir1(_("Documents|#o#O"), string(lyxrc.document_path)); return browseRelFile(in_name, kernel().bufferFilepath(), - title, pattern, false, dir1); + title, filters, false, dir1); } diff --git a/src/frontends/controllers/ControlBibtex.h b/src/frontends/controllers/ControlBibtex.h index de881baa8e..7c0bf1826a 100644 --- a/src/frontends/controllers/ControlBibtex.h +++ b/src/frontends/controllers/ControlBibtex.h @@ -18,6 +18,15 @@ #include +namespace lyx { +namespace support { + +class FileFilterList; + +} // namespace support +} // namespace lyx + + /** A controller for Bibtex dialogs. */ class ControlBibtex : public ControlCommand { @@ -26,7 +35,9 @@ public: ControlBibtex(Dialog &); /// Browse for a file - std::string const Browse(std::string const &, std::string const &, std::string const &); + std::string const browse(std::string const & in_name, + std::string const & title, + lyx::support::FileFilterList const & filters) const; /// get the list of bst files void getBibStyles(std::vector & data) const; /// get the list of bib files diff --git a/src/frontends/controllers/ControlExternal.C b/src/frontends/controllers/ControlExternal.C index 69007ce091..ac15b57ea9 100644 --- a/src/frontends/controllers/ControlExternal.C +++ b/src/frontends/controllers/ControlExternal.C @@ -28,10 +28,12 @@ #include "insets/ExternalTemplate.h" #include "support/filetools.h" +#include "support/globbing.h" #include "support/tostr.h" namespace external = lyx::external; +using lyx::support::FileFilterList; using lyx::support::MakeAbsPath; using lyx::support::readBB_from_PSFile; @@ -135,23 +137,27 @@ external::Template ControlExternal::getTemplate(int i) const } -string const ControlExternal::Browse(string const & input) const +string const ControlExternal::browse(string const & input, + string const & template_name) const { string const title = _("Select external file"); string const bufpath = kernel().bufferFilepath(); /// Determine the template file extension - string pattern = "*"; + external::TemplateManager const & etm = + external::TemplateManager::get(); external::Template const * const et_ptr = - external::getTemplatePtr(params()); - if (et_ptr) - pattern = et_ptr->fileRegExp; + etm.getTemplateByName(template_name); + + FileFilterList const filter = et_ptr ? + FileFilterList(et_ptr->fileRegExp) : + FileFilterList(); std::pair dir1(N_("Documents|#o#O"), - string(lyxrc.document_path)); + string(lyxrc.document_path)); - return browseRelFile(input, bufpath, title, pattern, false, dir1); + return browseRelFile(input, bufpath, title, filter, false, dir1); } diff --git a/src/frontends/controllers/ControlExternal.h b/src/frontends/controllers/ControlExternal.h index f1db7bd958..604bc98e93 100644 --- a/src/frontends/controllers/ControlExternal.h +++ b/src/frontends/controllers/ControlExternal.h @@ -28,10 +28,8 @@ class InsetExternalParams; namespace lyx { namespace external { - class Template; class RotationDataType; - } // namespace external } // namespace lyx @@ -63,7 +61,8 @@ public: /// lyx::external::Template getTemplate(int) const; /// - std::string const Browse(std::string const &) const; + std::string const browse(std::string const & input_file, + std::string const & tempalate_name) const; /// Read the Bounding Box from a eps or ps-file std::string const readBB(std::string const & file); diff --git a/src/frontends/controllers/ControlGraphics.C b/src/frontends/controllers/ControlGraphics.C index 2dd18b2b80..d478f1e535 100644 --- a/src/frontends/controllers/ControlGraphics.C +++ b/src/frontends/controllers/ControlGraphics.C @@ -27,11 +27,13 @@ #include "support/FileInfo.h" #include "support/filetools.h" +#include "support/globbing.h" #include "support/path_defines.h" #include "support/tostr.h" #include "support/types.h" using lyx::support::AddName; +using lyx::support::FileFilterList; using lyx::support::FileInfo; using lyx::support::IsFileReadable; using lyx::support::MakeAbsPath; @@ -74,7 +76,7 @@ void ControlGraphics::dispatchParams() } -string const ControlGraphics::Browse(string const & in_name) +string const ControlGraphics::browse(string const & in_name) const { string const title = _("Select graphics file"); @@ -88,7 +90,9 @@ string const ControlGraphics::Browse(string const & in_name) pair dir2(_("Documents|#o#O"), string(lyxrc.document_path)); // Show the file browser dialog return browseRelFile(in_name, kernel().bufferFilepath(), - title, "*.*", false, dir1, dir2); + title, + FileFilterList(), + false, dir1, dir2); } diff --git a/src/frontends/controllers/ControlGraphics.h b/src/frontends/controllers/ControlGraphics.h index 4433125221..cff0959530 100644 --- a/src/frontends/controllers/ControlGraphics.h +++ b/src/frontends/controllers/ControlGraphics.h @@ -44,7 +44,7 @@ public: InsetGraphicsParams const & params() const { return *params_.get(); } /// Browse for a file - std::string const Browse(std::string const &); + std::string const browse(std::string const &) const; /// Read the Bounding Box from a eps or ps-file std::string const readBB(std::string const & file); /// Control the bb diff --git a/src/frontends/controllers/ControlInclude.C b/src/frontends/controllers/ControlInclude.C index f8f8061ff9..513339d96e 100644 --- a/src/frontends/controllers/ControlInclude.C +++ b/src/frontends/controllers/ControlInclude.C @@ -24,9 +24,11 @@ #include "insets/insetinclude.h" #include "support/filetools.h" +#include "support/globbing.h" #include +using lyx::support::FileFilterList; using lyx::support::IsFileReadable; using lyx::support::MakeAbsPath; using lyx::support::OnlyPath; @@ -66,23 +68,18 @@ void ControlInclude::setParams(InsetCommandParams const & params) } -string const ControlInclude::Browse(string const & in_name, Type in_type) +string const ControlInclude::browse(string const & in_name, Type in_type) const { string const title = _("Select document to include"); // input TeX, verbatim, or LyX file ? - string pattern; + FileFilterList filters; switch (in_type) { - case INPUT: - pattern = _("*.(tex|lyx)| LaTeX/LyX Documents (*.tex *.lyx)"); - break; - - case VERBATIM: - pattern = _("*| All files (*)"); - break; - case INCLUDE: - pattern = _("*.(tex|lyx)| LaTeX/LyX Documents (*.tex *.lyx)"); + case INPUT: + filters = FileFilterList(_("LaTeX/LyX Documents (*.tex *.lyx)")); + break; + case VERBATIM: break; } @@ -91,7 +88,8 @@ string const ControlInclude::Browse(string const & in_name, Type in_type) string const docpath = OnlyPath(kernel().buffer().fileName()); - return browseRelFile(in_name, docpath, title, pattern, false, dir1); + return browseRelFile(in_name, docpath, title, + filters, false, dir1); } diff --git a/src/frontends/controllers/ControlInclude.h b/src/frontends/controllers/ControlInclude.h index 6a011ccd5f..eeb62c3f94 100644 --- a/src/frontends/controllers/ControlInclude.h +++ b/src/frontends/controllers/ControlInclude.h @@ -50,7 +50,7 @@ public: void setParams(InsetCommandParams const &); /// Browse for a file - std::string const Browse(std::string const &, Type); + std::string const browse(std::string const &, Type) const; /// load a file void load(std::string const & file); diff --git a/src/frontends/controllers/ControlPrefs.C b/src/frontends/controllers/ControlPrefs.C index b5e1f4bb05..35b225e2b7 100644 --- a/src/frontends/controllers/ControlPrefs.C +++ b/src/frontends/controllers/ControlPrefs.C @@ -27,11 +27,13 @@ #include "frontends/LyXView.h" #include "support/filetools.h" +#include "support/globbing.h" #include "support/path_defines.h" #include using lyx::support::AddName; +using lyx::support::FileFilterList; using lyx::support::system_lyxdir; using lyx::support::user_lyxdir; @@ -66,7 +68,7 @@ void ControlPrefs::apply() } -string const ControlPrefs::browsebind(string const & file) +string const ControlPrefs::browsebind(string const & file) const { string dir = AddName(system_lyxdir(), "bind"); // FIXME: stupid name @@ -78,11 +80,12 @@ string const ControlPrefs::browsebind(string const & file) name = _("User Bind|#U#u"); pair dir2(name, dir); - return browseFile(file, _("Choose bind file"), "*.bind", false, dir1, dir2); + return browseFile(file, _("Choose bind file"), + FileFilterList("*.bind"), false, dir1, dir2); } -string const ControlPrefs::browseUI(string const & file) +string const ControlPrefs::browseUI(string const & file) const { string dir = AddName(system_lyxdir(), "ui"); // FIXME: stupid name @@ -94,33 +97,38 @@ string const ControlPrefs::browseUI(string const & file) name = _("User UI|#U#u"); pair dir2(name, dir); - return browseFile(file, _("Choose UI file"), "*.ui", false, dir1, dir2); + return browseFile(file, _("Choose UI file"), + FileFilterList("*.ui"), false, dir1, dir2); } -string const ControlPrefs::browsekbmap(string const & file) +string const ControlPrefs::browsekbmap(string const & file) const { string const dir = AddName(system_lyxdir(), "kbd"); string const name = _("Key maps|#K#k"); pair dir1(name, dir); - return browseFile(file, _("Choose keyboard map"), "*.kmap", false, dir1); + return browseFile(file, _("Choose keyboard map"), + FileFilterList("*.kmap"), false, dir1); } -string const ControlPrefs::browsedict(string const & file) +string const ControlPrefs::browsedict(string const & file) const { - return browseFile(file, _("Choose personal dictionary"), "*.ispell"); + return browseFile(file, _("Choose personal dictionary"), + FileFilterList("*.ispell")); } -string const ControlPrefs::browse(string const & file, string const & title) +string const ControlPrefs::browse(string const & file, + string const & title) const { - return browseFile(file, title, "*", true); + return browseFile(file, title, FileFilterList(), true); } -string const ControlPrefs::browsedir(string const & path, string const & title) +string const ControlPrefs::browsedir(string const & path, + string const & title) const { return browseDir(path, title); } diff --git a/src/frontends/controllers/ControlPrefs.h b/src/frontends/controllers/ControlPrefs.h index aa54bb41df..3e2f0768ee 100644 --- a/src/frontends/controllers/ControlPrefs.h +++ b/src/frontends/controllers/ControlPrefs.h @@ -34,16 +34,18 @@ public: LyXRC const & rc() const { return rc_; } /// various file pickers - std::string const browsebind(std::string const & file); - std::string const browseUI(std::string const & file); - std::string const browsekbmap(std::string const & file); - std::string const browsedict(std::string const & file); + std::string const browsebind(std::string const & file) const; + std::string const browseUI(std::string const & file) const; + std::string const browsekbmap(std::string const & file) const; + std::string const browsedict(std::string const & file) const; /// general browse - std::string const browse(std::string const & file, std::string const & title); + std::string const browse(std::string const & file, + std::string const & title) const; /// browse directory - std::string const browsedir(std::string const & path, std::string const & title); + std::string const browsedir(std::string const & path, + std::string const & title) const; /// redraw widgets (for xforms color change) void redrawGUI(); diff --git a/src/frontends/controllers/ControlPrint.C b/src/frontends/controllers/ControlPrint.C index 55ea077ade..8c3fb6c829 100644 --- a/src/frontends/controllers/ControlPrint.C +++ b/src/frontends/controllers/ControlPrint.C @@ -26,6 +26,7 @@ #include "support/tostr.h" #include "support/filetools.h" +#include "support/globbing.h" #include "support/path.h" #include "support/systemcall.h" @@ -33,6 +34,7 @@ using lyx::support::bformat; using lyx::support::ChangeExtension; +using lyx::support::FileFilterList; using lyx::support::IsDirWriteable; using lyx::support::MakeAbsPath; using lyx::support::MakeDisplayPath; @@ -80,14 +82,12 @@ void ControlPrint::clearParams() } -string const ControlPrint::Browse(string const & in_name) +string const ControlPrint::browse(string const & in_name) const { - string const title = _("Print to file"); - string const pattern = "*.ps"; - - // Show the file browser dialog - return browseRelFile(in_name, buffer()->filePath(), - title, pattern, true); + return browseRelFile(in_name, buffer().filePath(), + _("Print to file"), + FileFilterList("PostScript files (*.ps)"), + true); } diff --git a/src/frontends/controllers/ControlPrint.h b/src/frontends/controllers/ControlPrint.h index f02df010b1..99d60256ba 100644 --- a/src/frontends/controllers/ControlPrint.h +++ b/src/frontends/controllers/ControlPrint.h @@ -27,7 +27,7 @@ public: ControlPrint(LyXView &, Dialogs &); /// Browse for a file - std::string const Browse(std::string const &); + std::string const browse(std::string const &) const; /// PrinterParams & params() const; private: diff --git a/src/frontends/controllers/helper_funcs.C b/src/frontends/controllers/helper_funcs.C index 9ae3f80ed7..9c82f5763d 100644 --- a/src/frontends/controllers/helper_funcs.C +++ b/src/frontends/controllers/helper_funcs.C @@ -19,7 +19,9 @@ #include "frontends/FileDialog.h" #include "support/filetools.h" // OnlyPath, OnlyFilename +#include "support/globbing.h" +using lyx::support::FileFilterList; using lyx::support::MakeAbsPath; using lyx::support::MakeRelPath; using lyx::support::OnlyFilename; @@ -33,7 +35,7 @@ using std::string; string const browseFile(string const & filename, string const & title, - string const & pattern, + FileFilterList const & filters, bool save, pair const & dir1, pair const & dir2) @@ -48,10 +50,10 @@ string const browseFile(string const & filename, while (true) { if (save) - result = fileDlg.save(lastPath, pattern, + result = fileDlg.save(lastPath, filters, OnlyFilename(filename)); else - result = fileDlg.open(lastPath, pattern, + result = fileDlg.open(lastPath, filters, OnlyFilename(filename)); if (result.second.empty()) @@ -73,16 +75,16 @@ string const browseFile(string const & filename, string const browseRelFile(string const & filename, - string const & refpath, - string const & title, - string const & pattern, - bool save, - pair const & dir1, - pair const & dir2) + string const & refpath, + string const & title, + FileFilterList const & filters, + bool save, + pair const & dir1, + pair const & dir2) { string const fname = MakeAbsPath(filename, refpath); - string const outname = browseFile(fname, title, pattern, save, + string const outname = browseFile(fname, title, filters, save, dir1, dir2); string const reloutname = MakeRelPath(outname, refpath); if (prefixIs(reloutname, "../")) diff --git a/src/frontends/controllers/helper_funcs.h b/src/frontends/controllers/helper_funcs.h index 6f0d73de31..5673c8f27c 100644 --- a/src/frontends/controllers/helper_funcs.h +++ b/src/frontends/controllers/helper_funcs.h @@ -12,11 +12,18 @@ #ifndef HELPERFUNCS_H #define HELPERFUNCS_H +#include #include #include #include +namespace lyx { +namespace support { +class FileFilterList; +} // namespace support +} // namespace lyx + /** Launch a file dialog and return the chosen file. filename: a suggested filename. title: the title of the dialog. @@ -26,7 +33,7 @@ std::string const browseFile(std::string const & filename, std::string const & title, - std::string const & pattern, + lyx::support::FileFilterList const & filters, bool save = false, std::pair const & dir1 = std::make_pair(std::string(), std::string()), @@ -44,7 +51,7 @@ std::string const browseRelFile(std::string const & filename, std::string const & refpath, std::string const & title, - std::string const & pattern, + lyx::support::FileFilterList const & filters, bool save = false, std::pair const & dir1 = std::make_pair(std::string(), std::string()), @@ -73,44 +80,24 @@ std::vector const getLatexUnits(); /** Functions to extract vectors of the first and second elems from a vector > */ - -namespace detail { - -template -struct firster { - typedef typename Pair::first_type first_type; - first_type const & operator()(Pair const & p) { return p.first; } -}; - -template -struct seconder { - typedef typename Pair::second_type second_type; - second_type const & operator()(Pair const & p) { return p.second; } -}; - -} // namespace detail - -/// template std::vector const getFirst(std::vector const & pr) { std::vector tmp(pr.size()); std::transform(pr.begin(), pr.end(), tmp.begin(), - detail::firster()); + boost::bind(&Pair::first, _1)); return tmp; } -/// template std::vector const getSecond(std::vector const & pr) { std::vector tmp(pr.size()); std::transform(pr.begin(), pr.end(), tmp.begin(), - detail::seconder()); + boost::bind(&Pair::second, _1)); return tmp; } - -#endif // HELPERFUNCS_H +#endif // NOT HELPERFUNCS_H diff --git a/src/frontends/qt2/ChangeLog b/src/frontends/qt2/ChangeLog index 472872f955..86a96b3822 100644 --- a/src/frontends/qt2/ChangeLog +++ b/src/frontends/qt2/ChangeLog @@ -1,3 +1,16 @@ +2004-01-08 Angus Leeming + + * FileDialog.C (open, save): + * FileDialog_private.[Ch] (c-tor): + the file filter mask is now passed as a FileFilterList rather than + as a string. + + * QExternalDialog.C (browseClicked): + * QGraphicsDialog.C (browse_clicked): + * QInclude.C (browse): + changes doe to the name change controller().Browse() to + controller().browse(). + 2003-12-15 Ronald Florence * qfont_loader.C: fixed headers to compile w/o X11 diff --git a/src/frontends/qt2/FileDialog.C b/src/frontends/qt2/FileDialog.C index 0938cd8135..8622ae6dd9 100644 --- a/src/frontends/qt2/FileDialog.C +++ b/src/frontends/qt2/FileDialog.C @@ -11,13 +11,21 @@ #include -#include "debug.h" #include "frontends/FileDialog.h" -#include "FileDialog_private.h" -#include "qt_helpers.h" + +#include "debug.h" #include "gettext.h" +#include "support/globbing.h" + +#include "FileDialog_private.h" +#include "qt_helpers.h" + + +using lyx::support::FileFilterList; + using std::endl; +using std::string; struct FileDialog::Private { @@ -26,7 +34,7 @@ struct FileDialog::Private { }; -FileDialog::FileDialog(std::string const & t, +FileDialog::FileDialog(string const & t, kb_action s, Button b1, Button b2) : private_(new FileDialog::Private), title_(t), success_(s) { @@ -41,17 +49,13 @@ FileDialog::~FileDialog() } -FileDialog::Result const FileDialog::save(std::string const & path, - std::string const & mask, - std::string const & suggested) +FileDialog::Result const FileDialog::save(string const & path, + FileFilterList const & filters, + string const & suggested) { - std::string filter(mask); - if (mask.empty()) - filter = _("All files (*)"); - - LyXFileDialog dlg(path, filter, title_, private_->b1, private_->b2); + LyXFileDialog dlg(path, filters, title_, private_->b1, private_->b2); lyxerr[Debug::GUI] << "Select with path \"" << path - << "\", mask \"" << filter + << "\", mask \"" << filters.str(false) << "\", suggested \"" << suggested << endl; dlg.setMode(QFileDialog::AnyFile); @@ -71,17 +75,13 @@ FileDialog::Result const FileDialog::save(std::string const & path, } -FileDialog::Result const FileDialog::open(std::string const & path, - std::string const & mask, - std::string const & suggested) +FileDialog::Result const FileDialog::open(string const & path, + FileFilterList const & filters, + string const & suggested) { - std::string filter(mask); - if (mask.empty()) - filter = _("All files (*)"); - - LyXFileDialog dlg(path, filter, title_, private_->b1, private_->b2); + LyXFileDialog dlg(path, filters, title_, private_->b1, private_->b2); lyxerr[Debug::GUI] << "Select with path \"" << path - << "\", mask \"" << filter + << "\", mask \"" << filters.str(false) << "\", suggested \"" << suggested << endl; if (!suggested.empty()) @@ -99,10 +99,10 @@ FileDialog::Result const FileDialog::open(std::string const & path, } -FileDialog::Result const FileDialog::opendir(std::string const & path, - std::string const & suggested) +FileDialog::Result const FileDialog::opendir(string const & path, + string const & suggested) { - std::string filter = _("Directories"); + FileFilterList const filter(_("Directories")); LyXFileDialog dlg(path, filter, title_, private_->b1, private_->b2); lyxerr[Debug::GUI] << "Select with path \"" << path diff --git a/src/frontends/qt2/FileDialog_private.C b/src/frontends/qt2/FileDialog_private.C index 01acfdf1fd..bada6eff9c 100644 --- a/src/frontends/qt2/FileDialog_private.C +++ b/src/frontends/qt2/FileDialog_private.C @@ -20,7 +20,6 @@ #include #include -using lyx::support::convert_brace_glob; using lyx::support::split; using std::string; @@ -44,10 +43,12 @@ string const getLabel(string const & str) { } // namespace anon -LyXFileDialog::LyXFileDialog(string const & p, string const & m, +LyXFileDialog::LyXFileDialog(string const & p, + lyx::support::FileFilterList const & filters, string const & t, - FileDialog::Button const & b1, FileDialog::Button const & b2) - : QFileDialog(toqstr(p), toqstr(convert_brace_glob(m)), + FileDialog::Button const & b1, + FileDialog::Button const & b2) + : QFileDialog(toqstr(p), toqstr(filters.str(true)), qApp->focusWidget() ? qApp->focusWidget() : qApp->mainWidget(), toqstr(t), true), b1_(0), b2_(0) { diff --git a/src/frontends/qt2/FileDialog_private.h b/src/frontends/qt2/FileDialog_private.h index 2029ad4504..cbaca73ff7 100644 --- a/src/frontends/qt2/FileDialog_private.h +++ b/src/frontends/qt2/FileDialog_private.h @@ -16,13 +16,24 @@ #include "frontends/FileDialog.h" #include +namespace lyx { +namespace support { + +class FileFilterList; + +} // namespace support +} // namespace lyx + + class QToolButton; class LyXFileDialog : public QFileDialog { Q_OBJECT public: - LyXFileDialog(std::string const & p, std::string const & m, std::string const & t, + LyXFileDialog(std::string const & path, + lyx::support::FileFilterList const & filters, + std::string const & title, FileDialog::Button const & b1, FileDialog::Button const & b2); public slots: diff --git a/src/frontends/qt2/QExternalDialog.C b/src/frontends/qt2/QExternalDialog.C index e8286ed306..c579a014ff 100644 --- a/src/frontends/qt2/QExternalDialog.C +++ b/src/frontends/qt2/QExternalDialog.C @@ -11,6 +11,8 @@ #include +#include "insets/ExternalTemplate.h" + #include "controllers/ButtonController.h" #include "controllers/ControlExternal.h" @@ -124,8 +126,12 @@ void QExternalDialog::bbChanged() void QExternalDialog::browseClicked() { + int const choice = externalCO->currentItem(); + string const template_name = + form_->controller().getTemplate(choice).lyxName; string const str = - form_->controller().Browse(fromqstr(fileED->text())); + form_->controller().browse(fromqstr(fileED->text()), + template_name); fileED->setText(toqstr(str)); form_->changed(); } diff --git a/src/frontends/qt2/QGraphicsDialog.C b/src/frontends/qt2/QGraphicsDialog.C index 9fc6a5b80e..195abf78a3 100644 --- a/src/frontends/qt2/QGraphicsDialog.C +++ b/src/frontends/qt2/QGraphicsDialog.C @@ -83,7 +83,7 @@ void QGraphicsDialog::closeEvent(QCloseEvent * e) void QGraphicsDialog::browse_clicked() { string const str = - form_->controller().Browse(fromqstr(filename->text())); + form_->controller().browse(fromqstr(filename->text())); filename->setText(toqstr(str)); form_->changed(); } diff --git a/src/frontends/qt2/QInclude.C b/src/frontends/qt2/QInclude.C index bc7f3dc97b..d5f9959b80 100644 --- a/src/frontends/qt2/QInclude.C +++ b/src/frontends/qt2/QInclude.C @@ -118,7 +118,7 @@ void QInclude::browse() else type = ControlInclude::VERBATIM; - string const & name = controller().Browse(fromqstr(dialog_->filenameED->text()), type); + string const & name = controller().browse(fromqstr(dialog_->filenameED->text()), type); if (!name.empty()) dialog_->filenameED->setText(toqstr(name)); } diff --git a/src/frontends/xforms/ChangeLog b/src/frontends/xforms/ChangeLog index 150ca6c2da..8768f0907e 100644 --- a/src/frontends/xforms/ChangeLog +++ b/src/frontends/xforms/ChangeLog @@ -1,3 +1,16 @@ +2004-01-08 Angus Leeming + + * FileDialog.C (open, save): + * FormFileDialog: + the file filter mask is now passed as a FileFilterList rather than + as a string. + + * QExternalDialog.C (browseClicked): + * QGraphicsDialog.C (browse_clicked): + * QInclude.C (browse): + changes doe to the name change controller().Browse() to + controller().browse(). + 2004-01-07 Lars Gullik Bjonnes * FormForks.C: make FindPID adaptable and constify operator() diff --git a/src/frontends/xforms/FileDialog.C b/src/frontends/xforms/FileDialog.C index 9a2ba425c9..43ef10feb1 100644 --- a/src/frontends/xforms/FileDialog.C +++ b/src/frontends/xforms/FileDialog.C @@ -16,9 +16,11 @@ #include "debug.h" #include "gettext.h" +#include "support/globbing.h" #include "support/lstrings.h" using lyx::support::rsplit; +using lyx::support::FileFilterList; using std::endl; using std::string; @@ -40,9 +42,11 @@ FileDialog::~FileDialog() } -FileDialog::Result const FileDialog::save(string const & path, string const & mask, string const & suggested) +FileDialog::Result const FileDialog::save(string const & path, + FileFilterList const & filters, + string const & suggested) { - return open(path, mask, suggested); + return open(path, filters, suggested); } @@ -62,21 +66,20 @@ FileDialog::Result const FileDialog::opendir(string const & path, string const & } -FileDialog::Result const FileDialog::open(string const & path, string const & mask, string const & suggested) +FileDialog::Result const FileDialog::open(string const & path, + FileFilterList const & filters, + string const & suggested) { - string filter = mask; - if (filter.empty()) - filter = "*"; - - lyxerr[Debug::GUI] << "filedialog open with path \"" << path << "\", mask \"" - << filter << "\", suggested \"" << suggested << '"' << endl; + lyxerr[Debug::GUI] << "filedialog open with path \"" << path + << "\", mask \"" << filters.str(false) + << "\", suggested \"" << suggested << '"' << endl; // no support for asynchronous selection yet FileDialog::Result result; result.first = FileDialog::Chosen; - result.second = private_->Select(title_, path, filter, suggested); + result.second = private_->Select(title_, path, filters, suggested); return result; } diff --git a/src/frontends/xforms/FormBibtex.C b/src/frontends/xforms/FormBibtex.C index 0680b60d19..71416187e1 100644 --- a/src/frontends/xforms/FormBibtex.C +++ b/src/frontends/xforms/FormBibtex.C @@ -22,6 +22,7 @@ #include "xformsBC.h" #include "support/filetools.h" +#include "support/globbing.h" #include "support/lstrings.h" #include "support/lyxalgo.h" @@ -30,6 +31,7 @@ using lyx::support::ChangeExtension; using lyx::support::compare; using lyx::support::contains; +using lyx::support::FileFilterList; using lyx::support::getStringFromVector; using lyx::support::getVectorFromString; using lyx::support::OnlyFilename; @@ -113,10 +115,11 @@ ButtonPolicy::SMInput FormBibtex::input(FL_OBJECT * ob, long ob_value) if (ob == dialog_->button_database_browse) { // When browsing, take the first file only string const in_name = getString(dialog_->input_database); + FileFilterList const + filter(_("*.bib| BibTeX Databases (*.bib)")); string out_name = - controller().Browse("", - _("Select Database"), - _("*.bib| BibTeX Databases (*.bib)")); + controller().browse("", _("Select Database"), + filter); if (!out_name.empty()) { // add the database to any existing ones if (!in_name.empty()) @@ -127,9 +130,10 @@ ButtonPolicy::SMInput FormBibtex::input(FL_OBJECT * ob, long ob_value) } else if (ob == dialog_->button_style_browse) { string const in_name = getString(dialog_->input_style); - string const style = controller().Browse(in_name, - _("Select BibTeX-Style"), - _("*.bst| BibTeX Styles (*.bst)")); + FileFilterList const + filter(_("*.bst| BibTeX Styles (*.bst)")); + string const style = controller() + .browse(in_name, _("Select BibTeX-Style"), filter); if (!style.empty()) { fl_set_input(dialog_->input_style, style.c_str()); } diff --git a/src/frontends/xforms/FormExternal.C b/src/frontends/xforms/FormExternal.C index db52d959f8..dfc7d0c4a2 100644 --- a/src/frontends/xforms/FormExternal.C +++ b/src/frontends/xforms/FormExternal.C @@ -629,7 +629,12 @@ ButtonPolicy::SMInput FormExternal::input(FL_OBJECT * ob, long) } else if (ob == file_->button_browse) { string const in_name = fl_get_input(file_->input_file); - string const out_name = controller().Browse(in_name); + + int const choice = fl_get_choice(file_->choice_template) - 1; + string const template_name = + controller().getTemplate(choice).lyxName; + string const out_name = + controller().browse(in_name, template_name); fl_set_input(file_->input_file, out_name.c_str()); } else if (ob == file_->button_edit) { diff --git a/src/frontends/xforms/FormFiledialog.C b/src/frontends/xforms/FormFiledialog.C index 7ae6fc843b..60e32ba098 100644 --- a/src/frontends/xforms/FormFiledialog.C +++ b/src/frontends/xforms/FormFiledialog.C @@ -58,6 +58,7 @@ using lyx::support::AbsolutePath; using lyx::support::AddName; using lyx::support::ExpandPath; +using lyx::support::FileFilterList; using lyx::support::FileInfo; using lyx::support::getcwd; using lyx::support::GetEnvPath; @@ -394,13 +395,16 @@ void FileDialog::Private::SetDirectory(string const & path) } -// SetMask: sets dialog file mask -void FileDialog::Private::SetMask(string const & newmask) +void FileDialog::Private::SetFilters(string const & mask) { - mask_ = trim(newmask); - if (mask_.empty()) - mask_ = "*"; + SetFilters(FileFilterList(mask)); +} + +void FileDialog::Private::SetFilters(FileFilterList const & filters) +{ + // Just take the first one for now. + mask_ = filters.filters()[0].globs(); fl_set_input(file_dlg_form_->PatBox, mask_.c_str()); } @@ -416,7 +420,6 @@ void FileDialog::Private::SetInfoLine(string const & line) FileDialog::Private::Private() { directory_ = MakeAbsPath(string(".")); - mask_ = "*"; // Creates form if necessary. if (!file_dlg_form_) { @@ -552,7 +555,7 @@ void FileDialog::Private::FileDlgCB(FL_OBJECT *, long arg) break; case 1: // get mask - current_dlg_->SetMask(fl_get_input(file_dlg_form_->PatBox)); + current_dlg_->SetFilters(fl_get_input(file_dlg_form_->PatBox)); current_dlg_->Reread(); break; @@ -562,25 +565,25 @@ void FileDialog::Private::FileDlgCB(FL_OBJECT *, long arg) case 10: // rescan current_dlg_->SetDirectory(fl_get_input(file_dlg_form_->DirBox)); - current_dlg_->SetMask(fl_get_input(file_dlg_form_->PatBox)); + current_dlg_->SetFilters(fl_get_input(file_dlg_form_->PatBox)); current_dlg_->Reread(); break; case 11: // home current_dlg_->SetDirectory(GetEnvPath("HOME")); - current_dlg_->SetMask(fl_get_input(file_dlg_form_->PatBox)); + current_dlg_->SetFilters(fl_get_input(file_dlg_form_->PatBox)); current_dlg_->Reread(); break; case 12: // user button 1 current_dlg_->SetDirectory(current_dlg_->user_path1_); - current_dlg_->SetMask(fl_get_input(file_dlg_form_->PatBox)); + current_dlg_->SetFilters(fl_get_input(file_dlg_form_->PatBox)); current_dlg_->Reread(); break; case 13: // user button 2 current_dlg_->SetDirectory(current_dlg_->user_path2_); - current_dlg_->SetMask(fl_get_input(file_dlg_form_->PatBox)); + current_dlg_->SetFilters(fl_get_input(file_dlg_form_->PatBox)); current_dlg_->Reread(); break; @@ -666,7 +669,7 @@ bool FileDialog::Private::HandleOK() // mask was changed string tmp = fl_get_input(file_dlg_form_->PatBox); if (tmp != mask_) { - SetMask(tmp); + SetFilters(tmp); Reread(); return false; } @@ -724,21 +727,13 @@ void FileDialog::Private::Force(bool cancel) // Select: launches dialog and returns selected file string const FileDialog::Private::Select(string const & title, string const & path, - string const & mask, + FileFilterList const & filters, string const & suggested) { // handles new mask and path - bool isOk = true; - if (!mask.empty()) { - SetMask(mask); - isOk = false; - } - if (!path.empty()) { - SetDirectory(path); - isOk = false; - } - if (!isOk) - Reread(); + SetFilters(filters); + SetDirectory(path); + Reread(); // highlight the suggested file in the browser, if it exists. int sel = 0; @@ -782,7 +777,7 @@ string const FileDialog::Private::Select(string const & title, FL_PLACE_MOUSE | FL_FREE_SIZE, 0, title.c_str()); - isOk = RunDialog(); + bool const isOk = RunDialog(); fl_hide_form(file_dlg_form_->form); fl_activate_all_forms(); @@ -805,7 +800,7 @@ string const FileDialog::Private::SelectDir(string const & title, string const & path, string const & suggested) { - SetMask("*/"); + SetFilters("*/"); // handles new path bool isOk = true; if (!path.empty()) { diff --git a/src/frontends/xforms/FormFiledialog.h b/src/frontends/xforms/FormFiledialog.h index 9c79303c2b..93b97b26c3 100644 --- a/src/frontends/xforms/FormFiledialog.h +++ b/src/frontends/xforms/FormFiledialog.h @@ -45,6 +45,15 @@ public: class FD_filedialog; +namespace lyx { +namespace support { + +class FileFilterList; + +} // namespace support +} // namespace lyx + + class FileDialog::Private : public boost::signals::trackable { public: /// @@ -58,10 +67,10 @@ public: /// gets last dialog directory std::string const GetDirectory() const; /// launches dialog and returns selected file - std::string const Select(std::string const & pszTitle = std::string(), - std::string const & pszPath = std::string(), - std::string const & pszMask = std::string(), - std::string const & pszSuggested = std::string()); + std::string const Select(std::string const & pszTitle, + std::string const & pszPath, + lyx::support::FileFilterList const & filters, + std::string const & pszSuggested); /// launches dialog and returns selected directory std::string const SelectDir(std::string const & pszTitle = std::string(), std::string const & pszPath = std::string(), @@ -118,7 +127,8 @@ private: /// sets dialog current directory void SetDirectory(std::string const & pszPath); /// sets dialog file mask - void SetMask(std::string const & pszNewMask); + void SetFilters(std::string const & filters); + void SetFilters(lyx::support::FileFilterList const & filters); /// sets dialog information line void SetInfoLine(std::string const & pszLine); /// handle dialog during file selection diff --git a/src/frontends/xforms/FormGraphics.C b/src/frontends/xforms/FormGraphics.C index e2f2db1e5f..af3f41d5cc 100644 --- a/src/frontends/xforms/FormGraphics.C +++ b/src/frontends/xforms/FormGraphics.C @@ -574,7 +574,7 @@ ButtonPolicy::SMInput FormGraphics::input(FL_OBJECT * ob, long) if (ob == file_->button_browse) { // Get the filename from the dialog string const in_name = getString(file_->input_filename); - string const out_name = controller().Browse(in_name); + string const out_name = controller().browse(in_name); lyxerr[Debug::GRAPHICS] << "[FormGraphics]out_name: " << out_name << endl; if (out_name != in_name && !out_name.empty()) { diff --git a/src/frontends/xforms/FormInclude.C b/src/frontends/xforms/FormInclude.C index c2dbd1fbc8..69b9185122 100644 --- a/src/frontends/xforms/FormInclude.C +++ b/src/frontends/xforms/FormInclude.C @@ -145,7 +145,7 @@ ButtonPolicy::SMInput FormInclude::input(FL_OBJECT * ob, long) string const in_name = getString(dialog_->input_filename); fl_freeze_form(form()); ControlInclude::Type const type = ControlInclude::Type(type_.get()); - string const out_name = controller().Browse(in_name, type); + string const out_name = controller().browse(in_name, type); fl_set_input(dialog_->input_filename, out_name.c_str()); fl_unfreeze_form(form()); diff --git a/src/frontends/xforms/FormPrint.C b/src/frontends/xforms/FormPrint.C index 3da4346df4..ca497e0f38 100644 --- a/src/frontends/xforms/FormPrint.C +++ b/src/frontends/xforms/FormPrint.C @@ -185,7 +185,7 @@ ButtonPolicy::SMInput FormPrint::input(FL_OBJECT * ob, long) if (ob == dialog_->button_browse) { // Get the filename from the dialog string const in_name = getString(dialog_->input_file); - string const out_name = controller().Browse(in_name); + string const out_name = controller().browse(in_name); // Save the filename to the dialog if (out_name != in_name && !out_name.empty()) { diff --git a/src/lyx_cb.C b/src/lyx_cb.C index bf31a58e88..fda8f46af6 100644 --- a/src/lyx_cb.C +++ b/src/lyx_cb.C @@ -36,6 +36,7 @@ #include "support/FileInfo.h" #include "support/filetools.h" #include "support/forkedcall.h" +#include "support/globbing.h" #include "support/lyxlib.h" #include "support/os.h" #include "support/path.h" @@ -48,6 +49,7 @@ using lyx::support::AddName; using lyx::support::bformat; using lyx::support::destroyDir; +using lyx::support::FileFilterList; using lyx::support::FileInfo; using lyx::support::ForkedProcess; using lyx::support::IsLyXFilename; @@ -128,10 +130,12 @@ bool WriteAs(Buffer * buffer, string const & filename) if (!IsLyXFilename(fname)) fname += ".lyx"; + FileFilterList const filter (_("LyX Documents (*.lyx)")); + FileDialog::Result result = fileDlg.save(OnlyPath(fname), - _("*.lyx| LyX Documents (*.lyx)"), - OnlyFilename(fname)); + filter, + OnlyFilename(fname)); if (result.first == FileDialog::Later) return false; @@ -372,7 +376,9 @@ string getContentsOfAsciiFile(BufferView * bv, string const & f, bool asParagrap FileDialog fileDlg(_("Select file to insert"), (asParagraph) ? LFUN_FILE_INSERT_ASCII_PARA : LFUN_FILE_INSERT_ASCII); - FileDialog::Result result = fileDlg.open(bv->owner()->buffer()->filePath()); + FileDialog::Result result = + fileDlg.open(bv->owner()->buffer()->filePath(), + FileFilterList(), string()); if (result.first == FileDialog::Later) return string(); diff --git a/src/lyxfunc.C b/src/lyxfunc.C index 1bc6a9dff4..77bd54b1e8 100644 --- a/src/lyxfunc.C +++ b/src/lyxfunc.C @@ -77,6 +77,7 @@ #include "support/FileInfo.h" #include "support/filetools.h" #include "support/forkedcontr.h" +#include "support/globbing.h" #include "support/path.h" #include "support/path_defines.h" #include "support/tostr.h" @@ -93,6 +94,7 @@ using lyx::support::AddName; using lyx::support::AddPath; using lyx::support::bformat; using lyx::support::ChangeExtension; +using lyx::support::FileFilterList; using lyx::support::FileInfo; using lyx::support::FileSearch; using lyx::support::ForkedcallsController; @@ -1569,7 +1571,8 @@ void LyXFunc::menuNew(string const & name, bool fromTemplate) FileDialog::Result result = fileDlg.open(lyxrc.template_path, - _("*.lyx| LyX Documents (*.lyx)")); + FileFilterList(_("LyX Documents (*.lyx)")), + string()); if (result.first == FileDialog::Later) return; @@ -1605,7 +1608,8 @@ void LyXFunc::open(string const & fname) FileDialog::Result result = fileDlg.open(initpath, - _("*.lyx| LyX Documents (*.lyx)")); + FileFilterList(_("LyX Documents (*.lyx)")), + string()); if (result.first == FileDialog::Later) return; @@ -1678,12 +1682,13 @@ void LyXFunc::doImport(string const & argument) make_pair(string(_("Examples|#E#e")), string(AddPath(system_lyxdir(), "examples")))); - string const extension = "*." + formats.extension(format) - + "| " + formats.prettyName(format) + string const filter = formats.prettyName(format) + " (*." + formats.extension(format) + ')'; - FileDialog::Result result = fileDlg.open(initpath, - extension); + FileDialog::Result result = + fileDlg.open(initpath, + FileFilterList(filter), + string()); if (result.first == FileDialog::Later) return; diff --git a/src/support/ChangeLog b/src/support/ChangeLog index ba5e14a142..0a65f4b3b7 100644 --- a/src/support/ChangeLog +++ b/src/support/ChangeLog @@ -1,3 +1,8 @@ +2004-01-08 Angus Leeming + + * globbing.[Ch]: add a new class FileFilterList to parse a Qt-style + list of available file filters and generate the corresponding vector. + 2003-12-14 Ronald Florence * tostr.[hC]: added tostr(long unsigned int i). diff --git a/src/support/globbing.C b/src/support/globbing.C index 195a8db549..61f10d1edf 100644 --- a/src/support/globbing.C +++ b/src/support/globbing.C @@ -8,15 +8,22 @@ * Full author contact details are available in file CREDITS. */ +#include + #include "globbing.h" +#include "gettext.h" + +#include "lstrings.h" #include "path.h" +#include "std_sstream.h" #include #include #include "glob.h" +using std::ostringstream; using std::string; using std::vector; @@ -68,7 +75,7 @@ string const convert_brace_glob(string const & glob) vector const glob(string const & pattern, int flags) { glob_t glob_buffer; - glob_buffer.gl_offs = 0; + glob_buffer.gl_offs = 0; glob(pattern.c_str(), flags, 0, &glob_buffer); vector const matches(glob_buffer.gl_pathv, glob_buffer.gl_pathv + @@ -86,13 +93,13 @@ vector const expand_globs(string const & mask, // Given " ... *.{abc,def} ", expand to // " ... *.abc *.def " - string const expanded_glob = convert_brace_glob(mask); + string const converted_glob = convert_brace_glob(mask); Path p(directory); // Split into individual globs and then call 'glob' on each one. vector matches; - Tokenizer const tokens(expanded_glob, separator); + Tokenizer const tokens(converted_glob, separator); Tokenizer::const_iterator it = tokens.begin(); Tokenizer::const_iterator const end = tokens.end(); for (; it != end; ++it) { @@ -102,5 +109,76 @@ vector const expand_globs(string const & mask, return matches; } + +FileFilterList::FileFilterList(string const & qt_style_filter) +{ + string const filter = qt_style_filter.empty() ? + _("All files (*)") : qt_style_filter; + + // Split data such as "TeX documents (*.tex);;LyX Documents (*.lyx)" + // into individual filters. + static boost::regex const separator_re(";;"); + + string::const_iterator it = filter.begin(); + string::const_iterator const end = filter.end(); + while (true) { + boost::match_results what; + + if (!boost::regex_search(it, end, what, separator_re)) { + parse_filter(string(it, end)); + break; + } + + // Everything from the start of the input to + // the start of the match. + parse_filter(string(what[-1].first, what[-1].second)); + + // Increment the iterator to the end of the match. + it += std::distance(it, what[0].second); + } +} + + +void FileFilterList::parse_filter(string const & filter) +{ + // Matches "TeX documents (*.tex)", + // storing "TeX documents " as group 1 and "*.tex" as group 2. + static boost::regex const filter_re("([^(]*)\\(([^)]+)\\) *$"); + + boost::match_results what; + if (!boost::regex_search(filter, what, filter_re)) { + // Just a glob, no description. + filters_.push_back(Filter(string(), trim(filter))); + } else { + string const desc = string(what[1].first, what[1].second); + string const globs = string(what[2].first, what[2].second); + filters_.push_back(Filter(trim(desc), trim(globs))); + } +} + + +string const FileFilterList::str(bool expand) const +{ + ostringstream ss; + + vector::const_iterator const begin = filters_.begin(); + vector::const_iterator const end = filters_.end(); + vector::const_iterator it = begin; + for (; it != end; ++it) { + string const globs = expand ? + convert_brace_glob(it->globs()) : it->globs(); + if (it != begin) + ss << ";;"; + bool const has_description = !it->description().empty(); + if (has_description) + ss << it->description() << " ("; + ss << globs; + if (has_description) + ss << ')'; + } + + return ss.str(); +} + } // namespace support } // namespace lyx diff --git a/src/support/globbing.h b/src/support/globbing.h index 809aae6bc1..08f117c47d 100644 --- a/src/support/globbing.h +++ b/src/support/globbing.h @@ -26,6 +26,7 @@ namespace support { */ std::string const convert_brace_glob(std::string const & glob); + /** A wrapper for the Posix function 'glob'. * \param pattern the glob to be expanded. Eg "*.[Ch]". * \param flags flags to be passed to the system function. See 'man glob'. @@ -33,19 +34,56 @@ std::string const convert_brace_glob(std::string const & glob); */ std::vector const glob(std::string const & pattern, int flags = 0); + /** Given a string " ", expand each glob in turn. * Any glob that cannot be expanded is ignored silently. - * Invokes \c expand_brace_glob and \c glob internally, so use only + * Invokes \c convert_brace_glob and \c glob internally, so use only * on systems supporting the Posix function 'glob'. - * \param mask the string " ". - * \param directory (if not empty) the current working directory from - * which \c glob is invoked. + * \param mask the string " ". + * \param directory (if not empty) the current working directory from + * which \c glob is invoked. * \returns a vector of all matching file names. */ std::vector const expand_globs(std::string const & mask, std::string const & directory = std::string()); + +/** \c FileFilterList parses a Qt-style list of available file filters + * to generate the corresponding vector. + * For example "TeX documents (*.tex);;LyX Documents (*.lyx)" + * will be parsed to fill a vector of size 2, whilst "*.{p[bgp]m} *.pdf" + * will result in a vector of size 1 in which the description field is empty. + */ +class FileFilterList { +public: + class Filter { + std::string desc_; + std::string globs_; + public: + Filter(std::string const & d, std::string const & g) + : desc_(d), globs_(g) {} + std::string const & description() const { return desc_; } + std::string const & globs() const { return globs_; } + }; + + /** \param qt_style_filter a list of available file filters. + * Eg. "TeX documents (*.tex);;LyX Documents (*.lyx)" + * If empty, set to "All files (*)". + */ + explicit FileFilterList(std::string const & qt_style_filter = std::string()); + std::vector const & filters() const { return filters_; } + + /** \param expand pass each glob through \c convert_brace_glob. + * \returns the equivalent of the string passed to the c-tor. + */ + std::string const str(bool expand) const; + +private: + void parse_filter(std::string const & filter); + std::vector filters_; +}; + } // namespace support } // namespace lyx