]> git.lyx.org Git - lyx.git/blob - src/frontends/qt3/lyx_gui.C
4ff2dfc0f11204917bca30475563736092283007
[lyx.git] / src / frontends / qt3 / lyx_gui.C
1 /**
2  * \file qt3/lyx_gui.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  *
9  * Full author contact details are available in file CREDITS.
10  */
11
12 #include <config.h>
13
14 #include "lyx_gui.h"
15
16 // FIXME: move this stuff out again
17 #include "bufferlist.h"
18 #include "BufferView.h"
19 #include "Color.h"
20 #include "funcrequest.h"
21 #include "LColor.h"
22 #include "lyx_main.h"
23 #include "LyXAction.h"
24 #include "lyxfunc.h"
25 #include "lyxrc.h"
26 #include "lyxserver.h"
27 #include "lyxsocket.h"
28
29 #include "graphics/LoaderQueue.h"
30
31 #include "support/lstrings.h"
32 #include "support/os.h"
33 #include "support/package.h"
34 #include "debug.h"
35
36 // Dear Lord, deliver us from Evil, aka the Qt headers
37 // Qt defines a macro 'signals' that clashes with a boost namespace.
38 // All is well if the namespace is visible first.
39 #include <boost/signal.hpp> // FIXME: Is this needed? (Lgb)
40 #include <boost/bind.hpp>
41 #include <boost/shared_ptr.hpp>
42
43 #include "GuiImplementation.h"
44 #include "QtView.h"
45 #include "lcolorcache.h"
46 #include "qfont_loader.h"
47 #include "QLImage.h"
48 #include "qt_helpers.h"
49 #include "socket_callback.h"
50
51 #ifdef Q_WS_MACX
52 #include <Carbon/Carbon.h>
53 #endif
54
55 #include <qapplication.h>
56 #if QT_VERSION >= 0x030100
57 #include <qeventloop.h>
58 #endif
59 #include <qpaintdevicemetrics.h>
60 #include <qtranslator.h>
61 #include <qtextcodec.h>
62
63 using lyx::support::ltrim;
64 using lyx::support::package;
65
66 using lyx::frontend::Gui;
67 using lyx::frontend::GuiImplementation;
68 using lyx::frontend::QtView;
69
70 namespace os = lyx::support::os;
71
72 using boost::shared_ptr;
73
74 #ifndef CXX_GLOBAL_CSTD
75 using std::exit;
76 #endif
77
78 using std::map;
79 using std::vector;
80 using std::string;
81
82
83 extern BufferList bufferlist;
84
85 // FIXME: wrong place !
86 LyXServer * lyxserver;
87 LyXServerSocket * lyxsocket;
88
89 namespace {
90
91 int getDPI()
92 {
93         QWidget w;
94         QPaintDeviceMetrics pdm(&w);
95         return int(0.5 * (pdm.logicalDpiX() + pdm.logicalDpiY()));
96 }
97
98 map<int, shared_ptr<socket_callback> > socket_callbacks;
99
100 void cleanup()
101 {
102         delete lyxsocket;
103         lyxsocket = 0;
104         delete lyxserver;
105         lyxserver = 0;
106 }
107
108 } // namespace anon
109
110 // in QLyXKeySym.C
111 extern void initEncodings();
112
113 #ifdef Q_WS_X11
114 extern bool lyxX11EventFilter(XEvent * xev);
115 #endif
116
117 #ifdef Q_WS_MACX
118 extern pascal OSErr
119 handleOpenDocuments(const AppleEvent* inEvent, AppleEvent* /*reply*/,
120                     long /*refCon*/);
121 #endif
122
123 class LQApplication : public QApplication
124 {
125 public:
126         LQApplication(int & argc, char ** argv);
127         //
128         Gui & gui() { return gui_; }
129
130 #ifdef Q_WS_X11
131         bool x11EventFilter (XEvent * ev) { return lyxX11EventFilter(ev); }
132 #endif
133 #ifdef Q_WS_MACX
134         bool macEventFilter(EventRef event);
135 #endif
136
137 private:
138         ///
139         GuiImplementation gui_;
140 };
141
142
143 LQApplication::LQApplication(int & argc, char ** argv)
144         : QApplication(argc, argv)
145 {
146 #ifdef Q_WS_MACX
147         AEInstallEventHandler(kCoreEventClass, kAEOpenDocuments,
148                               NewAEEventHandlerUPP(handleOpenDocuments),
149                               0, false);
150 #endif
151 }
152
153
154 #ifdef Q_WS_MACX
155 bool LQApplication::macEventFilter(EventRef event)
156 {
157         if (GetEventClass(event) == kEventClassAppleEvent) {
158                 EventRecord eventrec;
159                 ConvertEventRefToEventRecord(event, &eventrec);
160                 AEProcessAppleEvent(&eventrec);
161
162                 return false;
163         }
164         return false;
165 }
166 #endif
167
168 LQApplication * theApp;
169
170 namespace lyx_gui {
171
172 bool use_gui = true;
173
174
175 int exec(int & argc, char * argv[])
176 {
177         // Force adding of font path _before_ QApplication is initialized
178         FontLoader::initFontPath();
179
180         LQApplication app(argc, argv);
181         theApp = &app;
182
183 #if QT_VERSION >= 0x030200
184         // install translation file for Qt built-in dialogs
185         // These are only installed since Qt 3.2.x
186         QTranslator qt_trans(0);
187         if (qt_trans.load(QString("qt_") + QTextCodec::locale(),
188                           qInstallPathTranslations())) {
189                 qApp->installTranslator(&qt_trans);
190                 // even if the language calls for RtL, don't do that
191                 qApp->setReverseLayout(false);
192                 lyxerr[Debug::GUI]
193                         << "Successfully installed Qt translations for locale "
194                         << QTextCodec::locale() << std::endl;
195         } else
196                 lyxerr[Debug::GUI]
197                         << "Could not find  Qt translations for locale "
198                         << QTextCodec::locale() << std::endl;
199 #endif
200
201 #ifdef Q_WS_MACX
202         // These translations are meant to break Qt/Mac menu merging
203         // algorithm on some entries. It lists the menu names that
204         // should not be moved to the LyX menu
205         QTranslator aqua_trans(0);
206         aqua_trans.insert(QTranslatorMessage("QMenuBar", "Setting", 0,
207                                              "do_not_merge_me"));
208         aqua_trans.insert(QTranslatorMessage("QMenuBar", "Config", 0,
209                                              "do_not_merge_me"));
210         aqua_trans.insert(QTranslatorMessage("QMenuBar", "Options", 0,
211                                              "do_not_merge_me"));
212         aqua_trans.insert(QTranslatorMessage("QMenuBar", "Setup", 0,
213                                              "do_not_merge_me"));
214
215         qApp->installTranslator(&aqua_trans);
216 #endif
217
218         using namespace lyx::graphics;
219
220         Image::newImage = boost::bind(&QLImage::newImage);
221         Image::loadableFormats = boost::bind(&QLImage::loadableFormats);
222
223         // needs to be done before reading lyxrc
224         lyxrc.dpi = getDPI();
225
226         LoaderQueue::setPriority(10,100);
227
228         return LyX::ref().exec2(argc, argv);
229 }
230
231
232 void parse_lyxrc()
233 {}
234
235
236 LyXView* create_view(unsigned int width, unsigned int height, int posx, int posy,
237               bool maximize)
238 {
239         // this can't be done before because it needs the Languages object
240         initEncodings();
241
242         int view_id = theApp->gui().newView(width, height);
243         QtView & view = static_cast<QtView &> (theApp->gui().view(view_id));
244         theApp->gui().newWorkArea(width, height, 0);
245
246         LyX::ref().addLyXView(&view);
247
248         view.init();
249
250         if (width != 0 && height != 0) {
251                 view.initFloatingGeometry(QRect(posx, posy, width, height));
252                 view.resize(width, height);
253                 if (posx != -1 && posy != -1)
254                         view.move(posx, posy);
255                 view.show();
256                 if (maximize)
257                         view.setWindowState(Qt::WindowMaximized);
258         } else
259                 view.show();
260
261         return &view;
262 }
263
264
265 int start(LyXView * view, string const & batch)
266 {
267         // FIXME: some code below needs moving
268
269         lyxserver = new LyXServer(&view->getLyXFunc(), lyxrc.lyxpipes);
270         lyxsocket = new LyXServerSocket(&view->getLyXFunc(),
271                           os::internal_path(package().temp_dir() + "/lyxsocket"));
272
273         // handle the batch commands the user asked for
274         if (!batch.empty()) {
275                 view->getLyXFunc().dispatch(lyxaction.lookupFunc(batch));
276         }
277
278         int const status = qApp->exec();
279
280         // FIXME
281         cleanup();
282         return status;
283 }
284
285
286 void sync_events()
287 {
288         // This is the ONLY place where processEvents may be called.
289         // During screen update/ redraw, this method is disabled to
290         // prevent keyboard events being handed to the LyX core, where
291         // they could cause re-entrant calls to screen update.
292 #if QT_VERSION >= 0x030100
293         qApp->eventLoop()->processEvents(QEventLoop::ExcludeUserInput);
294 #endif
295 }
296
297
298 void exit(int status)
299 {
300         cleanup();
301         QApplication::exit(status);
302 }
303
304
305 FuncStatus getStatus(FuncRequest const & ev)
306 {
307         FuncStatus flag;
308         switch (ev.action) {
309         case LFUN_TOOLTIPS_TOGGLE:
310                 flag.unknown(true);
311                 break;
312         default:
313                 break;
314         }
315
316         return flag;
317 }
318
319
320 bool getRGBColor(LColor_color col, lyx::RGBColor & rgbcol)
321 {
322         QColor const & qcol = lcolorcache.get(col);
323         if (!qcol.isValid()) {
324                 rgbcol.r = 0;
325                 rgbcol.g = 0;
326                 rgbcol.b = 0;
327                 return false;
328         }
329         rgbcol.r = qcol.red();
330         rgbcol.g = qcol.green();
331         rgbcol.b = qcol.blue();
332         return true;
333 }
334
335
336 string const hexname(LColor_color col)
337 {
338         return ltrim(fromqstr(lcolorcache.get(col).name()), "#");
339 }
340
341
342 void update_color(LColor_color)
343 {
344         // FIXME: Bleh, can't we just clear them all at once ?
345         lcolorcache.clear();
346 }
347
348
349 void update_fonts()
350 {
351         fontloader.update();
352 }
353
354
355 bool font_available(LyXFont const & font)
356 {
357         return fontloader.available(font);
358 }
359
360
361 void register_socket_callback(int fd, boost::function<void()> func)
362 {
363         socket_callbacks[fd] = shared_ptr<socket_callback>(new socket_callback(fd, func));
364 }
365
366
367 void unregister_socket_callback(int fd)
368 {
369         socket_callbacks.erase(fd);
370 }
371
372
373 string const roman_font_name()
374 {
375         if (!use_gui)
376                 return "serif";
377
378         QFont font;
379         font.setStyleHint(QFont::Serif);
380         font.setFamily("serif");
381
382         return fromqstr(QFontInfo(font).family());
383 }
384
385
386 string const sans_font_name()
387 {
388         if (!use_gui)
389                 return "sans";
390
391         QFont font;
392         font.setStyleHint(QFont::SansSerif);
393         font.setFamily("sans");
394
395         return fromqstr(QFontInfo(font).family());
396 }
397
398
399 string const typewriter_font_name()
400 {
401         if (!use_gui)
402                 return "monospace";
403
404         QFont font;
405         font.setStyleHint(QFont::TypeWriter);
406         font.setFamily("monospace");
407
408         return fromqstr(QFontInfo(font).family());
409 }
410
411 }; // namespace lyx_gui