source: trunk/src/gui/dialogs/qerrormessage.cpp@ 350

Last change on this file since 350 was 2, checked in by Dmitry A. Kuminov, 16 years ago

Initially imported qt-all-opensource-src-4.5.1 from Trolltech.

File size: 11.3 KB
Line 
1/****************************************************************************
2**
3** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
4** Contact: Qt Software Information ([email protected])
5**
6** This file is part of the QtGui module of the Qt Toolkit.
7**
8** $QT_BEGIN_LICENSE:LGPL$
9** Commercial Usage
10** Licensees holding valid Qt Commercial licenses may use this file in
11** accordance with the Qt Commercial License Agreement provided with the
12** Software or, alternatively, in accordance with the terms contained in
13** a written agreement between you and Nokia.
14**
15** GNU Lesser General Public License Usage
16** Alternatively, this file may be used under the terms of the GNU Lesser
17** General Public License version 2.1 as published by the Free Software
18** Foundation and appearing in the file LICENSE.LGPL included in the
19** packaging of this file. Please review the following information to
20** ensure the GNU Lesser General Public License version 2.1 requirements
21** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
22**
23** In addition, as a special exception, Nokia gives you certain
24** additional rights. These rights are described in the Nokia Qt LGPL
25** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
26** package.
27**
28** GNU General Public License Usage
29** Alternatively, this file may be used under the terms of the GNU
30** General Public License version 3.0 as published by the Free Software
31** Foundation and appearing in the file LICENSE.GPL included in the
32** packaging of this file. Please review the following information to
33** ensure the GNU General Public License version 3.0 requirements will be
34** met: http://www.gnu.org/copyleft/gpl.html.
35**
36** If you are unsure which license is appropriate for your use, please
37** contact the sales department at [email protected].
38** $QT_END_LICENSE$
39**
40****************************************************************************/
41
42#include "qerrormessage.h"
43
44#ifndef QT_NO_ERRORMESSAGE
45
46#include "qapplication.h"
47#include "qcheckbox.h"
48#include "qlabel.h"
49#include "qlayout.h"
50#include "qmessagebox.h"
51#include "qpushbutton.h"
52#include "qstringlist.h"
53#include "qtextedit.h"
54#include "qdialog_p.h"
55#include "qpixmap.h"
56#include "qmetaobject.h"
57#include "qthread.h"
58#include "qqueue.h"
59#include "qset.h"
60
61#include <stdio.h>
62#include <stdlib.h>
63
64#ifdef Q_OS_WINCE
65extern bool qt_wince_is_mobile(); //defined in qguifunctions_wince.cpp
66extern bool qt_wince_is_high_dpi(); //defined in qguifunctions_wince.cpp
67
68#include "qguifunctions_wince.h"
69#endif
70
71QT_BEGIN_NAMESPACE
72
73class QErrorMessagePrivate : public QDialogPrivate
74{
75 Q_DECLARE_PUBLIC(QErrorMessage)
76public:
77 QPushButton * ok;
78 QCheckBox * again;
79 QTextEdit * errors;
80 QLabel * icon;
81 QQueue<QPair<QString, QString> > pending;
82 QSet<QString> doNotShow;
83 QSet<QString> doNotShowType;
84 QString currentMessage;
85 QString currentType;
86
87 bool nextPending();
88 void retranslateStrings();
89};
90
91class QErrorMessageTextView : public QTextEdit
92{
93public:
94 QErrorMessageTextView(QWidget *parent)
95 : QTextEdit(parent) { setReadOnly(true); }
96
97 virtual QSize minimumSizeHint() const;
98 virtual QSize sizeHint() const;
99};
100
101QSize QErrorMessageTextView::minimumSizeHint() const
102{
103#ifdef Q_OS_WINCE
104 if (qt_wince_is_mobile())
105 if (qt_wince_is_high_dpi())
106 return QSize(200, 200);
107 else
108 return QSize(100, 100);
109 else
110 return QSize(70, 70);
111#else
112 return QSize(50, 50);
113#endif
114}
115
116QSize QErrorMessageTextView::sizeHint() const
117{
118#ifdef Q_OS_WINCE
119 if (qt_wince_is_mobile())
120 if (qt_wince_is_high_dpi())
121 return QSize(400, 200);
122 else
123 return QSize(320, 120);
124 else
125 return QSize(300, 100);
126#else
127 return QSize(250, 75);
128#endif
129}
130
131/*!
132 \class QErrorMessage
133
134 \brief The QErrorMessage class provides an error message display dialog.
135
136 \ingroup dialogs
137 \ingroup misc
138
139 An error message widget consists of a text label and a checkbox. The
140 checkbox lets the user control whether the same error message will be
141 displayed again in the future, typically displaying the text,
142 "Show this message again" translated into the appropriate local
143 language.
144
145 For production applications, the class can be used to display messages which
146 the user only needs to see once. To use QErrorMessage like this, you create
147 the dialog in the usual way, and show it by calling the showMessage() slot or
148 connecting signals to it.
149
150 The static qtHandler() function installs a message handler
151 using qInstallMsgHandler() and creates a QErrorMessage that displays
152 qDebug(), qWarning() and qFatal() messages. This is most useful in
153 environments where no console is available to display warnings and
154 error messages.
155
156 In both cases QErrorMessage will queue pending messages and display
157 them in order, with each new message being shown as soon as the user
158 has accepted the previous message. Once the user has specified that a
159 message is not to be shown again it is automatically skipped, and the
160 dialog will show the next appropriate message in the queue.
161
162 The \l{dialogs/standarddialogs}{Standard Dialogs} example shows
163 how to use QErrorMessage as well as other built-in Qt dialogs.
164
165 \img qerrormessage.png
166
167 \sa QMessageBox, QStatusBar::showMessage(), {Standard Dialogs Example}
168*/
169
170static QErrorMessage * qtMessageHandler = 0;
171
172static void deleteStaticcQErrorMessage() // post-routine
173{
174 if (qtMessageHandler) {
175 delete qtMessageHandler;
176 qtMessageHandler = 0;
177 }
178}
179
180static bool metFatal = false;
181
182static void jump(QtMsgType t, const char * m)
183{
184 if (!qtMessageHandler)
185 return;
186
187 QString rich;
188
189 switch (t) {
190 case QtDebugMsg:
191 default:
192 rich = QErrorMessage::tr("Debug Message:");
193 break;
194 case QtWarningMsg:
195 rich = QErrorMessage::tr("Warning:");
196 break;
197 case QtFatalMsg:
198 rich = QErrorMessage::tr("Fatal Error:");
199 }
200 rich = QString::fromLatin1("<p><b>%1</b></p>").arg(rich);
201 rich += Qt::convertFromPlainText(QLatin1String(m), Qt::WhiteSpaceNormal);
202
203 // ### work around text engine quirk
204 if (rich.endsWith(QLatin1String("</p>")))
205 rich.chop(4);
206
207 if (!metFatal) {
208 if (QThread::currentThread() == qApp->thread()) {
209 qtMessageHandler->showMessage(rich);
210 } else {
211 QMetaObject::invokeMethod(qtMessageHandler,
212 "showMessage",
213 Qt::QueuedConnection,
214 Q_ARG(QString, rich));
215 }
216 metFatal = (t == QtFatalMsg);
217 }
218}
219
220
221/*!
222 Constructs and installs an error handler window with the given \a
223 parent.
224*/
225
226QErrorMessage::QErrorMessage(QWidget * parent)
227 : QDialog(*new QErrorMessagePrivate, parent)
228{
229 Q_D(QErrorMessage);
230 QGridLayout * grid = new QGridLayout(this);
231 d->icon = new QLabel(this);
232#ifndef QT_NO_MESSAGEBOX
233 d->icon->setPixmap(QMessageBox::standardIcon(QMessageBox::Information));
234 d->icon->setAlignment(Qt::AlignHCenter | Qt::AlignTop);
235#endif
236 grid->addWidget(d->icon, 0, 0, Qt::AlignTop);
237 d->errors = new QErrorMessageTextView(this);
238 grid->addWidget(d->errors, 0, 1);
239 d->again = new QCheckBox(this);
240 d->again->setChecked(true);
241 grid->addWidget(d->again, 1, 1, Qt::AlignTop);
242 d->ok = new QPushButton(this);
243#ifdef Q_OS_WINCE
244 d->ok->setFixedSize(0,0);
245#endif
246 connect(d->ok, SIGNAL(clicked()), this, SLOT(accept()));
247 d->ok->setFocus();
248 grid->addWidget(d->ok, 2, 0, 1, 2, Qt::AlignCenter);
249 grid->setColumnStretch(1, 42);
250 grid->setRowStretch(0, 42);
251 d->retranslateStrings();
252}
253
254
255/*!
256 Destroys the error message dialog.
257*/
258
259QErrorMessage::~QErrorMessage()
260{
261 if (this == qtMessageHandler) {
262 qtMessageHandler = 0;
263 QtMsgHandler tmp = qInstallMsgHandler(0);
264 // in case someone else has later stuck in another...
265 if (tmp != jump)
266 qInstallMsgHandler(tmp);
267 }
268}
269
270
271/*! \reimp */
272
273void QErrorMessage::done(int a)
274{
275 Q_D(QErrorMessage);
276 if (!d->again->isChecked() && !d->currentMessage.isEmpty() && d->currentType.isEmpty()) {
277 d->doNotShow.insert(d->currentMessage);
278 }
279 if (!d->again->isChecked() && !d->currentType.isEmpty()) {
280 d->doNotShowType.insert(d->currentType);
281 }
282 d->currentMessage.clear();
283 d->currentType.clear();
284 if (!d->nextPending()) {
285 QDialog::done(a);
286 if (this == qtMessageHandler && metFatal)
287 exit(1);
288 }
289}
290
291
292/*!
293 Returns a pointer to a QErrorMessage object that outputs the
294 default Qt messages. This function creates such an object, if there
295 isn't one already.
296*/
297
298QErrorMessage * QErrorMessage::qtHandler()
299{
300 if (!qtMessageHandler) {
301 qtMessageHandler = new QErrorMessage(0);
302 qAddPostRoutine(deleteStaticcQErrorMessage); // clean up
303 qtMessageHandler->setWindowTitle(qApp->applicationName());
304 qInstallMsgHandler(jump);
305 }
306 return qtMessageHandler;
307}
308
309
310/*! \internal */
311
312bool QErrorMessagePrivate::nextPending()
313{
314 while (!pending.isEmpty()) {
315 QPair<QString,QString> pendingMessage = pending.dequeue();
316 QString message = pendingMessage.first;
317 QString type = pendingMessage.second;
318 if (!message.isEmpty() && ((type.isEmpty() && !doNotShow.contains(message)) || (!type.isEmpty() && !doNotShowType.contains(type)))) {
319#ifndef QT_NO_TEXTHTMLPARSER
320 errors->setHtml(message);
321#else
322 errors->setPlainText(message);
323#endif
324 currentMessage = message;
325 currentType = type;
326 return true;
327 }
328 }
329 return false;
330}
331
332
333/*!
334 Shows the given message, \a message, and returns immediately. If the user
335 has requested for the message not to be shown again, this function does
336 nothing.
337
338 Normally, the message is displayed immediately. However, if there are
339 pending messages, it will be queued to be displayed later.
340*/
341
342void QErrorMessage::showMessage(const QString &message)
343{
344 Q_D(QErrorMessage);
345 if (d->doNotShow.contains(message))
346 return;
347 d->pending.enqueue(qMakePair(message,QString()));
348 if (!isVisible() && d->nextPending())
349 show();
350}
351
352/*!
353 \since 4.5
354 \overload
355
356 Shows the given message, \a message, and returns immediately. If the user
357 has requested for messages of type, \a type, not to be shown again, this
358 function does nothing.
359
360 Normally, the message is displayed immediately. However, if there are
361 pending messages, it will be queued to be displayed later.
362
363 \sa showMessage()
364*/
365
366void QErrorMessage::showMessage(const QString &message, const QString &type)
367{
368 Q_D(QErrorMessage);
369 if (d->doNotShow.contains(message) && d->doNotShowType.contains(type))
370 return;
371 d->pending.push_back(qMakePair(message,type));
372 if (!isVisible() && d->nextPending())
373 show();
374}
375
376
377/*!
378 \reimp
379*/
380void QErrorMessage::changeEvent(QEvent *e)
381{
382 Q_D(QErrorMessage);
383 if (e->type() == QEvent::LanguageChange) {
384 d->retranslateStrings();
385 }
386 QDialog::changeEvent(e);
387}
388
389void QErrorMessagePrivate::retranslateStrings()
390{
391 again->setText(QErrorMessage::tr("&Show this message again"));
392 ok->setText(QErrorMessage::tr("&OK"));
393}
394
395/*!
396 \fn void QErrorMessage::message(const QString & message)
397
398 Use showMessage(\a message) instead.
399*/
400
401QT_END_NAMESPACE
402
403#endif // QT_NO_ERRORMESSAGE
Note: See TracBrowser for help on using the repository browser.