]> git.lyx.org Git - lyx.git/blob - src/frontends/qt4/GuiApplication.C
This commit introduces frontends/Application.[Ch] and makes qt4/GuiApplication (renam...
[lyx.git] / src / frontends / qt4 / GuiApplication.C
1 /**
2  * \file qt4/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 "GuiApplication.h"
16
17 #include "GuiView.h"
18 #include "GuiWorkArea.h"
19 #include "qt_helpers.h"
20 #include "QLImage.h"
21
22 #include "BufferView.h"
23
24 #include "graphics/LoaderQueue.h"
25
26 #include "support/lstrings.h"
27 #include "support/os.h"
28 #include "support/package.h"
29
30 #include "lyx_main.h"
31 #include "lyxrc.h"
32 #include "debug.h"
33
34 #include <QApplication>
35 #include <QClipboard>
36 #include <QEventLoop>
37 #include <QLocale>
38 #include <QLibraryInfo>
39 #include <QTextCodec>
40 #include <QTranslator>
41
42 #ifdef Q_WS_X11
43 #include <X11/Xlib.h>
44 #endif
45
46 #include <boost/bind.hpp>
47
48 using lyx::support::subst;
49
50 using std::string;
51 using std::endl;
52
53 // in QLyXKeySym.C
54 extern void initEncodings();
55
56 ///////////////////////////////////////////////////////////////
57 // You can find other X11 and MACX specific stuff
58 // at the end of this file...
59 ///////////////////////////////////////////////////////////////
60
61 namespace {
62
63 int getDPI()
64 {
65         QWidget w;
66         return int(0.5 * (w.logicalDpiX() + w.logicalDpiY()));
67 }
68
69 } // namespace anon
70
71
72 namespace lyx {
73 namespace frontend {
74
75 GuiApplication::GuiApplication(int & argc, char ** argv)
76         : QApplication(argc, argv), Application(argc, argv)
77 {
78 #ifdef Q_WS_X11
79         // doubleClickInterval() is 400 ms on X11 witch is just too long.
80         // On Windows and Mac OS X, the operating system's value is used.
81         // On Microsoft Windows, calling this function sets the double
82         // click interval for all applications. So we don't!
83         QApplication::setDoubleClickInterval(300);
84 #endif
85
86 #ifdef Q_WS_MACX
87         AEInstallEventHandler(kCoreEventClass, kAEOpenDocuments,
88                               NewAEEventHandlerUPP(handleOpenDocuments),
89                               0, false);
90 #endif
91
92         // install translation file for Qt built-in dialogs
93         // These are only installed since Qt 3.2.x
94         QTranslator qt_trans;
95         QString language_name = QString("qt_") + QLocale::system().name();
96         language_name.truncate(5);
97         if (qt_trans.load(language_name,
98                 QLibraryInfo::location(QLibraryInfo::TranslationsPath)))
99         {
100                 qApp->installTranslator(&qt_trans);
101                 // even if the language calls for RtL, don't do that
102                 qApp->setLayoutDirection(Qt::LeftToRight);
103                 lyxerr[Debug::GUI]
104                         << "Successfully installed Qt translations for locale "
105                         << fromqstr(language_name) << std::endl;
106         } else
107                 lyxerr[Debug::GUI]
108                         << "Could not find  Qt translations for locale "
109                         << fromqstr(language_name) << std::endl;
110
111 /*#ifdef Q_WS_MACX
112         // These translations are meant to break Qt/Mac menu merging
113         // algorithm on some entries. It lists the menu names that
114         // should not be moved to the LyX menu
115         QTranslator aqua_trans(0);
116         aqua_trans.insert(QTranslatorMessage("QMenuBar", "Setting", 0,
117                                              "do_not_merge_me"));
118         aqua_trans.insert(QTranslatorMessage("QMenuBar", "Config", 0,
119                                              "do_not_merge_me"));
120         aqua_trans.insert(QTranslatorMessage("QMenuBar", "Options", 0,
121                                              "do_not_merge_me"));
122         aqua_trans.insert(QTranslatorMessage("QMenuBar", "Setup", 0,
123                                              "do_not_merge_me"));
124
125         qApp->installTranslator(&aqua_trans);
126 #endif
127 */
128         using namespace lyx::graphics;
129
130         Image::newImage = boost::bind(&QLImage::newImage);
131         Image::loadableFormats = boost::bind(&QLImage::loadableFormats);
132
133         // needs to be done before reading lyxrc
134         lyxrc.dpi = getDPI();
135
136         LoaderQueue::setPriority(10,100);
137 }
138
139
140 int const GuiApplication::exec()
141 {
142         return QApplication::exec();
143 }
144
145
146 void GuiApplication::exit(int status)
147 {
148         QApplication::exit(status);
149 }
150
151
152 // FIXME: this whole method needs to be moved to Application.
153 LyXView & GuiApplication::createView(unsigned int width,
154                                                                           unsigned int height,
155                                                                           int posx, int posy,
156                                                                           bool maximize)
157 {
158         // this can't be done before because it needs the Languages object
159         initEncodings();
160
161         int view_id = gui().newView(width, height);
162         GuiView & view = static_cast<GuiView &> (gui().view(view_id));
163
164         lyxfunc_.reset(new LyXFunc(&view));
165
166         // FIXME: for now we assume that there is only one LyXView with id = 0.
167         /*int workArea_id_ =*/ gui().newWorkArea(width, height, 0);
168         //WorkArea * workArea_ = & theApp->gui().workArea(workArea_id_);
169
170         LyX::ref().addLyXView(&view);
171
172         view.init();
173
174         // FIXME: put this initialisation code in GuiView accessible via
175         // a pure virtual method in LyXView.
176
177         // only true when the -geometry option was NOT used
178         if (width != 0 && height != 0) {
179                 if (posx != -1 && posy != -1) {
180 #ifdef Q_OS_WIN32
181                         // FIXME: use only setGeoemtry when Trolltech has
182                         // fixed the qt4/X11 bug
183                         view.setGeometry(posx, posy,width, height);
184 #else
185                         view.resize(width, height);
186                         view.move(posx, posy);
187 #endif
188                 } else {
189                         view.resize(width, height);
190                 }
191
192                 if (maximize)
193                         view.setWindowState(Qt::WindowMaximized);
194         }
195
196         view.show();
197
198         return view;
199 }
200
201
202 ////////////////////////////////////////////////////////////////////////
203 // X11 specific stuff goes here...
204 #ifdef Q_WS_X11
205 bool GuiApplication::x11EventFilter(XEvent * xev)
206 {
207         switch (xev->type) {
208         case SelectionRequest:
209                 lyxerr[Debug::GUI] << "X requested selection." << endl;
210                 if (buffer_view_) {
211                         lyx::docstring const sel = buffer_view_->requestSelection();
212                         if (!sel.empty())
213                                 gui_.selection().put(sel);
214                 }
215                 break;
216         case SelectionClear:
217                 lyxerr[Debug::GUI] << "Lost selection." << endl;
218                 if (buffer_view_)
219                         buffer_view_->clearSelection();
220                 break;
221         }
222         return false;
223 }
224 #endif
225
226
227 ////////////////////////////////////////////////////////////////////////
228 // Mac OSX specific stuff goes here...
229
230 #ifdef Q_WS_MACX
231 namespace{
232
233 OSErr checkAppleEventForMissingParams(const AppleEvent& theAppleEvent)
234  {
235         DescType returnedType;
236         Size actualSize;
237         OSErr err = AEGetAttributePtr(&theAppleEvent, keyMissedKeywordAttr,
238                                       typeWildCard, &returnedType, nil, 0,
239                                       &actualSize);
240         switch (err) {
241         case errAEDescNotFound:
242                 return noErr;
243         case noErr:
244                 return errAEEventNotHandled;
245         default:
246                 return err;
247         }
248  }
249
250 } // namespace
251
252 OSErr GuiApplication::handleOpenDocuments(const AppleEvent* inEvent,
253                                        AppleEvent* /*reply*/, long /*refCon*/)
254 {
255         QString s_arg;
256         AEDescList documentList;
257         OSErr err = AEGetParamDesc(inEvent, keyDirectObject, typeAEList,
258                                    &documentList);
259         if (err != noErr)
260                 return err;
261
262         err = checkAppleEventForMissingParams(*inEvent);
263         if (err == noErr) {
264                 long documentCount;
265                 err = AECountItems(&documentList, &documentCount);
266                 for (long documentIndex = 1;
267                      err == noErr && documentIndex <= documentCount;
268                      documentIndex++) {
269                         DescType returnedType;
270                         Size actualSize;
271                         AEKeyword keyword;
272                         FSRef ref;
273                         char qstr_buf[1024];
274                         err = AESizeOfNthItem(&documentList, documentIndex,
275                                               &returnedType, &actualSize);
276                         if (err == noErr) {
277                                 err = AEGetNthPtr(&documentList, documentIndex,
278                                                   typeFSRef, &keyword,
279                                                   &returnedType, (Ptr)&ref,
280                                                   sizeof(FSRef), &actualSize);
281                                 if (err == noErr) {
282                                         FSRefMakePath(&ref, (UInt8*)qstr_buf,
283                                                       1024);
284                                         s_arg=QString::fromUtf8(qstr_buf);
285 //                                      buffer_view_->workAreaDispatch(
286 //                                              FuncRequest(LFUN_FILE_OPEN,
287 //                                                          fromqstr(s_arg)));
288                                         break;
289                                 }
290                         }
291                 } // for ...
292         }
293         AEDisposeDesc(&documentList);
294
295         return err;
296 }
297
298 bool GuiApplication::macEventFilter(EventRef event)
299 {
300         if (GetEventClass(event) == kEventClassAppleEvent) {
301                 EventRecord eventrec;
302                 ConvertEventRefToEventRecord(event, &eventrec);
303                 AEProcessAppleEvent(&eventrec);
304
305                 return false;
306         }
307         return false;
308 }
309
310 #endif  // Q_WS_MACX
311
312 } // namespace frontend
313 } // namespace lyx