]> git.lyx.org Git - lyx.git/blob - src/frontends/qt4/lyx_gui.C
Pass width = 0 and height = 0 as unsigned int to indicate the usage of the geometry...
[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 void 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         LyX::ref().exec2(argc, argv);
189 }
190
191
192 void parse_lyxrc()
193 {}
194
195
196 void start(string const & batch, vector<string> const & files,
197            unsigned int width, unsigned int height, int posx, int posy, bool maximize)
198 {
199         // this can't be done before because it needs the Languages object
200         initEncodings();
201
202         int view_id = theApp->gui().newView(width, height);
203         GuiView & view = static_cast<GuiView &> (theApp->gui().view(view_id));
204
205         // FIXME: for now we assume that there is only one LyXView with id = 0.
206         int workArea_id_ = theApp->gui().newWorkArea(width, height, 0);
207         //WorkArea * workArea_ = & theApp->gui().workArea(workArea_id_);
208
209         LyX::ref().addLyXView(&view);
210
211         view.init();
212                 
213         // only true when the -geometry option was NOT used
214         if (width != 0 && height != 0) {
215                 if (posx != -1 && posy != -1) {
216 #ifdef Q_OS_WIN32
217                         // FIXME: use only setGeoemtry when Trolltech has
218                         // fixed the qt4/X11 bug
219                         view.setGeometry(posx, posy,width, height);
220 #else
221                         view.resize(width, height);
222                         view.move(posx, posy);
223 #endif
224                 } else {
225                         view.resize(width, height);
226                 }
227
228                 if (maximize)
229                         view.setWindowState(Qt::WindowMaximized);
230         }
231
232         view.show();
233
234         // FIXME: some code below needs moving
235
236         lyxserver = new LyXServer(&view.getLyXFunc(), lyxrc.lyxpipes);
237         lyxsocket = new LyXServerSocket(&view.getLyXFunc(),
238                           os::internal_path(package().temp_dir() + "/lyxsocket"));
239
240         for_each(files.begin(), files.end(),
241                  bind(&BufferView::loadLyXFile, view.view(), _1, true));
242
243         // handle the batch commands the user asked for
244         if (!batch.empty()) {
245                 view.getLyXFunc().dispatch(lyxaction.lookupFunc(batch));
246         }
247
248         qApp->exec();
249
250         // FIXME
251         cleanup();
252 }
253
254
255 void sync_events()
256 {
257         // This is the ONLY place where processEvents may be called.
258         // During screen update/ redraw, this method is disabled to
259         // prevent keyboard events being handed to the LyX core, where
260         // they could cause re-entrant calls to screen update.
261         qApp->processEvents(QEventLoop::ExcludeUserInputEvents);
262 }
263
264
265 void exit(int status)
266 {
267         cleanup();
268
269         // we cannot call QApplication::exit(status) - that could return us
270         // into a static dialog return in the lyx code (for example,
271         // load autosave file QMessageBox. We have to just get the hell
272         // out.
273
274         ::exit(status);
275 }
276
277
278 FuncStatus getStatus(FuncRequest const & ev)
279 {
280         FuncStatus flag;
281         switch (ev.action) {
282         case LFUN_DIALOG_SHOW:
283                 if (ev.argument == "preamble")
284                         flag.unknown(true);
285                 break;
286         case LFUN_TOOLTIPS_TOGGLE:
287                 flag.unknown(true);
288                 break;
289         default:
290                 break;
291         }
292
293         return flag;
294 }
295
296
297 bool getRGBColor(LColor_color col, lyx::RGBColor & rgbcol)
298 {
299         QColor const & qcol = lcolorcache.get(col);
300         if (!qcol.isValid()) {
301                 rgbcol.r = 0;
302                 rgbcol.g = 0;
303                 rgbcol.b = 0;
304                 return false;
305         }
306         rgbcol.r = qcol.red();
307         rgbcol.g = qcol.green();
308         rgbcol.b = qcol.blue();
309         return true;
310 }
311
312
313 string const hexname(LColor_color col)
314 {
315         return ltrim(fromqstr(lcolorcache.get(col).name()), "#");
316 }
317
318
319 void update_color(LColor_color)
320 {
321         // FIXME: Bleh, can't we just clear them all at once ?
322         lcolorcache.clear();
323 }
324
325
326 void update_fonts()
327 {
328         theApp->fontLoader().update();
329 }
330
331
332 bool font_available(LyXFont const & font)
333 {
334         return theApp->fontLoader().available(font);
335 }
336
337
338 void register_socket_callback(int fd, boost::function<void()> func)
339 {
340         socket_callbacks[fd] = shared_ptr<socket_callback>(new socket_callback(fd, func));
341 }
342
343
344 void unregister_socket_callback(int fd)
345 {
346         socket_callbacks.erase(fd);
347 }
348
349
350 string const roman_font_name()
351 {
352         if (!use_gui)
353                 return "serif";
354
355         QFont font;
356         font.setStyleHint(QFont::Serif);
357         font.setFamily("serif");
358
359         return fromqstr(QFontInfo(font).family());
360 }
361
362
363 string const sans_font_name()
364 {
365         if (!use_gui)
366                 return "sans";
367
368         QFont font;
369         font.setStyleHint(QFont::SansSerif);
370         font.setFamily("sans");
371
372         return fromqstr(QFontInfo(font).family());
373 }
374
375
376 string const typewriter_font_name()
377 {
378         if (!use_gui)
379                 return "monospace";
380
381         QFont font;
382         font.setStyleHint(QFont::TypeWriter);
383         font.setFamily("monospace");
384
385         return fromqstr(QFontInfo(font).family());
386 }
387
388 }; // namespace lyx_gui