]> git.lyx.org Git - lyx.git/blob - src/frontends/qt3/GuiApplication.C
0c96371d7fd21a40b2ac8d5fc99d54a330e374e8
[lyx.git] / src / frontends / qt3 / GuiApplication.C
1 /**
2  * \file qt3/GuiApplication.C
3  * This file is part of LyX, the document processor.
4  * Licence details can be found in the file COPYING.
5  *
6  * \author unknown
7  * \author John Levon
8  * \author Abdelrazak Younes
9  *
10  * Full author contact details are available in file CREDITS.
11  */
12
13 #include <config.h>
14
15 #include "frontends/LyXView.h"
16 #include "frontends/WorkArea.h"
17
18 #include "GuiApplication.h"
19
20 #include "lcolorcache.h"
21 #include "qt_helpers.h"
22 #include "QLImage.h"
23 #include "socket_callback.h"
24
25 #include "graphics/LoaderQueue.h"
26
27 #include "support/lstrings.h"
28 #include "support/os.h"
29 #include "support/package.h"
30
31 #include "BufferView.h"
32 #include "Color.h"
33 #include "lyx_main.h"
34 #include "lyxrc.h"
35 #include "debug.h"
36
37 #include <qapplication.h>
38 #include <qclipboard.h>
39 #include <qeventloop.h>
40 #include <qlocale.h>
41 #include <qpaintdevicemetrics.h>
42 #include <qtextcodec.h>
43 #include <qtranslator.h>
44
45 #ifdef Q_WS_X11
46 #include <X11/Xlib.h>
47 #endif
48
49 #include <boost/bind.hpp>
50
51 using lyx::support::subst;
52
53 using std::string;
54 using std::endl;
55
56 // in QLyXKeySym.C
57 extern void initEncodings();
58
59 ///////////////////////////////////////////////////////////////
60 // You can find other X11 and MACX specific stuff
61 // at the end of this file...
62 ///////////////////////////////////////////////////////////////
63
64 namespace {
65
66 std::map<int, boost::shared_ptr<socket_callback> > socket_callbacks;
67
68 int getDPI()
69 {
70         QWidget w;
71         QPaintDeviceMetrics pdm(&w);
72         return int(0.5 * (pdm.logicalDpiX() + pdm.logicalDpiY()));
73 }
74
75 } // namespace anon
76
77
78 namespace lyx {
79
80 frontend::Application * createApplication(int & argc, char * argv[])
81 {
82         frontend::GuiApplication app(argc, argv);
83
84         return &app;
85 }
86
87 namespace frontend {
88
89 GuiApplication::GuiApplication(int & argc, char ** argv)
90         : QApplication(argc, argv), Application(argc, argv)
91 {
92 #ifdef Q_WS_X11
93         // doubleClickInterval() is 400 ms on X11 witch is just too long.
94         // On Windows and Mac OS X, the operating system's value is used.
95         // On Microsoft Windows, calling this function sets the double
96         // click interval for all applications. So we don't!
97         QApplication::setDoubleClickInterval(300);
98 #endif
99
100 #ifdef Q_WS_MACX
101         AEInstallEventHandler(kCoreEventClass, kAEOpenDocuments,
102                               NewAEEventHandlerUPP(handleOpenDocuments),
103                               0, false);
104 #endif
105
106 #if QT_VERSION >= 0x030200
107         // install translation file for Qt built-in dialogs
108         // These are only installed since Qt 3.2.x
109         QTranslator qt_trans(0);
110         if (qt_trans.load(QString("qt_") + QTextCodec::locale(),
111                                 qInstallPathTranslations())) {
112                 qApp->installTranslator(&qt_trans);
113                 // even if the language calls for RtL, don't do that
114                 qApp->setReverseLayout(false);
115                 lyxerr[Debug::GUI]
116                         << "Successfully installed Qt translations for locale "
117                         << QTextCodec::locale() << std::endl;
118         } else
119                 lyxerr[Debug::GUI]
120                         << "Could not find  Qt translations for locale "
121                         << QTextCodec::locale() << std::endl;
122 #endif
123
124 #ifdef Q_WS_MACX
125         // These translations are meant to break Qt/Mac menu merging
126         // algorithm on some entries. It lists the menu names that
127         // should not be moved to the LyX menu
128         QTranslator aqua_trans(0);
129         aqua_trans.insert(QTranslatorMessage("QMenuBar", "Setting", 0,
130                                              "do_not_merge_me"));
131         aqua_trans.insert(QTranslatorMessage("QMenuBar", "Config", 0,
132                                              "do_not_merge_me"));
133         aqua_trans.insert(QTranslatorMessage("QMenuBar", "Options", 0,
134                                              "do_not_merge_me"));
135         aqua_trans.insert(QTranslatorMessage("QMenuBar", "Setup", 0,
136                                              "do_not_merge_me"));
137
138         qApp->installTranslator(&aqua_trans);
139 #endif
140
141         using namespace lyx::graphics;
142
143         Image::newImage = boost::bind(&QLImage::newImage);
144         Image::loadableFormats = boost::bind(&QLImage::loadableFormats);
145
146         // needs to be done before reading lyxrc
147         lyxrc.dpi = getDPI();
148
149         LoaderQueue::setPriority(10,100);
150 }
151
152
153 Clipboard& GuiApplication::clipboard()
154 {
155         return clipboard_;
156 }
157
158
159 Selection& GuiApplication::selection()
160 {
161         return selection_;
162 }
163
164
165 int const GuiApplication::exec()
166 {
167         return QApplication::exec();
168 }
169
170
171 void GuiApplication::exit(int status)
172 {
173         QApplication::exit(status);
174 }
175
176
177 string const GuiApplication::romanFontName()
178 {
179         QFont font;
180         font.setStyleHint(QFont::Serif);
181         font.setFamily("serif");
182
183         return fromqstr(QFontInfo(font).family());
184 }
185
186
187 string const GuiApplication::sansFontName()
188 {
189         QFont font;
190         font.setStyleHint(QFont::SansSerif);
191         font.setFamily("sans");
192
193         return fromqstr(QFontInfo(font).family());
194 }
195
196
197 string const GuiApplication::typewriterFontName()
198 {
199         QFont font;
200         font.setStyleHint(QFont::TypeWriter);
201         font.setFamily("monospace");
202
203         return fromqstr(QFontInfo(font).family());
204 }
205
206
207 void GuiApplication::syncEvents()
208 {
209         // This is the ONLY place where processEvents may be called.
210         // During screen update/ redraw, this method is disabled to
211         // prevent keyboard events being handed to the LyX core, where
212         // they could cause re-entrant calls to screen update.
213 #if QT_VERSION >= 0x030100
214         qApp->eventLoop()->processEvents(QEventLoop::ExcludeUserInput);
215 #endif
216 }
217
218
219 bool GuiApplication::getRgbColor(LColor_color col,
220                                                                  lyx::RGBColor & rgbcol)
221 {
222         QColor const & qcol = lcolorcache.get(col);
223         if (!qcol.isValid()) {
224                 rgbcol.r = 0;
225                 rgbcol.g = 0;
226                 rgbcol.b = 0;
227                 return false;
228         }
229         rgbcol.r = qcol.red();
230         rgbcol.g = qcol.green();
231         rgbcol.b = qcol.blue();
232         return true;
233 }
234
235
236 string const GuiApplication::hexName(LColor_color col)
237 {
238         return lyx::support::ltrim(fromqstr(lcolorcache.get(col).name()), "#");
239 }
240
241
242 void GuiApplication::updateColor(LColor_color)
243 {
244         // FIXME: Bleh, can't we just clear them all at once ?
245         lcolorcache.clear();
246 }
247
248
249 void GuiApplication::registerSocketCallback(int fd, boost::function<void()> func)
250 {
251         socket_callbacks[fd] = boost::shared_ptr<socket_callback>(new socket_callback(fd, func));
252 }
253
254
255 void GuiApplication::unregisterSocketCallback(int fd)
256 {
257         socket_callbacks.erase(fd);
258 }
259
260
261 ////////////////////////////////////////////////////////////////////////
262 // X11 specific stuff goes here...
263 #ifdef Q_WS_X11
264 bool GuiApplication::x11EventFilter(XEvent * xev)
265 {
266         switch (xev->type) {
267         case SelectionRequest:
268                 lyxerr[Debug::GUI] << "X requested selection." << endl;
269                 if (buffer_view_) {
270                         lyx::docstring const sel = buffer_view_->requestSelection();
271                         if (!sel.empty())
272                                 selection_.put(sel);
273                 }
274                 break;
275         case SelectionClear:
276                 lyxerr[Debug::GUI] << "Lost selection." << endl;
277                 if (buffer_view_)
278                         buffer_view_->clearSelection();
279                 break;
280         }
281         return false;
282 }
283 #endif
284
285
286 ////////////////////////////////////////////////////////////////////////
287 // Mac OSX specific stuff goes here...
288
289 #ifdef Q_WS_MACX
290 namespace{
291
292 OSErr checkAppleEventForMissingParams(const AppleEvent& theAppleEvent)
293  {
294         DescType returnedType;
295         Size actualSize;
296         OSErr err = AEGetAttributePtr(&theAppleEvent, keyMissedKeywordAttr,
297                                       typeWildCard, &returnedType, nil, 0,
298                                       &actualSize);
299         switch (err) {
300         case errAEDescNotFound:
301                 return noErr;
302         case noErr:
303                 return errAEEventNotHandled;
304         default:
305                 return err;
306         }
307  }
308
309 } // namespace
310
311 OSErr GuiApplication::handleOpenDocuments(const AppleEvent* inEvent,
312                                        AppleEvent* /*reply*/, long /*refCon*/)
313 {
314         QString s_arg;
315         AEDescList documentList;
316         OSErr err = AEGetParamDesc(inEvent, keyDirectObject, typeAEList,
317                                    &documentList);
318         if (err != noErr)
319                 return err;
320
321         err = checkAppleEventForMissingParams(*inEvent);
322         if (err == noErr) {
323                 long documentCount;
324                 err = AECountItems(&documentList, &documentCount);
325                 for (long documentIndex = 1;
326                      err == noErr && documentIndex <= documentCount;
327                      documentIndex++) {
328                         DescType returnedType;
329                         Size actualSize;
330                         AEKeyword keyword;
331                         FSRef ref;
332                         char qstr_buf[1024];
333                         err = AESizeOfNthItem(&documentList, documentIndex,
334                                               &returnedType, &actualSize);
335                         if (err == noErr) {
336                                 err = AEGetNthPtr(&documentList, documentIndex,
337                                                   typeFSRef, &keyword,
338                                                   &returnedType, (Ptr)&ref,
339                                                   sizeof(FSRef), &actualSize);
340                                 if (err == noErr) {
341                                         FSRefMakePath(&ref, (UInt8*)qstr_buf,
342                                                       1024);
343                                         s_arg=QString::fromUtf8(qstr_buf);
344 //                                      buffer_view_->workAreaDispatch(
345 //                                              FuncRequest(LFUN_FILE_OPEN,
346 //                                                          fromqstr(s_arg)));
347                                         break;
348                                 }
349                         }
350                 } // for ...
351         }
352         AEDisposeDesc(&documentList);
353
354         return err;
355 }
356
357 bool GuiApplication::macEventFilter(EventRef event)
358 {
359         if (GetEventClass(event) == kEventClassAppleEvent) {
360                 EventRecord eventrec;
361                 ConvertEventRefToEventRecord(event, &eventrec);
362                 AEProcessAppleEvent(&eventrec);
363
364                 return false;
365         }
366         return false;
367 }
368
369 #endif  // Q_WS_MACX
370
371 } // namespace frontend
372 } // namespace lyx