]> git.lyx.org Git - lyx.git/blob - src/frontends/qt4/GuiAlert.cpp
Add missing breaks
[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 int doPrompt(docstring const & title0, docstring const & question,
73                   int default_button, int cancel_button,
74                   docstring const & b1, docstring const & b2,
75                   docstring const & b3, docstring const & b4)
76 {
77         //lyxerr << "PROMPT" << title0 << "FOCUS: " << qApp->focusWidget() << endl;
78         if (!use_gui || lyxerr.debugging()) {
79                 lyxerr << title0 << '\n'
80                        << "----------------------------------------\n"
81                        << question << endl;
82
83                 lyxerr << "Assuming answer is ";
84                 switch (default_button) {
85                 case 0: lyxerr << b1 << endl; break;
86                 case 1: lyxerr << b2 << endl; break;
87                 case 2: lyxerr << b3 << endl; break;
88                 case 3: lyxerr << b4 << endl;
89                 }
90                 if (!use_gui)
91                         return default_button;
92         }
93
94         docstring const title = bformat(_("LyX: %1$s"), title0);
95
96         /// Long operation in progress prevents user from Ok-ing the error dialog
97         bool long_op = theApp()->longOperationStarted();
98         if (long_op)
99                 theApp()->stopLongOperation();
100
101         // For some reason, sometimes Qt uses a hourglass or watch cursor when
102         // displaying the alert. Hence, we ask for the standard cursor shape.
103         qApp->setOverrideCursor(Qt::ArrowCursor);
104
105         // FIXME replace that with guiApp->currentView()
106         //LYXERR0("FOCUS: " << qApp->focusWidget());
107         QPushButton * b[4] = { 0, 0, 0, 0 };
108         QMessageBox msg_box(QMessageBox::Information,
109                         toqstr(title), toqstr(question),
110                         QMessageBox::NoButton, qApp->focusWidget());
111         b[0] = msg_box.addButton(b1.empty() ? "OK" : toqstr(b1),
112                                         QMessageBox::ActionRole);
113         if (!b2.empty())
114                 b[1] = msg_box.addButton(toqstr(b2), QMessageBox::ActionRole);
115         if (!b3.empty())
116                 b[2] = msg_box.addButton(toqstr(b3), QMessageBox::ActionRole);
117         if (!b4.empty())
118                 b[3] = msg_box.addButton(toqstr(b4), QMessageBox::ActionRole);
119         msg_box.setDefaultButton(b[default_button]);
120         msg_box.setEscapeButton(static_cast<QAbstractButton *>(b[cancel_button]));
121         int res = msg_box.exec();
122
123         qApp->restoreOverrideCursor();
124
125         if (long_op)
126                 theApp()->startLongOperation();
127
128         // Qt bug: can return -1 on cancel or WM close, despite the docs.
129         if (res == -1)
130                 res = cancel_button;
131         return res;
132 }
133
134 int prompt(docstring const & title0, docstring const & question,
135                   int default_button, int cancel_button,
136                   docstring const & b1, docstring const & b2,
137                   docstring const & b3, docstring const & b4)
138 {
139 #ifdef EXPORT_in_THREAD
140         return InGuiThread<int>().call(&doPrompt,
141 #else
142         return doPrompt(
143 #endif
144                                 title0, question, default_button,
145                                 cancel_button, b1, b2, b3, b4);
146 }
147
148 void doWarning(docstring const & title0, docstring const & message,
149              bool const & askshowagain)
150 {
151         lyxerr << "Warning: " << title0 << '\n'
152                << "----------------------------------------\n"
153                << message << endl;
154
155         if (!use_gui)
156                 return;
157
158         docstring const title = bformat(_("LyX: %1$s"), title0);
159
160         if (theApp() == 0) {
161                 noAppDialog(toqstr(title), toqstr(message), QMessageBox::Warning);
162                 return;
163         }
164
165         /// Long operation in progress prevents user from Ok-ing the error dialog
166         bool long_op = theApp()->longOperationStarted();
167         if (long_op)
168                 theApp()->stopLongOperation();
169
170         // Don't use a hourglass cursor while displaying the alert
171         qApp->setOverrideCursor(Qt::ArrowCursor);
172
173         if (!askshowagain) {
174                 ProgressInterface::instance()->warning(
175                                 toqstr(title),
176                                 toqstr(message));
177         } else {
178                 ProgressInterface::instance()->toggleWarning(
179                                 toqstr(title),
180                                 toqstr(message),
181                                 toqstr(message));
182         }
183
184         qApp->restoreOverrideCursor();
185
186         if (long_op)
187                 theApp()->startLongOperation();
188 }
189
190 void warning(docstring const & title0, docstring const & message,
191              bool const & askshowagain)
192 {
193 #ifdef EXPORT_in_THREAD 
194         InGuiThread<void>().call(&doWarning,
195 #else
196         doWarning(
197 #endif
198                                 title0, message, askshowagain);
199 }
200
201 void doError(docstring const & title0, docstring const & message, bool backtrace)
202 {
203         lyxerr << "Error: " << title0 << '\n'
204                << "----------------------------------------\n"
205                << message << endl;
206
207         QString details;
208         if (backtrace) {
209                 details = QString::fromLocal8Bit(to_local8bit(printCallStack()).c_str());
210         }
211
212         if (!use_gui)
213                 return;
214
215         docstring const title = bformat(_("LyX: %1$s"), title0);
216
217         if (theApp() == 0) {
218                 noAppDialog(toqstr(title), toqstr(message), QMessageBox::Critical);
219                 return;
220         }
221
222         /// Long operation in progress prevents user from Ok-ing the error dialog
223         bool long_op = theApp()->longOperationStarted();
224         if (long_op)
225                 theApp()->stopLongOperation();
226
227         // Don't use a hourglass cursor while displaying the alert
228         qApp->setOverrideCursor(Qt::ArrowCursor);
229
230         ProgressInterface::instance()->error(
231                 toqstr(title),
232                 toqstr(message),
233                 details);
234
235         qApp->restoreOverrideCursor();
236
237         if (long_op)
238                 theApp()->startLongOperation();
239 }
240
241 void error(docstring const & title0, docstring const & message, bool backtrace)
242 {
243 #ifdef EXPORT_in_THREAD
244         InGuiThread<void>().call(&doError, 
245 #else
246         doError(
247 #endif
248                                 title0, message, backtrace);
249 }
250
251 void doInformation(docstring const & title0, docstring const & message)
252 {
253         if (!use_gui || lyxerr.debugging())
254                 lyxerr << title0 << '\n'
255                        << "----------------------------------------\n"
256                        << message << endl;
257
258         if (!use_gui)
259                 return;
260
261         docstring const title = bformat(_("LyX: %1$s"), title0);
262
263         if (theApp() == 0) {
264                 noAppDialog(toqstr(title), toqstr(message), QMessageBox::Information);
265                 return;
266         }
267
268         /// Long operation in progress prevents user from Ok-ing the error dialog
269         bool long_op = theApp()->longOperationStarted();
270         if (long_op)
271                 theApp()->stopLongOperation();
272
273         // Don't use a hourglass cursor while displaying the alert
274         qApp->setOverrideCursor(Qt::ArrowCursor);
275
276         ProgressInterface::instance()->information(
277                 toqstr(title),
278                 toqstr(message));
279
280         qApp->restoreOverrideCursor();
281
282         if (long_op)
283                 theApp()->startLongOperation();
284 }
285
286 void information(docstring const & title0, docstring const & message)
287 {
288 #ifdef EXPORT_in_THREAD
289         InGuiThread<void>().call(&doInformation,
290 #else
291         doInformation(
292 #endif
293                                 title0, message);
294 }
295
296 bool doAskForText(docstring & response, docstring const & msg,
297         docstring const & dflt)
298 {
299         if (!use_gui || lyxerr.debugging()) {
300                 lyxerr << "----------------------------------------\n"
301                        << msg << '\n'
302                        << "Assuming answer is " << dflt << '\n'
303                        << "----------------------------------------" << endl;
304                 if (!use_gui) {
305                         response = dflt;
306                         return true;
307                 }
308         }
309
310         docstring const title = bformat(_("LyX: %1$s"), msg);
311
312         /// Long operation in progress prevents user from Ok-ing the error dialog
313         bool long_op = theApp()->longOperationStarted();
314         if (long_op)
315                 theApp()->stopLongOperation();
316
317         bool ok;
318         QString text = QInputDialog::getText(qApp->focusWidget(),
319                 toqstr(title),
320                 toqstr(char_type('&') + msg),
321                 QLineEdit::Normal,
322                 toqstr(dflt), &ok);
323
324         if (long_op)
325                 theApp()->startLongOperation();
326
327         if (ok) {
328                 response = qstring_to_ucs4(text);
329                 return true;
330         }
331         response.clear();
332         return false;
333 }
334
335 bool askForText(docstring & response, docstring const & msg,
336         docstring const & dflt)
337 {
338 #ifdef EXPORT_in_THREAD
339         return InGuiThread<bool>().call(&doAskForText,
340 #else
341         return doAskForText(
342 #endif
343                                 response, msg, dflt);
344 }
345
346 } // namespace Alert
347 } // namespace frontend
348 } // namespace lyx