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