From: Angus Leeming Date: Fri, 26 Nov 2004 12:31:39 +0000 (+0000) Subject: Clean-up FileFilterList API. X-Git-Tag: 1.6.10~14790 X-Git-Url: https://git.lyx.org/gitweb/?a=commitdiff_plain;h=d23bb9eaa8025e9779d10a70dcbc840a0e1af16e;p=features.git Clean-up FileFilterList API. git-svn-id: svn://svn.lyx.org/lyx/lyx-devel/trunk@9311 a592a061-630c-0410-9148-cb99ea01b6c8 --- diff --git a/src/frontends/qt2/ChangeLog b/src/frontends/qt2/ChangeLog index f37cdd4904..f5ab8852f2 100644 --- a/src/frontends/qt2/ChangeLog +++ b/src/frontends/qt2/ChangeLog @@ -1,3 +1,8 @@ +2004-11-26 Angus Leeming + + * FileDialog.C: + * FileDialog_private.C: changes due to the changed FileFilterList API. + 2004-11-25 Angus Leeming * FileDialog.C: diff --git a/src/frontends/qt2/FileDialog.C b/src/frontends/qt2/FileDialog.C index 90e92d8c87..bd8460b33d 100644 --- a/src/frontends/qt2/FileDialog.C +++ b/src/frontends/qt2/FileDialog.C @@ -72,7 +72,7 @@ FileDialog::Result const FileDialog::save(string const & path, string const & suggested) { lyxerr[Debug::GUI] << "Select with path \"" << path - << "\", mask \"" << filters.str(false) + << "\", mask \"" << filters.as_string() << "\", suggested \"" << suggested << '"' << endl; FileDialog::Result result; result.first = FileDialog::Chosen; @@ -81,7 +81,7 @@ FileDialog::Result const FileDialog::save(string const & path, string const startsWith = MakeAbsPath(suggested, path); result.second = fromqstr( QFileDialog::getSaveFileName(toqstr(startsWith), - toqstr(filters.str(true)), + toqstr(filters.as_string()), qApp->focusWidget() ? qApp->focusWidget() : qApp->mainWidget(), title_.c_str())); #else @@ -107,7 +107,7 @@ FileDialog::Result const FileDialog::open(string const & path, string const & suggested) { lyxerr[Debug::GUI] << "Select with path \"" << path - << "\", mask \"" << filters.str(false) + << "\", mask \"" << filters.as_string() << "\", suggested \"" << suggested << '"' << endl; FileDialog::Result result; result.first = FileDialog::Chosen; @@ -116,7 +116,7 @@ FileDialog::Result const FileDialog::open(string const & path, string const startsWith = MakeAbsPath(suggested, path); result.second = fromqstr( QFileDialog::getOpenFileName(toqstr(startsWith), - toqstr(filters.str(true)), + toqstr(filters.as_string()), qApp->focusWidget() ? qApp->focusWidget() : qApp->mainWidget(), title_.c_str())); #else diff --git a/src/frontends/qt2/FileDialog_private.C b/src/frontends/qt2/FileDialog_private.C index bad9d561c0..1d665f5e75 100644 --- a/src/frontends/qt2/FileDialog_private.C +++ b/src/frontends/qt2/FileDialog_private.C @@ -47,7 +47,7 @@ LyXFileDialog::LyXFileDialog(string const & p, string const & t, FileDialog::Button const & b1, FileDialog::Button const & b2) - : QFileDialog(toqstr(p), toqstr(filters.str(true)), + : QFileDialog(toqstr(p), toqstr(filters.as_string()), qApp->focusWidget() ? qApp->focusWidget() : qApp->mainWidget(), toqstr(t), true), b1_(0), b2_(0) { diff --git a/src/frontends/xforms/ChangeLog b/src/frontends/xforms/ChangeLog index 4a187c0dee..0eb91a053f 100644 --- a/src/frontends/xforms/ChangeLog +++ b/src/frontends/xforms/ChangeLog @@ -1,3 +1,11 @@ +2004-11-26 Angus Leeming + + * FileDialog.C: + * FormFiledialog.C: changes due to the changed FileFilterList API. + + * FormFiledialog.C (expand_globs): moved here from + support/globbing.[Ch]. + 2004-11-25 Angus Leeming * FileDialog.C: s/globbing.h/filefilterlist.h/ in #includes. diff --git a/src/frontends/xforms/FileDialog.C b/src/frontends/xforms/FileDialog.C index 9402b5d728..4ee22b27ba 100644 --- a/src/frontends/xforms/FileDialog.C +++ b/src/frontends/xforms/FileDialog.C @@ -71,7 +71,7 @@ FileDialog::Result const FileDialog::open(string const & path, string const & suggested) { lyxerr[Debug::GUI] << "filedialog open with path \"" << path - << "\", mask \"" << filters.str(false) + << "\", mask \"" << filters.as_string() << "\", suggested \"" << suggested << '"' << endl; // no support for asynchronous selection yet diff --git a/src/frontends/xforms/FormFiledialog.C b/src/frontends/xforms/FormFiledialog.C index e75b9f3e19..b0fbdb4850 100644 --- a/src/frontends/xforms/FormFiledialog.C +++ b/src/frontends/xforms/FormFiledialog.C @@ -25,15 +25,19 @@ #include "support/globbing.h" #include "support/lstrings.h" #include "support/lyxlib.h" +#include "support/path.h" #include "support/tostr.h" #include "lyx_forms.h" #include #include +#include #include #include +#include + #include #include @@ -66,6 +70,7 @@ using lyx::support::GetEnvPath; using lyx::support::LyXReadLink; using lyx::support::MakeAbsPath; using lyx::support::OnlyFilename; +using lyx::support::Path; using lyx::support::split; using lyx::support::subst; using lyx::support::suffixIs; @@ -73,6 +78,7 @@ using lyx::support::trim; using std::max; using std::sort; +using std::ostringstream; using std::string; using std::map; using std::vector; @@ -81,6 +87,36 @@ using namespace lyx::frontend; namespace { +/** Given a string " ", expand each glob in turn. + * Any glob that cannot be expanded is ignored silently. + * 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 the current working directory from + * which \c glob is invoked. + * \returns a vector of all matching file names. + */ +vector const expand_globs(string const & mask, + string const & directory) +{ + Path p(directory); + + // Split into individual globs and then call 'glob' on each one. + typedef boost::tokenizer > Tokenizer; + boost::char_separator const separator(" "); + + vector matches; + Tokenizer const tokens(mask, separator); + Tokenizer::const_iterator it = tokens.begin(); + Tokenizer::const_iterator const end = tokens.end(); + for (; it != end; ++it) { + vector const tmp = lyx::support::glob(*it); + matches.insert(matches.end(), tmp.begin(), tmp.end()); + } + return matches; +} + + // six months, in seconds long const SIX_MONTH_SEC = 6L * 30L * 24L * 60L * 60L; //static @@ -241,8 +277,7 @@ void FileDialog::Private::Reread() ++depth_; } - vector const glob_matches = - lyx::support::expand_globs(mask_, directory_); + vector const glob_matches = expand_globs(mask_, directory_); time_t curTime = time(0); rewinddir(dir); @@ -404,8 +439,24 @@ void FileDialog::Private::SetFilters(string const & mask) void FileDialog::Private::SetFilters(FileFilterList const & filters) { + if (filters.empty()) + return; + // Just take the first one for now. - mask_ = filters.filters()[0].globs(); + typedef FileFilterList::Filter::glob_iterator glob_iterator; + glob_iterator const begin = filters[0].begin(); + glob_iterator const end = filters[0].end(); + if (begin == end) + return; + + ostringstream ss; + for (glob_iterator it = begin; it != end; ++it) { + if (it != begin) + ss << ' '; + ss << *it; + } + + mask_ = ss.str(); fl_set_input(file_dlg_form_->PatBox, mask_.c_str()); } diff --git a/src/support/ChangeLog b/src/support/ChangeLog index 5e5a357c05..a63249d18f 100644 --- a/src/support/ChangeLog +++ b/src/support/ChangeLog @@ -1,3 +1,13 @@ +2004-11-26 Angus Leeming + + * filefilterlist.C (convert_brace_glob): moved here from + globbing.[Ch]. + + * filefilterlist.[Ch]: clean-up FileFilterList API. + + * globbing.[Ch] (convert_brace_glob): moved to filefilterlist.C. + (expand_globs): moved to xforms/FormFiledialog.C. + 2004-11-25 Angus Leeming * filefilterlist.[Ch]: diff --git a/src/support/filefilterlist.C b/src/support/filefilterlist.C index 168a95eeb5..109a045e02 100644 --- a/src/support/filefilterlist.C +++ b/src/support/filefilterlist.C @@ -11,15 +11,13 @@ #include #include "support/filefilterlist.h" -#include "support/globbing.h" #include "support/lstrings.h" // FIXME Interface violation #include "gettext.h" #include - -#include +#include #include @@ -29,9 +27,78 @@ using std::string; using std::vector; +namespace { + +/** Given a string such as + * " ... *.{abc,def} ", + * convert the csh-style brace expresions: + * " ... *.abc *.def ". + * Requires no system support, so should work equally on Unix, Mac, Win32. + */ +string const convert_brace_glob(string const & glob) +{ + // Matches " *.{abc,def,ghi}", storing "*." as group 1 and + // "abc,def,ghi" as group 2. + static boost::regex const glob_re(" *([^ {]*)\\{([^ }]+)\\}"); + // Matches "abc" and "abc,", storing "abc" as group 1. + static boost::regex const block_re("([^,}]+),?"); + + string pattern; + + string::const_iterator it = glob.begin(); + string::const_iterator const end = glob.end(); + while (true) { + boost::match_results what; + if (!boost::regex_search(it, end, what, glob_re)) { + // Ensure that no information is lost. + pattern += string(it, end); + break; + } + + // Everything from the start of the input to + // the start of the match. + pattern += string(what[-1].first, what[-1].second); + + // Given " *.{abc,def}", head == "*." and tail == "abc,def". + string const head = string(what[1].first, what[1].second); + string const tail = string(what[2].first, what[2].second); + + // Split the ','-separated chunks of tail so that + // $head{$chunk1,$chunk2} becomes "$head$chunk1 $head$chunk2". + string const fmt = " " + head + "$1"; + pattern += boost::regex_merge(tail, block_re, fmt); + + // Increment the iterator to the end of the match. + it += distance(it, what[0].second); + } + + return pattern; +} + +} // namespace anon + + namespace lyx { namespace support { +FileFilterList::Filter::Filter(std::string const & description, + std::string const & globs) + : desc_(description) +{ + typedef boost::tokenizer > Tokenizer; + boost::char_separator const separator(" "); + + // Given " ... *.{abc,def} ", expand to + // " ... *.abc *.def " + string const expanded_globs = convert_brace_glob(globs); + + // Split into individual globs. + vector matches; + Tokenizer const tokens(expanded_globs, separator); + globs_ = vector(tokens.begin(), tokens.end()); +} + + FileFilterList::FileFilterList(string const & qt_style_filter) { string const filter = qt_style_filter @@ -80,22 +147,31 @@ void FileFilterList::parse_filter(string const & filter) } -string const FileFilterList::str(bool expand) const +string const FileFilterList::as_string() 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) + vector::const_iterator fit = filters_.begin(); + vector::const_iterator const fend = filters_.end(); + for (; fit != fend; ++fit) { + Filter::glob_iterator const gbegin = fit->begin(); + Filter::glob_iterator const gend = fit->end(); + if (gbegin == gend) + continue; + + if (ss.tellp() > 0) ss << ";;"; - bool const has_description = !it->description().empty(); + + bool const has_description = !fit->description().empty(); if (has_description) - ss << it->description() << " ("; - ss << globs; + ss << fit->description() << " ("; + + for (Filter::glob_iterator git = gbegin; git != gend; ++git) { + if (git != gbegin) + ss << ' '; + ss << *git; + } + if (has_description) ss << ')'; } diff --git a/src/support/filefilterlist.h b/src/support/filefilterlist.h index 984d1398f8..bb4197778b 100644 --- a/src/support/filefilterlist.h +++ b/src/support/filefilterlist.h @@ -28,25 +28,41 @@ class FileFilterList { public: class Filter { std::string desc_; - std::string globs_; + std::vector globs_; public: - Filter(std::string const & d, std::string const & g) - : desc_(d), globs_(g) {} + /* \param description text describing the filters. + * \param one or more wildcard patterns, separated by + * whitespace. + */ + Filter(std::string const & description, + std::string const & globs); + std::string const & description() const { return desc_; } - std::string const & globs() const { return globs_; } + + typedef std::vector::const_iterator glob_iterator; + glob_iterator begin() const { return globs_.begin(); } + glob_iterator end() const { return globs_.end(); } }; /** \param qt_style_filter a list of available file filters. * Eg. "TeX documents (*.tex);;LyX Documents (*.lyx)". * The "All files (*)" filter is always added to the list. */ - explicit FileFilterList(std::string const & qt_style_filter = std::string()); - std::vector const & filters() const { return filters_; } + explicit FileFilterList(std::string const & qt_style_filter = + std::string()); + + typedef std::vector::size_type size_type; + + bool empty() const { return filters_.empty(); } + size_type size() const { return filters_.size(); } + Filter & operator[](size_type i) { return filters_[i]; } + Filter const & operator[](size_type i) const { return filters_[i]; } - /** \param expand pass each glob through \c convert_brace_glob. - * \returns the equivalent of the string passed to the c-tor. + /** \returns the equivalent of the string passed to the c-tor + * although any brace expressions are expanded. + * (E.g. "*.{png,jpg}" -> "*.png *.jpg") */ - std::string const str(bool expand) const; + std::string const as_string() const; private: void parse_filter(std::string const & filter); diff --git a/src/support/globbing.C b/src/support/globbing.C index 8e663a0cc3..0000f34e3a 100644 --- a/src/support/globbing.C +++ b/src/support/globbing.C @@ -11,15 +11,9 @@ #include #include "support/globbing.h" -#include "support/lstrings.h" -#include "support/path.h" - -#include -#include #include -using std::distance; using std::string; using std::vector; @@ -27,47 +21,6 @@ using std::vector; namespace lyx { namespace support { -string const convert_brace_glob(string const & glob) -{ - // Matches " *.{abc,def,ghi}", storing "*." as group 1 and - // "abc,def,ghi" as group 2. - static boost::regex const glob_re(" *([^ {]*)\\{([^ }]+)\\}"); - // Matches "abc" and "abc,", storing "abc" as group 1. - static boost::regex const block_re("([^,}]+),?"); - - string pattern; - - string::const_iterator it = glob.begin(); - string::const_iterator const end = glob.end(); - while (true) { - boost::match_results what; - if (!boost::regex_search(it, end, what, glob_re)) { - // Ensure that no information is lost. - pattern += string(it, end); - break; - } - - // Everything from the start of the input to - // the start of the match. - pattern += string(what[-1].first, what[-1].second); - - // Given " *.{abc,def}", head == "*." and tail == "abc,def". - string const head = string(what[1].first, what[1].second); - string const tail = string(what[2].first, what[2].second); - - // Split the ','-separated chunks of tail so that - // $head{$chunk1,$chunk2} becomes "$head$chunk1 $head$chunk2". - string const fmt = " " + head + "$1"; - pattern += boost::regex_merge(tail, block_re, fmt); - - // Increment the iterator to the end of the match. - it += distance(it, what[0].second); - } - - return pattern; -} - - vector const glob(string const & pattern, int flags) { glob_t glob_buffer; @@ -80,30 +33,5 @@ vector const glob(string const & pattern, int flags) return matches; } - -vector const expand_globs(string const & mask, - string const & directory) -{ - typedef boost::tokenizer > Tokenizer; - boost::char_separator const separator(" "); - - // Given " ... *.{abc,def} ", expand to - // " ... *.abc *.def " - 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(converted_glob, separator); - Tokenizer::const_iterator it = tokens.begin(); - Tokenizer::const_iterator const end = tokens.end(); - for (; it != end; ++it) { - vector const tmp = glob(*it); - matches.insert(matches.end(), tmp.begin(), tmp.end()); - } - return matches; -} - } // namespace support } // namespace lyx diff --git a/src/support/globbing.h b/src/support/globbing.h index 0ee1141512..e4c53c808b 100644 --- a/src/support/globbing.h +++ b/src/support/globbing.h @@ -18,15 +18,6 @@ namespace lyx { namespace support { -/** Given a string such as - * " ... *.{abc,def} ", - * convert the csh-style brace expresions: - * " ... *.abc *.def ". - * Requires no system support, so should work equally on Unix, Mac, Win32. - */ -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'. @@ -34,20 +25,6 @@ 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 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. - * \returns a vector of all matching file names. - */ -std::vector const -expand_globs(std::string const & mask, - std::string const & directory = std::string()); - } // namespace support } // namespace lyx