2 * \file qt4/GuiApplication.cpp
3 * This file is part of LyX, the document processor.
4 * Licence details can be found in the file COPYING.
8 * \author Abdelrazak Younes
10 * Full author contact details are available in file CREDITS.
15 #include "GuiApplication.h"
17 #include "qt_helpers.h"
19 #include "socket_callback.h"
21 #include "frontends/LyXView.h"
23 #include "graphics/LoaderQueue.h"
25 #include "support/FileName.h"
26 #include "support/lstrings.h"
27 #include "support/os.h"
28 #include "support/Package.h"
30 #include "BufferView.h"
33 #include "FuncRequest.h"
39 #include <QApplication>
42 #include <QFileOpenEvent>
44 #include <QLibraryInfo>
45 #include <QPixmapCache>
48 #include <QTranslator>
52 #include <X11/Xatom.h>
56 #include <boost/bind.hpp>
63 ///////////////////////////////////////////////////////////////
64 // You can find other X11 specific stuff
65 // at the end of this file...
66 ///////////////////////////////////////////////////////////////
73 return int(0.5 * (w.logicalDpiX() + w.logicalDpiY()));
81 using support::FileName;
83 frontend::Application * createApplication(int & argc, char * argv[])
85 return new frontend::GuiApplication(argc, argv);
91 GuiApplication * guiApp;
94 GuiApplication::~GuiApplication()
96 socket_callbacks_.clear();
100 GuiApplication::GuiApplication(int & argc, char ** argv)
101 : QApplication(argc, argv), Application(argc, argv)
103 // Qt bug? setQuitOnLastWindowClosed(true); does not work
104 setQuitOnLastWindowClosed(false);
107 // doubleClickInterval() is 400 ms on X11 which is just too long.
108 // On Windows and Mac OS X, the operating system's value is used.
109 // On Microsoft Windows, calling this function sets the double
110 // click interval for all applications. So we don't!
111 QApplication::setDoubleClickInterval(300);
114 // install translation file for Qt built-in dialogs
115 QString language_name = QString("qt_") + QLocale::system().name();
117 // language_name can be short (e.g. qt_zh) or long (e.g. qt_zh_CN).
118 // Short-named translator can be loaded from a long name, but not the
119 // opposite. Therefore, long name should be used without truncation.
120 // c.f. http://doc.trolltech.com/4.1/qtranslator.html#load
121 if (qt_trans_.load(language_name,
122 QLibraryInfo::location(QLibraryInfo::TranslationsPath)))
124 installTranslator(&qt_trans_);
125 // even if the language calls for RtL, don't do that
126 setLayoutDirection(Qt::LeftToRight);
128 << "Successfully installed Qt translations for locale "
129 << fromqstr(language_name) << std::endl;
132 << "Could not find Qt translations for locale "
133 << fromqstr(language_name) << std::endl;
136 // This allows to translate the strings that appear in the LyX menu.
140 using namespace lyx::graphics;
142 Image::newImage = boost::bind(&QLImage::newImage);
143 Image::loadableFormats = boost::bind(&QLImage::loadableFormats);
145 // needs to be done before reading lyxrc
146 lyxrc.dpi = getDPI();
148 LoaderQueue::setPriority(10,100);
152 // Set the cache to 5120 kilobytes which corresponds to screen size of
153 // 1280 by 1024 pixels with a color depth of 32 bits.
154 QPixmapCache::setCacheLimit(5120);
158 Clipboard& GuiApplication::clipboard()
164 Selection& GuiApplication::selection()
170 int const GuiApplication::exec()
172 QTimer::singleShot(1, this, SLOT(execBatchCommands()));
173 return QApplication::exec();
177 void GuiApplication::exit(int status)
179 QApplication::exit(status);
183 void GuiApplication::execBatchCommands()
185 LyX::ref().execBatchCommands();
189 string const GuiApplication::romanFontName()
192 font.setKerning(false);
193 font.setStyleHint(QFont::Serif);
194 font.setFamily("serif");
196 return fromqstr(QFontInfo(font).family());
200 string const GuiApplication::sansFontName()
203 font.setKerning(false);
204 font.setStyleHint(QFont::SansSerif);
205 font.setFamily("sans");
207 return fromqstr(QFontInfo(font).family());
211 string const GuiApplication::typewriterFontName()
214 font.setKerning(false);
215 font.setStyleHint(QFont::TypeWriter);
216 font.setFamily("monospace");
218 return fromqstr(QFontInfo(font).family());
222 bool GuiApplication::event(QEvent * e)
225 case QEvent::FileOpen: {
226 // Open a file; this happens only on Mac OS X for now
227 QFileOpenEvent * foe = static_cast<QFileOpenEvent *>(e);
229 if (!currentView() || !currentView()->view())
230 // The application is not properly initialized yet.
231 // So we acknowledge the event and delay the file opening
232 // until LyX is ready.
233 // FIXME UNICODE: FileName accept an utf8 encoded string.
234 LyX::ref().addFileToLoad(FileName(fromqstr(foe->file())));
236 lyx::dispatch(FuncRequest(LFUN_FILE_OPEN,
237 qstring_to_ucs4(foe->file())));
243 return QApplication::event(e);
248 bool GuiApplication::notify(QObject * receiver, QEvent * event)
252 return_value = QApplication::notify(receiver, event);
254 catch (std::exception const & e) {
255 lyxerr << "Caught \"normal\" exception: " << e.what() << endl;
256 LyX::cref().emergencyCleanup();
260 lyxerr << "Caught some really weird exception..." << endl;
261 LyX::cref().emergencyCleanup();
269 void GuiApplication::syncEvents()
271 // This is the ONLY place where processEvents may be called.
272 // During screen update/ redraw, this method is disabled to
273 // prevent keyboard events being handed to the LyX core, where
274 // they could cause re-entrant calls to screen update.
275 processEvents(QEventLoop::ExcludeUserInputEvents);
279 bool GuiApplication::getRgbColor(Color_color col,
282 QColor const & qcol = color_cache_.get(col);
283 if (!qcol.isValid()) {
289 rgbcol.r = qcol.red();
290 rgbcol.g = qcol.green();
291 rgbcol.b = qcol.blue();
296 string const GuiApplication::hexName(Color_color col)
298 return lyx::support::ltrim(fromqstr(color_cache_.get(col).name()), "#");
302 void GuiApplication::updateColor(Color_color)
304 // FIXME: Bleh, can't we just clear them all at once ?
305 color_cache_.clear();
309 void GuiApplication::registerSocketCallback(int fd, boost::function<void()> func)
311 socket_callbacks_[fd] =
312 boost::shared_ptr<socket_callback>(new socket_callback(fd, func));
316 void GuiApplication::unregisterSocketCallback(int fd)
318 socket_callbacks_.erase(fd);
321 ////////////////////////////////////////////////////////////////////////
322 // X11 specific stuff goes here...
324 bool GuiApplication::x11EventFilter(XEvent * xev)
330 case SelectionRequest: {
331 if (xev->xselectionrequest.selection != XA_PRIMARY)
333 LYXERR(Debug::GUI) << "X requested selection." << endl;
334 BufferView * bv = currentView()->view();
336 docstring const sel = bv->requestSelection();
342 case SelectionClear: {
343 if (xev->xselectionclear.selection != XA_PRIMARY)
345 LYXERR(Debug::GUI) << "Lost selection." << endl;
346 BufferView * bv = currentView()->view();
348 bv->clearSelection();
357 ////////////////////////////////////////////////////////////////////////
358 // Mac specific stuff goes here...
360 class MenuTranslator : public QTranslator {
362 virtual ~MenuTranslator() {};
363 virtual QString translate(const char * context,
364 const char * sourceText,
365 const char * comment = 0) const;
369 QString MenuTranslator::translate(const char * /*context*/,
370 const char * sourceText,
373 string const s = sourceText;
374 if (s == N_("About %1") || s == N_("Preferences")
375 || s == N_("Reconfigure") || s == N_("Quit %1"))
382 void GuiApplication::addMenuTranslator()
384 menu_trans_.reset(new MenuTranslator());
385 installTranslator(menu_trans_.get());
389 } // namespace frontend
392 #include "GuiApplication_moc.cpp"