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