]> git.lyx.org Git - lyx.git/blob - src/frontends/qt4/GuiAlert.cpp
Account for old versions of Pygments
[lyx.git] / src / frontends / qt4 / GuiAlert.cpp
1 /**
2  * \file qt4/GuiAlert.cpp
3  * This file is part of LyX, the document processor.
4  * Licence details can be found in the file COPYING.
5  *
6  * \author John Levon
7  * \author Jürgen Spitzmüller
8  * \author Abdelrazak Younes
9  *
10  * Full author contact details are available in file CREDITS.
11  */
12
13 #include <config.h>
14
15 #include "alert.h"
16 #include "InGuiThread.h"
17
18 #include "frontends/Application.h"
19
20 #include "qt_helpers.h"
21 #include "LyX.h" // for lyx::use_gui
22
23 #include "support/gettext.h"
24 #include "support/debug.h"
25 #include "support/docstring.h"
26 #include "support/lstrings.h"
27 #include "support/lassert.h"
28 #include "support/ProgressInterface.h"
29
30 #include <QApplication>
31 #include <QCheckBox>
32 #include <QMessageBox>
33 #include <QLineEdit>
34 #include <QInputDialog>
35 #include <QPushButton>
36 #include <QSettings>
37
38 #include <iomanip>
39 #include <iostream>
40
41
42 // sync with GuiView.cpp
43 #define EXPORT_in_THREAD 1
44
45
46 using namespace std;
47 using namespace lyx::support;
48
49 namespace lyx {
50 namespace frontend {
51
52
53 void noAppDialog(QString const & title, QString const & msg, QMessageBox::Icon mode)
54 {
55         int argc = 1;
56         const char *argv[] = { "lyx", 0 };
57
58         QApplication app(argc, (char**)argv);
59         switch (mode)
60         {
61                 case QMessageBox::Information: QMessageBox::information(0, title, msg); break;
62                 case QMessageBox::Warning: QMessageBox::warning(0, title, msg); break;
63                 case QMessageBox::Critical: QMessageBox::critical(0, title, msg); break;
64                 default: break;
65         }
66 }
67
68
69 namespace Alert {
70
71
72 docstring toPlainText(docstring const & msg)
73 {
74         return qstring_to_ucs4(qtHtmlToPlainText(toqstr(msg)));
75 }
76
77
78 int doPrompt(docstring const & title0, docstring const & question,
79                   int default_button, int cancel_button,
80                   docstring const & b1, docstring const & b2,
81                   docstring const & b3, docstring const & b4)
82 {
83         //lyxerr << "PROMPT" << title0 << "FOCUS: " << qApp->focusWidget() << endl;
84         if (!use_gui || lyxerr.debugging()) {
85                 lyxerr << toPlainText(title0) << '\n'
86                        << "----------------------------------------\n"
87                        << toPlainText(question) << endl;
88
89                 lyxerr << "Assuming answer is ";
90                 switch (default_button) {
91                 case 0: lyxerr << b1 << endl; break;
92                 case 1: lyxerr << b2 << endl; break;
93                 case 2: lyxerr << b3 << endl; break;
94                 case 3: lyxerr << b4 << endl;
95                 }
96                 if (!use_gui)
97                         return default_button;
98         }
99
100         docstring const title = bformat(_("LyX: %1$s"), title0);
101
102         /// Long operation in progress prevents user from Ok-ing the error dialog
103         bool long_op = theApp()->longOperationStarted();
104         if (long_op)
105                 theApp()->stopLongOperation();
106
107         // For some reason, sometimes Qt uses a hourglass or watch cursor when
108         // displaying the alert. Hence, we ask for the standard cursor shape.
109         qApp->setOverrideCursor(Qt::ArrowCursor);
110
111         // FIXME replace that with guiApp->currentView()
112         //LYXERR0("FOCUS: " << qApp->focusWidget());
113         QPushButton * b[4] = { 0, 0, 0, 0 };
114         QMessageBox msg_box(QMessageBox::Information,
115                         toqstr(title), toqstr(question),
116                         QMessageBox::NoButton, qApp->focusWidget());
117         b[0] = msg_box.addButton(b1.empty() ? "OK" : toqstr(b1),
118                                         QMessageBox::ActionRole);
119         if (!b2.empty())
120                 b[1] = msg_box.addButton(toqstr(b2), QMessageBox::ActionRole);
121         if (!b3.empty())
122                 b[2] = msg_box.addButton(toqstr(b3), QMessageBox::ActionRole);
123         if (!b4.empty())
124                 b[3] = msg_box.addButton(toqstr(b4), QMessageBox::ActionRole);
125         msg_box.setDefaultButton(b[default_button]);
126         msg_box.setEscapeButton(static_cast<QAbstractButton *>(b[cancel_button]));
127         int res = msg_box.exec();
128
129         qApp->restoreOverrideCursor();
130
131         if (long_op)
132                 theApp()->startLongOperation();
133
134         // Qt bug: can return -1 on cancel or WM close, despite the docs.
135         if (res == -1)
136                 res = cancel_button;
137         return res;
138 }
139
140 int prompt(docstring const & title0, docstring const & question,
141                   int default_button, int cancel_button,
142                   docstring const & b1, docstring const & b2,
143                   docstring const & b3, docstring const & b4)
144 {
145 #ifdef EXPORT_in_THREAD
146         return InGuiThread<int>().call(&doPrompt,
147 #else
148         return doPrompt(
149 #endif
150                                 title0, question, default_button,
151                                 cancel_button, b1, b2, b3, b4);
152 }
153
154 void doWarning(docstring const & title0, docstring const & message,
155              bool const & askshowagain)
156 {
157         lyxerr << "Warning: " << toPlainText(title0) << '\n'
158                << "----------------------------------------\n"
159                << toPlainText(message) << endl;
160
161         if (!use_gui)
162                 return;
163
164         docstring const title = bformat(_("LyX: %1$s"), title0);
165
166         if (theApp() == 0) {
167                 noAppDialog(toqstr(title), toqstr(message), QMessageBox::Warning);
168                 return;
169         }
170
171         /// Long operation in progress prevents user from Ok-ing the error dialog
172         bool long_op = theApp()->longOperationStarted();
173         if (long_op)
174                 theApp()->stopLongOperation();
175
176         // Don't use a hourglass cursor while displaying the alert
177         qApp->setOverrideCursor(Qt::ArrowCursor);
178
179         if (!askshowagain) {
180                 ProgressInterface::instance()->warning(
181                                 toqstr(title),
182                                 toqstr(message));
183         } else {
184                 ProgressInterface::instance()->toggleWarning(
185                                 toqstr(title),
186                                 toqstr(message),
187                                 toqstr(message));
188         }
189
190         qApp->restoreOverrideCursor();
191
192         if (long_op)
193                 theApp()->startLongOperation();
194 }
195
196 void warning(docstring const & title0, docstring const & message,
197              bool const & askshowagain)
198 {
199 #ifdef EXPORT_in_THREAD 
200         InGuiThread<void>().call(&doWarning,
201 #else
202         doWarning(
203 #endif
204                                 title0, message, askshowagain);
205 }
206
207 void doError(docstring const & title0, docstring const & message, bool backtrace)
208 {
209         lyxerr << "Error: " << toPlainText(title0) << '\n'
210                << "----------------------------------------\n"
211                << toPlainText(message) << endl;
212
213         QString details;
214         if (backtrace)
215                 details = toqstr(printCallStack());
216
217         if (!use_gui)
218                 return;
219
220         docstring const title = bformat(_("LyX: %1$s"), title0);
221
222         if (theApp() == 0) {
223                 noAppDialog(toqstr(title), toqstr(message), QMessageBox::Critical);
224                 return;
225         }
226
227         /// Long operation in progress prevents user from Ok-ing the error dialog
228         bool long_op = theApp()->longOperationStarted();
229         if (long_op)
230                 theApp()->stopLongOperation();
231
232         // Don't use a hourglass cursor while displaying the alert
233         qApp->setOverrideCursor(Qt::ArrowCursor);
234
235         ProgressInterface::instance()->error(
236                 toqstr(title),
237                 toqstr(message),
238                 details);
239
240         qApp->restoreOverrideCursor();
241
242         if (long_op)
243                 theApp()->startLongOperation();
244 }
245
246 void error(docstring const & title0, docstring const & message, bool backtrace)
247 {
248 #ifdef EXPORT_in_THREAD
249         InGuiThread<void>().call(&doError, 
250 #else
251         doError(
252 #endif
253                                 title0, message, backtrace);
254 }
255
256 void doInformation(docstring const & title0, docstring const & message)
257 {
258         if (!use_gui || lyxerr.debugging())
259                 lyxerr << toPlainText(title0) << '\n'
260                        << "----------------------------------------\n"
261                        << toPlainText(message) << endl;
262
263         if (!use_gui)
264                 return;
265
266         docstring const title = bformat(_("LyX: %1$s"), title0);
267
268         if (theApp() == 0) {
269                 noAppDialog(toqstr(title), toqstr(message), QMessageBox::Information);
270                 return;
271         }
272
273         /// Long operation in progress prevents user from Ok-ing the error dialog
274         bool long_op = theApp()->longOperationStarted();
275         if (long_op)
276                 theApp()->stopLongOperation();
277
278         // Don't use a hourglass cursor while displaying the alert
279         qApp->setOverrideCursor(Qt::ArrowCursor);
280
281         ProgressInterface::instance()->information(
282                 toqstr(title),
283                 toqstr(message));
284
285         qApp->restoreOverrideCursor();
286
287         if (long_op)
288                 theApp()->startLongOperation();
289 }
290
291 void information(docstring const & title0, docstring const & message)
292 {
293 #ifdef EXPORT_in_THREAD
294         InGuiThread<void>().call(&doInformation,
295 #else
296         doInformation(
297 #endif
298                                 title0, message);
299 }
300
301 bool doAskForText(docstring & response, docstring const & msg,
302         docstring const & dflt)
303 {
304         if (!use_gui || lyxerr.debugging()) {
305                 lyxerr << "----------------------------------------\n"
306                        << toPlainText(msg) << '\n'
307                        << "Assuming answer is " << dflt << '\n'
308                        << "----------------------------------------" << endl;
309                 if (!use_gui) {
310                         response = dflt;
311                         return true;
312                 }
313         }
314
315         docstring const title = bformat(_("LyX: %1$s"), msg);
316
317         /// Long operation in progress prevents user from Ok-ing the error dialog
318         bool long_op = theApp()->longOperationStarted();
319         if (long_op)
320                 theApp()->stopLongOperation();
321
322         bool ok;
323         QString text = QInputDialog::getText(qApp->focusWidget(),
324                 toqstr(title),
325                 toqstr(char_type('&') + msg),
326                 QLineEdit::Normal,
327                 toqstr(dflt), &ok);
328
329         if (long_op)
330                 theApp()->startLongOperation();
331
332         if (ok) {
333                 response = qstring_to_ucs4(text);
334                 return true;
335         }
336         response.clear();
337         return false;
338 }
339
340 bool askForText(docstring & response, docstring const & msg,
341         docstring const & dflt)
342 {
343 #ifdef EXPORT_in_THREAD
344         return InGuiThread<bool>().call(&doAskForText,
345 #else
346         return doAskForText(
347 #endif
348                                 response, msg, dflt);
349 }
350
351 } // namespace Alert
352 } // namespace frontend
353 } // namespace lyx