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