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