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