]> git.lyx.org Git - lyx.git/blob - src/frontends/qt4/lyx_gui.C
Reduce calls of ::exit()
[lyx.git] / src / frontends / qt4 / lyx_gui.C
1 /**
2  * \file qt4/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  * \author Abdelrazak Younes
9  *
10  * Full author contact details are available in file CREDITS.
11  */
12
13 #undef QT3_SUPPORT
14
15 #include <config.h>
16
17 #include "lyx_gui.h"
18
19 // FIXME: move this stuff out again
20 #include "bufferlist.h"
21 #include "BufferView.h"
22 #include "Color.h"
23 #include "funcrequest.h"
24 #include "LColor.h"
25 #include "lyx_main.h"
26 #include "LyXAction.h"
27 #include "lyxfunc.h"
28 #include "lyxrc.h"
29 #include "lyxserver.h"
30 #include "lyxsocket.h"
31
32 #include "graphics/LoaderQueue.h"
33
34 #include "support/lstrings.h"
35 #include "support/os.h"
36 #include "support/package.h"
37 #include "debug.h"
38
39 #include <boost/bind.hpp>
40 #include <boost/shared_ptr.hpp>
41
42 #include "GuiView.h"
43 #include "ColorCache.h"
44 #include "FontLoader.h"
45 #include "QLImage.h"
46 #include "qt_helpers.h"
47 #include "socket_callback.h"
48 #include "Application.h"
49
50 #include <QApplication>
51 #include <QEventLoop>
52 #include <QTranslator>
53 #include <QTextCodec>
54 #include <QLocale>
55 #include <QLibraryInfo>
56
57
58
59 using lyx::support::ltrim;
60 using lyx::support::package;
61
62 using lyx::frontend::GuiImplementation;
63 using lyx::frontend::GuiView;
64 using lyx::frontend::Application;
65
66 namespace os = lyx::support::os;
67
68 using boost::shared_ptr;
69
70 #ifndef CXX_GLOBAL_CSTD
71 using std::exit;
72 #endif
73
74 using std::map;
75 using std::vector;
76 using std::string;
77
78 // FIXME: wrong place !
79 LyXServer * lyxserver;
80 LyXServerSocket * lyxsocket;
81
82 lyx::frontend::Application * theApp;
83
84 namespace {
85
86 int getDPI()
87 {
88         QWidget w;
89         return int(0.5 * (w.logicalDpiX() + w.logicalDpiY()));
90 }
91
92 map<int, shared_ptr<socket_callback> > socket_callbacks;
93
94 void cleanup()
95 {
96         delete lyxsocket;
97         lyxsocket = 0;
98         delete lyxserver;
99         lyxserver = 0;
100 }
101
102 } // namespace anon
103
104 // in QLyXKeySym.C
105 extern void initEncodings();
106
107 namespace lyx_gui {
108
109 bool use_gui = true;
110
111 int exec(int & argc, char * argv[])
112 {       
113         /*
114         FIXME : Abdel 29/05/2006 (younes.a@free.fr)
115         reorganize this code. In particular make sure that this
116         advice from Qt documentation is respected:
117         
118                 Since the QApplication object does so much initialization, it
119                 must be created before any other objects related to the user
120                 interface are created.
121         
122         Right now this is not the case, I suspect that a number of global variables
123         contains Qt object that are initialized before the passage through
124         parse_init(). This might also explain the message displayed by Qt
125         that caused the hanging:
126
127         QObject::killTimer: timers cannot be stopped from another thread
128         */
129
130         // Force adding of font path _before_ QApplication is initialized
131         FontLoader::initFontPath();
132
133 #ifdef Q_WS_WIN
134         static Application app(argc, argv);
135 #else
136         Application app(argc, argv);
137 #endif
138
139         theApp = &app;
140
141
142         // install translation file for Qt built-in dialogs
143         // These are only installed since Qt 3.2.x
144         QTranslator qt_trans;
145         QString language_name = QString("qt_") + QLocale::system().name();
146         language_name.truncate(5);
147         if (qt_trans.load(language_name,
148                 QLibraryInfo::location(QLibraryInfo::TranslationsPath)))
149         {
150                 qApp->installTranslator(&qt_trans);
151                 // even if the language calls for RtL, don't do that
152                 qApp->setLayoutDirection(Qt::LeftToRight);
153                 lyxerr[Debug::GUI]
154                         << "Successfully installed Qt translations for locale "
155                         << fromqstr(language_name) << std::endl;
156         } else
157                 lyxerr[Debug::GUI]
158                         << "Could not find  Qt translations for locale "
159                         << fromqstr(language_name) << std::endl;
160
161 /*#ifdef Q_WS_MACX
162         // These translations are meant to break Qt/Mac menu merging
163         // algorithm on some entries. It lists the menu names that
164         // should not be moved to the LyX menu
165         QTranslator aqua_trans(0);
166         aqua_trans.insert(QTranslatorMessage("QMenuBar", "Setting", 0,
167                                              "do_not_merge_me"));
168         aqua_trans.insert(QTranslatorMessage("QMenuBar", "Config", 0,
169                                              "do_not_merge_me"));
170         aqua_trans.insert(QTranslatorMessage("QMenuBar", "Options", 0,
171                                              "do_not_merge_me"));
172         aqua_trans.insert(QTranslatorMessage("QMenuBar", "Setup", 0,
173                                              "do_not_merge_me"));
174
175         qApp->installTranslator(&aqua_trans);
176 #endif
177 */
178         using namespace lyx::graphics;
179
180         Image::newImage = boost::bind(&QLImage::newImage);
181         Image::loadableFormats = boost::bind(&QLImage::loadableFormats);
182
183         // needs to be done before reading lyxrc
184         lyxrc.dpi = getDPI();
185
186         LoaderQueue::setPriority(10,100);
187
188         return LyX::ref().exec2(argc, argv);
189 }
190
191
192 void parse_lyxrc()
193 {}
194
195
196 int start(string const & batch, vector<string> const & files,
197           unsigned int width, unsigned int height, int posx, int posy,
198           bool maximize)
199 {
200         // this can't be done before because it needs the Languages object
201         initEncodings();
202
203         int view_id = theApp->gui().newView(width, height);
204         GuiView & view = static_cast<GuiView &> (theApp->gui().view(view_id));
205
206         // FIXME: for now we assume that there is only one LyXView with id = 0.
207         int workArea_id_ = theApp->gui().newWorkArea(width, height, 0);
208         //WorkArea * workArea_ = & theApp->gui().workArea(workArea_id_);
209
210         LyX::ref().addLyXView(&view);
211
212         view.init();
213                 
214         // only true when the -geometry option was NOT used
215         if (width != 0 && height != 0) {
216                 if (posx != -1 && posy != -1) {
217 #ifdef Q_OS_WIN32
218                         // FIXME: use only setGeoemtry when Trolltech has
219                         // fixed the qt4/X11 bug
220                         view.setGeometry(posx, posy,width, height);
221 #else
222                         view.resize(width, height);
223                         view.move(posx, posy);
224 #endif
225                 } else {
226                         view.resize(width, height);
227                 }
228
229                 if (maximize)
230                         view.setWindowState(Qt::WindowMaximized);
231         }
232
233         view.show();
234
235         // FIXME: some code below needs moving
236
237         lyxserver = new LyXServer(&view.getLyXFunc(), lyxrc.lyxpipes);
238         lyxsocket = new LyXServerSocket(&view.getLyXFunc(),
239                           os::internal_path(package().temp_dir() + "/lyxsocket"));
240
241         for_each(files.begin(), files.end(),
242                  bind(&BufferView::loadLyXFile, view.view(), _1, true));
243
244         // handle the batch commands the user asked for
245         if (!batch.empty()) {
246                 view.getLyXFunc().dispatch(lyxaction.lookupFunc(batch));
247         }
248
249         int const status = qApp->exec();
250
251         // FIXME
252         cleanup();
253         return status;
254 }
255
256
257 void sync_events()
258 {
259         // This is the ONLY place where processEvents may be called.
260         // During screen update/ redraw, this method is disabled to
261         // prevent keyboard events being handed to the LyX core, where
262         // they could cause re-entrant calls to screen update.
263         qApp->processEvents(QEventLoop::ExcludeUserInputEvents);
264 }
265
266
267 void exit(int status)
268 {
269         cleanup();
270         QApplication::exit(status);
271 }
272
273
274 FuncStatus getStatus(FuncRequest const & ev)
275 {
276         FuncStatus flag;
277         switch (ev.action) {
278         case LFUN_DIALOG_SHOW:
279                 if (ev.argument == "preamble")
280                         flag.unknown(true);
281                 break;
282         case LFUN_TOOLTIPS_TOGGLE:
283                 flag.unknown(true);
284                 break;
285         default:
286                 break;
287         }
288
289         return flag;
290 }
291
292
293 bool getRGBColor(LColor_color col, lyx::RGBColor & rgbcol)
294 {
295         QColor const & qcol = lcolorcache.get(col);
296         if (!qcol.isValid()) {
297                 rgbcol.r = 0;
298                 rgbcol.g = 0;
299                 rgbcol.b = 0;
300                 return false;
301         }
302         rgbcol.r = qcol.red();
303         rgbcol.g = qcol.green();
304         rgbcol.b = qcol.blue();
305         return true;
306 }
307
308
309 string const hexname(LColor_color col)
310 {
311         return ltrim(fromqstr(lcolorcache.get(col).name()), "#");
312 }
313
314
315 void update_color(LColor_color)
316 {
317         // FIXME: Bleh, can't we just clear them all at once ?
318         lcolorcache.clear();
319 }
320
321
322 void update_fonts()
323 {
324         theApp->fontLoader().update();
325 }
326
327
328 bool font_available(LyXFont const & font)
329 {
330         return theApp->fontLoader().available(font);
331 }
332
333
334 void register_socket_callback(int fd, boost::function<void()> func)
335 {
336         socket_callbacks[fd] = shared_ptr<socket_callback>(new socket_callback(fd, func));
337 }
338
339
340 void unregister_socket_callback(int fd)
341 {
342         socket_callbacks.erase(fd);
343 }
344
345
346 string const roman_font_name()
347 {
348         if (!use_gui)
349                 return "serif";
350
351         QFont font;
352         font.setStyleHint(QFont::Serif);
353         font.setFamily("serif");
354
355         return fromqstr(QFontInfo(font).family());
356 }
357
358
359 string const sans_font_name()
360 {
361         if (!use_gui)
362                 return "sans";
363
364         QFont font;
365         font.setStyleHint(QFont::SansSerif);
366         font.setFamily("sans");
367
368         return fromqstr(QFontInfo(font).family());
369 }
370
371
372 string const typewriter_font_name()
373 {
374         if (!use_gui)
375                 return "monospace";
376
377         QFont font;
378         font.setStyleHint(QFont::TypeWriter);
379         font.setFamily("monospace");
380
381         return fromqstr(QFontInfo(font).family());
382 }
383
384 }; // namespace lyx_gui