2006-06-26 17:18:28 +00:00
|
|
|
/**
|
2007-09-05 20:33:29 +00:00
|
|
|
* \file GuiApplication.cpp
|
2006-06-26 17:18:28 +00:00
|
|
|
* This file is part of LyX, the document processor.
|
|
|
|
* Licence details can be found in the file COPYING.
|
|
|
|
*
|
|
|
|
* \author unknown
|
|
|
|
* \author John Levon
|
|
|
|
* \author Abdelrazak Younes
|
|
|
|
*
|
|
|
|
* Full author contact details are available in file CREDITS.
|
|
|
|
*/
|
|
|
|
|
2006-07-01 18:14:58 +00:00
|
|
|
#include <config.h>
|
|
|
|
|
2006-09-22 09:47:39 +00:00
|
|
|
#include "GuiApplication.h"
|
2006-06-26 17:18:28 +00:00
|
|
|
|
2008-05-23 08:43:07 +00:00
|
|
|
#include "ColorCache.h"
|
2009-02-09 23:30:24 +00:00
|
|
|
#include "ColorSet.h"
|
2008-05-23 08:43:07 +00:00
|
|
|
#include "GuiClipboard.h"
|
2007-08-31 05:53:55 +00:00
|
|
|
#include "GuiImage.h"
|
2008-03-14 23:25:11 +00:00
|
|
|
#include "GuiKeySymbol.h"
|
2008-05-23 08:43:07 +00:00
|
|
|
#include "GuiSelection.h"
|
2007-11-17 20:47:50 +00:00
|
|
|
#include "GuiView.h"
|
2008-05-23 08:43:07 +00:00
|
|
|
#include "Menus.h"
|
|
|
|
#include "qt_helpers.h"
|
2008-05-25 08:30:06 +00:00
|
|
|
#include "Toolbars.h"
|
2006-08-17 08:37:46 +00:00
|
|
|
|
2007-09-21 20:27:07 +00:00
|
|
|
#include "frontends/alert.h"
|
2007-11-17 22:11:11 +00:00
|
|
|
#include "frontends/Application.h"
|
|
|
|
#include "frontends/FontLoader.h"
|
|
|
|
#include "frontends/FontMetrics.h"
|
2006-11-07 17:19:33 +00:00
|
|
|
|
2007-11-24 07:58:12 +00:00
|
|
|
#include "Buffer.h"
|
2007-08-27 06:35:24 +00:00
|
|
|
#include "BufferList.h"
|
2006-09-29 23:21:03 +00:00
|
|
|
#include "BufferView.h"
|
2010-02-09 16:11:13 +00:00
|
|
|
#include "CmdDef.h"
|
2008-05-23 09:53:27 +00:00
|
|
|
#include "Color.h"
|
2007-11-17 22:11:11 +00:00
|
|
|
#include "Font.h"
|
2007-04-26 04:41:58 +00:00
|
|
|
#include "FuncRequest.h"
|
2007-11-24 07:58:12 +00:00
|
|
|
#include "FuncStatus.h"
|
2009-10-04 20:58:20 +00:00
|
|
|
#include "Intl.h"
|
2009-10-04 22:40:00 +00:00
|
|
|
#include "KeyMap.h"
|
2008-05-08 09:03:38 +00:00
|
|
|
#include "Language.h"
|
2009-10-04 20:58:20 +00:00
|
|
|
#include "LaTeXFeatures.h"
|
2008-05-24 09:28:05 +00:00
|
|
|
#include "Lexer.h"
|
2007-04-26 04:41:58 +00:00
|
|
|
#include "LyX.h"
|
2008-06-05 08:31:22 +00:00
|
|
|
#include "LyXAction.h"
|
2007-04-26 04:41:58 +00:00
|
|
|
#include "LyXRC.h"
|
2010-02-09 16:11:13 +00:00
|
|
|
#include "Paragraph.h"
|
2009-10-04 20:58:20 +00:00
|
|
|
#include "Server.h"
|
2007-11-24 07:58:12 +00:00
|
|
|
#include "Session.h"
|
2009-10-04 22:40:00 +00:00
|
|
|
#include "SpellChecker.h"
|
2010-02-10 08:10:31 +00:00
|
|
|
#include "Thesaurus.h"
|
2007-11-16 22:10:35 +00:00
|
|
|
#include "version.h"
|
2006-06-26 17:18:28 +00:00
|
|
|
|
2010-02-09 16:11:13 +00:00
|
|
|
#include "support/convert.h"
|
2008-02-18 07:14:42 +00:00
|
|
|
#include "support/debug.h"
|
|
|
|
#include "support/ExceptionMessage.h"
|
|
|
|
#include "support/FileName.h"
|
2009-09-22 19:55:15 +00:00
|
|
|
#include "support/filetools.h"
|
2008-05-23 18:09:40 +00:00
|
|
|
#include "support/foreach.h"
|
2008-02-18 07:14:42 +00:00
|
|
|
#include "support/ForkedCalls.h"
|
2008-03-06 21:50:27 +00:00
|
|
|
#include "support/gettext.h"
|
2010-02-09 16:11:13 +00:00
|
|
|
#include "support/lassert.h"
|
2008-02-18 07:14:42 +00:00
|
|
|
#include "support/lstrings.h"
|
2008-06-05 08:31:22 +00:00
|
|
|
#include "support/lyxalgo.h" // sorted
|
2008-07-28 11:26:46 +00:00
|
|
|
#include "support/Messages.h"
|
2008-02-18 07:14:42 +00:00
|
|
|
#include "support/os.h"
|
|
|
|
#include "support/Package.h"
|
2009-10-04 20:58:20 +00:00
|
|
|
#include "support/Path.h"
|
|
|
|
#include "support/Systemcall.h"
|
2008-02-18 07:14:42 +00:00
|
|
|
|
2008-05-23 07:52:39 +00:00
|
|
|
#ifdef Q_WS_MACX
|
|
|
|
#include "support/linkback/LinkBackProxy.h"
|
|
|
|
#endif
|
|
|
|
|
2008-11-15 16:29:58 +00:00
|
|
|
#include <queue>
|
|
|
|
|
2008-06-06 12:29:58 +00:00
|
|
|
#include <QByteArray>
|
2006-09-22 09:47:39 +00:00
|
|
|
#include <QClipboard>
|
2008-09-21 22:11:59 +00:00
|
|
|
#include <QDateTime>
|
2008-06-05 13:27:37 +00:00
|
|
|
#include <QDir>
|
2006-06-26 17:18:28 +00:00
|
|
|
#include <QEventLoop>
|
2006-11-29 09:06:37 +00:00
|
|
|
#include <QFileOpenEvent>
|
2008-09-21 21:28:37 +00:00
|
|
|
#include <QFileInfo>
|
2008-05-23 18:09:40 +00:00
|
|
|
#include <QHash>
|
2008-06-05 08:31:22 +00:00
|
|
|
#include <QIcon>
|
2008-06-06 12:29:58 +00:00
|
|
|
#include <QImageReader>
|
2006-09-22 09:47:39 +00:00
|
|
|
#include <QLocale>
|
|
|
|
#include <QLibraryInfo>
|
2008-06-05 08:31:22 +00:00
|
|
|
#include <QList>
|
2008-05-23 07:52:39 +00:00
|
|
|
#include <QMacPasteboardMime>
|
2007-12-26 09:54:48 +00:00
|
|
|
#include <QMenuBar>
|
2008-05-23 07:52:39 +00:00
|
|
|
#include <QMimeData>
|
2008-06-05 08:31:22 +00:00
|
|
|
#include <QObject>
|
|
|
|
#include <QPixmap>
|
2007-08-21 07:33:46 +00:00
|
|
|
#include <QPixmapCache>
|
2007-11-15 12:58:44 +00:00
|
|
|
#include <QRegExp>
|
2007-08-27 06:35:24 +00:00
|
|
|
#include <QSessionManager>
|
2008-09-21 21:28:37 +00:00
|
|
|
#include <QSettings>
|
2007-09-15 20:31:50 +00:00
|
|
|
#include <QSocketNotifier>
|
2008-05-14 10:34:19 +00:00
|
|
|
#include <QSortFilterProxyModel>
|
2008-05-08 09:03:38 +00:00
|
|
|
#include <QStandardItemModel>
|
2006-06-26 17:18:28 +00:00
|
|
|
#include <QTextCodec>
|
2006-11-26 10:32:42 +00:00
|
|
|
#include <QTimer>
|
2006-09-22 09:47:39 +00:00
|
|
|
#include <QTranslator>
|
2010-04-19 19:55:15 +00:00
|
|
|
#if QT_VERSION >= 0x040400
|
2010-03-18 12:42:34 +00:00
|
|
|
#include <QThreadPool>
|
2010-03-24 08:50:06 +00:00
|
|
|
#endif
|
2006-09-29 23:10:17 +00:00
|
|
|
#include <QWidget>
|
2006-06-26 17:18:28 +00:00
|
|
|
|
|
|
|
#ifdef Q_WS_X11
|
2007-01-05 10:11:21 +00:00
|
|
|
#include <X11/Xatom.h>
|
2006-06-26 17:18:28 +00:00
|
|
|
#include <X11/Xlib.h>
|
2007-11-11 12:14:06 +00:00
|
|
|
#undef CursorShape
|
|
|
|
#undef None
|
2006-06-26 17:18:28 +00:00
|
|
|
#endif
|
|
|
|
|
2008-05-23 07:52:39 +00:00
|
|
|
#ifdef Q_WS_WIN
|
|
|
|
#include <QWindowsMime>
|
2008-10-15 22:03:13 +00:00
|
|
|
#ifdef Q_CC_GNU
|
2008-05-23 07:52:39 +00:00
|
|
|
#include <wtypes.h>
|
|
|
|
#endif
|
|
|
|
#include <objidl.h>
|
|
|
|
#endif // Q_WS_WIN
|
|
|
|
|
2010-04-22 11:16:58 +00:00
|
|
|
#include "support/bind.h"
|
2008-06-19 11:28:11 +00:00
|
|
|
#include <boost/crc.hpp>
|
2006-09-22 09:47:39 +00:00
|
|
|
|
2007-04-02 10:18:12 +00:00
|
|
|
#include <exception>
|
2009-10-05 14:56:51 +00:00
|
|
|
#include <sstream>
|
2008-06-05 08:31:22 +00:00
|
|
|
#include <vector>
|
2007-04-02 10:18:12 +00:00
|
|
|
|
2007-12-12 10:16:00 +00:00
|
|
|
using namespace std;
|
2007-12-12 19:57:42 +00:00
|
|
|
using namespace lyx::support;
|
2006-06-26 17:18:28 +00:00
|
|
|
|
2008-05-23 07:52:39 +00:00
|
|
|
|
2008-06-05 08:31:22 +00:00
|
|
|
static void initializeResources()
|
|
|
|
{
|
|
|
|
static bool initialized = false;
|
|
|
|
if (!initialized) {
|
2011-01-16 04:02:59 +00:00
|
|
|
Q_INIT_RESOURCE(Resources);
|
2008-06-05 08:31:22 +00:00
|
|
|
initialized = true;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2007-09-15 17:47:35 +00:00
|
|
|
namespace lyx {
|
2006-09-22 09:47:39 +00:00
|
|
|
|
2007-09-15 17:47:35 +00:00
|
|
|
frontend::Application * createApplication(int & argc, char * argv[])
|
2006-09-22 09:47:39 +00:00
|
|
|
{
|
2008-10-09 07:19:34 +00:00
|
|
|
#ifndef Q_WS_X11
|
|
|
|
// prune -geometry argument(s) by shifting
|
|
|
|
// the following ones 2 places down.
|
|
|
|
for (int i = 0 ; i < argc ; ++i) {
|
2008-11-08 23:44:43 +00:00
|
|
|
if (strcmp(argv[i], "-geometry") == 0) {
|
2008-10-09 07:19:34 +00:00
|
|
|
int const remove = (i+1) < argc ? 2 : 1;
|
|
|
|
argc -= remove;
|
|
|
|
for (int j = i; j < argc; ++j)
|
|
|
|
argv[j] = argv[j + remove];
|
|
|
|
--i;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
#endif
|
2010-08-08 23:11:02 +00:00
|
|
|
frontend::GuiApplication * guiApp = new frontend::GuiApplication(argc, argv);
|
|
|
|
// I'd rather do that in the constructor, but I do not think that
|
|
|
|
// the palette is accessible there.
|
|
|
|
guiApp->colorCache().setPalette(guiApp->palette());
|
|
|
|
return guiApp;
|
2006-09-22 09:47:39 +00:00
|
|
|
}
|
|
|
|
|
2007-09-15 17:47:35 +00:00
|
|
|
namespace frontend {
|
2006-09-22 09:47:39 +00:00
|
|
|
|
2008-06-06 12:29:58 +00:00
|
|
|
|
|
|
|
/// Return the list of loadable formats.
|
|
|
|
vector<string> loadableImageFormats()
|
|
|
|
{
|
|
|
|
vector<string> fmts;
|
|
|
|
|
|
|
|
QList<QByteArray> qt_formats = QImageReader::supportedImageFormats();
|
|
|
|
|
|
|
|
LYXERR(Debug::GRAPHICS,
|
|
|
|
"\nThe image loader can load the following directly:\n");
|
|
|
|
|
|
|
|
if (qt_formats.empty())
|
|
|
|
LYXERR(Debug::GRAPHICS, "\nQt4 Problem: No Format available!");
|
|
|
|
|
|
|
|
for (QList<QByteArray>::const_iterator it = qt_formats.begin(); it != qt_formats.end(); ++it) {
|
|
|
|
|
|
|
|
LYXERR(Debug::GRAPHICS, (const char *) *it << ", ");
|
|
|
|
|
|
|
|
string ext = ascii_lowercase((const char *) *it);
|
|
|
|
// special case
|
|
|
|
if (ext == "jpeg")
|
|
|
|
ext = "jpg";
|
|
|
|
fmts.push_back(ext);
|
|
|
|
}
|
|
|
|
|
|
|
|
return fmts;
|
|
|
|
}
|
2008-11-05 14:04:37 +00:00
|
|
|
|
|
|
|
|
2008-06-05 08:31:22 +00:00
|
|
|
////////////////////////////////////////////////////////////////////////
|
2008-11-16 12:22:54 +00:00
|
|
|
//
|
|
|
|
// Icon loading support code
|
|
|
|
//
|
2008-06-05 08:31:22 +00:00
|
|
|
////////////////////////////////////////////////////////////////////////
|
|
|
|
|
|
|
|
namespace {
|
|
|
|
|
|
|
|
struct PngMap {
|
|
|
|
QString key;
|
|
|
|
QString value;
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
bool operator<(PngMap const & lhs, PngMap const & rhs)
|
|
|
|
{
|
|
|
|
return lhs.key < rhs.key;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
class CompareKey {
|
|
|
|
public:
|
|
|
|
CompareKey(QString const & name) : name_(name) {}
|
|
|
|
bool operator()(PngMap const & other) const { return other.key == name_; }
|
|
|
|
private:
|
|
|
|
QString const name_;
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
// this must be sorted alphabetically
|
|
|
|
// Upper case comes before lower case
|
|
|
|
PngMap sorted_png_map[] = {
|
|
|
|
{ "Bumpeq", "bumpeq2" },
|
|
|
|
{ "Cap", "cap2" },
|
|
|
|
{ "Cup", "cup2" },
|
|
|
|
{ "Delta", "delta2" },
|
2010-01-23 09:59:48 +00:00
|
|
|
{ "Diamond", "diamond2" },
|
2008-06-05 08:31:22 +00:00
|
|
|
{ "Downarrow", "downarrow2" },
|
|
|
|
{ "Gamma", "gamma2" },
|
|
|
|
{ "Lambda", "lambda2" },
|
|
|
|
{ "Leftarrow", "leftarrow2" },
|
|
|
|
{ "Leftrightarrow", "leftrightarrow2" },
|
|
|
|
{ "Longleftarrow", "longleftarrow2" },
|
|
|
|
{ "Longleftrightarrow", "longleftrightarrow2" },
|
|
|
|
{ "Longrightarrow", "longrightarrow2" },
|
|
|
|
{ "Omega", "omega2" },
|
|
|
|
{ "Phi", "phi2" },
|
|
|
|
{ "Pi", "pi2" },
|
|
|
|
{ "Psi", "psi2" },
|
|
|
|
{ "Rightarrow", "rightarrow2" },
|
|
|
|
{ "Sigma", "sigma2" },
|
|
|
|
{ "Subset", "subset2" },
|
|
|
|
{ "Supset", "supset2" },
|
|
|
|
{ "Theta", "theta2" },
|
|
|
|
{ "Uparrow", "uparrow2" },
|
|
|
|
{ "Updownarrow", "updownarrow2" },
|
|
|
|
{ "Upsilon", "upsilon2" },
|
|
|
|
{ "Vdash", "vdash3" },
|
|
|
|
{ "Vert", "vert2" },
|
|
|
|
{ "Xi", "xi2" },
|
|
|
|
{ "nLeftarrow", "nleftarrow2" },
|
|
|
|
{ "nLeftrightarrow", "nleftrightarrow2" },
|
|
|
|
{ "nRightarrow", "nrightarrow2" },
|
|
|
|
{ "nVDash", "nvdash3" },
|
|
|
|
{ "nvDash", "nvdash2" },
|
|
|
|
{ "textrm \\AA", "textrm_AA"},
|
|
|
|
{ "textrm \\O", "textrm_O"},
|
2011-01-01 19:19:32 +00:00
|
|
|
{ "vDash", "vdash2" }
|
2008-06-05 08:31:22 +00:00
|
|
|
};
|
|
|
|
|
|
|
|
size_t const nr_sorted_png_map = sizeof(sorted_png_map) / sizeof(PngMap);
|
|
|
|
|
|
|
|
|
|
|
|
QString findPng(QString const & name)
|
|
|
|
{
|
|
|
|
PngMap const * const begin = sorted_png_map;
|
|
|
|
PngMap const * const end = begin + nr_sorted_png_map;
|
|
|
|
LASSERT(sorted(begin, end), /**/);
|
|
|
|
|
|
|
|
PngMap const * const it = find_if(begin, end, CompareKey(name));
|
|
|
|
|
|
|
|
QString png_name;
|
|
|
|
if (it != end) {
|
|
|
|
png_name = it->value;
|
|
|
|
} else {
|
|
|
|
png_name = name;
|
|
|
|
png_name.replace('_', "underscore");
|
|
|
|
png_name.replace(' ', '_');
|
|
|
|
|
|
|
|
// This way we can have "math-delim { }" on the toolbar.
|
|
|
|
png_name.replace('(', "lparen");
|
|
|
|
png_name.replace(')', "rparen");
|
|
|
|
png_name.replace('[', "lbracket");
|
|
|
|
png_name.replace(']', "rbracket");
|
|
|
|
png_name.replace('{', "lbrace");
|
|
|
|
png_name.replace('}', "rbrace");
|
|
|
|
png_name.replace('|', "bars");
|
|
|
|
png_name.replace(',', "thinspace");
|
|
|
|
png_name.replace(':', "mediumspace");
|
|
|
|
png_name.replace(';', "thickspace");
|
|
|
|
png_name.replace('!', "negthinspace");
|
|
|
|
}
|
|
|
|
|
|
|
|
LYXERR(Debug::GUI, "findPng(" << name << ")\n"
|
|
|
|
<< "Looking for math PNG called \"" << png_name << '"');
|
|
|
|
return png_name;
|
|
|
|
}
|
|
|
|
|
|
|
|
} // namespace anon
|
|
|
|
|
|
|
|
|
|
|
|
QString iconName(FuncRequest const & f, bool unknown)
|
|
|
|
{
|
|
|
|
initializeResources();
|
|
|
|
QString name1;
|
|
|
|
QString name2;
|
|
|
|
QString path;
|
2010-04-09 19:00:42 +00:00
|
|
|
switch (f.action()) {
|
2008-06-05 08:31:22 +00:00
|
|
|
case LFUN_MATH_INSERT:
|
|
|
|
if (!f.argument().empty()) {
|
|
|
|
path = "math/";
|
|
|
|
name1 = findPng(toqstr(f.argument()).mid(1));
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
case LFUN_MATH_DELIM:
|
|
|
|
case LFUN_MATH_BIGDELIM:
|
|
|
|
path = "math/";
|
|
|
|
name1 = findPng(toqstr(f.argument()));
|
|
|
|
break;
|
|
|
|
case LFUN_CALL:
|
|
|
|
path = "commands/";
|
|
|
|
name1 = toqstr(f.argument());
|
|
|
|
break;
|
2009-01-25 17:04:57 +00:00
|
|
|
case LFUN_COMMAND_ALTERNATIVES: {
|
|
|
|
// use the first of the alternative commands
|
|
|
|
docstring firstcom;
|
|
|
|
docstring dummy = split(f.argument(), firstcom, ';');
|
|
|
|
name1 = toqstr(firstcom);
|
2010-02-18 08:28:46 +00:00
|
|
|
// FIXME: we should rename the icons to tabular-xxx instead of
|
|
|
|
// "tabular-feature-xxx"
|
|
|
|
name1.replace("inset-modify tabular", "tabular-feature");
|
2009-01-25 17:04:57 +00:00
|
|
|
name1.replace(' ', '_');
|
|
|
|
break;
|
|
|
|
}
|
2010-02-18 08:28:46 +00:00
|
|
|
case LFUN_INSET_MODIFY: {
|
|
|
|
// FIXME: we should rename the icons to tabular-xxx instead of
|
|
|
|
// "tabular-feature-xxx" and generalize this naming to all
|
|
|
|
// insets, not to tabular using ones.
|
|
|
|
string inset_name;
|
|
|
|
string const command = split(to_utf8(f.argument()), inset_name, ' ');
|
|
|
|
if (insetCode(inset_name) == TABULAR_CODE) {
|
|
|
|
name1 = "tabular-feature "+ toqstr(command);
|
|
|
|
name1.replace(' ', '_');
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
2008-06-05 08:31:22 +00:00
|
|
|
default:
|
2010-04-09 19:00:42 +00:00
|
|
|
name2 = toqstr(lyxaction.getActionName(f.action()));
|
2008-06-05 08:31:22 +00:00
|
|
|
name1 = name2;
|
|
|
|
|
|
|
|
if (!f.argument().empty()) {
|
|
|
|
name1 = name2 + ' ' + toqstr(f.argument());
|
|
|
|
name1.replace(' ', '_');
|
2009-01-02 01:52:54 +00:00
|
|
|
name1.replace('\\', "backslash");
|
2008-06-05 08:31:22 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
FileName fname = libFileSearch("images/" + path, name1, "png");
|
|
|
|
if (fname.exists())
|
2010-04-21 01:19:09 +00:00
|
|
|
return toqstr(fname.absFileName());
|
2008-06-05 08:31:22 +00:00
|
|
|
|
|
|
|
fname = libFileSearch("images/" + path, name2, "png");
|
|
|
|
if (fname.exists())
|
2010-04-21 01:19:09 +00:00
|
|
|
return toqstr(fname.absFileName());
|
2008-06-05 08:31:22 +00:00
|
|
|
|
|
|
|
path = ":/images/" + path;
|
|
|
|
QDir res(path);
|
|
|
|
if (!res.exists()) {
|
2011-01-16 04:02:59 +00:00
|
|
|
LYXERR0("Directory " << path << " not found in resource!");
|
2008-06-05 08:31:22 +00:00
|
|
|
return QString();
|
|
|
|
}
|
|
|
|
name1 += ".png";
|
|
|
|
if (res.exists(name1))
|
|
|
|
return path + name1;
|
|
|
|
|
|
|
|
name2 += ".png";
|
|
|
|
if (res.exists(name2))
|
|
|
|
return path + name2;
|
|
|
|
|
2009-01-05 19:05:46 +00:00
|
|
|
LYXERR(Debug::GUI, "Cannot find icon with filename "
|
|
|
|
<< "\"" << name1 << "\""
|
|
|
|
<< " or filename "
|
2011-01-16 04:02:59 +00:00
|
|
|
<< "\"" << name2 << "\""
|
2009-01-05 19:05:46 +00:00
|
|
|
<< " for command \""
|
2010-04-09 19:00:42 +00:00
|
|
|
<< lyxaction.getActionName(f.action())
|
2008-06-05 08:31:22 +00:00
|
|
|
<< '(' << to_utf8(f.argument()) << ")\"");
|
|
|
|
|
2009-04-03 17:00:09 +00:00
|
|
|
if (unknown) {
|
2009-04-27 11:56:13 +00:00
|
|
|
fname = libFileSearch(QString("images/"), "unknown", "png");
|
2009-04-03 17:00:09 +00:00
|
|
|
if (fname.exists())
|
2010-04-21 01:19:09 +00:00
|
|
|
return toqstr(fname.absFileName());
|
2008-06-05 08:31:22 +00:00
|
|
|
return QString(":/images/unknown.png");
|
2009-04-03 17:00:09 +00:00
|
|
|
}
|
2008-06-05 08:31:22 +00:00
|
|
|
|
|
|
|
return QString();
|
|
|
|
}
|
|
|
|
|
2009-04-03 17:00:09 +00:00
|
|
|
QPixmap getPixmap(QString const & path, QString const & name, QString const & ext)
|
|
|
|
{
|
|
|
|
QPixmap pixmap;
|
|
|
|
FileName fname = libFileSearch(path, name, ext);
|
2010-04-21 01:19:09 +00:00
|
|
|
QString path1 = toqstr(fname.absFileName());
|
2009-04-03 17:00:09 +00:00
|
|
|
QString path2 = ":/" + path + name + "." + ext;
|
|
|
|
|
|
|
|
if (pixmap.load(path1)) {
|
|
|
|
return pixmap;
|
|
|
|
}
|
|
|
|
else if (pixmap.load(path2)) {
|
|
|
|
return pixmap;
|
|
|
|
}
|
|
|
|
|
|
|
|
LYXERR0("Cannot load pixmap \""
|
|
|
|
<< path << name << '.' << ext
|
|
|
|
<< "\", please verify resource system!");
|
|
|
|
|
|
|
|
return QPixmap();
|
|
|
|
}
|
2008-06-05 08:31:22 +00:00
|
|
|
|
|
|
|
QIcon getIcon(FuncRequest const & f, bool unknown)
|
|
|
|
{
|
|
|
|
QString icon = iconName(f, unknown);
|
|
|
|
if (icon.isEmpty())
|
|
|
|
return QIcon();
|
|
|
|
|
2008-06-19 14:22:32 +00:00
|
|
|
//LYXERR(Debug::GUI, "Found icon: " << icon);
|
2008-06-05 08:31:22 +00:00
|
|
|
QPixmap pm;
|
|
|
|
if (!pm.load(icon)) {
|
|
|
|
LYXERR0("Cannot load icon " << icon << " please verify resource system!");
|
|
|
|
return QIcon();
|
|
|
|
}
|
|
|
|
|
|
|
|
return QIcon(pm);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
////////////////////////////////////////////////////////////////////////
|
2008-11-16 12:22:54 +00:00
|
|
|
//
|
2008-06-05 08:31:22 +00:00
|
|
|
// LyX server support code.
|
2008-11-16 12:22:54 +00:00
|
|
|
//
|
2008-06-05 08:31:22 +00:00
|
|
|
////////////////////////////////////////////////////////////////////////
|
2008-11-16 12:22:54 +00:00
|
|
|
|
2007-09-15 20:31:50 +00:00
|
|
|
class SocketNotifier : public QSocketNotifier
|
|
|
|
{
|
|
|
|
public:
|
|
|
|
/// connect a connection notification from the LyXServerSocket
|
|
|
|
SocketNotifier(QObject * parent, int fd, Application::SocketCallback func)
|
|
|
|
: QSocketNotifier(fd, QSocketNotifier::Read, parent), func_(func)
|
|
|
|
{}
|
|
|
|
|
|
|
|
public:
|
|
|
|
/// The callback function
|
|
|
|
Application::SocketCallback func_;
|
|
|
|
};
|
|
|
|
|
|
|
|
|
2007-09-15 17:47:35 +00:00
|
|
|
////////////////////////////////////////////////////////////////////////
|
2008-11-16 12:22:54 +00:00
|
|
|
//
|
2007-09-15 17:47:35 +00:00
|
|
|
// Mac specific stuff goes here...
|
2008-11-16 12:22:54 +00:00
|
|
|
//
|
2008-06-05 08:31:22 +00:00
|
|
|
////////////////////////////////////////////////////////////////////////
|
2007-05-04 17:20:53 +00:00
|
|
|
|
2007-09-15 17:47:35 +00:00
|
|
|
class MenuTranslator : public QTranslator
|
2006-10-12 14:10:13 +00:00
|
|
|
{
|
2007-09-15 17:47:35 +00:00
|
|
|
public:
|
2007-09-15 20:31:50 +00:00
|
|
|
MenuTranslator(QObject * parent)
|
|
|
|
: QTranslator(parent)
|
|
|
|
{}
|
|
|
|
|
2011-01-16 04:02:59 +00:00
|
|
|
QString translate(const char * /*context*/,
|
|
|
|
const char * sourceText,
|
|
|
|
const char * /*comment*/ = 0)
|
2007-09-15 17:47:35 +00:00
|
|
|
{
|
|
|
|
string const s = sourceText;
|
2011-01-16 04:02:59 +00:00
|
|
|
if (s == N_("About %1") || s == N_("Preferences")
|
2007-09-15 17:47:35 +00:00
|
|
|
|| s == N_("Reconfigure") || s == N_("Quit %1"))
|
|
|
|
return qt_(s);
|
2011-01-16 04:02:59 +00:00
|
|
|
else
|
2007-09-15 17:47:35 +00:00
|
|
|
return QString();
|
|
|
|
}
|
|
|
|
};
|
2006-10-12 14:10:13 +00:00
|
|
|
|
2008-03-14 23:25:11 +00:00
|
|
|
class GlobalMenuBar : public QMenuBar
|
|
|
|
{
|
|
|
|
public:
|
|
|
|
///
|
|
|
|
GlobalMenuBar() : QMenuBar(0) {}
|
2011-01-16 04:02:59 +00:00
|
|
|
|
2008-03-14 23:25:11 +00:00
|
|
|
///
|
|
|
|
bool event(QEvent * e)
|
|
|
|
{
|
|
|
|
if (e->type() == QEvent::ShortcutOverride) {
|
|
|
|
// && activeWindow() == 0) {
|
|
|
|
QKeyEvent * ke = static_cast<QKeyEvent*>(e);
|
|
|
|
KeySymbol sym;
|
|
|
|
setKeySymbol(&sym, ke);
|
2009-10-04 20:58:20 +00:00
|
|
|
guiApp->processKeySym(sym, q_key_state(ke->modifiers()));
|
2008-03-14 23:25:11 +00:00
|
|
|
e->accept();
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
};
|
2006-10-12 14:10:13 +00:00
|
|
|
|
2008-05-23 07:52:39 +00:00
|
|
|
#ifdef Q_WS_MACX
|
|
|
|
// QMacPasteboardMimeGraphics can only be compiled on Mac.
|
|
|
|
|
|
|
|
class QMacPasteboardMimeGraphics : public QMacPasteboardMime
|
|
|
|
{
|
|
|
|
public:
|
|
|
|
QMacPasteboardMimeGraphics()
|
|
|
|
: QMacPasteboardMime(MIME_QT_CONVERTOR|MIME_ALL)
|
|
|
|
{}
|
|
|
|
|
|
|
|
QString convertorName() { return "Graphics"; }
|
|
|
|
|
|
|
|
QString flavorFor(QString const & mime)
|
|
|
|
{
|
|
|
|
LYXERR(Debug::ACTION, "flavorFor " << mime);
|
2008-05-26 13:43:35 +00:00
|
|
|
if (mime == pdfMimeType())
|
2008-05-23 07:52:39 +00:00
|
|
|
return QLatin1String("com.adobe.pdf");
|
|
|
|
return QString();
|
|
|
|
}
|
|
|
|
|
|
|
|
QString mimeFor(QString flav)
|
|
|
|
{
|
|
|
|
LYXERR(Debug::ACTION, "mimeFor " << flav);
|
|
|
|
if (flav == QLatin1String("com.adobe.pdf"))
|
2008-05-26 13:43:35 +00:00
|
|
|
return pdfMimeType();
|
2008-05-23 07:52:39 +00:00
|
|
|
return QString();
|
|
|
|
}
|
|
|
|
|
|
|
|
bool canConvert(QString const & mime, QString flav)
|
2008-05-29 17:57:57 +00:00
|
|
|
{
|
|
|
|
return mimeFor(flav) == mime;
|
|
|
|
}
|
2008-05-23 07:52:39 +00:00
|
|
|
|
2008-06-05 13:27:37 +00:00
|
|
|
QVariant convertToMime(QString const & /*mime*/, QList<QByteArray> data,
|
|
|
|
QString /*flav*/)
|
2008-05-23 07:52:39 +00:00
|
|
|
{
|
|
|
|
if(data.count() > 1)
|
|
|
|
qWarning("QMacPasteboardMimeGraphics: Cannot handle multiple member data");
|
|
|
|
return data.first();
|
|
|
|
}
|
|
|
|
|
2008-06-05 13:27:37 +00:00
|
|
|
QList<QByteArray> convertFromMime(QString const & /*mime*/,
|
|
|
|
QVariant data, QString /*flav*/)
|
2008-05-23 07:52:39 +00:00
|
|
|
{
|
|
|
|
QList<QByteArray> ret;
|
|
|
|
ret.append(data.toByteArray());
|
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
};
|
|
|
|
#endif
|
|
|
|
|
2007-09-15 17:47:35 +00:00
|
|
|
///////////////////////////////////////////////////////////////
|
2008-11-16 12:22:54 +00:00
|
|
|
//
|
|
|
|
// You can find more platform specific stuff at the end of this file...
|
|
|
|
//
|
2007-09-15 17:47:35 +00:00
|
|
|
///////////////////////////////////////////////////////////////
|
2006-06-26 17:18:28 +00:00
|
|
|
|
2008-05-23 07:52:39 +00:00
|
|
|
////////////////////////////////////////////////////////////////////////
|
|
|
|
// Windows specific stuff goes here...
|
|
|
|
|
|
|
|
#ifdef Q_WS_WIN
|
|
|
|
// QWindowsMimeMetafile can only be compiled on Windows.
|
|
|
|
|
|
|
|
static FORMATETC cfFromMime(QString const & mimetype)
|
|
|
|
{
|
|
|
|
FORMATETC formatetc;
|
2008-05-25 07:49:16 +00:00
|
|
|
if (mimetype == emfMimeType()) {
|
2008-05-23 07:52:39 +00:00
|
|
|
formatetc.cfFormat = CF_ENHMETAFILE;
|
|
|
|
formatetc.tymed = TYMED_ENHMF;
|
2008-05-25 07:49:16 +00:00
|
|
|
} else if (mimetype == wmfMimeType()) {
|
2008-05-23 07:52:39 +00:00
|
|
|
formatetc.cfFormat = CF_METAFILEPICT;
|
|
|
|
formatetc.tymed = TYMED_MFPICT;
|
|
|
|
}
|
|
|
|
formatetc.ptd = 0;
|
|
|
|
formatetc.dwAspect = DVASPECT_CONTENT;
|
|
|
|
formatetc.lindex = -1;
|
|
|
|
return formatetc;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
class QWindowsMimeMetafile : public QWindowsMime {
|
|
|
|
public:
|
|
|
|
QWindowsMimeMetafile() {}
|
|
|
|
|
|
|
|
bool canConvertFromMime(FORMATETC const & formatetc,
|
|
|
|
QMimeData const * mimedata) const
|
|
|
|
{
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
bool canConvertToMime(QString const & mimetype,
|
|
|
|
IDataObject * pDataObj) const
|
|
|
|
{
|
2008-05-25 07:49:16 +00:00
|
|
|
if (mimetype != emfMimeType() && mimetype != wmfMimeType())
|
2008-05-23 07:52:39 +00:00
|
|
|
return false;
|
|
|
|
FORMATETC formatetc = cfFromMime(mimetype);
|
|
|
|
return pDataObj->QueryGetData(&formatetc) == S_OK;
|
|
|
|
}
|
|
|
|
|
|
|
|
bool convertFromMime(FORMATETC const & formatetc,
|
|
|
|
const QMimeData * mimedata, STGMEDIUM * pmedium) const
|
|
|
|
{
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
QVariant convertToMime(QString const & mimetype, IDataObject * pDataObj,
|
|
|
|
QVariant::Type preferredType) const
|
|
|
|
{
|
|
|
|
QByteArray data;
|
|
|
|
if (!canConvertToMime(mimetype, pDataObj))
|
|
|
|
return data;
|
|
|
|
|
|
|
|
FORMATETC formatetc = cfFromMime(mimetype);
|
|
|
|
STGMEDIUM s;
|
|
|
|
if (pDataObj->GetData(&formatetc, &s) != S_OK)
|
|
|
|
return data;
|
|
|
|
|
|
|
|
int dataSize;
|
|
|
|
if (s.tymed == TYMED_ENHMF) {
|
|
|
|
dataSize = GetEnhMetaFileBits(s.hEnhMetaFile, 0, 0);
|
|
|
|
data.resize(dataSize);
|
|
|
|
dataSize = GetEnhMetaFileBits(s.hEnhMetaFile, dataSize,
|
|
|
|
(LPBYTE)data.data());
|
|
|
|
} else if (s.tymed == TYMED_MFPICT) {
|
|
|
|
dataSize = GetMetaFileBitsEx((HMETAFILE)s.hMetaFilePict, 0, 0);
|
|
|
|
data.resize(dataSize);
|
|
|
|
dataSize = GetMetaFileBitsEx((HMETAFILE)s.hMetaFilePict, dataSize,
|
|
|
|
(LPBYTE)data.data());
|
|
|
|
}
|
|
|
|
data.detach();
|
|
|
|
ReleaseStgMedium(&s);
|
|
|
|
|
|
|
|
return data;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2008-11-28 23:01:20 +00:00
|
|
|
QVector<FORMATETC> formatsForMime(QString const & mimetype,
|
|
|
|
QMimeData const * mimedata) const
|
2008-05-23 07:52:39 +00:00
|
|
|
{
|
|
|
|
QVector<FORMATETC> formats;
|
2008-11-28 22:48:50 +00:00
|
|
|
if (mimetype == emfMimeType() || mimetype == wmfMimeType())
|
2008-11-28 23:01:20 +00:00
|
|
|
formats += cfFromMime(mimetype);
|
2008-05-23 07:52:39 +00:00
|
|
|
return formats;
|
|
|
|
}
|
|
|
|
|
|
|
|
QString mimeForFormat(FORMATETC const & formatetc) const
|
|
|
|
{
|
|
|
|
switch (formatetc.cfFormat) {
|
|
|
|
case CF_ENHMETAFILE:
|
2011-01-16 04:02:59 +00:00
|
|
|
return emfMimeType();
|
2008-05-23 07:52:39 +00:00
|
|
|
case CF_METAFILEPICT:
|
2008-05-25 07:49:16 +00:00
|
|
|
return wmfMimeType();
|
2008-05-23 07:52:39 +00:00
|
|
|
}
|
|
|
|
return QString();
|
|
|
|
}
|
|
|
|
};
|
|
|
|
|
|
|
|
#endif // Q_WS_WIN
|
|
|
|
|
|
|
|
////////////////////////////////////////////////////////////////////////
|
|
|
|
// GuiApplication::Private definition and implementation.
|
|
|
|
////////////////////////////////////////////////////////////////////////
|
|
|
|
|
|
|
|
struct GuiApplication::Private
|
|
|
|
{
|
2009-10-04 22:58:53 +00:00
|
|
|
Private(): language_model_(0), meta_fake_bit(NoModifier),
|
|
|
|
global_menubar_(0)
|
2009-04-19 13:43:00 +00:00
|
|
|
{
|
|
|
|
#ifdef Q_WS_WIN
|
|
|
|
/// WMF Mime handler for Windows clipboard.
|
|
|
|
wmf_mime_ = new QWindowsMimeMetafile();
|
|
|
|
#endif
|
2009-10-04 20:58:20 +00:00
|
|
|
initKeySequences(&theTopLevelKeymap());
|
|
|
|
}
|
|
|
|
|
|
|
|
void initKeySequences(KeyMap * kb)
|
|
|
|
{
|
|
|
|
keyseq = KeySequence(kb, kb);
|
|
|
|
cancel_meta_seq = KeySequence(kb, kb);
|
2009-04-19 13:43:00 +00:00
|
|
|
}
|
2008-05-23 07:52:39 +00:00
|
|
|
|
2008-05-23 08:43:07 +00:00
|
|
|
///
|
|
|
|
QSortFilterProxyModel * language_model_;
|
|
|
|
///
|
|
|
|
GuiClipboard clipboard_;
|
|
|
|
///
|
|
|
|
GuiSelection selection_;
|
|
|
|
///
|
|
|
|
FontLoader font_loader_;
|
|
|
|
///
|
|
|
|
ColorCache color_cache_;
|
|
|
|
///
|
|
|
|
QTranslator qt_trans_;
|
|
|
|
///
|
2008-05-23 18:09:40 +00:00
|
|
|
QHash<int, SocketNotifier *> socket_notifiers_;
|
2008-05-23 08:43:07 +00:00
|
|
|
///
|
|
|
|
Menus menus_;
|
2008-05-25 08:30:06 +00:00
|
|
|
///
|
|
|
|
/// The global instance
|
|
|
|
Toolbars toolbars_;
|
|
|
|
|
2008-05-23 08:43:07 +00:00
|
|
|
/// this timer is used for any regular events one wants to
|
|
|
|
/// perform. at present it is used to check if forked processes
|
|
|
|
/// are done.
|
|
|
|
QTimer general_timer_;
|
|
|
|
|
2008-11-15 16:29:58 +00:00
|
|
|
/// delayed FuncRequests
|
|
|
|
std::queue<FuncRequest> func_request_queue_;
|
|
|
|
|
2009-10-04 20:58:20 +00:00
|
|
|
///
|
|
|
|
KeySequence keyseq;
|
|
|
|
///
|
|
|
|
KeySequence cancel_meta_seq;
|
|
|
|
///
|
|
|
|
KeyModifier meta_fake_bit;
|
|
|
|
|
2008-05-23 08:43:07 +00:00
|
|
|
/// Multiple views container.
|
|
|
|
/**
|
|
|
|
* Warning: This must not be a smart pointer as the destruction of the
|
|
|
|
* object is handled by Qt when the view is closed
|
|
|
|
* \sa Qt::WA_DeleteOnClose attribute.
|
|
|
|
*/
|
2008-05-23 18:09:40 +00:00
|
|
|
QHash<int, GuiView *> views_;
|
2008-05-23 08:43:07 +00:00
|
|
|
|
2008-05-23 07:52:39 +00:00
|
|
|
/// Only used on mac.
|
|
|
|
GlobalMenuBar * global_menubar_;
|
|
|
|
|
|
|
|
#ifdef Q_WS_MACX
|
|
|
|
/// Linkback mime handler for MacOSX.
|
|
|
|
QMacPasteboardMimeGraphics mac_pasteboard_mime_;
|
|
|
|
#endif
|
|
|
|
|
|
|
|
#ifdef Q_WS_WIN
|
|
|
|
/// WMF Mime handler for Windows clipboard.
|
2009-04-19 13:43:00 +00:00
|
|
|
QWindowsMimeMetafile * wmf_mime_;
|
2008-05-23 07:52:39 +00:00
|
|
|
#endif
|
|
|
|
};
|
|
|
|
|
2006-10-21 00:16:43 +00:00
|
|
|
|
2007-09-15 17:47:35 +00:00
|
|
|
GuiApplication * guiApp;
|
2006-10-13 16:48:12 +00:00
|
|
|
|
2008-05-23 07:52:39 +00:00
|
|
|
GuiApplication::~GuiApplication()
|
|
|
|
{
|
|
|
|
#ifdef Q_WS_MACX
|
|
|
|
closeAllLinkBackLinks();
|
|
|
|
#endif
|
|
|
|
delete d;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2006-09-22 09:47:39 +00:00
|
|
|
GuiApplication::GuiApplication(int & argc, char ** argv)
|
2009-06-29 08:44:32 +00:00
|
|
|
: QApplication(argc, argv), current_view_(0),
|
|
|
|
d(new GuiApplication::Private)
|
2006-06-26 17:18:28 +00:00
|
|
|
{
|
2007-11-16 22:10:35 +00:00
|
|
|
QString app_name = "LyX";
|
|
|
|
QCoreApplication::setOrganizationName(app_name);
|
2007-09-27 14:05:05 +00:00
|
|
|
QCoreApplication::setOrganizationDomain("lyx.org");
|
2009-06-29 08:44:32 +00:00
|
|
|
QCoreApplication::setApplicationName(lyx_package);
|
2007-09-27 14:05:05 +00:00
|
|
|
|
2008-07-28 11:26:46 +00:00
|
|
|
// Install translator for GUI elements.
|
|
|
|
installTranslator(&d->qt_trans_);
|
|
|
|
|
2008-03-14 23:26:47 +00:00
|
|
|
// FIXME: quitOnLastWindowClosed is true by default. We should have a
|
|
|
|
// lyxrc setting for this in order to let the application stay resident.
|
|
|
|
// But then we need some kind of dock icon, at least on Windows.
|
2008-02-27 11:44:37 +00:00
|
|
|
/*
|
|
|
|
if (lyxrc.quit_on_last_window_closed)
|
|
|
|
setQuitOnLastWindowClosed(false);
|
|
|
|
*/
|
2008-03-17 10:23:02 +00:00
|
|
|
#ifdef Q_WS_MACX
|
2008-03-14 23:30:28 +00:00
|
|
|
// FIXME: Do we need a lyxrc setting for this on Mac? This behaviour
|
|
|
|
// seems to be the default case for applications like LyX.
|
2008-03-14 23:25:11 +00:00
|
|
|
setQuitOnLastWindowClosed(false);
|
2008-07-28 11:26:46 +00:00
|
|
|
// This allows to translate the strings that appear in the LyX menu.
|
|
|
|
/// A translator suitable for the entries in the LyX menu.
|
|
|
|
/// Only needed with Qt/Mac.
|
|
|
|
installTranslator(new MenuTranslator(this));
|
2008-03-14 23:25:11 +00:00
|
|
|
#endif
|
2011-01-16 04:02:59 +00:00
|
|
|
|
2006-06-26 17:18:28 +00:00
|
|
|
#ifdef Q_WS_X11
|
2006-10-22 14:37:32 +00:00
|
|
|
// doubleClickInterval() is 400 ms on X11 which is just too long.
|
2006-06-26 17:18:28 +00:00
|
|
|
// On Windows and Mac OS X, the operating system's value is used.
|
|
|
|
// On Microsoft Windows, calling this function sets the double
|
|
|
|
// click interval for all applications. So we don't!
|
|
|
|
QApplication::setDoubleClickInterval(300);
|
|
|
|
#endif
|
|
|
|
|
2008-03-14 23:25:11 +00:00
|
|
|
connect(this, SIGNAL(lastWindowClosed()), this, SLOT(onLastWindowClosed()));
|
2007-08-07 21:23:40 +00:00
|
|
|
|
2006-09-22 09:47:39 +00:00
|
|
|
// needs to be done before reading lyxrc
|
2007-09-15 17:47:35 +00:00
|
|
|
QWidget w;
|
|
|
|
lyxrc.dpi = (w.logicalDpiX() + w.logicalDpiY()) / 2;
|
2006-09-22 09:47:39 +00:00
|
|
|
|
2006-10-12 14:10:13 +00:00
|
|
|
guiApp = this;
|
2007-08-21 07:33:46 +00:00
|
|
|
|
|
|
|
// Set the cache to 5120 kilobytes which corresponds to screen size of
|
|
|
|
// 1280 by 1024 pixels with a color depth of 32 bits.
|
|
|
|
QPixmapCache::setCacheLimit(5120);
|
2007-11-18 20:36:52 +00:00
|
|
|
|
|
|
|
// Initialize RC Fonts
|
|
|
|
if (lyxrc.roman_font_name.empty())
|
|
|
|
lyxrc.roman_font_name = fromqstr(romanFontName());
|
|
|
|
|
|
|
|
if (lyxrc.sans_font_name.empty())
|
|
|
|
lyxrc.sans_font_name = fromqstr(sansFontName());
|
|
|
|
|
|
|
|
if (lyxrc.typewriter_font_name.empty())
|
|
|
|
lyxrc.typewriter_font_name = fromqstr(typewriterFontName());
|
2008-02-05 13:10:42 +00:00
|
|
|
|
2008-05-23 08:43:07 +00:00
|
|
|
d->general_timer_.setInterval(500);
|
|
|
|
connect(&d->general_timer_, SIGNAL(timeout()),
|
2008-02-05 13:10:42 +00:00
|
|
|
this, SLOT(handleRegularEvents()));
|
2008-05-23 08:43:07 +00:00
|
|
|
d->general_timer_.start();
|
2010-03-18 12:42:34 +00:00
|
|
|
|
2010-04-19 19:55:15 +00:00
|
|
|
#if QT_VERSION >= 0x040400
|
2010-03-18 12:42:34 +00:00
|
|
|
// maxThreadCount() defaults in general to 2 on single or dual-processor.
|
|
|
|
// This is clearly not enough in a time where we use threads for
|
|
|
|
// document preview and/or export. 20 should be OK.
|
|
|
|
QThreadPool::globalInstance()->setMaxThreadCount(20);
|
2010-03-24 08:50:06 +00:00
|
|
|
#endif
|
2006-06-26 17:18:28 +00:00
|
|
|
}
|
|
|
|
|
2007-04-25 16:39:21 +00:00
|
|
|
|
2008-11-16 12:22:54 +00:00
|
|
|
GuiApplication * theGuiApp()
|
|
|
|
{
|
|
|
|
return dynamic_cast<GuiApplication *>(theApp());
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2008-09-21 21:28:37 +00:00
|
|
|
void GuiApplication::clearSession()
|
|
|
|
{
|
|
|
|
QSettings settings;
|
|
|
|
settings.clear();
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2011-01-06 18:40:39 +00:00
|
|
|
docstring Application::iconName(FuncRequest const & f, bool unknown)
|
2008-06-05 08:31:22 +00:00
|
|
|
{
|
|
|
|
return qstring_to_ucs4(lyx::frontend::iconName(f, unknown));
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2010-02-09 16:11:13 +00:00
|
|
|
FuncStatus GuiApplication::getStatus(FuncRequest const & cmd) const
|
2007-11-24 07:58:12 +00:00
|
|
|
{
|
Refactor GuiApplication::getStatus().
* I didn't like the fact that the heart of the dispatch/status machinery is in the default clause of a long switch statement. Now, it is clear that we enter the app in getStatus, which then asks the GuiApplication itself, the GuiView, the current BufferView, the current Buffer, the document BufferView, the document Buffer,
* Shouldn't we let BufferView call the Buffer getStatus() functions ?,
* This also makes sure that if a command is not handled, it is turned off. Before r34164 this was caused by the default clause in BufferView,
* Now it is prevented that if the document BufferView is the same as the current BufferView, that the getStatus() functions are called twice,
* A warning can be outputted if the LFUN is not handled.
PS I want to do the same for the dispatch function.
git-svn-id: svn://svn.lyx.org/lyx/lyx-devel/trunk@34165 a592a061-630c-0410-9148-cb99ea01b6c8
2010-04-16 16:04:35 +00:00
|
|
|
FuncStatus status;
|
2010-02-09 16:11:13 +00:00
|
|
|
|
Refactor GuiApplication::getStatus().
* I didn't like the fact that the heart of the dispatch/status machinery is in the default clause of a long switch statement. Now, it is clear that we enter the app in getStatus, which then asks the GuiApplication itself, the GuiView, the current BufferView, the current Buffer, the document BufferView, the document Buffer,
* Shouldn't we let BufferView call the Buffer getStatus() functions ?,
* This also makes sure that if a command is not handled, it is turned off. Before r34164 this was caused by the default clause in BufferView,
* Now it is prevented that if the document BufferView is the same as the current BufferView, that the getStatus() functions are called twice,
* A warning can be outputted if the LFUN is not handled.
PS I want to do the same for the dispatch function.
git-svn-id: svn://svn.lyx.org/lyx/lyx-devel/trunk@34165 a592a061-630c-0410-9148-cb99ea01b6c8
2010-04-16 16:04:35 +00:00
|
|
|
BufferView * bv = 0;
|
|
|
|
BufferView * doc_bv = 0;
|
2011-01-16 04:02:59 +00:00
|
|
|
|
2010-04-09 19:00:42 +00:00
|
|
|
if (cmd.action() == LFUN_NOACTION) {
|
Refactor GuiApplication::getStatus().
* I didn't like the fact that the heart of the dispatch/status machinery is in the default clause of a long switch statement. Now, it is clear that we enter the app in getStatus, which then asks the GuiApplication itself, the GuiView, the current BufferView, the current Buffer, the document BufferView, the document Buffer,
* Shouldn't we let BufferView call the Buffer getStatus() functions ?,
* This also makes sure that if a command is not handled, it is turned off. Before r34164 this was caused by the default clause in BufferView,
* Now it is prevented that if the document BufferView is the same as the current BufferView, that the getStatus() functions are called twice,
* A warning can be outputted if the LFUN is not handled.
PS I want to do the same for the dispatch function.
git-svn-id: svn://svn.lyx.org/lyx/lyx-devel/trunk@34165 a592a061-630c-0410-9148-cb99ea01b6c8
2010-04-16 16:04:35 +00:00
|
|
|
status.message(from_utf8(N_("Nothing to do")));
|
|
|
|
status.setEnabled(false);
|
2010-02-09 16:11:13 +00:00
|
|
|
}
|
|
|
|
|
Refactor GuiApplication::getStatus().
* I didn't like the fact that the heart of the dispatch/status machinery is in the default clause of a long switch statement. Now, it is clear that we enter the app in getStatus, which then asks the GuiApplication itself, the GuiView, the current BufferView, the current Buffer, the document BufferView, the document Buffer,
* Shouldn't we let BufferView call the Buffer getStatus() functions ?,
* This also makes sure that if a command is not handled, it is turned off. Before r34164 this was caused by the default clause in BufferView,
* Now it is prevented that if the document BufferView is the same as the current BufferView, that the getStatus() functions are called twice,
* A warning can be outputted if the LFUN is not handled.
PS I want to do the same for the dispatch function.
git-svn-id: svn://svn.lyx.org/lyx/lyx-devel/trunk@34165 a592a061-630c-0410-9148-cb99ea01b6c8
2010-04-16 16:04:35 +00:00
|
|
|
else if (cmd.action() == LFUN_UNKNOWN_ACTION) {
|
|
|
|
status.setUnknown(true);
|
|
|
|
status.message(from_utf8(N_("Unknown action")));
|
|
|
|
status.setEnabled(false);
|
2010-02-09 16:11:13 +00:00
|
|
|
}
|
|
|
|
|
Refactor GuiApplication::getStatus().
* I didn't like the fact that the heart of the dispatch/status machinery is in the default clause of a long switch statement. Now, it is clear that we enter the app in getStatus, which then asks the GuiApplication itself, the GuiView, the current BufferView, the current Buffer, the document BufferView, the document Buffer,
* Shouldn't we let BufferView call the Buffer getStatus() functions ?,
* This also makes sure that if a command is not handled, it is turned off. Before r34164 this was caused by the default clause in BufferView,
* Now it is prevented that if the document BufferView is the same as the current BufferView, that the getStatus() functions are called twice,
* A warning can be outputted if the LFUN is not handled.
PS I want to do the same for the dispatch function.
git-svn-id: svn://svn.lyx.org/lyx/lyx-devel/trunk@34165 a592a061-630c-0410-9148-cb99ea01b6c8
2010-04-16 16:04:35 +00:00
|
|
|
// Does the GuiApplication know something?
|
|
|
|
else if (getStatus(cmd, status)) { }
|
|
|
|
|
|
|
|
// If we do not have a GuiView, then other functions are disabled
|
|
|
|
else if (!current_view_)
|
|
|
|
status.setEnabled(false);
|
2011-01-16 04:02:59 +00:00
|
|
|
|
Refactor GuiApplication::getStatus().
* I didn't like the fact that the heart of the dispatch/status machinery is in the default clause of a long switch statement. Now, it is clear that we enter the app in getStatus, which then asks the GuiApplication itself, the GuiView, the current BufferView, the current Buffer, the document BufferView, the document Buffer,
* Shouldn't we let BufferView call the Buffer getStatus() functions ?,
* This also makes sure that if a command is not handled, it is turned off. Before r34164 this was caused by the default clause in BufferView,
* Now it is prevented that if the document BufferView is the same as the current BufferView, that the getStatus() functions are called twice,
* A warning can be outputted if the LFUN is not handled.
PS I want to do the same for the dispatch function.
git-svn-id: svn://svn.lyx.org/lyx/lyx-devel/trunk@34165 a592a061-630c-0410-9148-cb99ea01b6c8
2010-04-16 16:04:35 +00:00
|
|
|
// Does the GuiView know something?
|
|
|
|
else if (current_view_->getStatus(cmd, status)) { }
|
|
|
|
|
|
|
|
// In LyX/Mac, when a dialog is open, the menus of the
|
|
|
|
// application can still be accessed without giving focus to
|
|
|
|
// the main window. In this case, we want to disable the menu
|
|
|
|
// entries that are buffer or view-related.
|
|
|
|
//FIXME: Abdel (09/02/10) This has very bad effect on Linux, don't know why...
|
|
|
|
/*
|
|
|
|
else if (cmd.origin() == FuncRequest::MENU && !current_view_->hasFocus())
|
|
|
|
status.setEnabled(false);
|
|
|
|
*/
|
|
|
|
|
|
|
|
// If we do not have a BufferView, then other functions are disabled
|
|
|
|
else if (!(bv = current_view_->currentBufferView()))
|
|
|
|
status.setEnabled(false);
|
2011-01-16 04:02:59 +00:00
|
|
|
|
Refactor GuiApplication::getStatus().
* I didn't like the fact that the heart of the dispatch/status machinery is in the default clause of a long switch statement. Now, it is clear that we enter the app in getStatus, which then asks the GuiApplication itself, the GuiView, the current BufferView, the current Buffer, the document BufferView, the document Buffer,
* Shouldn't we let BufferView call the Buffer getStatus() functions ?,
* This also makes sure that if a command is not handled, it is turned off. Before r34164 this was caused by the default clause in BufferView,
* Now it is prevented that if the document BufferView is the same as the current BufferView, that the getStatus() functions are called twice,
* A warning can be outputted if the LFUN is not handled.
PS I want to do the same for the dispatch function.
git-svn-id: svn://svn.lyx.org/lyx/lyx-devel/trunk@34165 a592a061-630c-0410-9148-cb99ea01b6c8
2010-04-16 16:04:35 +00:00
|
|
|
// Does the current BufferView know something?
|
|
|
|
else if (bv->getStatus(cmd, status)) { }
|
2011-01-16 04:02:59 +00:00
|
|
|
|
Refactor GuiApplication::getStatus().
* I didn't like the fact that the heart of the dispatch/status machinery is in the default clause of a long switch statement. Now, it is clear that we enter the app in getStatus, which then asks the GuiApplication itself, the GuiView, the current BufferView, the current Buffer, the document BufferView, the document Buffer,
* Shouldn't we let BufferView call the Buffer getStatus() functions ?,
* This also makes sure that if a command is not handled, it is turned off. Before r34164 this was caused by the default clause in BufferView,
* Now it is prevented that if the document BufferView is the same as the current BufferView, that the getStatus() functions are called twice,
* A warning can be outputted if the LFUN is not handled.
PS I want to do the same for the dispatch function.
git-svn-id: svn://svn.lyx.org/lyx/lyx-devel/trunk@34165 a592a061-630c-0410-9148-cb99ea01b6c8
2010-04-16 16:04:35 +00:00
|
|
|
// Does the current Buffer know something?
|
|
|
|
else if (bv->buffer().getStatus(cmd, status)) { }
|
|
|
|
|
|
|
|
// If we do not have a document BufferView, different from the
|
|
|
|
// current BufferView, then other functions are disabled
|
|
|
|
else if (!(doc_bv = current_view_->documentBufferView()) || doc_bv == bv)
|
|
|
|
status.setEnabled(false);
|
|
|
|
|
|
|
|
// Does the document Buffer know something?
|
|
|
|
else if (doc_bv->buffer().getStatus(cmd, status)) { }
|
|
|
|
|
2011-01-16 04:02:59 +00:00
|
|
|
else {
|
Refactor GuiApplication::getStatus().
* I didn't like the fact that the heart of the dispatch/status machinery is in the default clause of a long switch statement. Now, it is clear that we enter the app in getStatus, which then asks the GuiApplication itself, the GuiView, the current BufferView, the current Buffer, the document BufferView, the document Buffer,
* Shouldn't we let BufferView call the Buffer getStatus() functions ?,
* This also makes sure that if a command is not handled, it is turned off. Before r34164 this was caused by the default clause in BufferView,
* Now it is prevented that if the document BufferView is the same as the current BufferView, that the getStatus() functions are called twice,
* A warning can be outputted if the LFUN is not handled.
PS I want to do the same for the dispatch function.
git-svn-id: svn://svn.lyx.org/lyx/lyx-devel/trunk@34165 a592a061-630c-0410-9148-cb99ea01b6c8
2010-04-16 16:04:35 +00:00
|
|
|
LYXERR(Debug::ACTION, "LFUN not handled in getStatus(): " << cmd);
|
|
|
|
status.message(from_utf8(N_("Command not handled")));
|
|
|
|
status.setEnabled(false);
|
|
|
|
}
|
2011-01-16 04:02:59 +00:00
|
|
|
|
Refactor GuiApplication::getStatus().
* I didn't like the fact that the heart of the dispatch/status machinery is in the default clause of a long switch statement. Now, it is clear that we enter the app in getStatus, which then asks the GuiApplication itself, the GuiView, the current BufferView, the current Buffer, the document BufferView, the document Buffer,
* Shouldn't we let BufferView call the Buffer getStatus() functions ?,
* This also makes sure that if a command is not handled, it is turned off. Before r34164 this was caused by the default clause in BufferView,
* Now it is prevented that if the document BufferView is the same as the current BufferView, that the getStatus() functions are called twice,
* A warning can be outputted if the LFUN is not handled.
PS I want to do the same for the dispatch function.
git-svn-id: svn://svn.lyx.org/lyx/lyx-devel/trunk@34165 a592a061-630c-0410-9148-cb99ea01b6c8
2010-04-16 16:04:35 +00:00
|
|
|
// the default error message if we disable the command
|
|
|
|
if (!status.enabled() && status.message().empty())
|
|
|
|
status.message(from_utf8(N_("Command disabled")));
|
|
|
|
|
|
|
|
return status;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
bool GuiApplication::getStatus(FuncRequest const & cmd, FuncStatus & flag) const
|
|
|
|
{
|
2010-02-09 16:11:13 +00:00
|
|
|
// I would really like to avoid having this switch and rather try to
|
|
|
|
// encode this in the function itself.
|
|
|
|
// -- And I'd rather let an inset decide which LFUNs it is willing
|
|
|
|
// to handle (Andre')
|
2007-11-24 07:58:12 +00:00
|
|
|
bool enable = true;
|
2010-04-09 19:00:42 +00:00
|
|
|
switch (cmd.action()) {
|
2010-02-09 16:11:13 +00:00
|
|
|
|
|
|
|
// This could be used for the no-GUI version. The GUI version is handled in
|
2010-02-09 17:06:40 +00:00
|
|
|
// GuiView::getStatus(). See above.
|
2010-02-09 16:11:13 +00:00
|
|
|
/*
|
|
|
|
case LFUN_BUFFER_WRITE:
|
|
|
|
case LFUN_BUFFER_WRITE_AS: {
|
|
|
|
Buffer * b = theBufferList().getBuffer(FileName(cmd.getArg(0)));
|
|
|
|
enable = b && (b->isUnnamed() || !b->isClean());
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
*/
|
|
|
|
|
|
|
|
case LFUN_BOOKMARK_GOTO: {
|
|
|
|
const unsigned int num = convert<unsigned int>(to_utf8(cmd.argument()));
|
|
|
|
enable = theSession().bookmarks().isValid(num);
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
case LFUN_BOOKMARK_CLEAR:
|
|
|
|
enable = theSession().bookmarks().hasValid();
|
|
|
|
break;
|
2007-11-24 07:58:12 +00:00
|
|
|
|
2010-02-09 16:11:13 +00:00
|
|
|
// this one is difficult to get right. As a half-baked
|
|
|
|
// solution, we consider only the first action of the sequence
|
|
|
|
case LFUN_COMMAND_SEQUENCE: {
|
|
|
|
// argument contains ';'-terminated commands
|
|
|
|
string const firstcmd = token(to_utf8(cmd.argument()), ';', 0);
|
|
|
|
FuncRequest func(lyxaction.lookupFunc(firstcmd));
|
2010-04-09 19:00:42 +00:00
|
|
|
func.setOrigin(cmd.origin());
|
2010-02-09 16:11:13 +00:00
|
|
|
flag = getStatus(func);
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
// we want to check if at least one of these is enabled
|
|
|
|
case LFUN_COMMAND_ALTERNATIVES: {
|
|
|
|
// argument contains ';'-terminated commands
|
|
|
|
string arg = to_utf8(cmd.argument());
|
|
|
|
while (!arg.empty()) {
|
|
|
|
string first;
|
|
|
|
arg = split(arg, first, ';');
|
|
|
|
FuncRequest func(lyxaction.lookupFunc(first));
|
2010-04-09 19:00:42 +00:00
|
|
|
func.setOrigin(cmd.origin());
|
2010-02-09 16:11:13 +00:00
|
|
|
flag = getStatus(func);
|
|
|
|
// if this one is enabled, the whole thing is
|
|
|
|
if (flag.enabled())
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
case LFUN_CALL: {
|
|
|
|
FuncRequest func;
|
|
|
|
string name = to_utf8(cmd.argument());
|
|
|
|
if (theTopLevelCmdDef().lock(name, func)) {
|
2010-04-09 19:00:42 +00:00
|
|
|
func.setOrigin(cmd.origin());
|
2010-02-09 16:11:13 +00:00
|
|
|
flag = getStatus(func);
|
|
|
|
theTopLevelCmdDef().release(name);
|
|
|
|
} else {
|
|
|
|
// catch recursion or unknown command
|
|
|
|
// definition. all operations until the
|
|
|
|
// recursion or unknown command definition
|
|
|
|
// occurs are performed, so set the state to
|
|
|
|
// enabled
|
|
|
|
enable = true;
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
case LFUN_CURSOR_FOLLOWS_SCROLLBAR_TOGGLE:
|
|
|
|
case LFUN_REPEAT:
|
|
|
|
case LFUN_PREFERENCES_SAVE:
|
|
|
|
case LFUN_BUFFER_SAVE_AS_DEFAULT:
|
|
|
|
case LFUN_DEBUG_LEVEL_SET:
|
|
|
|
// these are handled in our dispatch()
|
|
|
|
break;
|
2007-11-24 07:58:12 +00:00
|
|
|
|
|
|
|
case LFUN_WINDOW_CLOSE:
|
2008-05-23 10:45:55 +00:00
|
|
|
enable = d->views_.size() > 0;
|
2007-11-24 07:58:12 +00:00
|
|
|
break;
|
|
|
|
|
2008-05-23 09:53:27 +00:00
|
|
|
case LFUN_BUFFER_NEW:
|
|
|
|
case LFUN_BUFFER_NEW_TEMPLATE:
|
|
|
|
case LFUN_FILE_OPEN:
|
2009-09-22 19:55:15 +00:00
|
|
|
case LFUN_HELP_OPEN:
|
2008-05-23 09:53:27 +00:00
|
|
|
case LFUN_SCREEN_FONT_UPDATE:
|
|
|
|
case LFUN_SET_COLOR:
|
|
|
|
case LFUN_WINDOW_NEW:
|
|
|
|
case LFUN_LYX_QUIT:
|
2009-10-04 20:58:20 +00:00
|
|
|
case LFUN_LYXRC_APPLY:
|
|
|
|
case LFUN_COMMAND_PREFIX:
|
|
|
|
case LFUN_CANCEL:
|
|
|
|
case LFUN_META_PREFIX:
|
|
|
|
case LFUN_RECONFIGURE:
|
|
|
|
case LFUN_SERVER_GET_FILENAME:
|
|
|
|
case LFUN_SERVER_NOTIFY:
|
2008-05-23 09:53:27 +00:00
|
|
|
enable = true;
|
|
|
|
break;
|
|
|
|
|
2007-11-24 07:58:12 +00:00
|
|
|
default:
|
Refactor GuiApplication::getStatus().
* I didn't like the fact that the heart of the dispatch/status machinery is in the default clause of a long switch statement. Now, it is clear that we enter the app in getStatus, which then asks the GuiApplication itself, the GuiView, the current BufferView, the current Buffer, the document BufferView, the document Buffer,
* Shouldn't we let BufferView call the Buffer getStatus() functions ?,
* This also makes sure that if a command is not handled, it is turned off. Before r34164 this was caused by the default clause in BufferView,
* Now it is prevented that if the document BufferView is the same as the current BufferView, that the getStatus() functions are called twice,
* A warning can be outputted if the LFUN is not handled.
PS I want to do the same for the dispatch function.
git-svn-id: svn://svn.lyx.org/lyx/lyx-devel/trunk@34165 a592a061-630c-0410-9148-cb99ea01b6c8
2010-04-16 16:04:35 +00:00
|
|
|
return false;
|
2007-11-24 07:58:12 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
if (!enable)
|
2008-05-29 15:14:00 +00:00
|
|
|
flag.setEnabled(false);
|
Refactor GuiApplication::getStatus().
* I didn't like the fact that the heart of the dispatch/status machinery is in the default clause of a long switch statement. Now, it is clear that we enter the app in getStatus, which then asks the GuiApplication itself, the GuiView, the current BufferView, the current Buffer, the document BufferView, the document Buffer,
* Shouldn't we let BufferView call the Buffer getStatus() functions ?,
* This also makes sure that if a command is not handled, it is turned off. Before r34164 this was caused by the default clause in BufferView,
* Now it is prevented that if the document BufferView is the same as the current BufferView, that the getStatus() functions are called twice,
* A warning can be outputted if the LFUN is not handled.
PS I want to do the same for the dispatch function.
git-svn-id: svn://svn.lyx.org/lyx/lyx-devel/trunk@34165 a592a061-630c-0410-9148-cb99ea01b6c8
2010-04-16 16:04:35 +00:00
|
|
|
return true;
|
2010-02-09 16:11:13 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
/// make a post-dispatch status message
|
|
|
|
static docstring makeDispatchMessage(docstring const & msg,
|
|
|
|
FuncRequest const & cmd)
|
|
|
|
{
|
2010-04-09 19:00:42 +00:00
|
|
|
const bool verbose = (cmd.origin() == FuncRequest::MENU
|
|
|
|
|| cmd.origin() == FuncRequest::TOOLBAR
|
|
|
|
|| cmd.origin() == FuncRequest::COMMANDBUFFER);
|
2010-02-09 16:11:13 +00:00
|
|
|
|
2010-04-09 19:00:42 +00:00
|
|
|
if (cmd.action() == LFUN_SELF_INSERT || !verbose) {
|
2010-02-09 16:11:13 +00:00
|
|
|
LYXERR(Debug::ACTION, "dispatch msg is " << msg);
|
|
|
|
return msg;
|
|
|
|
}
|
|
|
|
|
|
|
|
docstring dispatch_msg = msg;
|
|
|
|
if (!dispatch_msg.empty())
|
|
|
|
dispatch_msg += ' ';
|
|
|
|
|
2010-04-09 19:00:42 +00:00
|
|
|
docstring comname = from_utf8(lyxaction.getActionName(cmd.action()));
|
2010-02-09 16:11:13 +00:00
|
|
|
|
|
|
|
bool argsadded = false;
|
|
|
|
|
|
|
|
if (!cmd.argument().empty()) {
|
2010-04-09 19:00:42 +00:00
|
|
|
if (cmd.action() != LFUN_UNKNOWN_ACTION) {
|
2010-02-09 16:11:13 +00:00
|
|
|
comname += ' ' + cmd.argument();
|
|
|
|
argsadded = true;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
docstring const shortcuts = theTopLevelKeymap().
|
|
|
|
printBindings(cmd, KeySequence::ForGui);
|
|
|
|
|
|
|
|
if (!shortcuts.empty())
|
|
|
|
comname += ": " + shortcuts;
|
|
|
|
else if (!argsadded && !cmd.argument().empty())
|
|
|
|
comname += ' ' + cmd.argument();
|
|
|
|
|
|
|
|
if (!comname.empty()) {
|
|
|
|
comname = rtrim(comname);
|
|
|
|
dispatch_msg += '(' + rtrim(comname) + ')';
|
|
|
|
}
|
|
|
|
LYXERR(Debug::ACTION, "verbose dispatch msg " << to_utf8(dispatch_msg));
|
|
|
|
return dispatch_msg;
|
2007-11-24 07:58:12 +00:00
|
|
|
}
|
|
|
|
|
2009-10-04 20:58:20 +00:00
|
|
|
|
2010-02-09 16:11:13 +00:00
|
|
|
void GuiApplication::dispatch(FuncRequest const & cmd)
|
|
|
|
{
|
|
|
|
if (current_view_ && current_view_->currentBufferView())
|
|
|
|
current_view_->currentBufferView()->cursor().saveBeforeDispatchPosXY();
|
|
|
|
|
|
|
|
DispatchResult dr;
|
|
|
|
// redraw the screen at the end (first of the two drawing steps).
|
2010-10-14 20:49:34 +00:00
|
|
|
// This is done unless explicitly requested otherwise
|
2010-10-13 17:28:55 +00:00
|
|
|
dr.screenUpdate(Update::FitCursor);
|
2010-02-09 16:11:13 +00:00
|
|
|
dispatch(cmd, dr);
|
|
|
|
|
|
|
|
if (!current_view_)
|
|
|
|
return;
|
|
|
|
|
|
|
|
BufferView * bv = current_view_->currentBufferView();
|
|
|
|
if (bv) {
|
2010-11-26 17:30:45 +00:00
|
|
|
Cursor & cursor = bv->cursor();
|
|
|
|
Buffer & buf = bv->buffer();
|
|
|
|
|
|
|
|
// FIXME
|
|
|
|
// This check out to be done somewhere else. It got moved here
|
|
|
|
// from TextMetrics.cpp, where it definitely didn't need to be.
|
|
|
|
// Actually, this test ought not to be done at all, since the
|
|
|
|
// whole InsetBibitem business is a mess. But that is a different
|
|
|
|
// story.
|
2010-12-08 21:46:57 +00:00
|
|
|
int moveCursor = 0;
|
2010-11-28 17:02:10 +00:00
|
|
|
if (cursor.inTexted()) {
|
2010-12-08 21:46:57 +00:00
|
|
|
moveCursor = cursor.paragraph().checkBiblio(buf);
|
2010-11-28 17:02:10 +00:00
|
|
|
if (moveCursor > 0)
|
|
|
|
cursor.posForward();
|
|
|
|
else if (moveCursor < 0 && cursor.pos() >= -moveCursor)
|
|
|
|
cursor.posBackward();
|
2010-12-08 21:46:57 +00:00
|
|
|
}
|
|
|
|
if (moveCursor != 0 || dr.needBufferUpdate()) {
|
|
|
|
cursor.clearBufferUpdate();
|
|
|
|
buf.updateBuffer();
|
2010-07-09 14:37:00 +00:00
|
|
|
}
|
2010-02-09 16:11:13 +00:00
|
|
|
// BufferView::update() updates the ViewMetricsInfo and
|
|
|
|
// also initializes the position cache for all insets in
|
|
|
|
// (at least partially) visible top-level paragraphs.
|
|
|
|
// We will redraw the screen only if needed.
|
2010-10-13 17:28:55 +00:00
|
|
|
bv->processUpdateFlags(dr.screenUpdate());
|
2010-02-09 16:11:13 +00:00
|
|
|
|
|
|
|
// Do we have a selection?
|
|
|
|
theSelection().haveSelection(bv->cursor().selection());
|
|
|
|
|
|
|
|
// update gui
|
|
|
|
current_view_->restartCursor();
|
|
|
|
}
|
2010-10-17 10:44:53 +00:00
|
|
|
if (dr.needMessageUpdate()) {
|
|
|
|
// Some messages may already be translated, so we cannot use _()
|
|
|
|
current_view_->message(makeDispatchMessage(
|
|
|
|
translateIfPossible(dr.message()), cmd));
|
|
|
|
}
|
2010-02-09 16:11:13 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2010-10-18 14:20:03 +00:00
|
|
|
void GuiApplication::gotoBookmark(unsigned int idx, bool openFile,
|
|
|
|
bool switchToBuffer)
|
2010-02-09 16:11:13 +00:00
|
|
|
{
|
|
|
|
if (!theSession().bookmarks().isValid(idx))
|
|
|
|
return;
|
2010-10-18 14:20:03 +00:00
|
|
|
BookmarksSection::Bookmark const & bm =
|
|
|
|
theSession().bookmarks().bookmark(idx);
|
2010-02-09 16:11:13 +00:00
|
|
|
LASSERT(!bm.filename.empty(), /**/);
|
2010-04-21 01:19:09 +00:00
|
|
|
string const file = bm.filename.absFileName();
|
2010-02-09 16:11:13 +00:00
|
|
|
// if the file is not opened, open it.
|
|
|
|
if (!theBufferList().exists(bm.filename)) {
|
|
|
|
if (openFile)
|
|
|
|
dispatch(FuncRequest(LFUN_FILE_OPEN, file));
|
|
|
|
else
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
// open may fail, so we need to test it again
|
|
|
|
if (!theBufferList().exists(bm.filename))
|
|
|
|
return;
|
|
|
|
|
|
|
|
// bm can be changed when saving
|
|
|
|
BookmarksSection::Bookmark tmp = bm;
|
|
|
|
|
|
|
|
// Special case idx == 0 used for back-from-back jump navigation
|
|
|
|
if (idx == 0)
|
|
|
|
dispatch(FuncRequest(LFUN_BOOKMARK_SAVE, "0"));
|
|
|
|
|
|
|
|
// if the current buffer is not that one, switch to it.
|
2010-10-18 14:20:03 +00:00
|
|
|
BufferView * doc_bv = current_view_->documentBufferView();
|
|
|
|
if (!doc_bv || doc_bv->buffer().fileName() != tmp.filename) {
|
|
|
|
if (switchToBuffer) {
|
|
|
|
dispatch(FuncRequest(LFUN_BUFFER_SWITCH, file));
|
|
|
|
doc_bv = current_view_->documentBufferView();
|
|
|
|
} else
|
2010-02-09 16:11:13 +00:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
// moveToPosition try paragraph id first and then paragraph (pit, pos).
|
2010-10-18 14:20:03 +00:00
|
|
|
if (!doc_bv->moveToPosition(
|
|
|
|
tmp.bottom_pit, tmp.bottom_pos, tmp.top_id, tmp.top_pos))
|
2010-02-09 16:11:13 +00:00
|
|
|
return;
|
|
|
|
|
|
|
|
// bm changed
|
|
|
|
if (idx == 0)
|
|
|
|
return;
|
|
|
|
|
|
|
|
// Cursor jump succeeded!
|
2010-10-18 14:20:03 +00:00
|
|
|
Cursor const & cur = doc_bv->cursor();
|
2010-02-09 16:11:13 +00:00
|
|
|
pit_type new_pit = cur.pit();
|
|
|
|
pos_type new_pos = cur.pos();
|
|
|
|
int new_id = cur.paragraph().id();
|
|
|
|
|
|
|
|
// if bottom_pit, bottom_pos or top_id has been changed, update bookmark
|
|
|
|
// see http://www.lyx.org/trac/ticket/3092
|
|
|
|
if (bm.bottom_pit != new_pit || bm.bottom_pos != new_pos
|
|
|
|
|| bm.top_id != new_id) {
|
|
|
|
const_cast<BookmarksSection::Bookmark &>(bm).updatePos(
|
|
|
|
new_pit, new_pos, new_id);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2009-10-04 20:58:20 +00:00
|
|
|
// This function runs "configure" and then rereads lyx.defaults to
|
|
|
|
// reconfigure the automatic settings.
|
2010-04-07 12:50:47 +00:00
|
|
|
void GuiApplication::reconfigure(string const & option)
|
2009-10-04 20:58:20 +00:00
|
|
|
{
|
|
|
|
// emit message signal.
|
2010-04-07 12:50:47 +00:00
|
|
|
if (current_view_)
|
|
|
|
current_view_->message(_("Running configure..."));
|
2009-10-04 20:58:20 +00:00
|
|
|
|
|
|
|
// Run configure in user lyx directory
|
|
|
|
PathChanger p(package().user_support());
|
|
|
|
string configure_command = package().configure_command();
|
|
|
|
configure_command += option;
|
|
|
|
Systemcall one;
|
|
|
|
int ret = one.startscript(Systemcall::Wait, configure_command);
|
|
|
|
p.pop();
|
|
|
|
// emit message signal.
|
2010-04-07 12:50:47 +00:00
|
|
|
if (current_view_)
|
|
|
|
current_view_->message(_("Reloading configuration..."));
|
2011-01-17 15:54:51 +00:00
|
|
|
lyxrc.read(libFileSearch(QString(), "lyxrc.defaults"), false);
|
2009-10-04 20:58:20 +00:00
|
|
|
// Re-read packages.lst
|
|
|
|
LaTeXFeatures::getAvailable();
|
|
|
|
|
|
|
|
if (ret)
|
|
|
|
Alert::information(_("System reconfiguration failed"),
|
|
|
|
_("The system reconfiguration has failed.\n"
|
|
|
|
"Default textclass is used but LyX may "
|
|
|
|
"not be able to work properly.\n"
|
|
|
|
"Please reconfigure again if needed."));
|
|
|
|
else
|
|
|
|
Alert::information(_("System reconfigured"),
|
|
|
|
_("The system has been reconfigured.\n"
|
|
|
|
"You need to restart LyX to make use of any\n"
|
|
|
|
"updated document class specifications."));
|
|
|
|
}
|
|
|
|
|
2011-01-18 15:22:10 +00:00
|
|
|
void GuiApplication::validateCurrentView()
|
|
|
|
{
|
|
|
|
if (!d->views_.empty() && !current_view_) {
|
|
|
|
// currently at least one view exists but no view has the focus.
|
2011-01-18 15:30:59 +00:00
|
|
|
// choose the last view to make it current.
|
2011-01-18 15:22:10 +00:00
|
|
|
// a view without any open document is preferred.
|
|
|
|
GuiView * candidate = 0;
|
|
|
|
QHash<int, GuiView *>::const_iterator it = d->views_.begin();
|
|
|
|
QHash<int, GuiView *>::const_iterator end = d->views_.end();
|
|
|
|
for (; it != end; ++it) {
|
|
|
|
candidate = *it;
|
|
|
|
if (!candidate->documentBufferView())
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
setCurrentView(candidate);
|
|
|
|
}
|
|
|
|
}
|
2009-10-04 20:58:20 +00:00
|
|
|
|
|
|
|
void GuiApplication::dispatch(FuncRequest const & cmd, DispatchResult & dr)
|
2007-11-24 07:58:12 +00:00
|
|
|
{
|
2010-02-09 16:11:13 +00:00
|
|
|
string const argument = to_utf8(cmd.argument());
|
2010-04-09 19:00:42 +00:00
|
|
|
FuncCode const action = cmd.action();
|
2010-02-09 16:11:13 +00:00
|
|
|
|
|
|
|
LYXERR(Debug::ACTION, "cmd: " << cmd);
|
|
|
|
|
|
|
|
// we have not done anything wrong yet.
|
|
|
|
dr.setError(false);
|
|
|
|
|
|
|
|
FuncStatus const flag = getStatus(cmd);
|
|
|
|
if (!flag.enabled()) {
|
|
|
|
// We cannot use this function here
|
|
|
|
LYXERR(Debug::ACTION, "action "
|
|
|
|
<< lyxaction.getActionName(action)
|
|
|
|
<< " [" << action << "] is disabled at this location");
|
|
|
|
dr.setMessage(flag.message());
|
|
|
|
dr.setError(true);
|
|
|
|
dr.dispatched(false);
|
2010-10-13 17:28:55 +00:00
|
|
|
dr.screenUpdate(Update::None);
|
2010-07-09 14:37:00 +00:00
|
|
|
dr.clearBufferUpdate();
|
2010-02-09 16:11:13 +00:00
|
|
|
return;
|
|
|
|
};
|
|
|
|
|
|
|
|
// Assumes that the action will be dispatched.
|
|
|
|
dr.dispatched(true);
|
|
|
|
|
2010-04-09 19:00:42 +00:00
|
|
|
switch (cmd.action()) {
|
2007-11-24 07:58:12 +00:00
|
|
|
|
|
|
|
case LFUN_WINDOW_NEW:
|
2007-11-24 08:51:11 +00:00
|
|
|
createView(toqstr(cmd.argument()));
|
2007-11-24 07:58:12 +00:00
|
|
|
break;
|
|
|
|
|
|
|
|
case LFUN_WINDOW_CLOSE:
|
|
|
|
// update bookmark pit of the current buffer before window close
|
2008-07-14 08:35:00 +00:00
|
|
|
for (size_t i = 0; i < theSession().bookmarks().size(); ++i)
|
2010-02-09 16:11:13 +00:00
|
|
|
gotoBookmark(i+1, false, false);
|
2009-08-19 20:29:16 +00:00
|
|
|
// clear the last opened list, because
|
|
|
|
// maybe this will end the session
|
|
|
|
theSession().lastOpened().clear();
|
2010-06-07 22:07:38 +00:00
|
|
|
current_view_->closeScheduled();
|
2007-11-24 07:58:12 +00:00
|
|
|
break;
|
|
|
|
|
|
|
|
case LFUN_LYX_QUIT:
|
|
|
|
// quitting is triggered by the gui code
|
|
|
|
// (leaving the event loop).
|
2008-03-15 02:42:59 +00:00
|
|
|
if (current_view_)
|
|
|
|
current_view_->message(from_utf8(N_("Exiting.")));
|
2008-02-27 10:35:28 +00:00
|
|
|
if (closeAllViews())
|
|
|
|
quit();
|
2007-11-24 07:58:12 +00:00
|
|
|
break;
|
|
|
|
|
|
|
|
case LFUN_SCREEN_FONT_UPDATE: {
|
2010-02-09 16:30:12 +00:00
|
|
|
// handle the screen font changes.
|
|
|
|
d->font_loader_.update();
|
|
|
|
// Backup current_view_
|
|
|
|
GuiView * view = current_view_;
|
|
|
|
// Set current_view_ to zero to forbid GuiWorkArea::redraw()
|
|
|
|
// to skip the refresh.
|
|
|
|
current_view_ = 0;
|
|
|
|
theBufferList().changed(false);
|
|
|
|
// Restore current_view_
|
|
|
|
current_view_ = view;
|
|
|
|
break;
|
|
|
|
}
|
2007-11-24 07:58:12 +00:00
|
|
|
|
2008-03-14 23:24:45 +00:00
|
|
|
case LFUN_BUFFER_NEW:
|
2011-01-18 15:22:10 +00:00
|
|
|
validateCurrentView();
|
2008-05-23 11:08:12 +00:00
|
|
|
if (d->views_.empty()
|
2010-02-09 16:30:12 +00:00
|
|
|
|| (!lyxrc.open_buffers_in_tabs && current_view_->documentBufferView() != 0)) {
|
2008-03-14 23:33:05 +00:00
|
|
|
createView(QString(), false); // keep hidden
|
|
|
|
current_view_->newDocument(to_utf8(cmd.argument()), false);
|
|
|
|
current_view_->show();
|
|
|
|
setActiveWindow(current_view_);
|
2008-05-23 18:09:40 +00:00
|
|
|
} else {
|
2008-03-14 23:33:05 +00:00
|
|
|
current_view_->newDocument(to_utf8(cmd.argument()), false);
|
2008-05-23 18:09:40 +00:00
|
|
|
}
|
2008-03-14 23:24:45 +00:00
|
|
|
break;
|
|
|
|
|
|
|
|
case LFUN_BUFFER_NEW_TEMPLATE:
|
2011-01-18 15:22:10 +00:00
|
|
|
validateCurrentView();
|
2008-05-23 11:08:12 +00:00
|
|
|
if (d->views_.empty()
|
2010-02-09 16:30:12 +00:00
|
|
|
|| (!lyxrc.open_buffers_in_tabs && current_view_->documentBufferView() != 0)) {
|
2008-03-14 23:24:45 +00:00
|
|
|
createView();
|
|
|
|
current_view_->newDocument(to_utf8(cmd.argument()), true);
|
2009-09-05 15:09:45 +00:00
|
|
|
if (!current_view_->documentBufferView())
|
2008-03-14 23:24:45 +00:00
|
|
|
current_view_->close();
|
2008-05-23 18:09:40 +00:00
|
|
|
} else {
|
2008-03-14 23:24:45 +00:00
|
|
|
current_view_->newDocument(to_utf8(cmd.argument()), true);
|
2008-05-23 18:09:40 +00:00
|
|
|
}
|
2008-03-14 23:24:45 +00:00
|
|
|
break;
|
|
|
|
|
2010-10-18 14:20:03 +00:00
|
|
|
case LFUN_FILE_OPEN: {
|
2011-01-18 15:22:10 +00:00
|
|
|
validateCurrentView();
|
2009-09-22 19:55:15 +00:00
|
|
|
// FIXME: create a new method shared with LFUN_HELP_OPEN.
|
2010-10-18 14:20:03 +00:00
|
|
|
string const fname = to_utf8(cmd.argument());
|
2011-01-16 04:02:59 +00:00
|
|
|
if (d->views_.empty() || (!lyxrc.open_buffers_in_tabs
|
2010-10-18 14:20:03 +00:00
|
|
|
&& current_view_->documentBufferView() != 0)) {
|
2008-06-19 11:28:11 +00:00
|
|
|
// We want the ui session to be saved per document and not per
|
|
|
|
// window number. The filename crc is a good enough identifier.
|
|
|
|
boost::crc_32_type crc;
|
|
|
|
crc = for_each(fname.begin(), fname.end(), crc);
|
|
|
|
createView(crc.checksum());
|
|
|
|
current_view_->openDocument(fname);
|
2009-09-05 15:09:45 +00:00
|
|
|
if (current_view_ && !current_view_->documentBufferView())
|
2008-03-14 23:24:45 +00:00
|
|
|
current_view_->close();
|
|
|
|
} else
|
2010-10-18 14:20:03 +00:00
|
|
|
current_view_->openDocument(fname);
|
2008-03-14 23:24:45 +00:00
|
|
|
break;
|
2010-10-18 14:20:03 +00:00
|
|
|
}
|
2008-03-14 23:24:45 +00:00
|
|
|
|
2009-09-22 19:55:15 +00:00
|
|
|
case LFUN_HELP_OPEN: {
|
|
|
|
// FIXME: create a new method shared with LFUN_FILE_OPEN.
|
|
|
|
if (current_view_ == 0)
|
|
|
|
createView();
|
|
|
|
string const arg = to_utf8(cmd.argument());
|
|
|
|
if (arg.empty()) {
|
|
|
|
current_view_->message(_("Missing argument"));
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
FileName fname = i18nLibFileSearch("doc", arg, "lyx");
|
2010-02-09 16:11:13 +00:00
|
|
|
if (fname.empty())
|
2009-09-22 19:55:15 +00:00
|
|
|
fname = i18nLibFileSearch("examples", arg, "lyx");
|
|
|
|
|
|
|
|
if (fname.empty()) {
|
|
|
|
lyxerr << "LyX: unable to find documentation file `"
|
2010-02-09 16:30:12 +00:00
|
|
|
<< arg << "'. Bad installation?" << endl;
|
2009-09-22 19:55:15 +00:00
|
|
|
break;
|
|
|
|
}
|
|
|
|
current_view_->message(bformat(_("Opening help file %1$s..."),
|
2010-04-21 01:19:09 +00:00
|
|
|
makeDisplayPath(fname.absFileName())));
|
2009-09-22 19:55:15 +00:00
|
|
|
Buffer * buf = current_view_->loadDocument(fname, false);
|
2010-10-29 19:07:41 +00:00
|
|
|
|
2010-02-10 04:03:35 +00:00
|
|
|
#ifndef DEVEL_VERSION
|
2010-10-29 18:57:40 +00:00
|
|
|
if (buf)
|
2010-01-29 12:01:17 +00:00
|
|
|
buf->setReadonly(true);
|
2010-10-29 19:07:41 +00:00
|
|
|
#else
|
2010-10-29 20:54:26 +00:00
|
|
|
(void) buf;
|
2010-02-10 04:03:35 +00:00
|
|
|
#endif
|
2009-09-22 19:55:15 +00:00
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
2008-05-23 09:53:27 +00:00
|
|
|
case LFUN_SET_COLOR: {
|
|
|
|
string lyx_name;
|
|
|
|
string const x11_name = split(to_utf8(cmd.argument()), lyx_name, ' ');
|
|
|
|
if (lyx_name.empty() || x11_name.empty()) {
|
2010-10-22 20:54:18 +00:00
|
|
|
if (current_view_)
|
|
|
|
current_view_->message(
|
2010-02-09 16:11:13 +00:00
|
|
|
_("Syntax: set-color <lyx_name> <x11_name>"));
|
2008-05-23 09:53:27 +00:00
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
string const graphicsbg = lcolor.getLyXName(Color_graphicsbg);
|
2011-01-16 04:02:59 +00:00
|
|
|
bool const graphicsbg_changed =
|
2010-02-09 16:30:12 +00:00
|
|
|
lyx_name == graphicsbg && x11_name != graphicsbg;
|
2008-05-23 09:53:27 +00:00
|
|
|
if (graphicsbg_changed) {
|
|
|
|
// FIXME: The graphics cache no longer has a changeDisplay method.
|
|
|
|
#if 0
|
|
|
|
graphics::GCache::get().changeDisplay(true);
|
|
|
|
#endif
|
|
|
|
}
|
|
|
|
|
|
|
|
if (!lcolor.setColor(lyx_name, x11_name)) {
|
|
|
|
current_view_->message(
|
2010-02-09 16:30:12 +00:00
|
|
|
bformat(_("Set-color \"%1$s\" failed "
|
|
|
|
"- color is undefined or "
|
|
|
|
"may not be redefined"),
|
|
|
|
from_utf8(lyx_name)));
|
2008-05-23 09:53:27 +00:00
|
|
|
break;
|
|
|
|
}
|
|
|
|
// Make sure we don't keep old colors in cache.
|
|
|
|
d->color_cache_.clear();
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
2009-10-04 20:58:20 +00:00
|
|
|
case LFUN_LYXRC_APPLY: {
|
|
|
|
// reset active key sequences, since the bindings
|
|
|
|
// are updated (bug 6064)
|
|
|
|
d->keyseq.reset();
|
|
|
|
LyXRC const lyxrc_orig = lyxrc;
|
|
|
|
|
|
|
|
istringstream ss(to_utf8(cmd.argument()));
|
2011-01-16 20:28:43 +00:00
|
|
|
bool const success = lyxrc.read(ss);
|
2009-10-04 20:58:20 +00:00
|
|
|
|
|
|
|
if (!success) {
|
|
|
|
lyxerr << "Warning in LFUN_LYXRC_APPLY!\n"
|
2010-02-09 16:11:13 +00:00
|
|
|
<< "Unable to read lyxrc data"
|
|
|
|
<< endl;
|
2009-10-04 20:58:20 +00:00
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
actOnUpdatedPrefs(lyxrc_orig, lyxrc);
|
|
|
|
setSpellChecker();
|
|
|
|
resetGui();
|
|
|
|
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
case LFUN_COMMAND_PREFIX:
|
2010-02-09 16:11:13 +00:00
|
|
|
dispatch(FuncRequest(LFUN_MESSAGE, d->keyseq.printOptions(true)));
|
2009-10-04 20:58:20 +00:00
|
|
|
break;
|
|
|
|
|
|
|
|
case LFUN_CANCEL: {
|
|
|
|
d->keyseq.reset();
|
|
|
|
d->meta_fake_bit = NoModifier;
|
|
|
|
GuiView * gv = currentView();
|
|
|
|
if (gv && gv->currentBufferView())
|
|
|
|
// cancel any selection
|
2010-10-22 18:08:21 +00:00
|
|
|
processFuncRequest(FuncRequest(LFUN_MARK_OFF));
|
2009-10-04 20:58:20 +00:00
|
|
|
dr.setMessage(from_ascii(N_("Cancel")));
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
case LFUN_META_PREFIX:
|
|
|
|
d->meta_fake_bit = AltModifier;
|
|
|
|
dr.setMessage(d->keyseq.print(KeySequence::ForGui));
|
|
|
|
break;
|
|
|
|
|
|
|
|
// --- Menus -----------------------------------------------
|
|
|
|
case LFUN_RECONFIGURE:
|
|
|
|
// argument is any additional parameter to the configure.py command
|
2010-04-07 12:50:47 +00:00
|
|
|
reconfigure(to_utf8(cmd.argument()));
|
2009-10-04 20:58:20 +00:00
|
|
|
break;
|
|
|
|
|
|
|
|
// --- lyxserver commands ----------------------------
|
|
|
|
case LFUN_SERVER_GET_FILENAME: {
|
2010-04-07 12:47:19 +00:00
|
|
|
LASSERT(current_view_ && current_view_->documentBufferView(), return);
|
2009-10-04 20:58:20 +00:00
|
|
|
docstring const fname = from_utf8(
|
2010-04-07 12:47:19 +00:00
|
|
|
current_view_->documentBufferView()->buffer().absFileName());
|
2009-10-04 20:58:20 +00:00
|
|
|
dr.setMessage(fname);
|
|
|
|
LYXERR(Debug::INFO, "FNAME[" << fname << ']');
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
case LFUN_SERVER_NOTIFY: {
|
|
|
|
docstring const dispatch_buffer = d->keyseq.print(KeySequence::Portable);
|
|
|
|
dr.setMessage(dispatch_buffer);
|
|
|
|
theServer().notifyClient(to_utf8(dispatch_buffer));
|
|
|
|
break;
|
|
|
|
}
|
2010-02-09 16:11:13 +00:00
|
|
|
|
|
|
|
case LFUN_CURSOR_FOLLOWS_SCROLLBAR_TOGGLE:
|
|
|
|
lyxrc.cursor_follows_scrollbar = !lyxrc.cursor_follows_scrollbar;
|
|
|
|
break;
|
|
|
|
|
|
|
|
case LFUN_REPEAT: {
|
|
|
|
// repeat command
|
|
|
|
string countstr;
|
|
|
|
string rest = split(argument, countstr, ' ');
|
|
|
|
istringstream is(countstr);
|
|
|
|
int count = 0;
|
|
|
|
is >> count;
|
|
|
|
//lyxerr << "repeat: count: " << count << " cmd: " << rest << endl;
|
|
|
|
for (int i = 0; i < count; ++i)
|
|
|
|
dispatch(lyxaction.lookupFunc(rest));
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
case LFUN_COMMAND_SEQUENCE: {
|
|
|
|
// argument contains ';'-terminated commands
|
|
|
|
string arg = argument;
|
|
|
|
// FIXME: this LFUN should also work without any view.
|
|
|
|
Buffer * buffer = (current_view_ && current_view_->documentBufferView())
|
|
|
|
? &(current_view_->documentBufferView()->buffer()) : 0;
|
|
|
|
if (buffer)
|
|
|
|
buffer->undo().beginUndoGroup();
|
|
|
|
while (!arg.empty()) {
|
|
|
|
string first;
|
|
|
|
arg = split(arg, first, ';');
|
|
|
|
FuncRequest func(lyxaction.lookupFunc(first));
|
2010-04-09 19:00:42 +00:00
|
|
|
func.setOrigin(cmd.origin());
|
2010-02-09 16:11:13 +00:00
|
|
|
dispatch(func);
|
|
|
|
}
|
|
|
|
// the buffer may have been closed by one action
|
|
|
|
if (theBufferList().isLoaded(buffer))
|
|
|
|
buffer->undo().endUndoGroup();
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
case LFUN_COMMAND_ALTERNATIVES: {
|
|
|
|
// argument contains ';'-terminated commands
|
|
|
|
string arg = argument;
|
|
|
|
while (!arg.empty()) {
|
|
|
|
string first;
|
|
|
|
arg = split(arg, first, ';');
|
|
|
|
FuncRequest func(lyxaction.lookupFunc(first));
|
2010-04-09 19:00:42 +00:00
|
|
|
func.setOrigin(cmd.origin());
|
|
|
|
FuncStatus const stat = getStatus(func);
|
2010-02-09 16:11:13 +00:00
|
|
|
if (stat.enabled()) {
|
|
|
|
dispatch(func);
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
case LFUN_CALL: {
|
|
|
|
FuncRequest func;
|
|
|
|
if (theTopLevelCmdDef().lock(argument, func)) {
|
2010-04-09 19:00:42 +00:00
|
|
|
func.setOrigin(cmd.origin());
|
2010-02-09 16:11:13 +00:00
|
|
|
dispatch(func);
|
|
|
|
theTopLevelCmdDef().release(argument);
|
|
|
|
} else {
|
2010-04-09 19:00:42 +00:00
|
|
|
if (func.action() == LFUN_UNKNOWN_ACTION) {
|
2010-02-09 16:11:13 +00:00
|
|
|
// unknown command definition
|
|
|
|
lyxerr << "Warning: unknown command definition `"
|
|
|
|
<< argument << "'"
|
|
|
|
<< endl;
|
|
|
|
} else {
|
|
|
|
// recursion detected
|
|
|
|
lyxerr << "Warning: Recursion in the command definition `"
|
|
|
|
<< argument << "' detected"
|
|
|
|
<< endl;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
case LFUN_PREFERENCES_SAVE:
|
|
|
|
lyxrc.write(support::makeAbsPath("preferences",
|
2010-04-21 01:19:09 +00:00
|
|
|
package().user_support().absFileName()), false);
|
2010-02-09 16:11:13 +00:00
|
|
|
break;
|
|
|
|
|
|
|
|
case LFUN_BUFFER_SAVE_AS_DEFAULT: {
|
2010-04-21 01:19:09 +00:00
|
|
|
string const fname = addName(addPath(package().user_support().absFileName(),
|
2010-02-09 16:11:13 +00:00
|
|
|
"templates/"), "defaults.lyx");
|
|
|
|
Buffer defaults(fname);
|
|
|
|
|
|
|
|
istringstream ss(argument);
|
|
|
|
Lexer lex;
|
|
|
|
lex.setStream(ss);
|
|
|
|
int const unknown_tokens = defaults.readHeader(lex);
|
|
|
|
|
|
|
|
if (unknown_tokens != 0) {
|
|
|
|
lyxerr << "Warning in LFUN_BUFFER_SAVE_AS_DEFAULT!\n"
|
2010-02-09 16:30:12 +00:00
|
|
|
<< unknown_tokens << " unknown token"
|
|
|
|
<< (unknown_tokens == 1 ? "" : "s")
|
|
|
|
<< endl;
|
2010-02-09 16:11:13 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
if (defaults.writeFile(FileName(defaults.absFileName())))
|
|
|
|
dr.setMessage(bformat(_("Document defaults saved in %1$s"),
|
|
|
|
makeDisplayPath(fname)));
|
|
|
|
else {
|
|
|
|
dr.setError(true);
|
|
|
|
dr.setMessage(from_ascii(N_("Unable to save document defaults")));
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
case LFUN_BOOKMARK_GOTO:
|
|
|
|
// go to bookmark, open unopened file and switch to buffer if necessary
|
|
|
|
gotoBookmark(convert<unsigned int>(to_utf8(cmd.argument())), true, true);
|
2010-10-13 17:28:55 +00:00
|
|
|
dr.screenUpdate(Update::Force | Update::FitCursor);
|
2010-02-09 16:11:13 +00:00
|
|
|
break;
|
|
|
|
|
|
|
|
case LFUN_BOOKMARK_CLEAR:
|
|
|
|
theSession().bookmarks().clear();
|
|
|
|
break;
|
|
|
|
|
|
|
|
case LFUN_DEBUG_LEVEL_SET:
|
|
|
|
lyxerr.setLevel(Debug::value(to_utf8(cmd.argument())));
|
|
|
|
break;
|
|
|
|
|
2007-11-24 07:58:12 +00:00
|
|
|
default:
|
2010-12-04 22:48:08 +00:00
|
|
|
// The LFUN must be for one of GuiView, BufferView, Buffer or Cursor;
|
|
|
|
// let's try that:
|
|
|
|
if (current_view_)
|
|
|
|
current_view_->dispatch(cmd, dr);
|
|
|
|
break;
|
2010-02-09 16:11:13 +00:00
|
|
|
}
|
2009-10-04 20:58:20 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
docstring GuiApplication::viewStatusMessage()
|
|
|
|
{
|
|
|
|
// When meta-fake key is pressed, show the key sequence so far + "M-".
|
|
|
|
if (d->meta_fake_bit != NoModifier)
|
|
|
|
return d->keyseq.print(KeySequence::ForGui) + "M-";
|
|
|
|
|
|
|
|
// Else, when a non-complete key sequence is pressed,
|
|
|
|
// show the available options.
|
|
|
|
if (d->keyseq.length() > 0 && !d->keyseq.deleted())
|
|
|
|
return d->keyseq.printOptions(true);
|
|
|
|
|
|
|
|
return docstring();
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
void GuiApplication::handleKeyFunc(FuncCode action)
|
|
|
|
{
|
2009-10-04 21:09:39 +00:00
|
|
|
char_type c = 0;
|
2009-10-04 20:58:20 +00:00
|
|
|
|
|
|
|
if (d->keyseq.length())
|
|
|
|
c = 0;
|
|
|
|
GuiView * gv = currentView();
|
|
|
|
LASSERT(gv && gv->currentBufferView(), return);
|
|
|
|
BufferView * bv = gv->currentBufferView();
|
|
|
|
bv->getIntl().getTransManager().deadkey(
|
|
|
|
c, get_accent(action).accent, bv->cursor().innerText(),
|
|
|
|
bv->cursor());
|
|
|
|
// Need to clear, in case the minibuffer calls these
|
|
|
|
// actions
|
|
|
|
d->keyseq.clear();
|
|
|
|
// copied verbatim from do_accent_char
|
|
|
|
bv->cursor().resetAnchor();
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
void GuiApplication::processKeySym(KeySymbol const & keysym, KeyModifier state)
|
|
|
|
{
|
|
|
|
LYXERR(Debug::KEY, "KeySym is " << keysym.getSymbolName());
|
|
|
|
|
|
|
|
// Do nothing if we have nothing (JMarc)
|
|
|
|
if (!keysym.isOK()) {
|
|
|
|
LYXERR(Debug::KEY, "Empty kbd action (probably composing)");
|
2010-10-22 20:54:18 +00:00
|
|
|
if (current_view_)
|
|
|
|
current_view_->restartCursor();
|
2009-10-04 20:58:20 +00:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (keysym.isModifier()) {
|
|
|
|
LYXERR(Debug::KEY, "isModifier true");
|
2010-04-07 12:43:41 +00:00
|
|
|
if (current_view_)
|
|
|
|
current_view_->restartCursor();
|
2009-10-04 20:58:20 +00:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
char_type encoded_last_key = keysym.getUCSEncoded();
|
|
|
|
|
|
|
|
// Do a one-deep top-level lookup for
|
|
|
|
// cancel and meta-fake keys. RVDK_PATCH_5
|
|
|
|
d->cancel_meta_seq.reset();
|
|
|
|
|
|
|
|
FuncRequest func = d->cancel_meta_seq.addkey(keysym, state);
|
2010-04-09 19:00:42 +00:00
|
|
|
LYXERR(Debug::KEY, "action first set to [" << func.action() << ']');
|
2009-10-04 20:58:20 +00:00
|
|
|
|
|
|
|
// When not cancel or meta-fake, do the normal lookup.
|
|
|
|
// Note how the meta_fake Mod1 bit is OR-ed in and reset afterwards.
|
|
|
|
// Mostly, meta_fake_bit = NoModifier. RVDK_PATCH_5.
|
2010-04-09 19:00:42 +00:00
|
|
|
if ((func.action() != LFUN_CANCEL) && (func.action() != LFUN_META_PREFIX)) {
|
2009-10-04 20:58:20 +00:00
|
|
|
// remove Caps Lock and Mod2 as a modifiers
|
|
|
|
func = d->keyseq.addkey(keysym, (state | d->meta_fake_bit));
|
2010-04-09 19:00:42 +00:00
|
|
|
LYXERR(Debug::KEY, "action now set to [" << func.action() << ']');
|
2009-10-04 20:58:20 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
// Dont remove this unless you know what you are doing.
|
|
|
|
d->meta_fake_bit = NoModifier;
|
|
|
|
|
|
|
|
// Can this happen now ?
|
2010-04-09 19:00:42 +00:00
|
|
|
if (func.action() == LFUN_NOACTION)
|
2009-10-04 20:58:20 +00:00
|
|
|
func = FuncRequest(LFUN_COMMAND_PREFIX);
|
|
|
|
|
2010-04-09 19:00:42 +00:00
|
|
|
LYXERR(Debug::KEY, " Key [action=" << func.action() << "]["
|
2009-10-04 20:58:20 +00:00
|
|
|
<< d->keyseq.print(KeySequence::Portable) << ']');
|
|
|
|
|
|
|
|
// already here we know if it any point in going further
|
|
|
|
// why not return already here if action == -1 and
|
|
|
|
// num_bytes == 0? (Lgb)
|
|
|
|
|
2010-10-22 20:54:18 +00:00
|
|
|
if (d->keyseq.length() > 1 && current_view_)
|
2010-04-07 12:43:41 +00:00
|
|
|
current_view_->message(d->keyseq.print(KeySequence::ForGui));
|
2009-10-04 20:58:20 +00:00
|
|
|
|
|
|
|
|
|
|
|
// Maybe user can only reach the key via holding down shift.
|
|
|
|
// Let's see. But only if shift is the only modifier
|
2010-04-09 19:00:42 +00:00
|
|
|
if (func.action() == LFUN_UNKNOWN_ACTION && state == ShiftModifier) {
|
2009-10-04 20:58:20 +00:00
|
|
|
LYXERR(Debug::KEY, "Trying without shift");
|
|
|
|
func = d->keyseq.addkey(keysym, NoModifier);
|
2010-04-09 19:00:42 +00:00
|
|
|
LYXERR(Debug::KEY, "Action now " << func.action());
|
2009-10-04 20:58:20 +00:00
|
|
|
}
|
|
|
|
|
2010-04-09 19:00:42 +00:00
|
|
|
if (func.action() == LFUN_UNKNOWN_ACTION) {
|
2009-10-04 20:58:20 +00:00
|
|
|
// Hmm, we didn't match any of the keysequences. See
|
|
|
|
// if it's normal insertable text not already covered
|
|
|
|
// by a binding
|
|
|
|
if (keysym.isText() && d->keyseq.length() == 1) {
|
|
|
|
LYXERR(Debug::KEY, "isText() is true, inserting.");
|
|
|
|
func = FuncRequest(LFUN_SELF_INSERT,
|
|
|
|
FuncRequest::KEYBOARD);
|
|
|
|
} else {
|
|
|
|
LYXERR(Debug::KEY, "Unknown, !isText() - giving up");
|
2010-10-22 20:54:18 +00:00
|
|
|
if (current_view_) {
|
|
|
|
current_view_->message(_("Unknown function."));
|
|
|
|
current_view_->restartCursor();
|
|
|
|
}
|
2009-10-04 20:58:20 +00:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2010-04-09 19:00:42 +00:00
|
|
|
if (func.action() == LFUN_SELF_INSERT) {
|
2009-10-04 20:58:20 +00:00
|
|
|
if (encoded_last_key != 0) {
|
|
|
|
docstring const arg(1, encoded_last_key);
|
2010-10-22 18:08:21 +00:00
|
|
|
processFuncRequest(FuncRequest(LFUN_SELF_INSERT, arg,
|
2009-10-04 20:58:20 +00:00
|
|
|
FuncRequest::KEYBOARD));
|
|
|
|
LYXERR(Debug::KEY, "SelfInsert arg[`" << to_utf8(arg) << "']");
|
|
|
|
}
|
2010-04-07 12:43:41 +00:00
|
|
|
} else
|
2010-10-22 18:08:21 +00:00
|
|
|
processFuncRequest(func);
|
2007-11-24 07:58:12 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2010-10-22 18:08:21 +00:00
|
|
|
void GuiApplication::processFuncRequest(FuncRequest const & func)
|
2010-10-22 15:46:46 +00:00
|
|
|
{
|
2010-10-22 18:08:21 +00:00
|
|
|
lyx::dispatch(func);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
void GuiApplication::processFuncRequestAsync(FuncRequest const & func)
|
|
|
|
{
|
|
|
|
addToFuncRequestQueue(func);
|
2010-10-22 15:46:46 +00:00
|
|
|
processFuncRequestQueueAsync();
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2010-10-22 18:08:21 +00:00
|
|
|
void GuiApplication::processFuncRequestQueue()
|
2008-11-15 16:29:58 +00:00
|
|
|
{
|
2010-10-22 18:08:21 +00:00
|
|
|
while (!d->func_request_queue_.empty()) {
|
|
|
|
processFuncRequest(d->func_request_queue_.front());
|
|
|
|
d->func_request_queue_.pop();
|
|
|
|
}
|
2010-10-22 15:46:46 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
void GuiApplication::processFuncRequestQueueAsync()
|
|
|
|
{
|
2010-10-22 18:08:21 +00:00
|
|
|
QTimer::singleShot(0, this, SLOT(slotProcessFuncRequestQueue()));
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
void GuiApplication::addToFuncRequestQueue(FuncRequest const & func)
|
|
|
|
{
|
|
|
|
d->func_request_queue_.push(func);
|
2008-11-15 16:29:58 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2007-11-21 15:12:47 +00:00
|
|
|
void GuiApplication::resetGui()
|
|
|
|
{
|
2008-06-25 18:03:38 +00:00
|
|
|
// Set the language defined by the user.
|
2008-07-28 11:26:46 +00:00
|
|
|
setGuiLanguage();
|
2008-06-25 18:03:38 +00:00
|
|
|
|
|
|
|
// Read menus
|
|
|
|
if (!readUIFile(toqstr(lyxrc.ui_file)))
|
|
|
|
// Gives some error box here.
|
|
|
|
return;
|
|
|
|
|
2008-10-22 18:02:09 +00:00
|
|
|
if (d->global_menubar_)
|
|
|
|
d->menus_.fillMenuBar(d->global_menubar_, 0, false);
|
2008-06-25 18:03:38 +00:00
|
|
|
|
2008-05-23 18:09:40 +00:00
|
|
|
QHash<int, GuiView *>::iterator it;
|
2008-08-04 08:08:46 +00:00
|
|
|
for (it = d->views_.begin(); it != d->views_.end(); ++it) {
|
|
|
|
GuiView * gv = *it;
|
2009-09-30 14:30:16 +00:00
|
|
|
setCurrentView(gv);
|
2008-08-04 08:08:46 +00:00
|
|
|
gv->setLayoutDirection(layoutDirection());
|
|
|
|
gv->resetDialogs();
|
|
|
|
}
|
2007-11-24 07:58:12 +00:00
|
|
|
|
2010-10-22 18:08:21 +00:00
|
|
|
processFuncRequest(FuncRequest(LFUN_SCREEN_FONT_UPDATE));
|
2007-11-21 15:12:47 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2008-06-19 11:28:11 +00:00
|
|
|
void GuiApplication::createView(int view_id)
|
|
|
|
{
|
|
|
|
createView(QString(), true, view_id);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
void GuiApplication::createView(QString const & geometry_arg, bool autoShow,
|
|
|
|
int view_id)
|
2007-11-13 15:29:15 +00:00
|
|
|
{
|
2008-03-14 23:31:44 +00:00
|
|
|
// release the keyboard which might have been grabed by the global
|
|
|
|
// menubar on Mac to catch shortcuts even without any GuiView.
|
2008-05-23 07:52:39 +00:00
|
|
|
if (d->global_menubar_)
|
|
|
|
d->global_menubar_->releaseKeyboard();
|
2008-03-14 23:25:24 +00:00
|
|
|
|
2008-03-14 16:39:34 +00:00
|
|
|
// create new view
|
2008-06-19 14:22:32 +00:00
|
|
|
int id = view_id;
|
2009-09-12 23:50:03 +00:00
|
|
|
while (d->views_.find(id) != d->views_.end())
|
|
|
|
id++;
|
|
|
|
|
2008-06-19 14:22:32 +00:00
|
|
|
LYXERR(Debug::GUI, "About to create new window with ID " << id);
|
2008-03-14 16:39:34 +00:00
|
|
|
GuiView * view = new GuiView(id);
|
|
|
|
// register view
|
2008-05-23 08:43:07 +00:00
|
|
|
d->views_[id] = view;
|
2008-03-14 23:29:11 +00:00
|
|
|
|
2008-03-14 23:33:05 +00:00
|
|
|
if (autoShow) {
|
|
|
|
view->show();
|
|
|
|
setActiveWindow(view);
|
|
|
|
}
|
|
|
|
|
2007-11-24 08:51:11 +00:00
|
|
|
if (!geometry_arg.isEmpty()) {
|
2007-11-15 12:58:44 +00:00
|
|
|
#ifdef Q_WS_WIN
|
|
|
|
int x, y;
|
|
|
|
int w, h;
|
|
|
|
QRegExp re( "[=]*(?:([0-9]+)[xX]([0-9]+)){0,1}[ ]*(?:([+-][0-9]*)([+-][0-9]*)){0,1}" );
|
2007-11-24 08:51:11 +00:00
|
|
|
re.indexIn(geometry_arg);
|
2007-11-15 12:58:44 +00:00
|
|
|
w = re.cap(1).toInt();
|
|
|
|
h = re.cap(2).toInt();
|
|
|
|
x = re.cap(3).toInt();
|
|
|
|
y = re.cap(4).toInt();
|
2007-11-17 20:47:50 +00:00
|
|
|
view->setGeometry(x, y, w, h);
|
2007-11-15 12:58:44 +00:00
|
|
|
#endif
|
|
|
|
}
|
2007-11-17 20:47:50 +00:00
|
|
|
view->setFocus();
|
2007-11-13 15:29:15 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2007-09-15 17:47:35 +00:00
|
|
|
Clipboard & GuiApplication::clipboard()
|
2006-09-22 15:02:41 +00:00
|
|
|
{
|
2008-05-23 08:43:07 +00:00
|
|
|
return d->clipboard_;
|
2006-09-22 15:02:41 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2007-09-15 17:47:35 +00:00
|
|
|
Selection & GuiApplication::selection()
|
2006-09-22 15:02:41 +00:00
|
|
|
{
|
2008-05-23 08:43:07 +00:00
|
|
|
return d->selection_;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2011-01-16 04:02:59 +00:00
|
|
|
FontLoader & GuiApplication::fontLoader()
|
2008-05-23 08:43:07 +00:00
|
|
|
{
|
|
|
|
return d->font_loader_;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2011-01-16 04:02:59 +00:00
|
|
|
Toolbars const & GuiApplication::toolbars() const
|
2008-05-25 08:30:06 +00:00
|
|
|
{
|
|
|
|
return d->toolbars_;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
Toolbars & GuiApplication::toolbars()
|
|
|
|
{
|
2011-01-16 04:02:59 +00:00
|
|
|
return d->toolbars_;
|
2008-05-25 08:30:06 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2011-01-16 04:02:59 +00:00
|
|
|
Menus const & GuiApplication::menus() const
|
2008-05-23 08:43:07 +00:00
|
|
|
{
|
|
|
|
return d->menus_;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
Menus & GuiApplication::menus()
|
|
|
|
{
|
2011-01-16 04:02:59 +00:00
|
|
|
return d->menus_;
|
2008-05-23 08:43:07 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2008-05-23 18:09:40 +00:00
|
|
|
QList<int> GuiApplication::viewIds() const
|
2008-05-23 08:43:07 +00:00
|
|
|
{
|
2008-05-23 18:09:40 +00:00
|
|
|
return d->views_.keys();
|
2008-05-23 08:43:07 +00:00
|
|
|
}
|
|
|
|
|
2008-05-23 10:45:55 +00:00
|
|
|
|
2008-05-23 08:43:07 +00:00
|
|
|
ColorCache & GuiApplication::colorCache()
|
|
|
|
{
|
|
|
|
return d->color_cache_;
|
2006-09-22 15:02:41 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2007-09-15 17:47:35 +00:00
|
|
|
int GuiApplication::exec()
|
2006-06-26 17:18:28 +00:00
|
|
|
{
|
2008-11-05 14:04:37 +00:00
|
|
|
// asynchronously handle batch commands. This event will be in
|
|
|
|
// the event queue in front of other asynchronous events. Hence,
|
|
|
|
// we can assume in the latter that the gui is setup already.
|
|
|
|
QTimer::singleShot(0, this, SLOT(execBatchCommands()));
|
|
|
|
|
2006-09-22 09:47:39 +00:00
|
|
|
return QApplication::exec();
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
void GuiApplication::exit(int status)
|
|
|
|
{
|
|
|
|
QApplication::exit(status);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2008-07-28 11:26:46 +00:00
|
|
|
void GuiApplication::setGuiLanguage()
|
2006-11-26 02:18:32 +00:00
|
|
|
{
|
2008-06-25 11:10:10 +00:00
|
|
|
// Set the language defined by the user.
|
2008-07-14 08:35:00 +00:00
|
|
|
setRcGuiLanguage();
|
2008-06-25 11:10:10 +00:00
|
|
|
|
2008-07-28 11:26:46 +00:00
|
|
|
QString const default_language = toqstr(Messages::defaultLanguage());
|
2009-12-31 23:00:07 +00:00
|
|
|
LYXERR(Debug::LOCALE, "Trying to set default locale to: " << default_language);
|
2008-07-28 11:26:46 +00:00
|
|
|
QLocale const default_locale(default_language);
|
|
|
|
QLocale::setDefault(default_locale);
|
|
|
|
|
|
|
|
// install translation file for Qt built-in dialogs
|
|
|
|
QString const language_name = QString("qt_") + default_locale.name();
|
|
|
|
|
2011-01-16 04:02:59 +00:00
|
|
|
// language_name can be short (e.g. qt_zh) or long (e.g. qt_zh_CN).
|
2008-07-28 11:26:46 +00:00
|
|
|
// Short-named translator can be loaded from a long name, but not the
|
|
|
|
// opposite. Therefore, long name should be used without truncation.
|
|
|
|
// c.f. http://doc.trolltech.com/4.1/qtranslator.html#load
|
|
|
|
if (!d->qt_trans_.load(language_name,
|
|
|
|
QLibraryInfo::location(QLibraryInfo::TranslationsPath))) {
|
2009-12-31 23:00:07 +00:00
|
|
|
LYXERR(Debug::LOCALE, "Could not find Qt translations for locale "
|
2008-07-28 11:26:46 +00:00
|
|
|
<< language_name);
|
2008-07-29 07:06:57 +00:00
|
|
|
} else {
|
|
|
|
LYXERR(Debug::LOCALE, "Successfully installed Qt translations for locale "
|
|
|
|
<< language_name);
|
2008-07-28 11:26:46 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
switch (default_locale.language()) {
|
|
|
|
case QLocale::Arabic :
|
|
|
|
case QLocale::Hebrew :
|
|
|
|
case QLocale::Persian :
|
|
|
|
case QLocale::Urdu :
|
2010-03-15 16:26:09 +00:00
|
|
|
setLayoutDirection(Qt::RightToLeft);
|
2008-07-28 11:26:46 +00:00
|
|
|
break;
|
|
|
|
default:
|
2010-03-15 16:26:09 +00:00
|
|
|
setLayoutDirection(Qt::LeftToRight);
|
2008-07-28 11:26:46 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
void GuiApplication::execBatchCommands()
|
|
|
|
{
|
|
|
|
setGuiLanguage();
|
|
|
|
|
2008-05-24 09:28:05 +00:00
|
|
|
// Read menus
|
2008-05-24 09:51:17 +00:00
|
|
|
if (!readUIFile(toqstr(lyxrc.ui_file)))
|
2008-05-24 09:28:05 +00:00
|
|
|
// Gives some error box here.
|
|
|
|
return;
|
|
|
|
|
2008-10-22 18:14:30 +00:00
|
|
|
#ifdef Q_WS_MACX
|
2010-09-19 22:00:25 +00:00
|
|
|
#if QT_VERSION > 0x040600
|
|
|
|
setAttribute(Qt::AA_MacDontSwapCtrlAndMeta,lyxrc.mac_dontswap_ctrl_meta);
|
|
|
|
#endif
|
2008-10-22 18:14:30 +00:00
|
|
|
// Create the global default menubar which is shown for the dialogs
|
|
|
|
// and if no GuiView is visible.
|
|
|
|
// This must be done after the session was recovered to know the "last files".
|
|
|
|
d->global_menubar_ = new GlobalMenuBar();
|
|
|
|
d->menus_.fillMenuBar(d->global_menubar_, 0, true);
|
|
|
|
#endif
|
2008-05-23 08:57:41 +00:00
|
|
|
|
2008-07-14 08:35:00 +00:00
|
|
|
lyx::execBatchCommands();
|
2008-05-14 10:34:19 +00:00
|
|
|
}
|
|
|
|
|
2008-09-21 21:28:37 +00:00
|
|
|
|
2008-05-14 10:34:19 +00:00
|
|
|
QAbstractItemModel * GuiApplication::languageModel()
|
|
|
|
{
|
2008-05-23 08:43:07 +00:00
|
|
|
if (d->language_model_)
|
|
|
|
return d->language_model_;
|
2008-05-08 09:03:38 +00:00
|
|
|
|
2008-05-14 10:34:19 +00:00
|
|
|
QStandardItemModel * lang_model = new QStandardItemModel(this);
|
2010-02-10 08:10:31 +00:00
|
|
|
lang_model->insertColumns(0, 3);
|
2008-05-08 09:03:38 +00:00
|
|
|
int current_row;
|
2010-02-10 08:10:31 +00:00
|
|
|
QIcon speller(getPixmap("images/", "dialog-show_spellchecker", "png"));
|
|
|
|
QIcon saurus(getPixmap("images/", "thesaurus-entry", "png"));
|
2009-11-07 12:50:30 +00:00
|
|
|
Languages::const_iterator it = lyx::languages.begin();
|
|
|
|
Languages::const_iterator end = lyx::languages.end();
|
2008-05-08 09:03:38 +00:00
|
|
|
for (; it != end; ++it) {
|
2008-05-14 10:34:19 +00:00
|
|
|
current_row = lang_model->rowCount();
|
|
|
|
lang_model->insertRows(current_row, 1);
|
2010-02-10 08:10:31 +00:00
|
|
|
QModelIndex pl_item = lang_model->index(current_row, 0);
|
|
|
|
QModelIndex sp_item = lang_model->index(current_row, 1);
|
|
|
|
QModelIndex th_item = lang_model->index(current_row, 2);
|
|
|
|
lang_model->setData(pl_item, qt_(it->second.display()), Qt::DisplayRole);
|
|
|
|
lang_model->setData(pl_item, toqstr(it->second.lang()), Qt::UserRole);
|
|
|
|
lang_model->setData(sp_item, qt_(it->second.display()), Qt::DisplayRole);
|
|
|
|
lang_model->setData(sp_item, toqstr(it->second.lang()), Qt::UserRole);
|
2010-02-12 12:32:15 +00:00
|
|
|
if (theSpellChecker() && theSpellChecker()->hasDictionary(&it->second))
|
2010-02-10 08:10:31 +00:00
|
|
|
lang_model->setData(sp_item, speller, Qt::DecorationRole);
|
|
|
|
lang_model->setData(th_item, qt_(it->second.display()), Qt::DisplayRole);
|
|
|
|
lang_model->setData(th_item, toqstr(it->second.lang()), Qt::UserRole);
|
|
|
|
if (thesaurus.thesaurusInstalled(from_ascii(it->second.code())))
|
|
|
|
lang_model->setData(th_item, saurus, Qt::DecorationRole);
|
2008-05-08 09:03:38 +00:00
|
|
|
}
|
2008-05-23 08:43:07 +00:00
|
|
|
d->language_model_ = new QSortFilterProxyModel(this);
|
|
|
|
d->language_model_->setSourceModel(lang_model);
|
2008-05-16 14:30:46 +00:00
|
|
|
#if QT_VERSION >= 0x040300
|
2008-05-23 08:43:07 +00:00
|
|
|
d->language_model_->setSortLocaleAware(true);
|
2008-05-16 14:30:46 +00:00
|
|
|
#endif
|
2008-05-23 08:43:07 +00:00
|
|
|
return d->language_model_;
|
2006-11-26 02:18:32 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2008-02-06 23:02:57 +00:00
|
|
|
void GuiApplication::restoreGuiSession()
|
|
|
|
{
|
|
|
|
if (!lyxrc.load_session)
|
|
|
|
return;
|
|
|
|
|
2008-07-14 08:35:00 +00:00
|
|
|
Session & session = theSession();
|
2011-01-16 04:02:59 +00:00
|
|
|
LastOpenedSection::LastOpened const & lastopened =
|
2009-05-05 12:47:44 +00:00
|
|
|
session.lastOpened().getfiles();
|
|
|
|
|
|
|
|
FileName active_file;
|
2008-02-06 23:02:57 +00:00
|
|
|
// do not add to the lastfile list since these files are restored from
|
|
|
|
// last session, and should be already there (regular files), or should
|
|
|
|
// not be added at all (help files).
|
2009-08-19 20:06:57 +00:00
|
|
|
for (size_t i = 0; i < lastopened.size(); ++i) {
|
|
|
|
FileName const & file_name = lastopened[i].file_name;
|
2009-07-19 14:34:14 +00:00
|
|
|
if (d->views_.empty() || (!lyxrc.open_buffers_in_tabs
|
2009-09-05 15:09:45 +00:00
|
|
|
&& current_view_->documentBufferView() != 0)) {
|
2009-07-19 14:34:14 +00:00
|
|
|
boost::crc_32_type crc;
|
2010-04-21 01:19:09 +00:00
|
|
|
string const & fname = file_name.absFileName();
|
2009-07-19 14:34:14 +00:00
|
|
|
crc = for_each(fname.begin(), fname.end(), crc);
|
|
|
|
createView(crc.checksum());
|
|
|
|
}
|
|
|
|
current_view_->loadDocument(file_name, false);
|
|
|
|
|
2009-08-19 20:06:57 +00:00
|
|
|
if (lastopened[i].active)
|
2009-07-19 14:34:14 +00:00
|
|
|
active_file = file_name;
|
2009-05-05 12:47:44 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
// Restore last active buffer
|
|
|
|
Buffer * buffer = theBufferList().getBuffer(active_file);
|
|
|
|
if (buffer)
|
|
|
|
current_view_->setBuffer(buffer);
|
2008-02-06 23:02:57 +00:00
|
|
|
|
|
|
|
// clear this list to save a few bytes of RAM
|
|
|
|
session.lastOpened().clear();
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2007-11-18 20:36:52 +00:00
|
|
|
QString const GuiApplication::romanFontName()
|
2006-10-03 10:34:10 +00:00
|
|
|
{
|
|
|
|
QFont font;
|
2006-10-22 13:10:12 +00:00
|
|
|
font.setKerning(false);
|
2006-10-03 10:34:10 +00:00
|
|
|
font.setStyleHint(QFont::Serif);
|
|
|
|
font.setFamily("serif");
|
|
|
|
|
2007-11-18 20:36:52 +00:00
|
|
|
return QFontInfo(font).family();
|
2006-10-03 10:34:10 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2007-11-18 20:36:52 +00:00
|
|
|
QString const GuiApplication::sansFontName()
|
2006-10-03 10:34:10 +00:00
|
|
|
{
|
|
|
|
QFont font;
|
2006-10-22 13:10:12 +00:00
|
|
|
font.setKerning(false);
|
2006-10-03 10:34:10 +00:00
|
|
|
font.setStyleHint(QFont::SansSerif);
|
|
|
|
font.setFamily("sans");
|
|
|
|
|
2007-11-18 20:36:52 +00:00
|
|
|
return QFontInfo(font).family();
|
2006-10-03 10:34:10 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2007-11-18 20:36:52 +00:00
|
|
|
QString const GuiApplication::typewriterFontName()
|
2006-10-03 10:34:10 +00:00
|
|
|
{
|
|
|
|
QFont font;
|
2006-10-22 13:10:12 +00:00
|
|
|
font.setKerning(false);
|
2006-10-03 10:34:10 +00:00
|
|
|
font.setStyleHint(QFont::TypeWriter);
|
|
|
|
font.setFamily("monospace");
|
|
|
|
|
2007-11-18 20:36:52 +00:00
|
|
|
return QFontInfo(font).family();
|
2006-10-03 10:34:10 +00:00
|
|
|
}
|
2006-06-26 17:18:28 +00:00
|
|
|
|
|
|
|
|
2008-02-05 13:10:42 +00:00
|
|
|
void GuiApplication::handleRegularEvents()
|
|
|
|
{
|
|
|
|
ForkedCallsController::handleCompletedProcesses();
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2006-11-29 09:06:37 +00:00
|
|
|
bool GuiApplication::event(QEvent * e)
|
|
|
|
{
|
|
|
|
switch(e->type()) {
|
|
|
|
case QEvent::FileOpen: {
|
2008-11-05 14:04:37 +00:00
|
|
|
// Open a file; this happens only on Mac OS X for now.
|
|
|
|
//
|
|
|
|
// We do this asynchronously because on startup the batch
|
|
|
|
// commands are not executed here yet and the gui is not ready
|
|
|
|
// therefore.
|
2006-11-29 09:06:37 +00:00
|
|
|
QFileOpenEvent * foe = static_cast<QFileOpenEvent *>(e);
|
2010-10-22 18:08:21 +00:00
|
|
|
FuncRequest const fr(LFUN_FILE_OPEN, qstring_to_ucs4(foe->file()));
|
|
|
|
processFuncRequestAsync(fr);
|
2007-05-04 17:20:53 +00:00
|
|
|
e->accept();
|
2006-11-29 09:06:37 +00:00
|
|
|
return true;
|
|
|
|
}
|
|
|
|
default:
|
2007-01-31 16:07:37 +00:00
|
|
|
return QApplication::event(e);
|
2006-11-29 09:06:37 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2007-04-01 16:06:43 +00:00
|
|
|
bool GuiApplication::notify(QObject * receiver, QEvent * event)
|
|
|
|
{
|
|
|
|
try {
|
2007-11-13 23:00:36 +00:00
|
|
|
return QApplication::notify(receiver, event);
|
2007-04-01 16:06:43 +00:00
|
|
|
}
|
2007-12-12 19:57:42 +00:00
|
|
|
catch (ExceptionMessage const & e) {
|
2011-01-16 04:02:59 +00:00
|
|
|
switch(e.type_) {
|
2008-02-29 08:10:51 +00:00
|
|
|
case ErrorException:
|
2008-07-14 08:35:00 +00:00
|
|
|
emergencyCleanup();
|
2008-02-28 20:40:55 +00:00
|
|
|
setQuitOnLastWindowClosed(false);
|
|
|
|
closeAllViews();
|
2007-09-21 20:27:07 +00:00
|
|
|
Alert::error(e.title_, e.details_);
|
2008-02-28 20:40:55 +00:00
|
|
|
#ifndef NDEBUG
|
|
|
|
// Properly crash in debug mode in order to get a useful backtrace.
|
|
|
|
abort();
|
|
|
|
#endif
|
|
|
|
// In release mode, try to exit gracefully.
|
|
|
|
this->exit(1);
|
2008-02-29 08:10:51 +00:00
|
|
|
|
|
|
|
case BufferException: {
|
2009-09-05 15:12:51 +00:00
|
|
|
if (!current_view_->documentBufferView())
|
2009-09-05 15:09:45 +00:00
|
|
|
return false;
|
|
|
|
Buffer * buf = ¤t_view_->documentBufferView()->buffer();
|
2008-02-29 08:10:51 +00:00
|
|
|
docstring details = e.details_ + '\n';
|
2009-08-15 16:34:54 +00:00
|
|
|
details += buf->emergencyWrite();
|
2008-02-29 08:10:51 +00:00
|
|
|
theBufferList().release(buf);
|
2008-03-17 02:49:47 +00:00
|
|
|
details += "\n" + _("The current document was closed.");
|
2008-02-29 08:10:51 +00:00
|
|
|
Alert::error(e.title_, details);
|
2007-11-13 23:00:36 +00:00
|
|
|
return false;
|
2007-09-21 20:27:07 +00:00
|
|
|
}
|
2008-02-29 08:10:51 +00:00
|
|
|
case WarningException:
|
|
|
|
Alert::warning(e.title_, e.details_);
|
|
|
|
return false;
|
2008-03-26 22:25:43 +00:00
|
|
|
}
|
2007-09-21 20:27:07 +00:00
|
|
|
}
|
2007-12-12 19:28:07 +00:00
|
|
|
catch (exception const & e) {
|
2007-09-27 09:49:14 +00:00
|
|
|
docstring s = _("LyX has caught an exception, it will now "
|
2007-12-02 23:55:38 +00:00
|
|
|
"attempt to save all unsaved documents and exit."
|
2007-09-27 09:49:14 +00:00
|
|
|
"\n\nException: ");
|
|
|
|
s += from_ascii(e.what());
|
|
|
|
Alert::error(_("Software exception Detected"), s);
|
2008-07-14 08:35:00 +00:00
|
|
|
lyx_exit(1);
|
2007-04-02 10:18:12 +00:00
|
|
|
}
|
2007-04-01 16:06:43 +00:00
|
|
|
catch (...) {
|
2007-09-27 09:49:14 +00:00
|
|
|
docstring s = _("LyX has caught some really weird exception, it will "
|
2007-12-02 23:55:38 +00:00
|
|
|
"now attempt to save all unsaved documents and exit.");
|
2007-09-27 09:49:14 +00:00
|
|
|
Alert::error(_("Software exception Detected"), s);
|
2008-07-14 08:35:00 +00:00
|
|
|
lyx_exit(1);
|
2007-04-01 16:06:43 +00:00
|
|
|
}
|
|
|
|
|
2007-11-13 23:00:36 +00:00
|
|
|
return false;
|
2007-04-01 16:06:43 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2007-11-13 23:00:36 +00:00
|
|
|
bool GuiApplication::getRgbColor(ColorCode col, RGBColor & rgbcol)
|
2006-10-12 14:10:13 +00:00
|
|
|
{
|
2008-05-23 08:43:07 +00:00
|
|
|
QColor const & qcol = d->color_cache_.get(col);
|
2006-10-12 14:10:13 +00:00
|
|
|
if (!qcol.isValid()) {
|
|
|
|
rgbcol.r = 0;
|
|
|
|
rgbcol.g = 0;
|
|
|
|
rgbcol.b = 0;
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
rgbcol.r = qcol.red();
|
|
|
|
rgbcol.g = qcol.green();
|
|
|
|
rgbcol.b = qcol.blue();
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2011-01-06 18:40:39 +00:00
|
|
|
bool Application::getRgbColorUncached(ColorCode col, RGBColor & rgbcol)
|
|
|
|
{
|
|
|
|
QColor const qcol(lcolor.getX11Name(col).c_str());
|
|
|
|
if (!qcol.isValid()) {
|
|
|
|
rgbcol.r = 0;
|
|
|
|
rgbcol.g = 0;
|
|
|
|
rgbcol.b = 0;
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
rgbcol.r = qcol.red();
|
|
|
|
rgbcol.g = qcol.green();
|
|
|
|
rgbcol.b = qcol.blue();
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2007-10-25 12:41:02 +00:00
|
|
|
string const GuiApplication::hexName(ColorCode col)
|
2006-10-12 14:10:13 +00:00
|
|
|
{
|
2008-05-23 08:43:07 +00:00
|
|
|
return ltrim(fromqstr(d->color_cache_.get(col).name()), "#");
|
2006-10-12 14:10:13 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2007-09-15 20:31:50 +00:00
|
|
|
void GuiApplication::registerSocketCallback(int fd, SocketCallback func)
|
|
|
|
{
|
|
|
|
SocketNotifier * sn = new SocketNotifier(this, fd, func);
|
2008-05-23 08:43:07 +00:00
|
|
|
d->socket_notifiers_[fd] = sn;
|
2007-09-15 20:31:50 +00:00
|
|
|
connect(sn, SIGNAL(activated(int)), this, SLOT(socketDataReceived(int)));
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
void GuiApplication::socketDataReceived(int fd)
|
2006-10-12 14:10:13 +00:00
|
|
|
{
|
2008-05-23 08:43:07 +00:00
|
|
|
d->socket_notifiers_[fd]->func_();
|
2006-10-12 14:10:13 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2006-12-02 17:39:31 +00:00
|
|
|
void GuiApplication::unregisterSocketCallback(int fd)
|
2006-10-12 14:10:13 +00:00
|
|
|
{
|
2008-05-23 18:09:40 +00:00
|
|
|
d->socket_notifiers_.take(fd)->setEnabled(false);
|
2006-10-12 14:10:13 +00:00
|
|
|
}
|
|
|
|
|
2007-08-27 06:35:24 +00:00
|
|
|
|
|
|
|
void GuiApplication::commitData(QSessionManager & sm)
|
|
|
|
{
|
|
|
|
/// The implementation is required to avoid an application exit
|
|
|
|
/// when session state save is triggered by session manager.
|
|
|
|
/// The default implementation sends a close event to all
|
|
|
|
/// visible top level widgets when session managment allows
|
|
|
|
/// interaction.
|
2008-02-27 10:35:28 +00:00
|
|
|
/// We are changing that to close all wiew one by one.
|
|
|
|
/// FIXME: verify if the default implementation is enough now.
|
2010-11-18 22:14:49 +00:00
|
|
|
#ifdef QT_NO_SESSIONMANAGER
|
2010-11-20 01:43:18 +00:00
|
|
|
#warning Qt is compiled without session manager
|
2010-11-18 22:14:49 +00:00
|
|
|
(void) sm;
|
|
|
|
#else
|
|
|
|
if (sm.allowsInteraction() && !closeAllViews())
|
|
|
|
sm.cancel();
|
|
|
|
#endif
|
2007-08-27 06:35:24 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2008-05-23 10:54:34 +00:00
|
|
|
void GuiApplication::unregisterView(GuiView * gv)
|
2007-11-17 20:47:50 +00:00
|
|
|
{
|
2008-05-23 10:54:34 +00:00
|
|
|
LASSERT(d->views_[gv->id()] == gv, /**/);
|
2008-05-23 18:09:40 +00:00
|
|
|
d->views_.remove(gv->id());
|
2009-09-22 21:25:32 +00:00
|
|
|
if (current_view_ == gv)
|
2008-05-23 11:08:12 +00:00
|
|
|
current_view_ = 0;
|
2007-11-17 20:47:50 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
bool GuiApplication::closeAllViews()
|
|
|
|
{
|
2008-05-23 08:43:07 +00:00
|
|
|
if (d->views_.empty())
|
2007-11-17 20:47:50 +00:00
|
|
|
return true;
|
|
|
|
|
2009-05-09 19:59:53 +00:00
|
|
|
// When a view/window was closed before without quitting LyX, there
|
|
|
|
// are already entries in the lastOpened list.
|
|
|
|
theSession().lastOpened().clear();
|
|
|
|
|
2008-05-23 18:09:40 +00:00
|
|
|
QList<GuiView *> views = d->views_.values();
|
|
|
|
foreach (GuiView * view, views) {
|
2010-06-07 22:07:38 +00:00
|
|
|
if (!view->closeScheduled())
|
2008-02-27 10:35:28 +00:00
|
|
|
return false;
|
2007-11-17 20:47:50 +00:00
|
|
|
}
|
|
|
|
|
2008-05-23 08:43:07 +00:00
|
|
|
d->views_.clear();
|
2007-11-17 20:47:50 +00:00
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2007-11-19 20:56:05 +00:00
|
|
|
GuiView & GuiApplication::view(int id) const
|
2007-11-17 20:47:50 +00:00
|
|
|
{
|
2008-05-23 18:09:40 +00:00
|
|
|
LASSERT(d->views_.contains(id), /**/);
|
|
|
|
return *d->views_.value(id);
|
2007-11-17 20:47:50 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
void GuiApplication::hideDialogs(string const & name, Inset * inset) const
|
|
|
|
{
|
2008-05-23 18:09:40 +00:00
|
|
|
QList<GuiView *> views = d->views_.values();
|
|
|
|
foreach (GuiView * view, views)
|
|
|
|
view->hideDialog(name, inset);
|
2007-11-17 20:47:50 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
Buffer const * GuiApplication::updateInset(Inset const * inset) const
|
|
|
|
{
|
|
|
|
Buffer const * buffer_ = 0;
|
2008-05-23 18:09:40 +00:00
|
|
|
QHash<int, GuiView *>::iterator end = d->views_.end();
|
|
|
|
for (QHash<int, GuiView *>::iterator it = d->views_.begin(); it != end; ++it) {
|
|
|
|
if (Buffer const * ptr = (*it)->updateInset(inset))
|
2007-11-17 20:47:50 +00:00
|
|
|
buffer_ = ptr;
|
|
|
|
}
|
|
|
|
return buffer_;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2008-03-06 21:50:27 +00:00
|
|
|
bool GuiApplication::searchMenu(FuncRequest const & func,
|
2008-05-24 10:15:52 +00:00
|
|
|
docstring_list & names) const
|
2008-03-06 21:50:27 +00:00
|
|
|
{
|
2008-05-24 09:51:17 +00:00
|
|
|
return d->menus_.searchMenu(func, names);
|
2008-03-06 21:50:27 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2011-01-16 20:38:08 +00:00
|
|
|
// Ensure that a file is read only once (prevents include loops)
|
|
|
|
static QStringList uifiles;
|
|
|
|
// store which ui files define Toolbars
|
|
|
|
static QStringList toolbar_uifiles;
|
|
|
|
|
|
|
|
|
|
|
|
GuiApplication::ReturnValues GuiApplication::readUIFile(FileName ui_path)
|
|
|
|
{
|
|
|
|
enum {
|
|
|
|
ui_menuset = 1,
|
|
|
|
ui_toolbars,
|
|
|
|
ui_toolbarset,
|
|
|
|
ui_include,
|
2011-01-18 15:09:43 +00:00
|
|
|
ui_format,
|
2011-01-16 20:38:08 +00:00
|
|
|
ui_last
|
|
|
|
};
|
|
|
|
|
|
|
|
LexerKeyword uitags[] = {
|
2011-01-18 15:09:43 +00:00
|
|
|
{ "format", ui_format },
|
2011-01-16 20:38:08 +00:00
|
|
|
{ "include", ui_include },
|
|
|
|
{ "menuset", ui_menuset },
|
|
|
|
{ "toolbars", ui_toolbars },
|
|
|
|
{ "toolbarset", ui_toolbarset }
|
|
|
|
};
|
|
|
|
|
|
|
|
Lexer lex(uitags);
|
|
|
|
lex.setFile(ui_path);
|
|
|
|
if (!lex.isOK()) {
|
|
|
|
lyxerr << "Unable to set LyXLeX for ui file: " << ui_path
|
|
|
|
<< endl;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (lyxerr.debugging(Debug::PARSER))
|
|
|
|
lex.printTable(lyxerr);
|
|
|
|
|
|
|
|
bool error = false;
|
2011-01-18 15:09:43 +00:00
|
|
|
// format before introduction of format tag
|
|
|
|
unsigned int format = 0;
|
2011-01-16 20:38:08 +00:00
|
|
|
while (lex.isOK()) {
|
2011-01-18 15:09:43 +00:00
|
|
|
int const status = lex.lex();
|
|
|
|
|
|
|
|
// we have to do this check here, outside the switch,
|
|
|
|
// because otherwise we would start reading include files,
|
|
|
|
// e.g., if the first tag we hit was an include tag.
|
|
|
|
if (status == ui_format)
|
|
|
|
if (lex.next()) {
|
|
|
|
format = lex.getInteger();
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
|
|
|
|
// this will trigger unless the first tag we hit is a format
|
|
|
|
// tag, with the right format.
|
|
|
|
if (format != LFUN_FORMAT)
|
|
|
|
return FormatMismatch;
|
|
|
|
|
|
|
|
switch (status) {
|
|
|
|
case Lexer::LEX_FEOF:
|
|
|
|
continue;
|
|
|
|
|
2011-01-16 20:38:08 +00:00
|
|
|
case ui_include: {
|
|
|
|
lex.next(true);
|
|
|
|
QString const file = toqstr(lex.getString());
|
2011-01-18 15:09:43 +00:00
|
|
|
bool const success = readUIFile(file, true);
|
|
|
|
if (!success) {
|
|
|
|
LYXERR0("Failed to read inlcuded file: " << fromqstr(file));
|
2011-01-16 20:38:08 +00:00
|
|
|
return ReadError;
|
2011-01-18 15:09:43 +00:00
|
|
|
}
|
2011-01-16 20:38:08 +00:00
|
|
|
break;
|
|
|
|
}
|
2011-01-18 15:09:43 +00:00
|
|
|
|
2011-01-16 20:38:08 +00:00
|
|
|
case ui_menuset:
|
|
|
|
d->menus_.read(lex);
|
|
|
|
break;
|
|
|
|
|
|
|
|
case ui_toolbarset:
|
|
|
|
d->toolbars_.readToolbars(lex);
|
|
|
|
break;
|
|
|
|
|
|
|
|
case ui_toolbars:
|
|
|
|
d->toolbars_.readToolbarSettings(lex);
|
|
|
|
toolbar_uifiles.push_back(toqstr(ui_path.absFileName()));
|
|
|
|
break;
|
|
|
|
|
|
|
|
default:
|
|
|
|
if (!rtrim(lex.getString()).empty())
|
|
|
|
lex.printError("LyX::ReadUIFile: "
|
2011-01-18 15:09:43 +00:00
|
|
|
"Unknown menu tag: `$$Token'");
|
|
|
|
else
|
|
|
|
LYXERR0("Error with status: " << status);
|
2011-01-16 20:38:08 +00:00
|
|
|
error = true;
|
|
|
|
break;
|
|
|
|
}
|
2011-01-18 15:09:43 +00:00
|
|
|
|
2011-01-16 20:38:08 +00:00
|
|
|
}
|
|
|
|
return (error ? ReadError : ReadOK);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2008-05-24 09:51:17 +00:00
|
|
|
bool GuiApplication::readUIFile(QString const & name, bool include)
|
2008-05-24 09:28:05 +00:00
|
|
|
{
|
|
|
|
LYXERR(Debug::INIT, "About to read " << name << "...");
|
|
|
|
|
|
|
|
FileName ui_path;
|
|
|
|
if (include) {
|
2008-05-24 09:51:17 +00:00
|
|
|
ui_path = libFileSearch("ui", name, "inc");
|
2008-05-24 09:28:05 +00:00
|
|
|
if (ui_path.empty())
|
2008-05-24 09:51:17 +00:00
|
|
|
ui_path = libFileSearch("ui", changeExtension(name, "inc"));
|
|
|
|
} else {
|
|
|
|
ui_path = libFileSearch("ui", name, "ui");
|
2008-05-24 09:28:05 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
if (ui_path.empty()) {
|
2009-07-17 21:41:04 +00:00
|
|
|
static const QString defaultUIFile = "default";
|
2008-05-24 09:28:05 +00:00
|
|
|
LYXERR(Debug::INIT, "Could not find " << name);
|
2009-07-16 22:24:39 +00:00
|
|
|
if (include) {
|
|
|
|
Alert::warning(_("Could not find UI definition file"),
|
2009-07-17 21:36:34 +00:00
|
|
|
bformat(_("Error while reading the included file\n%1$s\n"
|
2009-07-16 22:24:39 +00:00
|
|
|
"Please check your installation."), qstring_to_ucs4(name)));
|
|
|
|
return false;
|
|
|
|
}
|
2009-07-17 21:41:04 +00:00
|
|
|
if (name == defaultUIFile) {
|
2009-07-16 22:24:39 +00:00
|
|
|
LYXERR(Debug::INIT, "Could not find default UI file!!");
|
|
|
|
Alert::warning(_("Could not find default UI file"),
|
2009-07-16 22:29:05 +00:00
|
|
|
_("LyX could not find the default UI file!\n"
|
2009-07-17 21:36:34 +00:00
|
|
|
"Please check your installation."));
|
2009-07-16 22:24:39 +00:00
|
|
|
return false;
|
|
|
|
}
|
2009-07-17 21:36:34 +00:00
|
|
|
Alert::warning(_("Could not find UI definition file"),
|
|
|
|
bformat(_("Error while reading the configuration file\n%1$s\n"
|
|
|
|
"Falling back to default.\n"
|
|
|
|
"Please look under Tools>Preferences>User Interface and\n"
|
|
|
|
"check which User Interface file you are using."), qstring_to_ucs4(name)));
|
2009-07-17 21:41:04 +00:00
|
|
|
return readUIFile(defaultUIFile, false);
|
2008-05-24 09:28:05 +00:00
|
|
|
}
|
|
|
|
|
2010-04-21 01:19:09 +00:00
|
|
|
QString const uifile = toqstr(ui_path.absFileName());
|
2008-09-21 21:28:37 +00:00
|
|
|
if (uifiles.contains(uifile)) {
|
|
|
|
if (!include) {
|
|
|
|
// We are reading again the top uifile so reset the safeguard:
|
|
|
|
uifiles.clear();
|
|
|
|
d->menus_.reset();
|
|
|
|
d->toolbars_.reset();
|
|
|
|
} else {
|
|
|
|
LYXERR(Debug::INIT, "UI file '" << name << "' has been read already. "
|
|
|
|
<< "Is this an include loop?");
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
uifiles.push_back(uifile);
|
2008-05-24 09:28:05 +00:00
|
|
|
|
|
|
|
LYXERR(Debug::INIT, "Found " << name << " in " << ui_path);
|
2008-09-21 21:28:37 +00:00
|
|
|
|
2011-01-18 15:09:43 +00:00
|
|
|
ReturnValues retval = readUIFile(ui_path);
|
|
|
|
|
|
|
|
if (retval == FormatMismatch) {
|
|
|
|
LYXERR(Debug::FILES, "Converting ui file to format " << LFUN_FORMAT);
|
|
|
|
FileName const tempfile = FileName::tempName("convert_ui");
|
|
|
|
bool const success = prefs2prefs(ui_path, tempfile, true);
|
|
|
|
if (!success) {
|
|
|
|
LYXERR0("Unable to convert " << ui_path.absFileName() <<
|
|
|
|
" to format " << LFUN_FORMAT << ".");
|
|
|
|
} else {
|
|
|
|
retval = readUIFile(tempfile);
|
|
|
|
tempfile.removeFile();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if (retval != ReadOK) {
|
|
|
|
LYXERR0("Unable to read UI file: " << ui_path.absFileName());
|
|
|
|
return false;
|
|
|
|
}
|
2008-09-21 21:28:37 +00:00
|
|
|
|
|
|
|
if (include)
|
|
|
|
return true;
|
|
|
|
|
|
|
|
QSettings settings;
|
|
|
|
settings.beginGroup("ui_files");
|
|
|
|
bool touched = false;
|
|
|
|
for (int i = 0; i != uifiles.size(); ++i) {
|
|
|
|
QFileInfo fi(uifiles[i]);
|
|
|
|
QDateTime const date_value = fi.lastModified();
|
|
|
|
QString const name_key = QString::number(i);
|
2009-06-30 11:00:16 +00:00
|
|
|
// if an ui file which defines Toolbars has changed,
|
|
|
|
// we have to reset the settings
|
|
|
|
if (toolbar_uifiles.contains(uifiles[i])
|
|
|
|
&& (!settings.contains(name_key)
|
2008-09-21 21:28:37 +00:00
|
|
|
|| settings.value(name_key).toString() != uifiles[i]
|
2009-06-30 11:00:16 +00:00
|
|
|
|| settings.value(name_key + "/date").toDateTime() != date_value)) {
|
2008-09-21 21:28:37 +00:00
|
|
|
touched = true;
|
|
|
|
settings.setValue(name_key, uifiles[i]);
|
|
|
|
settings.setValue(name_key + "/date", date_value);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
settings.endGroup();
|
|
|
|
if (touched)
|
|
|
|
settings.remove("views");
|
|
|
|
|
2008-05-24 09:28:05 +00:00
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2008-03-14 23:25:11 +00:00
|
|
|
void GuiApplication::onLastWindowClosed()
|
|
|
|
{
|
2008-05-23 07:52:39 +00:00
|
|
|
if (d->global_menubar_)
|
|
|
|
d->global_menubar_->grabKeyboard();
|
2008-03-14 23:25:11 +00:00
|
|
|
}
|
|
|
|
|
2008-03-27 00:07:54 +00:00
|
|
|
|
2006-06-26 17:18:28 +00:00
|
|
|
////////////////////////////////////////////////////////////////////////
|
2008-03-27 00:07:54 +00:00
|
|
|
//
|
2006-06-26 17:18:28 +00:00
|
|
|
// X11 specific stuff goes here...
|
2008-03-27 00:07:54 +00:00
|
|
|
|
2006-06-26 17:18:28 +00:00
|
|
|
#ifdef Q_WS_X11
|
2006-09-22 09:47:39 +00:00
|
|
|
bool GuiApplication::x11EventFilter(XEvent * xev)
|
2006-06-26 17:18:28 +00:00
|
|
|
{
|
2007-11-18 20:36:52 +00:00
|
|
|
if (!current_view_)
|
2006-12-04 13:52:02 +00:00
|
|
|
return false;
|
|
|
|
|
2006-11-07 18:17:15 +00:00
|
|
|
switch (xev->type) {
|
2007-01-04 15:36:29 +00:00
|
|
|
case SelectionRequest: {
|
2007-01-05 10:11:21 +00:00
|
|
|
if (xev->xselectionrequest.selection != XA_PRIMARY)
|
|
|
|
break;
|
2008-07-14 23:47:54 +00:00
|
|
|
LYXERR(Debug::SELECTION, "X requested selection.");
|
2009-09-05 15:40:07 +00:00
|
|
|
BufferView * bv = current_view_->currentBufferView();
|
2006-11-07 17:19:33 +00:00
|
|
|
if (bv) {
|
2007-01-05 10:11:21 +00:00
|
|
|
docstring const sel = bv->requestSelection();
|
2006-09-17 08:35:12 +00:00
|
|
|
if (!sel.empty())
|
2008-05-23 09:32:49 +00:00
|
|
|
d->selection_.put(sel);
|
2006-09-17 08:35:12 +00:00
|
|
|
}
|
2006-06-26 17:18:28 +00:00
|
|
|
break;
|
2007-01-04 15:36:29 +00:00
|
|
|
}
|
|
|
|
case SelectionClear: {
|
2007-01-05 10:11:21 +00:00
|
|
|
if (xev->xselectionclear.selection != XA_PRIMARY)
|
|
|
|
break;
|
2008-07-14 23:47:54 +00:00
|
|
|
LYXERR(Debug::SELECTION, "Lost selection.");
|
2009-09-05 15:40:07 +00:00
|
|
|
BufferView * bv = current_view_->currentBufferView();
|
2006-11-07 17:19:33 +00:00
|
|
|
if (bv)
|
|
|
|
bv->clearSelection();
|
2006-06-26 17:18:28 +00:00
|
|
|
break;
|
|
|
|
}
|
2007-01-04 15:36:29 +00:00
|
|
|
}
|
2006-06-26 17:18:28 +00:00
|
|
|
return false;
|
|
|
|
}
|
|
|
|
#endif
|
|
|
|
|
|
|
|
} // namespace frontend
|
2007-11-17 22:11:11 +00:00
|
|
|
|
|
|
|
|
2008-03-27 00:07:54 +00:00
|
|
|
void hideDialogs(std::string const & name, Inset * inset)
|
|
|
|
{
|
|
|
|
if (theApp())
|
2010-02-09 17:25:44 +00:00
|
|
|
frontend::guiApp->hideDialogs(name, inset);
|
2008-03-27 00:07:54 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2007-11-17 22:11:11 +00:00
|
|
|
////////////////////////////////////////////////////////////////////
|
|
|
|
//
|
|
|
|
// Font stuff
|
|
|
|
//
|
|
|
|
////////////////////////////////////////////////////////////////////
|
|
|
|
|
|
|
|
frontend::FontLoader & theFontLoader()
|
|
|
|
{
|
2008-04-10 21:49:34 +00:00
|
|
|
LASSERT(frontend::guiApp, /**/);
|
2007-11-18 20:36:52 +00:00
|
|
|
return frontend::guiApp->fontLoader();
|
2007-11-17 22:11:11 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
frontend::FontMetrics const & theFontMetrics(Font const & f)
|
|
|
|
{
|
|
|
|
return theFontMetrics(f.fontInfo());
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
frontend::FontMetrics const & theFontMetrics(FontInfo const & f)
|
|
|
|
{
|
2008-04-10 21:49:34 +00:00
|
|
|
LASSERT(frontend::guiApp, /**/);
|
2007-11-18 20:36:52 +00:00
|
|
|
return frontend::guiApp->fontLoader().metrics(f);
|
2007-11-17 22:11:11 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2008-03-27 00:07:54 +00:00
|
|
|
////////////////////////////////////////////////////////////////////
|
|
|
|
//
|
|
|
|
// Misc stuff
|
|
|
|
//
|
|
|
|
////////////////////////////////////////////////////////////////////
|
|
|
|
|
2007-11-17 22:11:11 +00:00
|
|
|
frontend::Clipboard & theClipboard()
|
|
|
|
{
|
2008-04-10 21:49:34 +00:00
|
|
|
LASSERT(frontend::guiApp, /**/);
|
2007-11-17 22:11:11 +00:00
|
|
|
return frontend::guiApp->clipboard();
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
frontend::Selection & theSelection()
|
|
|
|
{
|
2008-04-10 21:49:34 +00:00
|
|
|
LASSERT(frontend::guiApp, /**/);
|
2007-11-17 22:11:11 +00:00
|
|
|
return frontend::guiApp->selection();
|
|
|
|
}
|
|
|
|
|
2008-11-16 12:22:54 +00:00
|
|
|
|
2006-06-26 17:18:28 +00:00
|
|
|
} // namespace lyx
|
2006-10-23 16:29:24 +00:00
|
|
|
|
2008-11-14 14:28:50 +00:00
|
|
|
#include "moc_GuiApplication.cpp"
|