2006-03-05 17:24:44 +00:00
|
|
|
|
/**
|
2007-04-26 03:53:02 +00:00
|
|
|
|
* \file qt_helpers.cpp
|
2006-03-05 17:24:44 +00:00
|
|
|
|
* This file is part of LyX, the document processor.
|
|
|
|
|
* Licence details can be found in the file COPYING.
|
|
|
|
|
*
|
|
|
|
|
* \author Dekel Tsur
|
|
|
|
|
* \author J<EFBFBD>rgen Spitzm<EFBFBD>ller
|
2007-04-05 14:58:15 +00:00
|
|
|
|
* \author Richard Heck
|
2006-03-05 17:24:44 +00:00
|
|
|
|
*
|
|
|
|
|
* Full author contact details are available in file CREDITS.
|
|
|
|
|
*/
|
|
|
|
|
|
|
|
|
|
#include <config.h>
|
|
|
|
|
|
|
|
|
|
#include "qt_helpers.h"
|
|
|
|
|
|
2008-02-07 00:05:18 +00:00
|
|
|
|
#include "FileDialog.h"
|
2007-10-24 22:55:02 +00:00
|
|
|
|
#include "LengthCombo.h"
|
|
|
|
|
|
2008-02-18 07:14:42 +00:00
|
|
|
|
#include "frontends/alert.h"
|
|
|
|
|
|
2007-11-05 22:20:23 +00:00
|
|
|
|
#include "Language.h"
|
2007-10-24 22:55:02 +00:00
|
|
|
|
#include "Length.h"
|
2006-03-05 17:24:44 +00:00
|
|
|
|
|
2008-02-18 07:14:42 +00:00
|
|
|
|
#include "support/debug.h"
|
2007-11-05 22:20:23 +00:00
|
|
|
|
#include "support/filetools.h"
|
2008-03-08 07:59:47 +00:00
|
|
|
|
#include "support/foreach.h"
|
2008-02-18 07:14:42 +00:00
|
|
|
|
#include "support/gettext.h"
|
2006-03-05 17:24:44 +00:00
|
|
|
|
#include "support/lstrings.h"
|
2007-11-05 22:20:23 +00:00
|
|
|
|
#include "support/lyxalgo.h"
|
|
|
|
|
#include "support/os.h"
|
|
|
|
|
#include "support/Package.h"
|
|
|
|
|
#include "support/Path.h"
|
|
|
|
|
#include "support/Systemcall.h"
|
2006-03-05 17:24:44 +00:00
|
|
|
|
|
2007-04-05 14:58:15 +00:00
|
|
|
|
#include <QCheckBox>
|
2008-03-08 07:59:47 +00:00
|
|
|
|
#include <QComboBox>
|
2007-09-15 15:42:22 +00:00
|
|
|
|
#include <QLineEdit>
|
2008-03-08 07:59:47 +00:00
|
|
|
|
#include <QPalette>
|
|
|
|
|
#include <QSet>
|
2007-11-05 22:20:23 +00:00
|
|
|
|
|
2006-03-05 17:24:44 +00:00
|
|
|
|
#include <algorithm>
|
2007-11-05 22:20:23 +00:00
|
|
|
|
#include <fstream>
|
2007-11-14 02:01:50 +00:00
|
|
|
|
#include <locale>
|
2006-03-05 17:24:44 +00:00
|
|
|
|
|
2008-04-20 19:56:01 +00:00
|
|
|
|
// for FileFilter.
|
|
|
|
|
// FIXME: Remove
|
|
|
|
|
#include <boost/regex.hpp>
|
|
|
|
|
#include <boost/tokenizer.hpp>
|
|
|
|
|
|
|
|
|
|
|
2007-12-12 10:16:00 +00:00
|
|
|
|
using namespace std;
|
2007-12-12 18:57:56 +00:00
|
|
|
|
using namespace lyx::support;
|
2006-03-05 17:24:44 +00:00
|
|
|
|
|
2006-10-21 00:16:43 +00:00
|
|
|
|
namespace lyx {
|
2008-03-08 07:59:47 +00:00
|
|
|
|
|
|
|
|
|
FileName libFileSearch(QString const & dir, QString const & name,
|
|
|
|
|
QString const & ext)
|
|
|
|
|
{
|
|
|
|
|
return support::libFileSearch(fromqstr(dir), fromqstr(name), fromqstr(ext));
|
|
|
|
|
}
|
|
|
|
|
|
2007-11-05 22:20:23 +00:00
|
|
|
|
namespace frontend {
|
2006-03-05 17:24:44 +00:00
|
|
|
|
|
|
|
|
|
string widgetsToLength(QLineEdit const * input, LengthCombo const * combo)
|
|
|
|
|
{
|
2006-09-09 22:27:22 +00:00
|
|
|
|
QString const length = input->text();
|
2006-03-05 17:24:44 +00:00
|
|
|
|
if (length.isEmpty())
|
|
|
|
|
return string();
|
|
|
|
|
|
2006-09-09 22:27:22 +00:00
|
|
|
|
// Don't return unit-from-choice if the input(field) contains a unit
|
2006-03-05 17:24:44 +00:00
|
|
|
|
if (isValidGlueLength(fromqstr(length)))
|
|
|
|
|
return fromqstr(length);
|
|
|
|
|
|
2007-04-28 12:58:49 +00:00
|
|
|
|
Length::UNIT const unit = combo->currentLengthItem();
|
2006-03-05 17:24:44 +00:00
|
|
|
|
|
2007-04-28 12:58:49 +00:00
|
|
|
|
return Length(length.toDouble(), unit).asString();
|
2006-03-05 17:24:44 +00:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
2007-04-28 12:58:49 +00:00
|
|
|
|
Length widgetsToLength(QLineEdit const * input, QComboBox const * combo)
|
2006-03-05 17:24:44 +00:00
|
|
|
|
{
|
2006-09-09 22:27:22 +00:00
|
|
|
|
QString const length = input->text();
|
2006-03-05 17:24:44 +00:00
|
|
|
|
if (length.isEmpty())
|
2007-04-28 12:58:49 +00:00
|
|
|
|
return Length();
|
2006-03-05 17:24:44 +00:00
|
|
|
|
|
|
|
|
|
// don't return unit-from-choice if the input(field) contains a unit
|
|
|
|
|
if (isValidGlueLength(fromqstr(length)))
|
2007-04-28 12:58:49 +00:00
|
|
|
|
return Length(fromqstr(length));
|
2006-03-05 17:24:44 +00:00
|
|
|
|
|
2007-04-28 12:58:49 +00:00
|
|
|
|
Length::UNIT const unit = unitFromString(fromqstr(combo->currentText()));
|
2006-03-05 17:24:44 +00:00
|
|
|
|
|
2007-04-28 12:58:49 +00:00
|
|
|
|
return Length(length.toDouble(), unit);
|
2006-03-05 17:24:44 +00:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
2007-04-05 14:58:15 +00:00
|
|
|
|
void lengthToWidgets(QLineEdit * input, LengthCombo * combo,
|
2007-08-10 20:14:54 +00:00
|
|
|
|
Length const & len, Length::UNIT /*defaultUnit*/)
|
2007-04-05 14:58:15 +00:00
|
|
|
|
{
|
2007-09-15 15:42:22 +00:00
|
|
|
|
combo->setCurrentItem(len.unit());
|
2007-09-11 21:27:57 +00:00
|
|
|
|
input->setText(QString::number(Length(len).value()));
|
2007-04-05 14:58:15 +00:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
2006-03-05 17:24:44 +00:00
|
|
|
|
void lengthToWidgets(QLineEdit * input, LengthCombo * combo,
|
2007-04-28 12:58:49 +00:00
|
|
|
|
string const & len, Length::UNIT defaultUnit)
|
2006-03-05 17:24:44 +00:00
|
|
|
|
{
|
|
|
|
|
if (len.empty()) {
|
|
|
|
|
// no length (UNIT_NONE)
|
|
|
|
|
combo->setCurrentItem(defaultUnit);
|
|
|
|
|
input->setText("");
|
|
|
|
|
} else if (!isValidLength(len) && !isStrDbl(len)) {
|
|
|
|
|
// use input field only for gluelengths
|
|
|
|
|
combo->setCurrentItem(defaultUnit);
|
|
|
|
|
input->setText(toqstr(len));
|
|
|
|
|
} else {
|
2007-04-28 12:58:49 +00:00
|
|
|
|
lengthToWidgets(input, combo, Length(len), defaultUnit);
|
2006-03-05 17:24:44 +00:00
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
2007-05-28 22:27:45 +00:00
|
|
|
|
void lengthAutoToWidgets(QLineEdit * input, LengthCombo * combo,
|
2007-04-28 12:58:49 +00:00
|
|
|
|
Length const & len, Length::UNIT defaultUnit)
|
2007-04-05 14:58:15 +00:00
|
|
|
|
{
|
2007-05-28 22:27:45 +00:00
|
|
|
|
if (len.value() == 0)
|
2007-04-05 14:58:15 +00:00
|
|
|
|
lengthToWidgets(input, combo, "auto", defaultUnit);
|
|
|
|
|
else
|
|
|
|
|
lengthToWidgets(input, combo, len, defaultUnit);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
2007-09-15 13:06:48 +00:00
|
|
|
|
void setValid(QWidget * widget, bool valid)
|
|
|
|
|
{
|
|
|
|
|
if (valid) {
|
|
|
|
|
widget->setPalette(QPalette());
|
|
|
|
|
} else {
|
|
|
|
|
QPalette pal = widget->palette();
|
|
|
|
|
pal.setColor(QPalette::Active, QPalette::Foreground, QColor(255, 0, 0));
|
|
|
|
|
widget->setPalette(pal);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2007-11-05 22:20:23 +00:00
|
|
|
|
} // namespace frontend
|
2007-09-15 13:06:48 +00:00
|
|
|
|
|
2006-11-07 18:09:55 +00:00
|
|
|
|
QString const qt_(char const * str, const char *)
|
2006-03-05 17:24:44 +00:00
|
|
|
|
{
|
2006-09-09 22:27:22 +00:00
|
|
|
|
return toqstr(_(str));
|
2006-03-05 17:24:44 +00:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
QString const qt_(string const & str)
|
|
|
|
|
{
|
2006-09-09 22:27:22 +00:00
|
|
|
|
return toqstr(_(str));
|
2006-03-05 17:24:44 +00:00
|
|
|
|
}
|
|
|
|
|
|
2007-11-05 22:20:23 +00:00
|
|
|
|
namespace {
|
|
|
|
|
|
2007-11-14 02:01:50 +00:00
|
|
|
|
class Sorter
|
2007-11-05 22:20:23 +00:00
|
|
|
|
{
|
2007-11-14 02:01:50 +00:00
|
|
|
|
public:
|
|
|
|
|
#if !defined(USE_WCHAR_T) && defined(__GNUC__)
|
2008-03-08 07:59:47 +00:00
|
|
|
|
bool operator()(LanguagePair const & lhs, LanguagePair const & rhs) const
|
|
|
|
|
{
|
2007-11-05 22:20:23 +00:00
|
|
|
|
return lhs.first < rhs.first;
|
|
|
|
|
}
|
2007-11-14 02:01:50 +00:00
|
|
|
|
#else
|
|
|
|
|
Sorter() : loc_ok(true)
|
|
|
|
|
{
|
|
|
|
|
try {
|
2007-12-12 19:28:07 +00:00
|
|
|
|
loc_ = locale("");
|
2007-11-14 02:01:50 +00:00
|
|
|
|
} catch (...) {
|
|
|
|
|
loc_ok = false;
|
|
|
|
|
}
|
2008-03-08 07:59:47 +00:00
|
|
|
|
}
|
2007-11-14 02:01:50 +00:00
|
|
|
|
|
2008-03-08 07:59:47 +00:00
|
|
|
|
bool operator()(LanguagePair const & lhs, LanguagePair const & rhs) const
|
|
|
|
|
{
|
|
|
|
|
// FIXME: would that be "QString::localeAwareCompare()"?
|
2007-11-14 02:01:50 +00:00
|
|
|
|
if (loc_ok)
|
2008-03-08 07:59:47 +00:00
|
|
|
|
return loc_(fromqstr(lhs.first), fromqstr(rhs.first));
|
2007-11-14 02:01:50 +00:00
|
|
|
|
else
|
|
|
|
|
return lhs.first < rhs.first;
|
|
|
|
|
}
|
|
|
|
|
private:
|
2007-12-12 19:28:07 +00:00
|
|
|
|
locale loc_;
|
2007-11-14 02:01:50 +00:00
|
|
|
|
bool loc_ok;
|
|
|
|
|
#endif
|
2007-11-05 22:20:23 +00:00
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
} // namespace anon
|
|
|
|
|
|
|
|
|
|
|
2008-03-08 07:59:47 +00:00
|
|
|
|
QList<LanguagePair> languageData(bool character_dlg)
|
2007-11-05 22:20:23 +00:00
|
|
|
|
{
|
2008-03-08 07:59:47 +00:00
|
|
|
|
size_t const offset = character_dlg ? 2 : 0;
|
|
|
|
|
vector<LanguagePair> langs(languages.size() + offset);
|
2007-11-05 22:20:23 +00:00
|
|
|
|
|
|
|
|
|
if (character_dlg) {
|
2008-03-08 07:59:47 +00:00
|
|
|
|
langs[0].first = qt_("No change");
|
2007-11-05 22:20:23 +00:00
|
|
|
|
langs[0].second = "ignore";
|
2008-03-08 07:59:47 +00:00
|
|
|
|
langs[1].first = qt_("Reset");
|
2007-11-05 22:20:23 +00:00
|
|
|
|
langs[1].second = "reset";
|
|
|
|
|
}
|
|
|
|
|
|
2008-03-08 07:59:47 +00:00
|
|
|
|
Languages::const_iterator it = languages.begin();
|
|
|
|
|
for (size_t i = 0; i != languages.size(); ++i, ++it) {
|
|
|
|
|
langs[i + offset].first = qt_(it->second.display());
|
|
|
|
|
langs[i + offset].second = toqstr(it->second.lang());
|
2007-11-05 22:20:23 +00:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Don't sort "ignore" and "reset"
|
2008-03-08 07:59:47 +00:00
|
|
|
|
vector<LanguagePair>::iterator begin = langs.begin() + offset;
|
2007-12-12 19:28:07 +00:00
|
|
|
|
sort(begin, langs.end(), Sorter());
|
2007-11-05 22:20:23 +00:00
|
|
|
|
|
2008-03-08 07:59:47 +00:00
|
|
|
|
QList<LanguagePair> list;
|
|
|
|
|
foreach (LanguagePair const & l, langs)
|
|
|
|
|
list.append(l);
|
|
|
|
|
return list;
|
2007-11-05 22:20:23 +00:00
|
|
|
|
}
|
|
|
|
|
|
2008-03-08 07:59:47 +00:00
|
|
|
|
|
2007-11-05 22:20:23 +00:00
|
|
|
|
void rescanTexStyles()
|
|
|
|
|
{
|
|
|
|
|
// Run rescan in user lyx directory
|
2007-12-12 19:57:42 +00:00
|
|
|
|
PathChanger p(package().user_support());
|
2007-11-05 22:20:23 +00:00
|
|
|
|
FileName const command = libFileSearch("scripts", "TeXFiles.py");
|
|
|
|
|
Systemcall one;
|
|
|
|
|
int const status = one.startscript(Systemcall::Wait,
|
2007-12-12 19:57:42 +00:00
|
|
|
|
os::python() + ' ' +
|
2007-11-05 22:20:23 +00:00
|
|
|
|
quoteName(command.toFilesystemEncoding()));
|
|
|
|
|
if (status == 0)
|
|
|
|
|
return;
|
|
|
|
|
// FIXME UNICODE
|
|
|
|
|
frontend::Alert::error(_("Could not update TeX information"),
|
|
|
|
|
bformat(_("The script `%s' failed."), from_utf8(command.absFilename())));
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
2008-03-08 07:59:47 +00:00
|
|
|
|
QStringList texFileList(QString const & filename)
|
2007-11-05 22:20:23 +00:00
|
|
|
|
{
|
2008-03-08 07:59:47 +00:00
|
|
|
|
QStringList list;
|
|
|
|
|
FileName const file = libFileSearch(QString(), filename);
|
2007-11-05 22:20:23 +00:00
|
|
|
|
if (file.empty())
|
2008-03-08 07:59:47 +00:00
|
|
|
|
return list;
|
2007-11-05 22:20:23 +00:00
|
|
|
|
|
2007-12-02 11:55:25 +00:00
|
|
|
|
// FIXME Unicode.
|
2007-12-12 19:28:07 +00:00
|
|
|
|
vector<docstring> doclist =
|
2007-12-02 11:55:25 +00:00
|
|
|
|
getVectorFromString(file.fileContents("UTF-8"), from_ascii("\n"));
|
2007-11-05 22:20:23 +00:00
|
|
|
|
|
|
|
|
|
// Normalise paths like /foo//bar ==> /foo/bar
|
2008-03-08 07:59:47 +00:00
|
|
|
|
QSet<QString> set;
|
|
|
|
|
for (size_t i = 0; i != doclist.size(); ++i) {
|
|
|
|
|
QString file = toqstr(doclist[i]);
|
2008-03-08 09:54:48 +00:00
|
|
|
|
file.replace("\r", "");
|
2008-03-08 07:59:47 +00:00
|
|
|
|
while (file.contains("//"))
|
|
|
|
|
file.replace("//", "/");
|
|
|
|
|
if (!file.isEmpty())
|
|
|
|
|
set.insert(file);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// remove duplicates
|
|
|
|
|
return QList<QString>::fromSet(set);
|
2007-11-05 22:20:23 +00:00
|
|
|
|
}
|
|
|
|
|
|
2008-03-05 23:10:53 +00:00
|
|
|
|
|
|
|
|
|
QString internalPath(const QString & str)
|
|
|
|
|
{
|
|
|
|
|
return toqstr(os::internal_path(fromqstr(str)));
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
QString onlyFilename(const QString & str)
|
|
|
|
|
{
|
|
|
|
|
return toqstr(support::onlyFilename(fromqstr(str)));
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
QString onlyPath(const QString & str)
|
|
|
|
|
{
|
|
|
|
|
return toqstr(support::onlyPath(fromqstr(str)));
|
|
|
|
|
}
|
|
|
|
|
|
2008-03-08 07:59:47 +00:00
|
|
|
|
|
|
|
|
|
QString changeExtension(QString const & oldname, QString const & ext)
|
|
|
|
|
{
|
|
|
|
|
return toqstr(support::changeExtension(fromqstr(oldname), fromqstr(ext)));
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/// Remove the extension from \p name
|
|
|
|
|
QString removeExtension(QString const & name)
|
|
|
|
|
{
|
|
|
|
|
return toqstr(support::removeExtension(fromqstr(name)));
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/** Add the extension \p ext to \p name.
|
|
|
|
|
Use this instead of changeExtension if you know that \p name is without
|
|
|
|
|
extension, because changeExtension would wrongly interpret \p name if it
|
|
|
|
|
contains a dot.
|
|
|
|
|
*/
|
|
|
|
|
QString addExtension(QString const & name, QString const & ext)
|
|
|
|
|
{
|
|
|
|
|
return toqstr(support::addExtension(fromqstr(name), fromqstr(ext)));
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/// Return the extension of the file (not including the .)
|
|
|
|
|
QString getExtension(QString const & name)
|
|
|
|
|
{
|
|
|
|
|
return toqstr(support::getExtension(fromqstr(name)));
|
|
|
|
|
}
|
|
|
|
|
|
2008-04-20 19:56:01 +00:00
|
|
|
|
|
|
|
|
|
/** Convert relative path into absolute path based on a basepath.
|
|
|
|
|
If relpath is absolute, just use that.
|
|
|
|
|
If basepath doesn't exist use CWD.
|
|
|
|
|
*/
|
|
|
|
|
QString makeAbsPath(QString const & relpath, QString const & base)
|
|
|
|
|
{
|
|
|
|
|
return toqstr(support::makeAbsPath(fromqstr(relpath),
|
|
|
|
|
fromqstr(base)).absFilename());
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/////////////////////////////////////////////////////////////////////////
|
|
|
|
|
//
|
|
|
|
|
// FileFilterList
|
|
|
|
|
//
|
|
|
|
|
/////////////////////////////////////////////////////////////////////////
|
|
|
|
|
|
|
|
|
|
/** 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.
|
|
|
|
|
*/
|
|
|
|
|
static 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;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
struct Filter
|
|
|
|
|
{
|
|
|
|
|
/* \param description text describing the filters.
|
|
|
|
|
* \param one or more wildcard patterns, separated by
|
|
|
|
|
* whitespace.
|
|
|
|
|
*/
|
|
|
|
|
Filter(docstring const & description, std::string const & globs);
|
|
|
|
|
|
|
|
|
|
docstring const & description() const { return desc_; }
|
|
|
|
|
|
|
|
|
|
QString toString() const;
|
|
|
|
|
|
|
|
|
|
docstring desc_;
|
|
|
|
|
std::vector<std::string> globs_;
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
Filter::Filter(docstring const & description, 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());
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
QString Filter::toString() const
|
|
|
|
|
{
|
|
|
|
|
QString s;
|
|
|
|
|
|
|
|
|
|
bool const has_description = desc_.empty();
|
|
|
|
|
|
|
|
|
|
if (has_description) {
|
|
|
|
|
s += toqstr(desc_);
|
|
|
|
|
s += " (";
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
for (size_t i = 0; i != globs_.size(); ++i) {
|
|
|
|
|
if (i > 0)
|
|
|
|
|
s += ' ';
|
|
|
|
|
s += toqstr(globs_[i]);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (has_description)
|
|
|
|
|
s += ')';
|
|
|
|
|
return s;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/** \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.
|
|
|
|
|
*/
|
|
|
|
|
struct FileFilterList
|
|
|
|
|
{
|
|
|
|
|
// FIXME UNICODE: globs_ should be unicode...
|
|
|
|
|
/** \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(docstring const & qt_style_filter =
|
|
|
|
|
docstring());
|
|
|
|
|
|
|
|
|
|
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]; }
|
|
|
|
|
|
|
|
|
|
void parse_filter(std::string const & filter);
|
|
|
|
|
std::vector<Filter> filters_;
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
FileFilterList::FileFilterList(docstring const & qt_style_filter)
|
|
|
|
|
{
|
|
|
|
|
// FIXME UNICODE
|
|
|
|
|
string const filter = to_utf8(qt_style_filter)
|
|
|
|
|
+ (qt_style_filter.empty() ? string() : ";;")
|
|
|
|
|
+ to_utf8(_("All Files "))
|
|
|
|
|
#if defined(_WIN32)
|
|
|
|
|
+ ("(*.*)");
|
|
|
|
|
#else
|
|
|
|
|
+ ("(*)");
|
|
|
|
|
#endif
|
|
|
|
|
|
|
|
|
|
// 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<string::const_iterator> 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 += 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<string::const_iterator> what;
|
|
|
|
|
if (!boost::regex_search(filter, what, filter_re)) {
|
|
|
|
|
// Just a glob, no description.
|
|
|
|
|
filters_.push_back(Filter(docstring(), trim(filter)));
|
|
|
|
|
} else {
|
|
|
|
|
// FIXME UNICODE
|
|
|
|
|
docstring const desc = from_utf8(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)));
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/** \returns the equivalent of the string passed in
|
|
|
|
|
* although any brace expressions are expanded.
|
|
|
|
|
* (E.g. "*.{png,jpg}" -> "*.png *.jpg")
|
|
|
|
|
*/
|
|
|
|
|
QStringList fileFilters(QString const & desc)
|
|
|
|
|
{
|
|
|
|
|
// we have: "*.{gif,png,jpg,bmp,pbm,ppm,tga,tif,xpm,xbm}"
|
|
|
|
|
// but need: "*.cpp;*.cc;*.C;*.cxx;*.c++"
|
|
|
|
|
FileFilterList filters(qstring_to_ucs4(desc));
|
|
|
|
|
LYXERR0("DESC: " << fromqstr(desc));
|
|
|
|
|
QStringList list;
|
|
|
|
|
for (size_t i = 0; i != filters.filters_.size(); ++i) {
|
|
|
|
|
QString f = filters.filters_[i].toString();
|
|
|
|
|
LYXERR0("FILTER: " << fromqstr(f));
|
|
|
|
|
list.append(f);
|
|
|
|
|
}
|
|
|
|
|
return list;
|
|
|
|
|
}
|
|
|
|
|
|
2006-10-21 00:16:43 +00:00
|
|
|
|
} // namespace lyx
|