+2004-11-26 Angus Leeming <leeming@lyx.org>
+
+ * FileDialog.C:
+ * FileDialog_private.C: changes due to the changed FileFilterList API.
+
2004-11-25 Angus Leeming <leeming@lyx.org>
* FileDialog.C:
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;
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
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;
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
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)
{
+2004-11-26 Angus Leeming <leeming@lyx.org>
+
+ * 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 <leeming@lyx.org>
* FileDialog.C: s/globbing.h/filefilterlist.h/ in #includes.
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
#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 <boost/bind.hpp>
#include <boost/regex.hpp>
+#include <boost/tokenizer.hpp>
#include <algorithm>
#include <map>
+#include <sstream>
+
#include <grp.h>
#include <pwd.h>
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;
using std::max;
using std::sort;
+using std::ostringstream;
using std::string;
using std::map;
using std::vector;
namespace {
+/** Given a string "<glob> <glob> <glob>", 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 "<glob> <glob> <glob>".
+ * \param directory the current working directory from
+ * which \c glob is invoked.
+ * \returns a vector of all matching file names.
+ */
+vector<string> 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<boost::char_separator<char> > Tokenizer;
+ boost::char_separator<char> const separator(" ");
+
+ vector<string> matches;
+ Tokenizer const tokens(mask, separator);
+ Tokenizer::const_iterator it = tokens.begin();
+ Tokenizer::const_iterator const end = tokens.end();
+ for (; it != end; ++it) {
+ vector<string> 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
++depth_;
}
- vector<string> const glob_matches =
- lyx::support::expand_globs(mask_, directory_);
+ vector<string> const glob_matches = expand_globs(mask_, directory_);
time_t curTime = time(0);
rewinddir(dir);
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());
}
+2004-11-26 Angus Leeming <leeming@lyx.org>
+
+ * 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 <leeming@lyx.org>
* filefilterlist.[Ch]:
#include <config.h>
#include "support/filefilterlist.h"
-#include "support/globbing.h"
#include "support/lstrings.h"
// FIXME Interface violation
#include "gettext.h"
#include <boost/regex.hpp>
-
-#include </usr/include/glob.h>
+#include <boost/tokenizer.hpp>
#include <sstream>
using std::vector;
+namespace {
+
+/** Given a string such as
+ * "<glob> <glob> ... *.{abc,def} <glob>",
+ * convert the csh-style brace expresions:
+ * "<glob> <glob> ... *.abc *.def <glob>".
+ * 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<string::const_iterator> 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<boost::char_separator<char> > Tokenizer;
+ boost::char_separator<char> const separator(" ");
+
+ // Given "<glob> <glob> ... *.{abc,def} <glob>", expand to
+ // "<glob> <glob> ... *.abc *.def <glob>"
+ string const expanded_globs = convert_brace_glob(globs);
+
+ // Split into individual globs.
+ vector<string> matches;
+ Tokenizer const tokens(expanded_globs, separator);
+ globs_ = vector<string>(tokens.begin(), tokens.end());
+}
+
+
FileFilterList::FileFilterList(string const & qt_style_filter)
{
string const filter = qt_style_filter
}
-string const FileFilterList::str(bool expand) const
+string const FileFilterList::as_string() const
{
ostringstream ss;
- vector<Filter>::const_iterator const begin = filters_.begin();
- vector<Filter>::const_iterator const end = filters_.end();
- vector<Filter>::const_iterator it = begin;
- for (; it != end; ++it) {
- string const globs = expand ?
- convert_brace_glob(it->globs()) : it->globs();
- if (it != begin)
+ vector<Filter>::const_iterator fit = filters_.begin();
+ vector<Filter>::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 << ')';
}
public:
class Filter {
std::string desc_;
- std::string globs_;
+ std::vector<std::string> 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<std::string>::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<Filter> const & filters() const { return filters_; }
+ explicit FileFilterList(std::string const & qt_style_filter =
+ std::string());
+
+ typedef std::vector<Filter>::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);
#include <config.h>
#include "support/globbing.h"
-#include "support/lstrings.h"
-#include "support/path.h"
-
-#include <boost/regex.hpp>
-#include <boost/tokenizer.hpp>
#include <glob.h>
-using std::distance;
using std::string;
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<string::const_iterator> 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<string> const glob(string const & pattern, int flags)
{
glob_t glob_buffer;
return matches;
}
-
-vector<string> const expand_globs(string const & mask,
- string const & directory)
-{
- typedef boost::tokenizer<boost::char_separator<char> > Tokenizer;
- boost::char_separator<char> const separator(" ");
-
- // Given "<glob> <glob> ... *.{abc,def} <glob>", expand to
- // "<glob> <glob> ... *.abc *.def <glob>"
- string const converted_glob = convert_brace_glob(mask);
-
- Path p(directory);
-
- // Split into individual globs and then call 'glob' on each one.
- vector<string> 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<string> const tmp = glob(*it);
- matches.insert(matches.end(), tmp.begin(), tmp.end());
- }
- return matches;
-}
-
} // namespace support
} // namespace lyx
namespace lyx {
namespace support {
-/** Given a string such as
- * "<glob> <glob> ... *.{abc,def} <glob>",
- * convert the csh-style brace expresions:
- * "<glob> <glob> ... *.abc *.def <glob>".
- * 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'.
*/
std::vector<std::string> const glob(std::string const & pattern, int flags = 0);
-
-/** Given a string "<glob> <glob> <glob>", 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 "<glob> <glob> <glob>".
- * \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<std::string> const
-expand_globs(std::string const & mask,
- std::string const & directory = std::string());
-
} // namespace support
} // namespace lyx