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"
|
|
|
|
|
|
2007-10-24 22:55:02 +00:00
|
|
|
|
#include "LengthCombo.h"
|
|
|
|
|
|
|
|
|
|
#include "debug.h"
|
2006-03-05 17:24:44 +00:00
|
|
|
|
#include "gettext.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
|
|
|
|
|
2007-11-05 22:20:23 +00:00
|
|
|
|
#include "frontends/FileDialog.h"
|
|
|
|
|
#include "frontends/alert.h"
|
|
|
|
|
|
|
|
|
|
#include "support/filetools.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
|
|
|
|
|
|
|
|
|
#include <QComboBox>
|
2007-04-05 14:58:15 +00:00
|
|
|
|
#include <QCheckBox>
|
2007-09-15 13:06:48 +00:00
|
|
|
|
#include <QPalette>
|
2007-09-15 15:42:22 +00:00
|
|
|
|
#include <QLineEdit>
|
2006-03-05 17:24:44 +00:00
|
|
|
|
|
2007-11-05 22:20:23 +00:00
|
|
|
|
#include <boost/cregex.hpp>
|
|
|
|
|
|
2006-03-05 17:24:44 +00:00
|
|
|
|
#include <algorithm>
|
2007-11-05 22:20:23 +00:00
|
|
|
|
#include <fstream>
|
2006-03-05 17:24:44 +00:00
|
|
|
|
|
2007-11-05 22:20:23 +00:00
|
|
|
|
using std::string;
|
|
|
|
|
using std::vector;
|
|
|
|
|
using std::endl;
|
2006-03-05 17:24:44 +00:00
|
|
|
|
|
2006-10-21 00:16:43 +00:00
|
|
|
|
namespace lyx {
|
|
|
|
|
|
2007-11-05 22:20:23 +00:00
|
|
|
|
using support::addName;
|
|
|
|
|
using support::bformat;
|
|
|
|
|
using support::FileFilterList;
|
|
|
|
|
using support::FileName;
|
|
|
|
|
using support::getExtension;
|
|
|
|
|
using support::getVectorFromString;
|
|
|
|
|
using support::libFileSearch;
|
|
|
|
|
using support::makeAbsPath;
|
|
|
|
|
using support::makeRelPath;
|
|
|
|
|
using support::onlyFilename;
|
|
|
|
|
using support::onlyPath;
|
|
|
|
|
using support::package;
|
|
|
|
|
using support::prefixIs;
|
|
|
|
|
using support::quoteName;
|
|
|
|
|
using support::removeExtension;
|
|
|
|
|
using support::Systemcall;
|
|
|
|
|
using support::token;
|
Make libQtCore a support library like boost and implement encoding conversion
from/to the local 8bit encoding with it.
Only the autotools build system is updated, scons and cmake users need to
add qt4 cpp flags when compiling libsupport, and link libsupport against
libQtCore.
* src/frontends/qt4/qt_helpers.[Ch]
(toqstr, qchar_to_ucs4, ucs4_to_qchar, ucs4_to_qstring,
qstring_to_ucs4, fromqstr): Move these qstring conversion functions
from here ...
* src/support/qstring_helpers.[Ch] ... to these new files
* src/support/docstring.[Ch]
(from_local8bit): new conversion function from local 8bit encoding
to ucs4
(to_local8bit): new conversion function from ucs4 to local 8bit
encoding to ucs4
(to_local8bit_failure): exception that is thrown by to_local8bit if
the argument cannot be converted to the local encoding
* src/support/filename.C
(FileName::toFilesystemEncoding): implement with the help of QFile
* src/support/Makefile.am: Add new files, qt4 cpp flags and link
against libQtCore
* src/client/client.C: Convert commandline input from local encoding
to ucs4. Convert stuff that is sent to to the server to utf8,
because LyX interprets it as utf8 on the other end of the pipe.
* src/lyx_main.C
(LyX::exec): convert commandline input from local encoding to utf8
(LyX::init): ditto
(LyX::easyParse): ditto
* development/scons/scons_manifest.py: Add new files
* config/qt4.m4: Define new variables QT4_CORE_INCLUDES,
QT4_CORE_LDFLAGS and QT4_CORE_LIB
git-svn-id: svn://svn.lyx.org/lyx/lyx-devel/trunk@16257 a592a061-630c-0410-9148-cb99ea01b6c8
2006-12-12 20:19:46 +00:00
|
|
|
|
using support::isStrDbl;
|
2006-03-05 17:24:44 +00:00
|
|
|
|
|
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 {
|
|
|
|
|
|
|
|
|
|
struct Sorter
|
|
|
|
|
{
|
|
|
|
|
bool operator()(LanguagePair const & lhs, LanguagePair const & rhs) const {
|
|
|
|
|
return lhs.first < rhs.first;
|
|
|
|
|
}
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
} // namespace anon
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
vector<LanguagePair> const getLanguageData(bool character_dlg)
|
|
|
|
|
{
|
|
|
|
|
vector<LanguagePair>::size_type const size = character_dlg ?
|
|
|
|
|
languages.size() + 2 : languages.size();
|
|
|
|
|
|
|
|
|
|
vector<LanguagePair> langs(size);
|
|
|
|
|
|
|
|
|
|
if (character_dlg) {
|
|
|
|
|
langs[0].first = _("No change");
|
|
|
|
|
langs[0].second = "ignore";
|
|
|
|
|
langs[1].first = _("Reset");
|
|
|
|
|
langs[1].second = "reset";
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
vector<string>::size_type i = character_dlg ? 2 : 0;
|
|
|
|
|
for (Languages::const_iterator cit = languages.begin();
|
|
|
|
|
cit != languages.end(); ++cit) {
|
|
|
|
|
langs[i].first = _(cit->second.display());
|
|
|
|
|
langs[i].second = cit->second.lang();
|
|
|
|
|
++i;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Don't sort "ignore" and "reset"
|
|
|
|
|
vector<LanguagePair>::iterator begin = character_dlg ?
|
|
|
|
|
langs.begin() + 2 : langs.begin();
|
|
|
|
|
|
|
|
|
|
std::sort(begin, langs.end(), Sorter());
|
|
|
|
|
|
|
|
|
|
return langs;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
docstring browseFile(docstring const & filename, docstring const & title,
|
|
|
|
|
FileFilterList const & filters, bool save,
|
|
|
|
|
docstring const & label1, docstring const & dir1,
|
|
|
|
|
docstring const & label2, docstring const & dir2)
|
|
|
|
|
{
|
|
|
|
|
docstring lastPath = from_ascii(".");
|
|
|
|
|
if (!filename.empty())
|
|
|
|
|
lastPath = from_utf8(onlyPath(to_utf8(filename)));
|
|
|
|
|
|
|
|
|
|
FileDialog dlg(title, LFUN_SELECT_FILE_SYNC);
|
|
|
|
|
dlg.setButton1(label1, dir1);
|
|
|
|
|
dlg.setButton2(label2, dir2);
|
|
|
|
|
|
|
|
|
|
FileDialog::Result result;
|
|
|
|
|
|
|
|
|
|
if (save)
|
|
|
|
|
result = dlg.save(lastPath, filters,
|
|
|
|
|
from_utf8(onlyFilename(to_utf8(filename))));
|
|
|
|
|
else
|
|
|
|
|
result = dlg.open(lastPath, filters,
|
|
|
|
|
from_utf8(onlyFilename(to_utf8(filename))));
|
|
|
|
|
|
|
|
|
|
return result.second;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
docstring browseRelFile(docstring const & filename, docstring const & refpath,
|
|
|
|
|
docstring const & title, FileFilterList const & filters, bool save,
|
|
|
|
|
docstring const & label1, docstring const & dir1,
|
|
|
|
|
docstring const & label2, docstring const & dir2)
|
|
|
|
|
{
|
|
|
|
|
docstring const fname = from_utf8(makeAbsPath(
|
|
|
|
|
to_utf8(filename), to_utf8(refpath)).absFilename());
|
|
|
|
|
|
|
|
|
|
docstring const outname = browseFile(fname, title, filters, save,
|
|
|
|
|
label1, dir1, label2, dir2);
|
|
|
|
|
docstring const reloutname = makeRelPath(outname, refpath);
|
|
|
|
|
if (prefixIs(reloutname, from_ascii("../")))
|
|
|
|
|
return outname;
|
|
|
|
|
else
|
|
|
|
|
return reloutname;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
docstring browseLibFile(docstring const & dir, docstring const & name,
|
|
|
|
|
docstring const & ext, docstring const & title,
|
|
|
|
|
FileFilterList const & filters)
|
|
|
|
|
{
|
|
|
|
|
// FIXME UNICODE
|
|
|
|
|
docstring const label1 = _("System files|#S#s");
|
|
|
|
|
docstring const dir1 =
|
|
|
|
|
from_utf8(addName(package().system_support().absFilename(), to_utf8(dir)));
|
|
|
|
|
|
|
|
|
|
docstring const label2 = _("User files|#U#u");
|
|
|
|
|
docstring const dir2 =
|
|
|
|
|
from_utf8(addName(package().user_support().absFilename(), to_utf8(dir)));
|
|
|
|
|
|
|
|
|
|
docstring const result = browseFile(from_utf8(
|
|
|
|
|
libFileSearch(to_utf8(dir), to_utf8(name), to_utf8(ext)).absFilename()),
|
|
|
|
|
title, filters, false, dir1, dir2);
|
|
|
|
|
|
|
|
|
|
// remove the extension if it is the default one
|
|
|
|
|
docstring noextresult;
|
|
|
|
|
if (from_utf8(getExtension(to_utf8(result))) == ext)
|
|
|
|
|
noextresult = from_utf8(removeExtension(to_utf8(result)));
|
|
|
|
|
else
|
|
|
|
|
noextresult = result;
|
|
|
|
|
|
|
|
|
|
// remove the directory, if it is the default one
|
|
|
|
|
docstring const file = from_utf8(onlyFilename(to_utf8(noextresult)));
|
|
|
|
|
if (from_utf8(libFileSearch(to_utf8(dir), to_utf8(file), to_utf8(ext)).absFilename()) == result)
|
|
|
|
|
return file;
|
|
|
|
|
else
|
|
|
|
|
return noextresult;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
docstring browseDir(docstring const & pathname, docstring const & title,
|
|
|
|
|
docstring const & label1, docstring const & dir1,
|
|
|
|
|
docstring const & label2, docstring const & dir2)
|
|
|
|
|
{
|
|
|
|
|
docstring lastPath = from_ascii(".");
|
|
|
|
|
if (!pathname.empty())
|
|
|
|
|
lastPath = from_utf8(onlyPath(to_utf8(pathname)));
|
|
|
|
|
|
|
|
|
|
FileDialog dlg(title, LFUN_SELECT_FILE_SYNC);
|
|
|
|
|
dlg.setButton1(label1, dir1);
|
|
|
|
|
dlg.setButton2(label2, dir2);
|
|
|
|
|
|
|
|
|
|
FileDialog::Result const result =
|
|
|
|
|
dlg.opendir(lastPath, from_utf8(onlyFilename(to_utf8(pathname))));
|
|
|
|
|
|
|
|
|
|
return result.second;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
void rescanTexStyles()
|
|
|
|
|
{
|
|
|
|
|
// Run rescan in user lyx directory
|
2007-11-10 13:44:50 +00:00
|
|
|
|
support::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-11-10 13:44:50 +00:00
|
|
|
|
support::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())));
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
void getTexFileList(string const & filename, std::vector<string> & list)
|
|
|
|
|
{
|
|
|
|
|
list.clear();
|
|
|
|
|
FileName const file = libFileSearch("", filename);
|
|
|
|
|
if (file.empty())
|
|
|
|
|
return;
|
|
|
|
|
|
|
|
|
|
list = getVectorFromString(file.fileContents(), "\n");
|
|
|
|
|
|
|
|
|
|
// Normalise paths like /foo//bar ==> /foo/bar
|
|
|
|
|
boost::RegEx regex("/{2,}");
|
|
|
|
|
std::vector<string>::iterator it = list.begin();
|
|
|
|
|
std::vector<string>::iterator end = list.end();
|
|
|
|
|
for (; it != end; ++it)
|
|
|
|
|
*it = regex.Merge((*it), "/");
|
|
|
|
|
|
|
|
|
|
// remove empty items and duplicates
|
|
|
|
|
list.erase(std::remove(list.begin(), list.end(), ""), list.end());
|
|
|
|
|
eliminate_duplicates(list);
|
|
|
|
|
}
|
|
|
|
|
|
2006-10-21 00:16:43 +00:00
|
|
|
|
} // namespace lyx
|