]> git.lyx.org Git - lyx.git/blob - src/frontends/qt4/GuiAlert.cpp
Fix the tab ordering of GuiDocument components.
[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/ProgressInterface.h"
28
29 #include <QApplication>
30 #include <QCheckBox>
31 #include <QMessageBox>
32 #include <QLineEdit>
33 #include <QInputDialog>
34 #include <QPushButton>
35 #include <QSettings>
36
37 #include <iomanip>
38 #include <iostream>
39
40
41 // sync with GuiView.cpp
42 #define EXPORT_in_THREAD 1
43
44
45 using namespace std;
46 using namespace lyx::support;
47
48 namespace lyx {
49 namespace frontend {
50
51
52 void noAppDialog(QString const & title, QString const & msg, QMessageBox::Icon mode)
53 {
54         int argc = 1;
55         const char *argv[] = { "lyx", 0 };
56
57         QApplication app(argc, (char**)argv);
58         switch (mode)
59         {
60                 case QMessageBox::Information: QMessageBox::information(0, title, msg); break;
61                 case QMessageBox::Warning: QMessageBox::warning(0, title, msg); break;
62                 case QMessageBox::Critical: QMessageBox::critical(0, title, msg); break;
63                 default: break;
64         }
65 }
66
67
68 namespace Alert {
69
70
71 int doPrompt(docstring const & title0, docstring const & question,
72                   int default_button, int cancel_button,
73                   docstring const & b1, docstring const & b2,
74                   docstring const & b3, docstring const & b4)
75 {
76         //lyxerr << "PROMPT" << title0 << "FOCUS: " << qApp->focusWidget() << endl;
77         if (!use_gui || lyxerr.debugging()) {
78                 lyxerr << title0 << '\n'
79                        << "----------------------------------------\n"
80                        << question << endl;
81
82                 lyxerr << "Assuming answer is ";
83                 switch (default_button) {
84                 case 0: lyxerr << b1 << endl;
85                 case 1: lyxerr << b2 << endl;
86                 case 2: lyxerr << b3 << endl;
87                 case 3: lyxerr << b4 << endl;
88                 }
89                 if (!use_gui)
90                         return default_button;
91         }
92
93         docstring const title = bformat(_("LyX: %1$s"), title0);
94
95         // For some reason, sometimes Qt uses a hourglass or watch cursor when
96         // displaying the alert. Hence, we ask for the standard cursor shape.
97         qApp->setOverrideCursor(Qt::ArrowCursor);
98
99         // FIXME replace that with guiApp->currentView()
100         //LYXERR0("FOCUS: " << qApp->focusWidget());
101         QPushButton * b[4] = { 0, 0, 0, 0 };
102         QMessageBox msg_box(QMessageBox::Information,
103                         toqstr(title), toqstr(question),
104                         QMessageBox::NoButton, qApp->focusWidget());
105         b[0] = msg_box.addButton(b1.empty() ? "OK" : toqstr(b1),
106                                         QMessageBox::ActionRole);
107         if (!b2.empty())
108                 b[1] = msg_box.addButton(toqstr(b2), QMessageBox::ActionRole);
109         if (!b3.empty())
110                 b[2] = msg_box.addButton(toqstr(b3), QMessageBox::ActionRole);
111         if (!b4.empty())
112                 b[3] = msg_box.addButton(toqstr(b4), QMessageBox::ActionRole);
113         msg_box.setDefaultButton(b[default_button]);
114         msg_box.setEscapeButton(static_cast<QAbstractButton *>(b[cancel_button]));
115         int res = msg_box.exec();
116
117         qApp->restoreOverrideCursor();
118
119         // Qt bug: can return -1 on cancel or WM close, despite the docs.
120         if (res == -1)
121                 res = cancel_button;
122         return res;
123 }
124
125 int prompt(docstring const & title0, docstring const & question,
126                   int default_button, int cancel_button,
127                   docstring const & b1, docstring const & b2,
128                   docstring const & b3, docstring const & b4)
129 {
130 #ifdef EXPORT_in_THREAD
131         return InGuiThread<int>().call(&doPrompt,
132 #else
133         return doPrompt(
134 #endif
135                                 title0, question, default_button,
136                                 cancel_button, b1, b2, b3, b4);
137 }
138
139 void doWarning(docstring const & title0, docstring const & message,
140              bool const & askshowagain)
141 {
142         lyxerr << "Warning: " << title0 << '\n'
143                << "----------------------------------------\n"
144                << message << endl;
145
146         if (!use_gui)
147                 return;
148
149         docstring const title = bformat(_("LyX: %1$s"), title0);
150
151         if (theApp() == 0) {
152                 noAppDialog(toqstr(title), toqstr(message), QMessageBox::Warning);
153                 return;
154         }
155
156         // Don't use a hourglass cursor while displaying the alert
157         qApp->setOverrideCursor(Qt::ArrowCursor);
158
159         if (!askshowagain) {
160                 ProgressInterface::instance()->warning(
161                                 toqstr(title),
162                                 toqstr(message));
163         } else {
164                 ProgressInterface::instance()->toggleWarning(
165                                 toqstr(title),
166                                 toqstr(message),
167                                 toqstr(message));
168         }
169
170         qApp->restoreOverrideCursor();
171 }
172
173 void warning(docstring const & title0, docstring const & message,
174              bool const & askshowagain)
175 {
176 #ifdef EXPORT_in_THREAD 
177         InGuiThread<void>().call(&doWarning,
178 #else
179         doWarning(
180 #endif
181                                 title0, message, askshowagain);
182 }
183
184 void doError(docstring const & title0, docstring const & message)
185 {
186         lyxerr << "Error: " << title0 << '\n'
187                << "----------------------------------------\n"
188                << message << endl;
189
190         if (!use_gui)
191                 return;
192
193         docstring const title = bformat(_("LyX: %1$s"), title0);
194
195         if (theApp() == 0) {
196                 noAppDialog(toqstr(title), toqstr(message), QMessageBox::Critical);
197                 return;
198         }
199
200         // Don't use a hourglass cursor while displaying the alert
201         qApp->setOverrideCursor(Qt::ArrowCursor);
202
203         ProgressInterface::instance()->error(
204                 toqstr(title),
205                 toqstr(message));
206
207         qApp->restoreOverrideCursor();
208 }
209
210 void error(docstring const & title0, docstring const & message)
211 {
212 #ifdef EXPORT_in_THREAD
213         InGuiThread<void>().call(&doError, 
214 #else
215         doError(
216 #endif
217                                 title0, message);
218 }
219
220 void doInformation(docstring const & title0, docstring const & message)
221 {
222         if (!use_gui || lyxerr.debugging())
223                 lyxerr << title0 << '\n'
224                        << "----------------------------------------\n"
225                        << message << endl;
226
227         if (!use_gui)
228                 return;
229
230         docstring const title = bformat(_("LyX: %1$s"), title0);
231
232         if (theApp() == 0) {
233                 noAppDialog(toqstr(title), toqstr(message), QMessageBox::Information);
234                 return;
235         }
236
237         // Don't use a hourglass cursor while displaying the alert
238         qApp->setOverrideCursor(Qt::ArrowCursor);
239
240         ProgressInterface::instance()->information(
241                 toqstr(title),
242                 toqstr(message));
243
244         qApp->restoreOverrideCursor();
245 }
246
247 void information(docstring const & title0, docstring const & message)
248 {
249 #ifdef EXPORT_in_THREAD
250         InGuiThread<void>().call(&doInformation,
251 #else
252         doInformation(
253 #endif
254                                 title0, message);
255 }
256
257 bool doAskForText(docstring & response, docstring const & msg,
258         docstring const & dflt)
259 {
260         if (!use_gui || lyxerr.debugging()) {
261                 lyxerr << "----------------------------------------\n"
262                        << msg << '\n'
263                        << "Assuming answer is " << dflt << '\n'
264                        << "----------------------------------------" << endl;
265                 if (!use_gui) {
266                         response = dflt;
267                         return true;
268                 }
269         }
270
271         docstring const title = bformat(_("LyX: %1$s"), msg);
272
273         bool ok;
274         QString text = QInputDialog::getText(qApp->focusWidget(),
275                 toqstr(title),
276                 toqstr(char_type('&') + msg),
277                 QLineEdit::Normal,
278                 toqstr(dflt), &ok);
279
280         if (ok) {
281                 response = qstring_to_ucs4(text);
282                 return true;
283         }
284         response.clear();
285         return false;
286 }
287
288 bool askForText(docstring & response, docstring const & msg,
289         docstring const & dflt)
290 {
291 #ifdef EXPORT_in_THREAD
292         return InGuiThread<bool>().call(&doAskForText,
293 #else
294         return doAskForText(
295 #endif
296                                 response, msg, dflt);
297 }
298
299 } // namespace Alert
300 } // namespace frontend
301 } // namespace lyx