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
|
|
|
|
2016-06-05 19:35:35 +00:00
|
|
|
#include "ToolTipFormatter.h"
|
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"
|
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"
|
2014-08-06 15:43:22 +00:00
|
|
|
#include "BufferParams.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"
|
2016-06-04 07:09:33 +00:00
|
|
|
#include "Converter.h"
|
2014-08-06 15:43:22 +00:00
|
|
|
#include "CutAndPaste.h"
|
|
|
|
#include "ErrorList.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"
|
2012-07-20 08:50:29 +00:00
|
|
|
#include "GuiWorkArea.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"
|
2011-11-06 17:03:59 +00:00
|
|
|
#include "LaTeXPackages.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
|
|
|
|
2014-08-06 15:43:22 +00:00
|
|
|
#include "insets/InsetText.h"
|
|
|
|
|
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-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
|
2015-05-05 12:23:24 +00:00
|
|
|
#include "support/textutils.h"
|
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"
|
2014-06-09 11:05:50 +00:00
|
|
|
#include "support/TempFile.h"
|
2008-02-18 07:14:42 +00:00
|
|
|
|
2014-08-25 18:08:59 +00:00
|
|
|
#ifdef Q_OS_MAC
|
2012-08-19 20:27:20 +00:00
|
|
|
#include "support/AppleScript.h"
|
2008-05-23 07:52:39 +00:00
|
|
|
#include "support/linkback/LinkBackProxy.h"
|
|
|
|
#endif
|
|
|
|
|
2008-11-15 16:29:58 +00:00
|
|
|
#include <queue>
|
|
|
|
|
2016-04-15 09:49:04 +00:00
|
|
|
#include <QFontDatabase>
|
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>
|
2014-08-25 16:35:15 +00:00
|
|
|
#include <QDesktopWidget>
|
2008-06-05 13:27:37 +00:00
|
|
|
#include <QDir>
|
2012-03-06 23:21:12 +00:00
|
|
|
#include <QEvent>
|
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>
|
2012-03-06 23:21:12 +00:00
|
|
|
#include <QKeyEvent>
|
2006-09-22 09:47:39 +00:00
|
|
|
#include <QLocale>
|
|
|
|
#include <QLibraryInfo>
|
2008-06-05 08:31:22 +00:00
|
|
|
#include <QList>
|
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>
|
2012-03-06 23:21:12 +00:00
|
|
|
#include <QShowEvent>
|
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-03-18 12:42:34 +00:00
|
|
|
#include <QThreadPool>
|
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>
|
2016-07-10 17:31:32 +00:00
|
|
|
#include <QX11Info>
|
2007-11-11 12:14:06 +00:00
|
|
|
#undef CursorShape
|
|
|
|
#undef None
|
2015-04-07 10:59:41 +00:00
|
|
|
#elif defined(QPA_XCB)
|
|
|
|
#include <xcb/xcb.h>
|
2016-07-10 17:31:32 +00:00
|
|
|
#ifdef HAVE_QT5_X11_EXTRAS
|
|
|
|
#include <QtX11Extras/QX11Info>
|
|
|
|
#endif
|
2006-06-26 17:18:28 +00:00
|
|
|
#endif
|
|
|
|
|
2014-12-26 15:53:31 +00:00
|
|
|
#if (QT_VERSION < 0x050000) || (QT_VERSION >= 0x050400)
|
|
|
|
#if defined(Q_OS_WIN) || defined(Q_CYGWIN_WIN)
|
|
|
|
#if (QT_VERSION < 0x050000)
|
2008-05-23 07:52:39 +00:00
|
|
|
#include <QWindowsMime>
|
2014-12-26 15:53:31 +00:00
|
|
|
#define QWINDOWSMIME QWindowsMime
|
|
|
|
#else
|
|
|
|
#include <QWinMime>
|
|
|
|
#define QWINDOWSMIME QWinMime
|
|
|
|
#endif
|
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>
|
2014-12-26 15:53:31 +00:00
|
|
|
#endif
|
|
|
|
#endif
|
2008-05-23 07:52:39 +00:00
|
|
|
|
2014-08-25 18:08:59 +00:00
|
|
|
#ifdef Q_OS_MAC
|
2013-02-03 11:23:31 +00:00
|
|
|
#include <QMacPasteboardMime>
|
2014-08-25 18:08:59 +00:00
|
|
|
#endif // Q_OS_MAC
|
2013-02-03 11:23:31 +00:00
|
|
|
|
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
|
|
|
{
|
2015-01-11 18:36:41 +00:00
|
|
|
#if !defined(Q_WS_X11) && !defined(QPA_XCB)
|
2008-10-09 07:19:34 +00:00
|
|
|
// 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
|
|
|
}
|
|
|
|
|
2013-05-08 16:50:38 +00:00
|
|
|
|
|
|
|
void setLocale()
|
|
|
|
{
|
|
|
|
QLocale theLocale;
|
2015-03-17 10:34:28 +00:00
|
|
|
string code;
|
2013-05-08 16:50:38 +00:00
|
|
|
if (lyxrc.gui_language == "auto") {
|
|
|
|
theLocale = QLocale::system();
|
2015-03-17 10:34:28 +00:00
|
|
|
code = fromqstr(theLocale.name());
|
2013-05-08 16:50:38 +00:00
|
|
|
} else {
|
|
|
|
Language const * l = languages.getLanguage(lyxrc.gui_language);
|
2015-04-15 13:27:05 +00:00
|
|
|
code = l ? l->code() : "C";
|
2013-05-08 16:50:38 +00:00
|
|
|
theLocale = QLocale(toqstr(code));
|
|
|
|
}
|
2015-04-15 13:27:05 +00:00
|
|
|
// Qt tries to outsmart us and transforms en_US to C.
|
|
|
|
Messages::guiLanguage((code == "C") ? "en_US" : code);
|
2013-05-08 16:50:38 +00:00
|
|
|
QLocale::setDefault(theLocale);
|
2013-06-03 15:58:06 +00:00
|
|
|
setlocale(LC_NUMERIC, "C");
|
2013-05-08 16:50:38 +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!");
|
|
|
|
|
2016-06-02 20:31:27 +00:00
|
|
|
bool jpeg_found = false;
|
|
|
|
bool jpg_found = false;
|
2008-06-06 12:29:58 +00:00
|
|
|
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
|
2016-06-02 20:31:27 +00:00
|
|
|
if (ext == "jpeg") {
|
|
|
|
jpeg_found = true;
|
|
|
|
if (jpg_found)
|
|
|
|
continue;
|
2008-06-06 12:29:58 +00:00
|
|
|
ext = "jpg";
|
2016-06-02 20:31:27 +00:00
|
|
|
}
|
|
|
|
else if (ext == "jpg") {
|
|
|
|
jpg_found = true;
|
|
|
|
if (jpeg_found)
|
|
|
|
continue;
|
|
|
|
}
|
2016-06-04 07:09:33 +00:00
|
|
|
else if (lyxrc.use_converter_cache &&
|
|
|
|
(ext == "svg" || ext == "svgz") &&
|
|
|
|
theConverters().isReachable("svg", "png"))
|
|
|
|
// Qt only supports SVG 1.2 tiny. See #9778. We prefer displaying
|
|
|
|
// the SVG as in the output. However we require that the converter
|
|
|
|
// cache is enabled since this is expensive. We also require that
|
|
|
|
// an explicit svg->png converter is defined, since the default
|
|
|
|
// converter could produce bad quality as well. This assumes that
|
|
|
|
// png can always be loaded.
|
|
|
|
continue;
|
2008-06-06 12:29:58 +00:00
|
|
|
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 {
|
|
|
|
|
2015-12-07 18:14:44 +00:00
|
|
|
struct ImgMap {
|
2008-06-05 08:31:22 +00:00
|
|
|
QString key;
|
|
|
|
QString value;
|
|
|
|
};
|
|
|
|
|
|
|
|
|
2015-12-07 18:14:44 +00:00
|
|
|
bool operator<(ImgMap const & lhs, ImgMap const & rhs)
|
2008-06-05 08:31:22 +00:00
|
|
|
{
|
|
|
|
return lhs.key < rhs.key;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
class CompareKey {
|
|
|
|
public:
|
|
|
|
CompareKey(QString const & name) : name_(name) {}
|
2015-12-07 18:14:44 +00:00
|
|
|
bool operator()(ImgMap const & other) const { return other.key == name_; }
|
2008-06-05 08:31:22 +00:00
|
|
|
private:
|
|
|
|
QString const name_;
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
// this must be sorted alphabetically
|
|
|
|
// Upper case comes before lower case
|
2012-12-31 16:17:45 +00:00
|
|
|
// Please don't change the formatting, this list is parsed by
|
|
|
|
// development/tools/generate_symbols_images.py.
|
2015-12-07 18:14:44 +00:00
|
|
|
ImgMap sorted_img_map[] = {
|
2012-12-18 21:20:32 +00:00
|
|
|
{ "Arrownot", "arrownot2"},
|
2012-12-31 16:17:45 +00:00
|
|
|
{ "Arrowvert", "arrowvert2"},
|
|
|
|
{ "Bowtie", "bowtie2" },
|
|
|
|
{ "Box", "box2" },
|
2008-06-05 08:31:22 +00:00
|
|
|
{ "Bumpeq", "bumpeq2" },
|
2013-01-10 20:08:39 +00:00
|
|
|
{ "CIRCLE", "circle3" },
|
2008-06-05 08:31:22 +00:00
|
|
|
{ "Cap", "cap2" },
|
2013-01-10 20:08:39 +00:00
|
|
|
{ "CheckedBox", "checkedbox2" },
|
2012-12-31 16:17:45 +00:00
|
|
|
{ "Circle", "circle2" },
|
|
|
|
{ "Colonapprox", "colonapprox2" },
|
|
|
|
{ "Coloneq", "coloneq2" },
|
|
|
|
{ "Coloneqq", "coloneqq2" },
|
|
|
|
{ "Colonsim", "colonsim2" },
|
2008-06-05 08:31:22 +00:00
|
|
|
{ "Cup", "cup2" },
|
2013-01-10 20:08:39 +00:00
|
|
|
{ "DOWNarrow", "downarrow3" },
|
2008-06-05 08:31:22 +00:00
|
|
|
{ "Delta", "delta2" },
|
2010-01-23 09:59:48 +00:00
|
|
|
{ "Diamond", "diamond2" },
|
2012-12-31 16:17:45 +00:00
|
|
|
{ "Doteq", "doteq2" },
|
2008-06-05 08:31:22 +00:00
|
|
|
{ "Downarrow", "downarrow2" },
|
2012-12-31 16:17:45 +00:00
|
|
|
{ "Eqcolon", "eqcolon2" },
|
|
|
|
{ "Eqqcolon", "eqqcolon2" },
|
2008-06-05 08:31:22 +00:00
|
|
|
{ "Gamma", "gamma2" },
|
2013-01-10 20:08:39 +00:00
|
|
|
{ "Join", "join2" },
|
|
|
|
{ "LEFTCIRCLE", "leftcircle3" },
|
|
|
|
{ "LEFTarrow", "leftarrow3" },
|
|
|
|
{ "LEFTcircle", "leftcircle4" },
|
2012-12-31 16:17:45 +00:00
|
|
|
{ "LHD", "lhd2" },
|
2008-06-05 08:31:22 +00:00
|
|
|
{ "Lambda", "lambda2" },
|
2012-12-18 21:20:32 +00:00
|
|
|
{ "Lbag", "lbag2"},
|
2008-06-05 08:31:22 +00:00
|
|
|
{ "Leftarrow", "leftarrow2" },
|
2012-12-31 16:17:45 +00:00
|
|
|
{ "Leftcircle", "leftcircle2" },
|
2008-06-05 08:31:22 +00:00
|
|
|
{ "Leftrightarrow", "leftrightarrow2" },
|
2012-12-18 21:20:32 +00:00
|
|
|
{ "Longarrownot", "longarrownot2"},
|
2008-06-05 08:31:22 +00:00
|
|
|
{ "Longleftarrow", "longleftarrow2" },
|
|
|
|
{ "Longleftrightarrow", "longleftrightarrow2" },
|
2012-12-18 21:20:32 +00:00
|
|
|
{ "Longmapsfrom", "longmapsfrom2"},
|
|
|
|
{ "Longmapsto", "longmapsto2"},
|
2008-06-05 08:31:22 +00:00
|
|
|
{ "Longrightarrow", "longrightarrow2" },
|
2012-12-18 21:20:32 +00:00
|
|
|
{ "Mapsfrom", "mapsfrom2"},
|
|
|
|
{ "Mapsfromchar", "mapsfromchar2"},
|
|
|
|
{ "Mapsto", "mapsto2"},
|
|
|
|
{ "Mapstochar", "mapstochar2"},
|
2008-06-05 08:31:22 +00:00
|
|
|
{ "Omega", "omega2" },
|
|
|
|
{ "Phi", "phi2" },
|
|
|
|
{ "Pi", "pi2" },
|
|
|
|
{ "Psi", "psi2" },
|
2012-12-31 16:17:45 +00:00
|
|
|
{ "RHD", "rhd2" },
|
2013-01-10 20:08:39 +00:00
|
|
|
{ "RIGHTCIRCLE", "rightcircle3" },
|
|
|
|
{ "RIGHTarrow", "rightarrow3" },
|
|
|
|
{ "RIGHTcircle", "rightcircle4" },
|
2012-12-18 21:20:32 +00:00
|
|
|
{ "Rbag", "rbag2"},
|
2008-06-05 08:31:22 +00:00
|
|
|
{ "Rightarrow", "rightarrow2" },
|
2012-12-31 16:17:45 +00:00
|
|
|
{ "Rightcircle", "rightcircle2" },
|
2008-06-05 08:31:22 +00:00
|
|
|
{ "Sigma", "sigma2" },
|
2012-12-31 16:17:45 +00:00
|
|
|
{ "Square", "square2" },
|
2008-06-05 08:31:22 +00:00
|
|
|
{ "Subset", "subset2" },
|
|
|
|
{ "Supset", "supset2" },
|
|
|
|
{ "Theta", "theta2" },
|
2012-12-31 16:17:45 +00:00
|
|
|
{ "Thorn", "thorn2" },
|
2013-01-10 20:08:39 +00:00
|
|
|
{ "UParrow", "uparrow3" },
|
2008-06-05 08:31:22 +00:00
|
|
|
{ "Uparrow", "uparrow2" },
|
|
|
|
{ "Updownarrow", "updownarrow2" },
|
|
|
|
{ "Upsilon", "upsilon2" },
|
|
|
|
{ "Vdash", "vdash3" },
|
|
|
|
{ "Vert", "vert2" },
|
2013-01-10 20:08:39 +00:00
|
|
|
{ "XBox", "xbox3" },
|
|
|
|
{ "Xbox", "xbox2" },
|
2008-06-05 08:31:22 +00:00
|
|
|
{ "Xi", "xi2" },
|
2014-11-16 22:09:28 +00:00
|
|
|
{ "lVert", "vert2" },
|
|
|
|
{ "lvert", "vert" },
|
2008-06-05 08:31:22 +00:00
|
|
|
{ "nLeftarrow", "nleftarrow2" },
|
|
|
|
{ "nLeftrightarrow", "nleftrightarrow2" },
|
|
|
|
{ "nRightarrow", "nrightarrow2" },
|
|
|
|
{ "nVDash", "nvdash3" },
|
2012-12-31 16:17:45 +00:00
|
|
|
{ "nVdash", "nvdash4" },
|
2008-06-05 08:31:22 +00:00
|
|
|
{ "nvDash", "nvdash2" },
|
2014-11-16 22:09:28 +00:00
|
|
|
{ "rVert", "vert2" },
|
|
|
|
{ "rvert", "vert" },
|
2008-06-05 08:31:22 +00:00
|
|
|
{ "textrm \\AA", "textrm_AA"},
|
|
|
|
{ "textrm \\O", "textrm_O"},
|
2012-12-31 16:17:45 +00:00
|
|
|
{ "vDash", "vdash2" },
|
|
|
|
{ "varDelta", "vardelta2" },
|
|
|
|
{ "varGamma", "vargamma2" },
|
|
|
|
{ "varLambda", "varlambda2" },
|
|
|
|
{ "varOmega", "varomega2" },
|
|
|
|
{ "varPhi", "varphi2" },
|
|
|
|
{ "varPi", "varpi2" },
|
|
|
|
{ "varPsi", "varpsi2" },
|
|
|
|
{ "varSigma", "varsigma2" },
|
|
|
|
{ "varTheta", "vartheta2" },
|
|
|
|
{ "varUpsilon", "varupsilon2" },
|
|
|
|
{ "varXi", "varxi2" }
|
2008-06-05 08:31:22 +00:00
|
|
|
};
|
|
|
|
|
2012-12-31 16:17:45 +00:00
|
|
|
|
2015-12-07 18:14:44 +00:00
|
|
|
size_t const nr_sorted_img_map = sizeof(sorted_img_map) / sizeof(ImgMap);
|
2008-06-05 08:31:22 +00:00
|
|
|
|
2012-05-09 09:14:08 +00:00
|
|
|
// This list specifies which system's theme icon is related to which lyx
|
|
|
|
// command. It was based on:
|
|
|
|
// http://standards.freedesktop.org/icon-naming-spec/icon-naming-spec-latest.html
|
|
|
|
// this must be sorted alphabetically
|
|
|
|
// Upper case comes before lower case
|
2015-12-07 18:14:44 +00:00
|
|
|
ImgMap sorted_theme_icon_map[] = {
|
2012-05-09 09:14:08 +00:00
|
|
|
{ "bookmark-goto 0", "go-jump" },
|
|
|
|
{ "buffer-new", "document-new" },
|
|
|
|
{ "buffer-write", "document-save" },
|
|
|
|
{ "buffer-write-as", "document-save-as" },
|
|
|
|
{ "buffer-zoom-in", "zoom-in" },
|
|
|
|
{ "buffer-zoom-out", "zoom-out" },
|
|
|
|
{ "copy", "edit-copy" },
|
|
|
|
{ "cut", "edit-cut" },
|
|
|
|
{ "depth-decrement", "format-indent-less" },
|
|
|
|
{ "depth-increment", "format-indent-more" },
|
|
|
|
{ "dialog-show spellchecker", "tools-check-spelling" },
|
|
|
|
{ "dialog-show-new-inset graphics", "insert-image" },
|
|
|
|
{ "dialog-toggle findreplaceadv", "edit-find-replace" },
|
|
|
|
{ "file-open", "document-open" },
|
|
|
|
{ "font-bold", "format-text-bold" },
|
|
|
|
{ "font-ital", "format-text-italic" },
|
|
|
|
{ "font-strikeout", "format-text-strikethrough" },
|
|
|
|
{ "font-underline", "format-text-underline" },
|
|
|
|
{ "lyx-quit", "application-exit" },
|
|
|
|
{ "paste", "edit-paste" },
|
|
|
|
{ "redo", "edit-redo" },
|
|
|
|
{ "undo", "edit-undo" },
|
|
|
|
{ "window-close", "window-close" },
|
|
|
|
{ "window-new", "window-new" }
|
|
|
|
};
|
|
|
|
|
2015-12-07 18:14:44 +00:00
|
|
|
size_t const nr_sorted_theme_icon_map = sizeof(sorted_theme_icon_map) / sizeof(ImgMap);
|
2012-05-09 09:14:08 +00:00
|
|
|
|
2008-06-05 08:31:22 +00:00
|
|
|
|
2015-12-07 18:14:44 +00:00
|
|
|
QString findImg(QString const & name)
|
2008-06-05 08:31:22 +00:00
|
|
|
{
|
2015-12-07 18:14:44 +00:00
|
|
|
ImgMap const * const begin = sorted_img_map;
|
|
|
|
ImgMap const * const end = begin + nr_sorted_img_map;
|
2013-04-25 21:27:10 +00:00
|
|
|
LATTEST(sorted(begin, end));
|
2008-06-05 08:31:22 +00:00
|
|
|
|
2015-12-07 18:14:44 +00:00
|
|
|
ImgMap const * const it = find_if(begin, end, CompareKey(name));
|
2008-06-05 08:31:22 +00:00
|
|
|
|
2015-12-07 18:14:44 +00:00
|
|
|
QString img_name;
|
2008-06-05 08:31:22 +00:00
|
|
|
if (it != end) {
|
2015-12-07 18:14:44 +00:00
|
|
|
img_name = it->value;
|
2008-06-05 08:31:22 +00:00
|
|
|
} else {
|
2015-12-07 18:14:44 +00:00
|
|
|
img_name = name;
|
|
|
|
img_name.replace('_', "underscore");
|
|
|
|
img_name.replace(' ', '_');
|
2008-06-05 08:31:22 +00:00
|
|
|
|
|
|
|
// This way we can have "math-delim { }" on the toolbar.
|
2015-12-07 18:14:44 +00:00
|
|
|
img_name.replace('(', "lparen");
|
|
|
|
img_name.replace(')', "rparen");
|
|
|
|
img_name.replace('[', "lbracket");
|
|
|
|
img_name.replace(']', "rbracket");
|
|
|
|
img_name.replace('{', "lbrace");
|
|
|
|
img_name.replace('}', "rbrace");
|
|
|
|
img_name.replace('|', "bars");
|
|
|
|
img_name.replace(',', "thinspace");
|
|
|
|
img_name.replace(':', "mediumspace");
|
|
|
|
img_name.replace(';', "thickspace");
|
|
|
|
img_name.replace('!', "negthinspace");
|
2008-06-05 08:31:22 +00:00
|
|
|
}
|
|
|
|
|
2015-12-07 18:14:44 +00:00
|
|
|
LYXERR(Debug::GUI, "findImg(" << name << ")\n"
|
|
|
|
<< "Looking for math icon called \"" << img_name << '"');
|
|
|
|
return img_name;
|
2008-06-05 08:31:22 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
} // namespace anon
|
|
|
|
|
|
|
|
|
2012-05-09 09:14:08 +00:00
|
|
|
QString themeIconName(QString const & action)
|
|
|
|
{
|
2015-12-07 18:14:44 +00:00
|
|
|
ImgMap const * const begin = sorted_theme_icon_map;
|
|
|
|
ImgMap const * const end = begin + nr_sorted_theme_icon_map;
|
2012-05-09 09:14:08 +00:00
|
|
|
LASSERT(sorted(begin, end), /**/);
|
|
|
|
|
2015-12-07 18:14:44 +00:00
|
|
|
ImgMap const * const it = find_if(begin, end, CompareKey(action));
|
2012-05-09 09:14:08 +00:00
|
|
|
|
|
|
|
if (it != end)
|
|
|
|
return it->value;
|
|
|
|
return QString();
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2008-06-05 08:31:22 +00:00
|
|
|
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/";
|
2015-12-07 18:14:44 +00:00
|
|
|
name1 = findImg(toqstr(f.argument()).mid(1));
|
2008-06-05 08:31:22 +00:00
|
|
|
}
|
|
|
|
break;
|
|
|
|
case LFUN_MATH_DELIM:
|
|
|
|
case LFUN_MATH_BIGDELIM:
|
|
|
|
path = "math/";
|
2015-12-07 18:14:44 +00:00
|
|
|
name1 = findImg(toqstr(f.argument()));
|
2008-06-05 08:31:22 +00:00
|
|
|
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);
|
|
|
|
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
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2012-08-21 12:56:34 +00:00
|
|
|
QStringList imagedirs;
|
|
|
|
imagedirs << "images/" << "images/ipa/";
|
2014-10-18 13:50:22 +00:00
|
|
|
search_mode mode = theGuiApp()->imageSearchMode();
|
|
|
|
for (int i = 0; i < imagedirs.size(); ++i) {
|
2012-08-21 12:56:34 +00:00
|
|
|
QString imagedir = imagedirs.at(i) + path;
|
2015-03-12 23:47:21 +00:00
|
|
|
FileName fname = imageLibFileSearch(imagedir, name1, "svgz,png", mode);
|
2012-08-21 12:56:34 +00:00
|
|
|
if (fname.exists())
|
|
|
|
return toqstr(fname.absFileName());
|
2008-06-05 08:31:22 +00:00
|
|
|
|
2015-03-12 23:47:21 +00:00
|
|
|
fname = imageLibFileSearch(imagedir, name2, "svgz,png", mode);
|
2012-08-21 12:56:34 +00:00
|
|
|
if (fname.exists())
|
|
|
|
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();
|
|
|
|
}
|
2015-03-12 23:47:21 +00:00
|
|
|
if (res.exists(name1 + ".svgz"))
|
|
|
|
return path + name1 + ".svgz";
|
|
|
|
else if (res.exists(name1 + ".png"))
|
|
|
|
return path + name1 + ".png";
|
2008-06-05 08:31:22 +00:00
|
|
|
|
2015-03-12 23:47:21 +00:00
|
|
|
if (res.exists(name2 + ".svgz"))
|
|
|
|
return path + name2 + ".svgz";
|
|
|
|
else if (res.exists(name2 + ".png"))
|
|
|
|
return path + name2 + ".png";
|
2008-06-05 08:31:22 +00:00
|
|
|
|
2009-01-05 19:05:46 +00:00
|
|
|
LYXERR(Debug::GUI, "Cannot find icon with filename "
|
2015-03-12 23:47:21 +00:00
|
|
|
<< "\"" << name1 << ".{svgz,png}\""
|
2009-01-05 19:05:46 +00:00
|
|
|
<< " or filename "
|
2015-03-12 23:47:21 +00:00
|
|
|
<< "\"" << name2 << ".{svgz,png}\""
|
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) {
|
2012-08-21 12:56:34 +00:00
|
|
|
QString imagedir = "images/";
|
2015-03-12 23:47:21 +00:00
|
|
|
FileName fname = imageLibFileSearch(imagedir, "unknown", "svgz,png", mode);
|
2009-04-03 17:00:09 +00:00
|
|
|
if (fname.exists())
|
2010-04-21 01:19:09 +00:00
|
|
|
return toqstr(fname.absFileName());
|
2015-12-07 18:14:44 +00:00
|
|
|
return QString(":/images/unknown.svgz");
|
2009-04-03 17:00:09 +00:00
|
|
|
}
|
2008-06-05 08:31:22 +00:00
|
|
|
|
|
|
|
return QString();
|
|
|
|
}
|
|
|
|
|
2015-05-19 20:46:06 +00:00
|
|
|
|
|
|
|
bool getPixmap(QPixmap & pixmap, QString const & path)
|
|
|
|
{
|
2016-05-07 07:56:03 +00:00
|
|
|
return pixmap.load(path);
|
2015-05-19 20:46:06 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2009-04-03 17:00:09 +00:00
|
|
|
QPixmap getPixmap(QString const & path, QString const & name, QString const & ext)
|
|
|
|
{
|
2011-03-25 01:59:34 +00:00
|
|
|
QString imagedir = path;
|
2014-10-18 13:50:22 +00:00
|
|
|
FileName fname = imageLibFileSearch(imagedir, name, ext, theGuiApp()->imageSearchMode());
|
2015-03-12 23:47:21 +00:00
|
|
|
QString fpath = toqstr(fname.absFileName());
|
2015-05-19 20:46:06 +00:00
|
|
|
QPixmap pixmap = QPixmap();
|
2009-04-03 17:00:09 +00:00
|
|
|
|
2015-05-19 20:46:06 +00:00
|
|
|
if (getPixmap(pixmap, fpath)) {
|
2009-04-03 17:00:09 +00:00
|
|
|
return pixmap;
|
2015-05-19 20:46:06 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
QStringList exts = ext.split(",");
|
|
|
|
fpath = ":/" + path + name + ".";
|
|
|
|
for (int i = 0; i < exts.size(); ++i) {
|
|
|
|
if (getPixmap(pixmap, fpath + exts.at(i))) {
|
2015-03-12 23:47:21 +00:00
|
|
|
return pixmap;
|
2015-05-19 20:46:06 +00:00
|
|
|
}
|
2009-04-03 17:00:09 +00:00
|
|
|
}
|
|
|
|
|
2015-03-12 23:47:21 +00:00
|
|
|
bool const list = ext.contains(",");
|
2009-04-03 17:00:09 +00:00
|
|
|
LYXERR0("Cannot load pixmap \""
|
2015-03-12 23:47:21 +00:00
|
|
|
<< path << name << "." << (list ? "{" : "") << ext
|
|
|
|
<< (list ? "}" : "") << "\", please verify resource system!");
|
2009-04-03 17:00:09 +00:00
|
|
|
|
|
|
|
return QPixmap();
|
|
|
|
}
|
2008-06-05 08:31:22 +00:00
|
|
|
|
2015-05-19 20:46:06 +00:00
|
|
|
|
2008-06-05 08:31:22 +00:00
|
|
|
QIcon getIcon(FuncRequest const & f, bool unknown)
|
|
|
|
{
|
2012-05-09 09:14:08 +00:00
|
|
|
#if (QT_VERSION >= 0x040600)
|
2012-05-08 15:55:59 +00:00
|
|
|
if (lyxrc.use_system_theme_icons) {
|
2016-05-23 00:39:46 +00:00
|
|
|
// use the icons from system theme that are available
|
2012-05-08 15:55:59 +00:00
|
|
|
QString action = toqstr(lyxaction.getActionName(f.action()));
|
|
|
|
if (!f.argument().empty())
|
|
|
|
action += " " + toqstr(f.argument());
|
|
|
|
QString const theme_icon = themeIconName(action);
|
2016-05-23 00:39:46 +00:00
|
|
|
if (QIcon::hasThemeIcon(theme_icon)) {
|
|
|
|
QIcon const thmicn = QIcon::fromTheme(theme_icon);
|
|
|
|
if (!thmicn.isNull())
|
|
|
|
return thmicn;
|
|
|
|
}
|
2012-05-08 15:55:59 +00:00
|
|
|
}
|
2012-05-09 09:14:08 +00:00
|
|
|
#endif
|
|
|
|
|
2008-06-05 08:31:22 +00:00
|
|
|
QString icon = iconName(f, unknown);
|
|
|
|
if (icon.isEmpty())
|
|
|
|
return QIcon();
|
|
|
|
|
2008-06-19 14:22:32 +00:00
|
|
|
//LYXERR(Debug::GUI, "Found icon: " << icon);
|
2015-05-19 20:46:06 +00:00
|
|
|
QPixmap pixmap = QPixmap();
|
|
|
|
if (!getPixmap(pixmap,icon)) {
|
2008-06-05 08:31:22 +00:00
|
|
|
LYXERR0("Cannot load icon " << icon << " please verify resource system!");
|
|
|
|
return QIcon();
|
|
|
|
}
|
|
|
|
|
2015-05-19 20:46:06 +00:00
|
|
|
return QIcon(pixmap);
|
2008-06-05 08:31:22 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
////////////////////////////////////////////////////////////////////////
|
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)
|
|
|
|
{}
|
|
|
|
|
2014-08-23 14:01:03 +00:00
|
|
|
#if QT_VERSION >= 0x050000
|
|
|
|
virtual QString translate(const char * /* context */,
|
|
|
|
const char *sourceText,
|
|
|
|
const char * /* disambiguation */ = 0, int /* n */ = -1) const
|
|
|
|
#else
|
2011-01-16 04:02:59 +00:00
|
|
|
QString translate(const char * /*context*/,
|
|
|
|
const char * sourceText,
|
2012-10-14 12:36:18 +00:00
|
|
|
const char * /*comment*/ = 0) const
|
2014-08-23 14:01:03 +00:00
|
|
|
#endif
|
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
|
|
|
|
2014-08-25 18:08:59 +00:00
|
|
|
#ifdef Q_OS_MAC
|
2008-05-23 07:52:39 +00:00
|
|
|
// 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...
|
|
|
|
|
2014-12-26 15:53:31 +00:00
|
|
|
#if (QT_VERSION < 0x050000) || (QT_VERSION >= 0x050400)
|
|
|
|
#if defined(Q_OS_WIN) || defined(Q_CYGWIN_WIN)
|
2008-05-23 07:52:39 +00:00
|
|
|
// 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;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2014-12-26 15:53:31 +00:00
|
|
|
class QWindowsMimeMetafile : public QWINDOWSMIME {
|
2008-05-23 07:52:39 +00:00
|
|
|
public:
|
|
|
|
QWindowsMimeMetafile() {}
|
|
|
|
|
2016-05-08 10:25:09 +00:00
|
|
|
bool canConvertFromMime(FORMATETC const & /*formatetc*/,
|
|
|
|
QMimeData const * /*mimedata*/) const
|
2008-05-23 07:52:39 +00:00
|
|
|
{
|
|
|
|
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;
|
|
|
|
}
|
|
|
|
|
2016-05-08 10:25:09 +00:00
|
|
|
bool convertFromMime(FORMATETC const & /*formatetc*/,
|
|
|
|
const QMimeData * /*mimedata*/, STGMEDIUM * /*pmedium*/) const
|
2008-05-23 07:52:39 +00:00
|
|
|
{
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
QVariant convertToMime(QString const & mimetype, IDataObject * pDataObj,
|
2016-05-08 10:25:09 +00:00
|
|
|
QVariant::Type /*preferredType*/) const
|
2008-05-23 07:52:39 +00:00
|
|
|
{
|
|
|
|
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,
|
2016-05-08 10:25:09 +00:00
|
|
|
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();
|
|
|
|
}
|
|
|
|
};
|
|
|
|
|
2014-12-26 15:53:31 +00:00
|
|
|
#endif
|
|
|
|
#endif
|
2008-05-23 07:52:39 +00:00
|
|
|
|
2012-03-06 23:21:12 +00:00
|
|
|
|
|
|
|
/// Allows to check whether ESC was pressed during a long operation
|
|
|
|
class KeyChecker : public QObject {
|
|
|
|
private:
|
|
|
|
bool pressed_;
|
2012-07-01 07:27:11 +00:00
|
|
|
bool started_;
|
2012-03-06 23:21:12 +00:00
|
|
|
public:
|
2012-09-07 14:33:40 +00:00
|
|
|
KeyChecker() : pressed_(false), started_(false) {}
|
|
|
|
|
2012-03-06 23:21:12 +00:00
|
|
|
void start() {
|
|
|
|
QCoreApplication::instance()->installEventFilter(this);
|
|
|
|
pressed_ = false;
|
2012-07-01 07:27:11 +00:00
|
|
|
started_ = true;
|
2012-03-06 23:21:12 +00:00
|
|
|
}
|
|
|
|
void stop() {
|
|
|
|
QCoreApplication::instance()->removeEventFilter(this);
|
2012-07-01 07:27:11 +00:00
|
|
|
started_ = false;
|
2012-03-06 23:21:12 +00:00
|
|
|
}
|
|
|
|
bool pressed() {
|
|
|
|
QCoreApplication::processEvents();
|
|
|
|
return pressed_;
|
|
|
|
}
|
2012-07-01 07:27:11 +00:00
|
|
|
bool started() const {
|
|
|
|
return started_;
|
|
|
|
}
|
2012-03-06 23:21:12 +00:00
|
|
|
bool eventFilter(QObject *obj, QEvent *event) {
|
|
|
|
LYXERR(Debug::ACTION, "Event Type: " << event->type());
|
|
|
|
switch (event->type()) {
|
|
|
|
case QEvent::Show:
|
|
|
|
case QEvent::Hide:
|
|
|
|
case QEvent::Resize:
|
2014-02-23 12:33:04 +00:00
|
|
|
case QEvent::UpdateRequest:
|
|
|
|
case QEvent::CursorChange:
|
|
|
|
case QEvent::ActionChanged:
|
2014-03-10 08:07:36 +00:00
|
|
|
case QEvent::EnabledChange:
|
|
|
|
case QEvent::SockAct:
|
|
|
|
case QEvent::Timer:
|
|
|
|
case QEvent::Paint:
|
|
|
|
case QEvent::ToolTipChange:
|
|
|
|
case QEvent::LayoutRequest:
|
|
|
|
case QEvent::MetaCall:
|
2012-03-06 23:21:12 +00:00
|
|
|
return QObject::eventFilter(obj, event);
|
|
|
|
default:
|
2014-02-23 12:33:04 +00:00
|
|
|
// FIXME Blocking all these events is a bad idea.
|
2012-03-06 23:21:12 +00:00
|
|
|
QKeyEvent *keyEvent = dynamic_cast<QKeyEvent*>(event);
|
|
|
|
if (keyEvent && keyEvent->key() == Qt::Key_Escape)
|
|
|
|
pressed_ = true;
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
};
|
|
|
|
|
|
|
|
|
2008-05-23 07:52:39 +00:00
|
|
|
////////////////////////////////////////////////////////////////////////
|
|
|
|
// 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
|
|
|
{
|
2014-12-26 15:53:31 +00:00
|
|
|
#if (QT_VERSION < 0x050000) || (QT_VERSION >= 0x050400)
|
|
|
|
#if defined(Q_OS_WIN) || defined(Q_CYGWIN_WIN)
|
2009-04-19 13:43:00 +00:00
|
|
|
/// WMF Mime handler for Windows clipboard.
|
2012-10-26 00:42:27 +00:00
|
|
|
wmf_mime_ = new QWindowsMimeMetafile;
|
2014-12-26 15:53:31 +00:00
|
|
|
#endif
|
2009-04-19 13:43:00 +00:00
|
|
|
#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;
|
|
|
|
|
2015-04-18 17:10:33 +00:00
|
|
|
/// The result of last dispatch action
|
|
|
|
DispatchResult dispatch_result_;
|
|
|
|
|
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.
|
2014-08-24 18:29:52 +00:00
|
|
|
QMenuBar * global_menubar_;
|
2008-05-23 07:52:39 +00:00
|
|
|
|
2014-08-25 18:08:59 +00:00
|
|
|
#ifdef Q_OS_MAC
|
2008-05-23 07:52:39 +00:00
|
|
|
/// Linkback mime handler for MacOSX.
|
|
|
|
QMacPasteboardMimeGraphics mac_pasteboard_mime_;
|
|
|
|
#endif
|
|
|
|
|
2014-12-26 15:53:31 +00:00
|
|
|
#if (QT_VERSION < 0x050000) || (QT_VERSION >= 0x050400)
|
|
|
|
#if defined(Q_OS_WIN) || defined(Q_CYGWIN_WIN)
|
2008-05-23 07:52:39 +00:00
|
|
|
/// WMF Mime handler for Windows clipboard.
|
2009-04-19 13:43:00 +00:00
|
|
|
QWindowsMimeMetafile * wmf_mime_;
|
2014-12-26 15:53:31 +00:00
|
|
|
#endif
|
2008-05-23 07:52:39 +00:00
|
|
|
#endif
|
2012-03-06 23:21:12 +00:00
|
|
|
|
|
|
|
/// Allows to check whether ESC was pressed during a long operation
|
|
|
|
KeyChecker key_checker_;
|
2008-05-23 07:52:39 +00:00
|
|
|
};
|
|
|
|
|
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()
|
|
|
|
{
|
2014-08-25 18:08:59 +00:00
|
|
|
#ifdef Q_OS_MAC
|
2008-05-23 07:52:39 +00:00
|
|
|
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);
|
2017-01-22 00:06:00 +00:00
|
|
|
#if QT_VERSION >= 0x050000
|
|
|
|
QCoreApplication::setAttribute(Qt::AA_UseHighDpiPixmaps);
|
|
|
|
#endif
|
2007-09-27 14:05:05 +00:00
|
|
|
|
2013-05-19 11:59:07 +00:00
|
|
|
qsrand(QDateTime::currentDateTime().toTime_t());
|
|
|
|
|
2008-07-28 11:26:46 +00:00
|
|
|
// Install translator for GUI elements.
|
|
|
|
installTranslator(&d->qt_trans_);
|
|
|
|
|
2015-04-07 10:59:41 +00:00
|
|
|
#ifdef QPA_XCB
|
|
|
|
// Enable reception of XCB events.
|
|
|
|
installNativeEventFilter(this);
|
|
|
|
#endif
|
|
|
|
|
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);
|
|
|
|
*/
|
2014-08-25 18:08:59 +00:00
|
|
|
#ifdef Q_OS_MAC
|
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));
|
2012-08-19 20:27:20 +00:00
|
|
|
///
|
2015-05-17 15:27:12 +00:00
|
|
|
setupApplescript();
|
2008-03-14 23:25:11 +00:00
|
|
|
#endif
|
2011-01-16 04:02:59 +00:00
|
|
|
|
2015-01-11 18:36:41 +00:00
|
|
|
#if defined(Q_WS_X11) || defined(QPA_XCB)
|
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
|
|
|
|
|
|
|
// 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);
|
2016-06-05 19:35:35 +00:00
|
|
|
|
|
|
|
// make sure tooltips are formatted
|
|
|
|
installEventFilter(new ToolTipFormatter(this));
|
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());
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2014-10-12 17:23:13 +00:00
|
|
|
double GuiApplication::pixelRatio() const
|
|
|
|
{
|
2014-10-18 13:50:22 +00:00
|
|
|
#if QT_VERSION >= 0x050000
|
2017-01-22 00:06:00 +00:00
|
|
|
return qt_scale_factor * devicePixelRatio();
|
2014-10-12 17:23:13 +00:00
|
|
|
#else
|
|
|
|
return 1.0;
|
|
|
|
#endif
|
|
|
|
}
|
2014-12-29 22:46:25 +00:00
|
|
|
|
|
|
|
|
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));
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2015-02-14 19:32:25 +00:00
|
|
|
docstring Application::mathIcon(docstring const & c)
|
|
|
|
{
|
2015-12-07 18:14:44 +00:00
|
|
|
return qstring_to_ucs4(findImg(toqstr(c)));
|
2015-02-14 19:32:25 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
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;
|
|
|
|
|
2012-07-20 08:50:29 +00:00
|
|
|
case LFUN_BUFFER_FORALL: {
|
2012-10-15 14:05:20 +00:00
|
|
|
if (theBufferList().empty()) {
|
|
|
|
flag.message(from_utf8(N_("Command not allowed without a buffer open")));
|
|
|
|
flag.setEnabled(false);
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
FuncRequest const cmdToPass = lyxaction.lookupFunc(cmd.getLongArg(0));
|
|
|
|
if (cmdToPass.action() == LFUN_UNKNOWN_ACTION) {
|
|
|
|
flag.message(from_utf8(N_("the <LFUN-COMMAND> argument of buffer-forall is not valid")));
|
2012-07-20 08:50:29 +00:00
|
|
|
flag.setEnabled(false);
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
2014-03-08 11:51:02 +00:00
|
|
|
case LFUN_DIALOG_SHOW: {
|
|
|
|
string const name = cmd.getArg(0);
|
|
|
|
return name == "aboutlyx"
|
|
|
|
|| name == "prefs"
|
|
|
|
|| name == "texinfo"
|
|
|
|
|| name == "progress"
|
|
|
|
|| name == "compare";
|
|
|
|
}
|
2012-07-20 08:50:29 +00:00
|
|
|
|
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
|
|
|
|
2015-04-18 17:10:33 +00:00
|
|
|
DispatchResult const & GuiApplication::dispatch(FuncRequest const & cmd)
|
2010-02-09 16:11:13 +00:00
|
|
|
{
|
2012-06-04 16:02:59 +00:00
|
|
|
Buffer * buffer = 0;
|
|
|
|
if (current_view_ && current_view_->currentBufferView()) {
|
2010-02-09 16:11:13 +00:00
|
|
|
current_view_->currentBufferView()->cursor().saveBeforeDispatchPosXY();
|
2012-06-04 16:02:59 +00:00
|
|
|
buffer = ¤t_view_->currentBufferView()->buffer();
|
|
|
|
if (buffer)
|
|
|
|
buffer->undo().beginUndoGroup();
|
|
|
|
}
|
2010-02-09 16:11:13 +00:00
|
|
|
|
|
|
|
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);
|
2012-04-13 00:57:25 +00:00
|
|
|
updateCurrentView(cmd, dr);
|
2012-06-04 16:02:59 +00:00
|
|
|
|
|
|
|
// the buffer may have been closed by one action
|
|
|
|
if (theBufferList().isLoaded(buffer))
|
|
|
|
buffer->undo().endUndoGroup();
|
2015-04-18 17:10:33 +00:00
|
|
|
|
|
|
|
d->dispatch_result_ = dr;
|
|
|
|
return d->dispatch_result_;
|
2012-04-13 00:57:25 +00:00
|
|
|
}
|
|
|
|
|
2010-02-09 16:11:13 +00:00
|
|
|
|
2012-04-13 00:57:25 +00:00
|
|
|
void GuiApplication::updateCurrentView(FuncRequest const & cmd, DispatchResult & dr)
|
|
|
|
{
|
2010-02-09 16:11:13 +00:00
|
|
|
if (!current_view_)
|
|
|
|
return;
|
|
|
|
|
|
|
|
BufferView * bv = current_view_->currentBufferView();
|
|
|
|
if (bv) {
|
2011-05-11 12:44:39 +00:00
|
|
|
if (dr.needBufferUpdate()) {
|
|
|
|
bv->cursor().clearBufferUpdate();
|
|
|
|
bv->buffer().updateBuffer();
|
2016-01-30 23:14:36 +00:00
|
|
|
} else if (dr.needChangesUpdate()) {
|
|
|
|
// updateBuffer() already updates the change-tracking presence flag
|
|
|
|
bv->buffer().updateChangesPresent();
|
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);
|
2013-04-25 21:27:10 +00:00
|
|
|
LASSERT(!bm.filename.empty(), return);
|
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.
|
2011-01-24 10:13:18 +00:00
|
|
|
BufferView * doc_bv = current_view_ ?
|
|
|
|
current_view_->documentBufferView() : 0;
|
2016-06-12 04:22:09 +00:00
|
|
|
// FIXME It's possible that doc_bv is null!!
|
|
|
|
// See coverity #102061
|
2015-04-22 01:11:17 +00:00
|
|
|
Cursor const old = doc_bv->cursor();
|
2010-10-18 14:20:03 +00:00
|
|
|
if (!doc_bv || doc_bv->buffer().fileName() != tmp.filename) {
|
|
|
|
if (switchToBuffer) {
|
|
|
|
dispatch(FuncRequest(LFUN_BUFFER_SWITCH, file));
|
2011-01-24 10:13:18 +00:00
|
|
|
if (!current_view_)
|
|
|
|
return;
|
2010-10-18 14:20:03 +00:00
|
|
|
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;
|
|
|
|
|
2015-04-22 01:11:17 +00:00
|
|
|
Cursor & cur = doc_bv->cursor();
|
|
|
|
if (cur != old)
|
|
|
|
notifyCursorLeavesOrEnters(old, cur);
|
|
|
|
|
2010-02-09 16:11:13 +00:00
|
|
|
// bm changed
|
|
|
|
if (idx == 0)
|
|
|
|
return;
|
|
|
|
|
|
|
|
// Cursor jump succeeded!
|
|
|
|
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
|
2014-12-29 22:46:25 +00:00
|
|
|
string const lock_file = package().getConfigureLockName();
|
|
|
|
int fd = fileLock(lock_file.c_str());
|
|
|
|
int const ret = package().reconfigureUserLyXDir(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(_("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
|
2011-11-06 17:03:59 +00:00
|
|
|
LaTeXPackages::getAvailable();
|
2014-12-29 22:46:25 +00:00
|
|
|
fileUnlock(fd, lock_file.c_str());
|
2009-10-04 20:58:20 +00:00
|
|
|
|
|
|
|
if (ret)
|
|
|
|
Alert::information(_("System reconfiguration failed"),
|
|
|
|
_("The system reconfiguration has failed.\n"
|
2012-09-12 23:38:26 +00:00
|
|
|
"Default textclass is used but LyX may\n"
|
2009-10-04 20:58:20 +00:00
|
|
|
"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;
|
|
|
|
};
|
|
|
|
|
2012-04-13 00:57:25 +00:00
|
|
|
if (cmd.origin() == FuncRequest::LYXSERVER) {
|
|
|
|
if (current_view_ && current_view_->currentBufferView())
|
|
|
|
current_view_->currentBufferView()->cursor().saveBeforeDispatchPosXY();
|
|
|
|
// we will also need to redraw the screen at the end
|
|
|
|
dr.screenUpdate(Update::FitCursor);
|
|
|
|
}
|
|
|
|
|
2010-02-09 16:11:13 +00:00
|
|
|
// 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();
|
2011-01-24 10:13:18 +00:00
|
|
|
// check for valid current_view_
|
|
|
|
validateCurrentView();
|
|
|
|
if (current_view_)
|
|
|
|
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());
|
2014-01-29 19:46:19 +00:00
|
|
|
bool const is_open = FileName::isAbsolute(fname)
|
|
|
|
&& theBufferList().getBuffer(FileName(fname));
|
2013-11-26 15:12:52 +00:00
|
|
|
if (d->views_.empty()
|
|
|
|
|| (!lyxrc.open_buffers_in_tabs
|
|
|
|
&& current_view_->documentBufferView() != 0
|
2013-12-02 08:50:21 +00:00
|
|
|
&& !is_open)) {
|
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());
|
2016-06-14 23:23:34 +00:00
|
|
|
// we know current_view_ is non-null, because createView sets it.
|
|
|
|
// but let's make sure
|
|
|
|
LASSERT(current_view_, break);
|
2008-06-19 11:28:11 +00:00
|
|
|
current_view_->openDocument(fname);
|
2016-07-03 20:58:25 +00:00
|
|
|
if (!current_view_->documentBufferView())
|
2008-03-14 23:24:45 +00:00
|
|
|
current_view_->close();
|
2016-07-04 23:01:02 +00:00
|
|
|
else if (cmd.origin() == FuncRequest::LYXSERVER) {
|
2016-07-03 20:58:25 +00:00
|
|
|
current_view_->raise();
|
|
|
|
current_view_->activateWindow();
|
|
|
|
current_view_->showNormal();
|
|
|
|
}
|
2016-06-12 02:54:15 +00:00
|
|
|
} else {
|
|
|
|
// we know !d->views.empty(), so this should be ok
|
2016-06-14 23:23:34 +00:00
|
|
|
// but let's make sure
|
|
|
|
LASSERT(current_view_, break);
|
2010-10-18 14:20:03 +00:00
|
|
|
current_view_->openDocument(fname);
|
2016-07-04 23:01:02 +00:00
|
|
|
if (cmd.origin() == FuncRequest::LYXSERVER) {
|
|
|
|
current_view_->raise();
|
|
|
|
current_view_->activateWindow();
|
|
|
|
current_view_->showNormal();
|
|
|
|
}
|
2016-06-12 02:54:15 +00:00
|
|
|
}
|
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;
|
|
|
|
}
|
|
|
|
|
2011-02-13 10:08:52 +00:00
|
|
|
#if 0
|
|
|
|
// FIXME: The graphics cache no longer has a changeDisplay method.
|
2008-05-23 09:53:27 +00:00
|
|
|
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;
|
2011-02-13 10:08:52 +00:00
|
|
|
if (graphicsbg_changed)
|
2008-05-23 09:53:27 +00:00
|
|
|
graphics::GCache::get().changeDisplay(true);
|
|
|
|
#endif
|
|
|
|
|
|
|
|
if (!lcolor.setColor(lyx_name, x11_name)) {
|
2011-01-24 10:13:18 +00:00
|
|
|
if (current_view_)
|
|
|
|
current_view_->message(
|
|
|
|
bformat(_("Set-color \"%1$s\" failed "
|
2010-02-09 16:30:12 +00:00
|
|
|
"- 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();
|
2015-07-21 22:56:34 +00:00
|
|
|
// Update the current view
|
|
|
|
lyx::dispatch(FuncRequest(LFUN_SCREEN_FONT_UPDATE));
|
2008-05-23 09:53:27 +00:00
|
|
|
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);
|
2014-02-17 20:49:53 +00:00
|
|
|
|
|
|
|
// If the request comes from the minibuffer, then we can't reset
|
|
|
|
// the GUI, since that would destory the minibuffer itself and
|
2014-12-29 22:46:25 +00:00
|
|
|
// cause a crash, since we are currently in one of the methods of
|
|
|
|
// GuiCommandBuffer. See bug #8540.
|
2014-02-17 20:49:53 +00:00
|
|
|
if (cmd.origin() != FuncRequest::COMMANDBUFFER)
|
|
|
|
resetGui();
|
|
|
|
// else
|
|
|
|
// FIXME Unfortunately, that leaves a bug here, since we cannot
|
|
|
|
// reset the GUI in this case. If the changes to lyxrc affected the
|
2014-12-29 22:46:25 +00:00
|
|
|
// UI, then, nothing would happen. This seems fairly unlikely, but
|
2014-02-17 20:49:53 +00:00
|
|
|
// it definitely is a bug.
|
2009-10-04 20:58:20 +00:00
|
|
|
|
|
|
|
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: {
|
2011-01-24 10:13:18 +00:00
|
|
|
if (current_view_ && current_view_->documentBufferView()) {
|
|
|
|
docstring const fname = from_utf8(
|
2010-04-07 12:47:19 +00:00
|
|
|
current_view_->documentBufferView()->buffer().absFileName());
|
2011-01-24 10:13:18 +00:00
|
|
|
dr.setMessage(fname);
|
|
|
|
LYXERR(Debug::INFO, "FNAME[" << fname << ']');
|
|
|
|
} else {
|
|
|
|
dr.setMessage(docstring());
|
|
|
|
LYXERR(Debug::INFO, "No current file for LFUN_SERVER_GET_FILENAME");
|
|
|
|
}
|
2009-10-04 20:58:20 +00:00
|
|
|
break;
|
|
|
|
}
|
2011-01-24 10:13:18 +00:00
|
|
|
|
2009-10-04 20:58:20 +00:00
|
|
|
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;
|
|
|
|
}
|
|
|
|
|
2012-07-20 08:50:29 +00:00
|
|
|
case LFUN_BUFFER_FORALL: {
|
2012-10-15 14:05:20 +00:00
|
|
|
FuncRequest const funcToRun = lyxaction.lookupFunc(cmd.getLongArg(0));
|
|
|
|
|
|
|
|
map<Buffer *, GuiView *> views_lVisible;
|
|
|
|
map<GuiView *, Buffer *> activeBuffers;
|
|
|
|
|
|
|
|
QList<GuiView *> allViews = d->views_.values();
|
2012-07-20 08:50:29 +00:00
|
|
|
|
2016-06-09 20:54:31 +00:00
|
|
|
// this for does not modify any buffer. It just collects info on local
|
|
|
|
// visibility of buffers and on which buffer is active in each view.
|
2012-07-20 08:50:29 +00:00
|
|
|
Buffer * const last = theBufferList().last();
|
2016-06-09 20:54:31 +00:00
|
|
|
for(GuiView * view : allViews) {
|
|
|
|
// all of the buffers might be locally hidden. That is, there is no
|
|
|
|
// active buffer.
|
2014-11-27 17:51:26 +00:00
|
|
|
if (!view || !view->currentBufferView())
|
2012-10-15 14:05:20 +00:00
|
|
|
activeBuffers[view] = 0;
|
|
|
|
else
|
|
|
|
activeBuffers[view] = &view->currentBufferView()->buffer();
|
|
|
|
|
|
|
|
// find out if each is locally visible or locally hidden.
|
|
|
|
// we don't use a for loop as the buffer list cycles.
|
|
|
|
Buffer * b = theBufferList().first();
|
|
|
|
while (true) {
|
|
|
|
bool const locallyVisible = view && view->workArea(*b);
|
|
|
|
if (locallyVisible) {
|
|
|
|
bool const exists_ = (views_lVisible.find(b) != views_lVisible.end());
|
|
|
|
// only need to overwrite/add if we don't already know a buffer is globally
|
|
|
|
// visible or we do know but we would prefer to dispatch LFUN from the
|
|
|
|
// current view because of cursor position issues.
|
|
|
|
if (!exists_ || (exists_ && views_lVisible[b] != current_view_))
|
|
|
|
views_lVisible[b] = view;
|
|
|
|
}
|
|
|
|
if (b == last)
|
|
|
|
break;
|
|
|
|
b = theBufferList().next(b);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
GuiView * const homeView = currentView();
|
2012-07-20 08:50:29 +00:00
|
|
|
Buffer * b = theBufferList().first();
|
|
|
|
Buffer * nextBuf = 0;
|
2012-10-15 14:05:20 +00:00
|
|
|
int numProcessed = 0;
|
2012-07-20 08:50:29 +00:00
|
|
|
while (true) {
|
|
|
|
if (b != last)
|
2012-10-15 14:05:20 +00:00
|
|
|
nextBuf = theBufferList().next(b); // get next now bc LFUN might close current.
|
|
|
|
|
|
|
|
bool const visible = (views_lVisible.find(b) != views_lVisible.end());
|
|
|
|
if (visible) {
|
|
|
|
// first change to a view where b is locally visible, preferably current_view_.
|
|
|
|
GuiView * const vLv = views_lVisible[b];
|
|
|
|
vLv->setBuffer(b);
|
|
|
|
lyx::dispatch(funcToRun);
|
|
|
|
numProcessed++;
|
2012-07-20 08:50:29 +00:00
|
|
|
}
|
|
|
|
if (b == last)
|
|
|
|
break;
|
|
|
|
b = nextBuf;
|
|
|
|
}
|
|
|
|
|
2012-10-15 14:05:20 +00:00
|
|
|
// put things back to how they were (if possible).
|
2016-06-09 20:54:31 +00:00
|
|
|
for (GuiView * view : allViews) {
|
2012-10-15 14:05:20 +00:00
|
|
|
Buffer * originalBuf = activeBuffers[view];
|
|
|
|
// there might not have been an active buffer in this view or it might have been closed by the LFUN.
|
|
|
|
if (theBufferList().isLoaded(originalBuf))
|
|
|
|
view->setBuffer(originalBuf);
|
|
|
|
}
|
|
|
|
homeView->setFocus();
|
|
|
|
|
|
|
|
dr.setMessage(bformat(_("Applied \"%1$s\" to %2$d buffer(s)"), from_utf8(cmd.getLongArg(0)), numProcessed));
|
2012-07-20 08:50:29 +00:00
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
2010-02-09 16:11:13 +00:00
|
|
|
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);
|
2014-12-29 22:46:25 +00:00
|
|
|
|
2014-08-06 15:43:22 +00:00
|
|
|
// See #9236
|
2014-12-29 22:46:25 +00:00
|
|
|
// We need to make sure that, after we recreat the DocumentClass,
|
2014-08-06 15:43:22 +00:00
|
|
|
// which we do in readHeader, we apply it to the document itself.
|
|
|
|
DocumentClassConstPtr olddc = defaults.params().documentClassPtr();
|
2010-02-09 16:11:13 +00:00
|
|
|
int const unknown_tokens = defaults.readHeader(lex);
|
2014-08-06 15:43:22 +00:00
|
|
|
DocumentClassConstPtr newdc = defaults.params().documentClassPtr();
|
|
|
|
ErrorList el;
|
|
|
|
InsetText & theinset = static_cast<InsetText &>(defaults.inset());
|
|
|
|
cap::switchBetweenClasses(olddc, newdc, theinset, el);
|
2010-02-09 16:11:13 +00:00
|
|
|
|
|
|
|
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;
|
|
|
|
|
2014-03-08 11:51:02 +00:00
|
|
|
case LFUN_DIALOG_SHOW: {
|
|
|
|
string const name = cmd.getArg(0);
|
|
|
|
|
|
|
|
if ( name == "aboutlyx"
|
|
|
|
|| name == "prefs"
|
|
|
|
|| name == "texinfo"
|
|
|
|
|| name == "progress"
|
|
|
|
|| name == "compare")
|
|
|
|
{
|
|
|
|
// work around: on Mac OS the application
|
|
|
|
// is not terminated when closing the last view.
|
|
|
|
// Create a new one to be able to dispatch the
|
|
|
|
// LFUN_DIALOG_SHOW to this view.
|
|
|
|
if (current_view_ == 0)
|
|
|
|
createView();
|
|
|
|
}
|
2015-09-20 16:34:49 +00:00
|
|
|
// fall through
|
2014-03-08 11:51:02 +00:00
|
|
|
}
|
|
|
|
|
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
|
|
|
}
|
2012-04-13 00:57:25 +00:00
|
|
|
|
|
|
|
if (cmd.origin() == FuncRequest::LYXSERVER)
|
|
|
|
updateCurrentView(cmd, dr);
|
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();
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2016-07-04 02:23:32 +00:00
|
|
|
//Keep this in sync with GuiApplication::processKeySym below
|
|
|
|
bool GuiApplication::queryKeySym(KeySymbol const & keysym,
|
|
|
|
KeyModifier state) const
|
|
|
|
{
|
|
|
|
// Do nothing if we have nothing
|
|
|
|
if (!keysym.isOK() || keysym.isModifier())
|
|
|
|
return false;
|
|
|
|
// Do a one-deep top-level lookup for cancel and meta-fake keys.
|
|
|
|
KeySequence seq;
|
|
|
|
FuncRequest func = seq.addkey(keysym, state);
|
|
|
|
// When not cancel or meta-fake, do the normal lookup.
|
|
|
|
if ((func.action() != LFUN_CANCEL) && (func.action() != LFUN_META_PREFIX)) {
|
|
|
|
seq = d->keyseq;
|
|
|
|
func = seq.addkey(keysym, (state | d->meta_fake_bit));
|
|
|
|
}
|
|
|
|
// Maybe user can only reach the key via holding down shift.
|
|
|
|
// Let's see. But only if shift is the only modifier
|
|
|
|
if (func.action() == LFUN_UNKNOWN_ACTION && state == ShiftModifier)
|
|
|
|
// If addkey looked up a command and did not find further commands then
|
|
|
|
// seq has been reset at this point
|
|
|
|
func = seq.addkey(keysym, NoModifier);
|
|
|
|
|
|
|
|
LYXERR(Debug::KEY, " Key (queried) [action=" << func.action() << "]["
|
|
|
|
<< seq.print(KeySequence::Portable) << ']');
|
|
|
|
return func.action() != LFUN_UNKNOWN_ACTION;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
//Keep this in sync with GuiApplication::queryKeySym above
|
2009-10-04 20:58:20 +00:00
|
|
|
void GuiApplication::processKeySym(KeySymbol const & keysym, KeyModifier state)
|
|
|
|
{
|
|
|
|
LYXERR(Debug::KEY, "KeySym is " << keysym.getSymbolName());
|
|
|
|
|
|
|
|
// Do nothing if we have nothing (JMarc)
|
2016-07-04 02:23:32 +00:00
|
|
|
if (!keysym.isOK() || keysym.isModifier()) {
|
|
|
|
if (!keysym.isOK())
|
|
|
|
LYXERR(Debug::KEY, "Empty kbd action (probably composing)");
|
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");
|
2016-07-04 02:23:32 +00:00
|
|
|
// If addkey looked up a command and did not find further commands then
|
|
|
|
// seq has been reset at this point
|
2009-10-04 20:58:20 +00:00
|
|
|
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) {
|
2015-05-16 15:14:51 +00:00
|
|
|
// We didn't match any of the key sequences.
|
|
|
|
// See if it's normal insertable text not already
|
|
|
|
// covered by a binding
|
2009-10-04 20:58:20 +00:00
|
|
|
if (keysym.isText() && d->keyseq.length() == 1) {
|
2015-05-05 12:23:24 +00:00
|
|
|
// Non-printable characters (such as ASCII control characters)
|
|
|
|
// must not be inserted (#5704)
|
|
|
|
if (!isPrintable(encoded_last_key)) {
|
|
|
|
LYXERR(Debug::KEY, "Non-printable character! Omitting.");
|
2015-12-15 00:14:53 +00:00
|
|
|
if (current_view_)
|
|
|
|
current_view_->restartCursor();
|
2015-05-05 12:23:24 +00:00
|
|
|
return;
|
|
|
|
}
|
2015-12-15 00:24:31 +00:00
|
|
|
// The following modifier check is not needed on Mac.
|
|
|
|
// The keysym is either not text or it is different
|
|
|
|
// from the non-modifier keysym. See #9875 for the
|
|
|
|
// broken alt-modifier effect of having this code active.
|
|
|
|
#if !defined(Q_OS_MAC)
|
2015-05-16 15:14:51 +00:00
|
|
|
// If a non-Shift Modifier is used we have a non-bound key sequence
|
|
|
|
// (such as Alt+j = j). This should be omitted (#5575).
|
2015-05-16 21:36:40 +00:00
|
|
|
// On Windows, AltModifier and ControlModifier are both
|
|
|
|
// set when AltGr is pressed. Therefore, in order to not
|
|
|
|
// break AltGr-bound symbols (see #5575 for details),
|
|
|
|
// unbound Ctrl+Alt key sequences are allowed.
|
|
|
|
if ((state & AltModifier || state & ControlModifier || state & MetaModifier)
|
|
|
|
#if defined(Q_OS_WIN) || defined(Q_CYGWIN_WIN)
|
|
|
|
&& !(state & AltModifier && state & ControlModifier)
|
|
|
|
#endif
|
2015-12-15 00:14:53 +00:00
|
|
|
)
|
|
|
|
{
|
|
|
|
if (current_view_) {
|
|
|
|
current_view_->message(_("Unknown function."));
|
|
|
|
current_view_->restartCursor();
|
|
|
|
}
|
2015-05-16 15:14:51 +00:00
|
|
|
return;
|
|
|
|
}
|
2015-12-15 00:24:31 +00:00
|
|
|
#endif
|
2015-05-16 15:14:51 +00:00
|
|
|
// Since all checks above were passed, we now really have text that
|
|
|
|
// is to be inserted (e.g., AltGr-bound symbols). Thus change the
|
|
|
|
// func to LFUN_SELF_INSERT and thus cause the text to be inserted
|
|
|
|
// below.
|
2009-10-04 20:58:20 +00:00
|
|
|
LYXERR(Debug::KEY, "isText() is true, inserting.");
|
2015-05-16 15:14:51 +00:00
|
|
|
func = FuncRequest(LFUN_SELF_INSERT, FuncRequest::KEYBOARD);
|
2009-10-04 20:58:20 +00:00
|
|
|
} else {
|
2015-05-16 15:14:51 +00:00
|
|
|
LYXERR(Debug::KEY, "Unknown Action and not 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()) {
|
2014-08-25 16:35:15 +00:00
|
|
|
#if defined(Q_OS_WIN) || defined(Q_CYGWIN_WIN)
|
2007-11-15 12:58:44 +00:00
|
|
|
int x, y;
|
|
|
|
int w, h;
|
2014-08-25 16:35:15 +00:00
|
|
|
QChar sx, sy;
|
|
|
|
QRegExp re( "[=]*(?:([0-9]+)[xX]([0-9]+)){0,1}[ ]*(?:([+-][0-9]*)){0,1}(?:([+-][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();
|
2014-08-25 16:35:15 +00:00
|
|
|
sx = re.cap(3).isEmpty() ? '+' : re.cap(3).at(0);
|
|
|
|
sy = re.cap(4).isEmpty() ? '+' : re.cap(4).at(0);
|
|
|
|
// Set initial geometry such that we can get the frame size.
|
2007-11-17 20:47:50 +00:00
|
|
|
view->setGeometry(x, y, w, h);
|
2014-08-25 16:35:15 +00:00
|
|
|
int framewidth = view->geometry().x() - view->x();
|
|
|
|
int titleheight = view->geometry().y() - view->y();
|
|
|
|
// Negative displacements must be interpreted as distances
|
|
|
|
// from the right or bottom screen borders.
|
|
|
|
if (sx == '-' || sy == '-') {
|
|
|
|
QRect rec = QApplication::desktop()->screenGeometry();
|
|
|
|
if (sx == '-')
|
|
|
|
x += rec.width() - w - framewidth;
|
|
|
|
if (sy == '-')
|
|
|
|
y += rec.height() - h - titleheight;
|
|
|
|
view->setGeometry(x, y, w, h);
|
|
|
|
}
|
|
|
|
// Make sure that the left and top frame borders are visible.
|
|
|
|
if (view->x() < 0 || view->y() < 0) {
|
|
|
|
if (view->x() < 0)
|
|
|
|
x = framewidth;
|
|
|
|
if (view->y() < 0)
|
|
|
|
y = titleheight;
|
|
|
|
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
|
|
|
{
|
2013-05-08 16:50:38 +00:00
|
|
|
setLocale();
|
|
|
|
QLocale theLocale;
|
2008-07-28 11:26:46 +00:00
|
|
|
// install translation file for Qt built-in dialogs
|
2013-05-08 16:50:38 +00:00
|
|
|
QString const language_name = QString("qt_") + theLocale.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
|
|
|
}
|
|
|
|
|
2013-05-08 16:50:38 +00:00
|
|
|
switch (theLocale.language()) {
|
2008-07-28 11:26:46 +00:00
|
|
|
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;
|
|
|
|
|
2014-08-25 18:08:59 +00:00
|
|
|
#ifdef Q_OS_MAC
|
2010-09-19 22:00:25 +00:00
|
|
|
#if QT_VERSION > 0x040600
|
|
|
|
setAttribute(Qt::AA_MacDontSwapCtrlAndMeta,lyxrc.mac_dontswap_ctrl_meta);
|
2015-05-19 20:46:06 +00:00
|
|
|
#endif
|
|
|
|
#if QT_VERSION > 0x050100
|
|
|
|
setAttribute(Qt::AA_UseHighDpiPixmaps,true);
|
2010-09-19 22:00:25 +00:00
|
|
|
#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".
|
2014-08-24 18:29:52 +00:00
|
|
|
d->global_menubar_ = new QMenuBar(0);
|
2008-10-22 18:14:30 +00:00
|
|
|
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);
|
2015-03-12 23:47:21 +00:00
|
|
|
QIcon speller(getPixmap("images/", "dialog-show_spellchecker", "svgz,png"));
|
|
|
|
QIcon saurus(getPixmap("images/", "thesaurus-entry", "svgz,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) {
|
2015-09-20 08:42:35 +00:00
|
|
|
int current_row = lang_model->rowCount();
|
2008-05-14 10:34:19 +00:00
|
|
|
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);
|
|
|
|
d->language_model_->setSortLocaleAware(true);
|
|
|
|
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();
|
|
|
|
|
2011-01-24 10:13:18 +00:00
|
|
|
validateCurrentView();
|
|
|
|
|
2009-05-05 12:47:44 +00:00
|
|
|
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);
|
2011-01-24 10:13:18 +00:00
|
|
|
if (buffer && current_view_)
|
2009-05-05 12:47:44 +00:00
|
|
|
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;
|
|
|
|
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;
|
|
|
|
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
|
|
|
{
|
2016-04-15 09:49:04 +00:00
|
|
|
return QFontInfo(typewriterSystemFont()).family();
|
|
|
|
}
|
2006-10-03 10:34:10 +00:00
|
|
|
|
2016-04-15 09:49:04 +00:00
|
|
|
|
|
|
|
namespace {
|
|
|
|
// We cannot use QFont::fixedPitch() because it doesn't
|
|
|
|
// return the fact but only if it is requested.
|
|
|
|
static bool isFixedPitch(const QFont & font) {
|
|
|
|
const QFontInfo fi(font);
|
|
|
|
return fi.fixedPitch();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
QFont const GuiApplication::typewriterSystemFont()
|
|
|
|
{
|
|
|
|
#if QT_VERSION >= 0x050200
|
|
|
|
QFont font = QFontDatabase::systemFont(QFontDatabase::FixedFont);
|
|
|
|
#else
|
|
|
|
QFont font("monospace");
|
|
|
|
#endif
|
|
|
|
if (!isFixedPitch(font)) {
|
|
|
|
// try to enforce a real monospaced font
|
|
|
|
font.setStyleHint(QFont::Monospace);
|
|
|
|
if (!isFixedPitch(font)) {
|
|
|
|
font.setStyleHint(QFont::TypeWriter);
|
|
|
|
if (!isFixedPitch(font)) font.setFamily("courier");
|
|
|
|
}
|
|
|
|
}
|
|
|
|
#ifdef Q_OS_MAC
|
|
|
|
// On a Mac the result is too small and it's not practical to
|
|
|
|
// rely on Qtconfig utility to change the system settings of Qt.
|
|
|
|
font.setPointSize(12);
|
|
|
|
#endif
|
|
|
|
return font;
|
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: {
|
2011-01-24 10:13:18 +00:00
|
|
|
if (!current_view_ || !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)
|
|
|
|
{
|
2015-04-06 11:50:32 +00:00
|
|
|
/** 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.
|
|
|
|
** We are changing that to check the state of each buffer in all
|
|
|
|
** views and ask the users what to do if buffers are dirty.
|
|
|
|
** Furthermore, we save the session state.
|
|
|
|
** We do NOT close the views here since the user still can cancel
|
|
|
|
** the logout process (see #9277); also, this would hide LyX from
|
|
|
|
** an OSes own session handling (application restoration).
|
|
|
|
**/
|
2010-11-18 22:14:49 +00:00
|
|
|
#ifdef QT_NO_SESSIONMANAGER
|
2012-03-16 11:22:34 +00:00
|
|
|
#ifndef _MSC_VER
|
|
|
|
#warning Qt is compiled without session manager
|
|
|
|
#else
|
|
|
|
#pragma message("warning: Qt is compiled without session manager")
|
|
|
|
#endif
|
2010-11-18 22:14:49 +00:00
|
|
|
(void) sm;
|
|
|
|
#else
|
2015-04-06 11:50:32 +00:00
|
|
|
if (sm.allowsInteraction() && !prepareAllViewsForLogout())
|
2010-11-18 22:14:49 +00:00
|
|
|
sm.cancel();
|
2015-04-06 11:50:32 +00:00
|
|
|
else
|
|
|
|
sm.release();
|
2010-11-18 22:14:49 +00:00
|
|
|
#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
|
|
|
{
|
2015-07-04 16:59:29 +00:00
|
|
|
if(d->views_.contains(gv->id()) && d->views_.value(gv->id()) == gv) {
|
|
|
|
d->views_.remove(gv->id());
|
|
|
|
if (current_view_ == gv)
|
|
|
|
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();
|
|
|
|
|
2012-09-17 08:01:26 +00:00
|
|
|
QList<GuiView *> const views = d->views_.values();
|
2016-06-09 20:54:31 +00:00
|
|
|
for (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;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2015-04-06 11:50:32 +00:00
|
|
|
bool GuiApplication::prepareAllViewsForLogout()
|
|
|
|
{
|
|
|
|
if (d->views_.empty())
|
|
|
|
return true;
|
|
|
|
|
|
|
|
QList<GuiView *> const views = d->views_.values();
|
2016-06-09 20:54:31 +00:00
|
|
|
for (GuiView * view : views) {
|
2015-04-06 11:50:32 +00:00
|
|
|
if (!view->prepareAllBuffersForLogout())
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2007-11-19 20:56:05 +00:00
|
|
|
GuiView & GuiApplication::view(int id) const
|
2007-11-17 20:47:50 +00:00
|
|
|
{
|
2013-04-27 21:52:55 +00:00
|
|
|
LAPPERR(d->views_.contains(id));
|
2008-05-23 18:09:40 +00:00
|
|
|
return *d->views_.value(id);
|
2007-11-17 20:47:50 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
void GuiApplication::hideDialogs(string const & name, Inset * inset) const
|
|
|
|
{
|
2012-09-17 08:01:26 +00:00
|
|
|
QList<GuiView *> const views = d->views_.values();
|
2016-06-09 20:54:31 +00:00
|
|
|
for (GuiView * view : views)
|
2008-05-23 18:09:40 +00:00
|
|
|
view->hideDialog(name, inset);
|
2007-11-17 20:47:50 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
Buffer const * GuiApplication::updateInset(Inset const * inset) const
|
|
|
|
{
|
|
|
|
Buffer const * buffer_ = 0;
|
2012-09-17 08:01:26 +00:00
|
|
|
QHash<int, GuiView *>::const_iterator end = d->views_.end();
|
2008-05-23 18:09:40 +00:00
|
|
|
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) {
|
2016-10-27 17:58:01 +00:00
|
|
|
LYXERR0("Failed to read included 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);
|
2014-06-09 11:05:50 +00:00
|
|
|
TempFile tmp("convertXXXXXX.ui");
|
|
|
|
FileName const tempfile = tmp.name();
|
2011-01-18 15:09:43 +00:00
|
|
|
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);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
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
|
|
|
|
2012-03-06 23:21:12 +00:00
|
|
|
void GuiApplication::startLongOperation() {
|
|
|
|
d->key_checker_.start();
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
bool GuiApplication::longOperationCancelled() {
|
|
|
|
return d->key_checker_.pressed();
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
void GuiApplication::stopLongOperation() {
|
|
|
|
d->key_checker_.stop();
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2012-07-01 07:27:11 +00:00
|
|
|
bool GuiApplication::longOperationStarted() {
|
|
|
|
return d->key_checker_.started();
|
|
|
|
}
|
|
|
|
|
|
|
|
|
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();
|
2016-07-10 17:31:32 +00:00
|
|
|
if (!sel.empty()) {
|
2008-05-23 09:32:49 +00:00
|
|
|
d->selection_.put(sel);
|
2016-07-10 17:31:32 +00:00
|
|
|
// Refresh the selection request timestamp.
|
|
|
|
// We have to do this by ourselves as Qt seems
|
|
|
|
// not doing that, maybe because of our
|
|
|
|
// "persistent selection" implementation
|
|
|
|
// (see comments in GuiSelection.cpp).
|
|
|
|
XSelectionEvent nev;
|
|
|
|
nev.type = SelectionNotify;
|
|
|
|
nev.display = xev->xselectionrequest.display;
|
|
|
|
nev.requestor = xev->xselectionrequest.requestor;
|
|
|
|
nev.selection = xev->xselectionrequest.selection;
|
|
|
|
nev.target = xev->xselectionrequest.target;
|
|
|
|
nev.property = 0L; // None
|
|
|
|
nev.time = CurrentTime;
|
|
|
|
XSendEvent(QX11Info::display(),
|
|
|
|
nev.requestor, False, 0,
|
|
|
|
reinterpret_cast<XEvent *>(&nev));
|
|
|
|
return true;
|
|
|
|
}
|
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;
|
|
|
|
}
|
2015-04-07 10:59:41 +00:00
|
|
|
#elif defined(QPA_XCB)
|
|
|
|
bool GuiApplication::nativeEventFilter(const QByteArray & eventType,
|
2015-08-24 19:05:48 +00:00
|
|
|
void * message, long *)
|
2015-04-07 10:59:41 +00:00
|
|
|
{
|
|
|
|
if (!current_view_ || eventType != "xcb_generic_event_t")
|
|
|
|
return false;
|
|
|
|
|
|
|
|
xcb_generic_event_t * ev = static_cast<xcb_generic_event_t *>(message);
|
|
|
|
|
|
|
|
switch (ev->response_type) {
|
|
|
|
case XCB_SELECTION_REQUEST: {
|
|
|
|
xcb_selection_request_event_t * srev =
|
|
|
|
reinterpret_cast<xcb_selection_request_event_t *>(ev);
|
2015-05-19 19:19:49 +00:00
|
|
|
if (srev->selection != XCB_ATOM_PRIMARY)
|
2015-04-07 10:59:41 +00:00
|
|
|
break;
|
|
|
|
LYXERR(Debug::SELECTION, "X requested selection.");
|
|
|
|
BufferView * bv = current_view_->currentBufferView();
|
|
|
|
if (bv) {
|
|
|
|
docstring const sel = bv->requestSelection();
|
2016-07-10 17:31:32 +00:00
|
|
|
if (!sel.empty()) {
|
2015-04-07 10:59:41 +00:00
|
|
|
d->selection_.put(sel);
|
2016-07-10 17:31:32 +00:00
|
|
|
#ifdef HAVE_QT5_X11_EXTRAS
|
|
|
|
// Refresh the selection request timestamp.
|
|
|
|
// We have to do this by ourselves as Qt seems
|
|
|
|
// not doing that, maybe because of our
|
|
|
|
// "persistent selection" implementation
|
|
|
|
// (see comments in GuiSelection.cpp).
|
|
|
|
xcb_selection_notify_event_t nev;
|
|
|
|
nev.response_type = XCB_SELECTION_NOTIFY;
|
|
|
|
nev.requestor = srev->requestor;
|
|
|
|
nev.selection = srev->selection;
|
|
|
|
nev.target = srev->target;
|
|
|
|
nev.property = XCB_NONE;
|
|
|
|
nev.time = XCB_CURRENT_TIME;
|
|
|
|
xcb_connection_t * con = QX11Info::connection();
|
|
|
|
xcb_send_event(con, 0, srev->requestor,
|
|
|
|
XCB_EVENT_MASK_NO_EVENT,
|
|
|
|
reinterpret_cast<char const *>(&nev));
|
|
|
|
xcb_flush(con);
|
|
|
|
#endif
|
|
|
|
return true;
|
|
|
|
}
|
2015-04-07 10:59:41 +00:00
|
|
|
}
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
case XCB_SELECTION_CLEAR: {
|
|
|
|
xcb_selection_clear_event_t * scev =
|
|
|
|
reinterpret_cast<xcb_selection_clear_event_t *>(ev);
|
2015-05-19 19:19:49 +00:00
|
|
|
if (scev->selection != XCB_ATOM_PRIMARY)
|
2015-04-07 10:59:41 +00:00
|
|
|
break;
|
|
|
|
LYXERR(Debug::SELECTION, "Lost selection.");
|
|
|
|
BufferView * bv = current_view_->currentBufferView();
|
|
|
|
if (bv)
|
|
|
|
bv->clearSelection();
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return false;
|
|
|
|
}
|
2006-06-26 17:18:28 +00:00
|
|
|
#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()
|
|
|
|
{
|
2013-04-27 21:52:55 +00:00
|
|
|
LAPPERR(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)
|
|
|
|
{
|
2013-04-27 21:52:55 +00:00
|
|
|
LAPPERR(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()
|
|
|
|
{
|
2013-04-27 21:52:55 +00:00
|
|
|
LAPPERR(frontend::guiApp);
|
2007-11-17 22:11:11 +00:00
|
|
|
return frontend::guiApp->clipboard();
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
frontend::Selection & theSelection()
|
|
|
|
{
|
2013-04-27 21:52:55 +00:00
|
|
|
LAPPERR(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"
|