/****************************************************************************+ −
**+ −
** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).+ −
** All rights reserved.+ −
** Contact: Nokia Corporation (qt-info@nokia.com)+ −
**+ −
** This file is part of the QtGui module of the Qt Toolkit.+ −
**+ −
** $QT_BEGIN_LICENSE:LGPL$+ −
** No Commercial Usage+ −
** This file contains pre-release code and may not be distributed.+ −
** You may use this file in accordance with the terms and conditions+ −
** contained in the Technology Preview License Agreement accompanying+ −
** this package.+ −
**+ −
** GNU Lesser General Public License Usage+ −
** Alternatively, this file may be used under the terms of the GNU Lesser+ −
** General Public License version 2.1 as published by the Free Software+ −
** Foundation and appearing in the file LICENSE.LGPL included in the+ −
** packaging of this file. Please review the following information to+ −
** ensure the GNU Lesser General Public License version 2.1 requirements+ −
** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.+ −
**+ −
** In addition, as a special exception, Nokia gives you certain additional+ −
** rights. These rights are described in the Nokia Qt LGPL Exception+ −
** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.+ −
**+ −
** If you have questions regarding the use of this file, please contact+ −
** Nokia at qt-info@nokia.com.+ −
**+ −
**+ −
**+ −
**+ −
**+ −
**+ −
**+ −
**+ −
** $QT_END_LICENSE$+ −
**+ −
****************************************************************************/+ −
+ −
#include "qerrormessage.h"+ −
+ −
#ifndef QT_NO_ERRORMESSAGE+ −
+ −
#include "qapplication.h"+ −
#include "qcheckbox.h"+ −
#include "qlabel.h"+ −
#include "qlayout.h"+ −
#include "qmessagebox.h"+ −
#include "qpushbutton.h"+ −
#include "qstringlist.h"+ −
#include "qtextedit.h"+ −
#include "qdialog_p.h"+ −
#include "qpixmap.h"+ −
#include "qmetaobject.h"+ −
#include "qthread.h"+ −
#include "qqueue.h"+ −
#include "qset.h"+ −
+ −
#include <stdio.h>+ −
#include <stdlib.h>+ −
+ −
#ifdef Q_WS_WINCE+ −
extern bool qt_wince_is_mobile(); //defined in qguifunctions_wince.cpp+ −
extern bool qt_wince_is_high_dpi(); //defined in qguifunctions_wince.cpp+ −
+ −
#include "qguifunctions_wince.h"+ −
#endif+ −
+ −
#if defined(QT_SOFTKEYS_ENABLED)+ −
#include <qaction.h>+ −
#endif+ −
#ifdef Q_WS_S60+ −
#include "private/qt_s60_p.h"+ −
#endif+ −
+ −
QT_BEGIN_NAMESPACE+ −
+ −
class QErrorMessagePrivate : public QDialogPrivate+ −
{+ −
Q_DECLARE_PUBLIC(QErrorMessage)+ −
public:+ −
QPushButton * ok;+ −
QCheckBox * again;+ −
QTextEdit * errors;+ −
QLabel * icon;+ −
#ifdef QT_SOFTKEYS_ENABLED+ −
QAction *okAction;+ −
#endif+ −
QQueue<QPair<QString, QString> > pending;+ −
QSet<QString> doNotShow;+ −
QSet<QString> doNotShowType;+ −
QString currentMessage;+ −
QString currentType;+ −
+ −
bool nextPending();+ −
void retranslateStrings();+ −
};+ −
+ −
class QErrorMessageTextView : public QTextEdit+ −
{+ −
public:+ −
QErrorMessageTextView(QWidget *parent)+ −
: QTextEdit(parent) { setReadOnly(true); }+ −
+ −
virtual QSize minimumSizeHint() const;+ −
virtual QSize sizeHint() const;+ −
};+ −
+ −
QSize QErrorMessageTextView::minimumSizeHint() const+ −
{+ −
#ifdef Q_WS_WINCE+ −
if (qt_wince_is_mobile())+ −
if (qt_wince_is_high_dpi())+ −
return QSize(200, 200);+ −
else+ −
return QSize(100, 100);+ −
else+ −
return QSize(70, 70);+ −
#else+ −
return QSize(50, 50);+ −
#endif+ −
}+ −
+ −
QSize QErrorMessageTextView::sizeHint() const+ −
{+ −
#ifdef Q_WS_WINCE+ −
if (qt_wince_is_mobile())+ −
if (qt_wince_is_high_dpi())+ −
return QSize(400, 200);+ −
else+ −
return QSize(320, 120);+ −
else+ −
return QSize(300, 100);+ −
#else+ −
+ −
#ifdef Q_WS_S60+ −
const int smallerDimension = qMin(S60->screenHeightInPixels, S60->screenWidthInPixels);+ −
// In S60 layout data, error messages seem to be one third of the screen height (in portrait) minus two.+ −
return QSize(smallerDimension, smallerDimension/3-2);+ −
#else+ −
return QSize(250, 75);+ −
#endif //Q_WS_S60+ −
#endif //Q_WS_WINCE+ −
}+ −
+ −
/*!+ −
\class QErrorMessage+ −
+ −
\brief The QErrorMessage class provides an error message display dialog.+ −
+ −
\ingroup standard-dialog+ −
+ −
An error message widget consists of a text label and a checkbox. The+ −
checkbox lets the user control whether the same error message will be+ −
displayed again in the future, typically displaying the text,+ −
"Show this message again" translated into the appropriate local+ −
language.+ −
+ −
For production applications, the class can be used to display messages which+ −
the user only needs to see once. To use QErrorMessage like this, you create+ −
the dialog in the usual way, and show it by calling the showMessage() slot or+ −
connecting signals to it.+ −
+ −
The static qtHandler() function installs a message handler+ −
using qInstallMsgHandler() and creates a QErrorMessage that displays+ −
qDebug(), qWarning() and qFatal() messages. This is most useful in+ −
environments where no console is available to display warnings and+ −
error messages.+ −
+ −
In both cases QErrorMessage will queue pending messages and display+ −
them in order, with each new message being shown as soon as the user+ −
has accepted the previous message. Once the user has specified that a+ −
message is not to be shown again it is automatically skipped, and the+ −
dialog will show the next appropriate message in the queue.+ −
+ −
The \l{dialogs/standarddialogs}{Standard Dialogs} example shows+ −
how to use QErrorMessage as well as other built-in Qt dialogs.+ −
+ −
\img qerrormessage.png+ −
+ −
\sa QMessageBox, QStatusBar::showMessage(), {Standard Dialogs Example}+ −
*/+ −
+ −
static QErrorMessage * qtMessageHandler = 0;+ −
+ −
static void deleteStaticcQErrorMessage() // post-routine+ −
{+ −
if (qtMessageHandler) {+ −
delete qtMessageHandler;+ −
qtMessageHandler = 0;+ −
}+ −
}+ −
+ −
static bool metFatal = false;+ −
+ −
static void jump(QtMsgType t, const char * m)+ −
{+ −
if (!qtMessageHandler)+ −
return;+ −
+ −
QString rich;+ −
+ −
switch (t) {+ −
case QtDebugMsg:+ −
default:+ −
rich = QErrorMessage::tr("Debug Message:");+ −
break;+ −
case QtWarningMsg:+ −
rich = QErrorMessage::tr("Warning:");+ −
break;+ −
case QtFatalMsg:+ −
rich = QErrorMessage::tr("Fatal Error:");+ −
}+ −
rich = QString::fromLatin1("<p><b>%1</b></p>").arg(rich);+ −
rich += Qt::convertFromPlainText(QLatin1String(m), Qt::WhiteSpaceNormal);+ −
+ −
// ### work around text engine quirk+ −
if (rich.endsWith(QLatin1String("</p>")))+ −
rich.chop(4);+ −
+ −
if (!metFatal) {+ −
if (QThread::currentThread() == qApp->thread()) {+ −
qtMessageHandler->showMessage(rich);+ −
} else {+ −
QMetaObject::invokeMethod(qtMessageHandler,+ −
"showMessage",+ −
Qt::QueuedConnection,+ −
Q_ARG(QString, rich));+ −
}+ −
metFatal = (t == QtFatalMsg);+ −
}+ −
}+ −
+ −
+ −
/*!+ −
Constructs and installs an error handler window with the given \a+ −
parent.+ −
*/+ −
+ −
QErrorMessage::QErrorMessage(QWidget * parent)+ −
: QDialog(*new QErrorMessagePrivate, parent)+ −
{+ −
Q_D(QErrorMessage);+ −
QGridLayout * grid = new QGridLayout(this);+ −
d->icon = new QLabel(this);+ −
#ifndef QT_NO_MESSAGEBOX+ −
d->icon->setPixmap(QMessageBox::standardIcon(QMessageBox::Information));+ −
d->icon->setAlignment(Qt::AlignHCenter | Qt::AlignTop);+ −
#endif+ −
grid->addWidget(d->icon, 0, 0, Qt::AlignTop);+ −
d->errors = new QErrorMessageTextView(this);+ −
grid->addWidget(d->errors, 0, 1);+ −
d->again = new QCheckBox(this);+ −
d->again->setChecked(true);+ −
grid->addWidget(d->again, 1, 1, Qt::AlignTop);+ −
d->ok = new QPushButton(this);+ −
#ifdef QT_SOFTKEYS_ENABLED+ −
d->okAction = new QAction(d->ok);+ −
d->okAction->setSoftKeyRole(QAction::PositiveSoftKey);+ −
connect(d->okAction, SIGNAL(triggered()), this, SLOT(accept()));+ −
addAction(d->okAction);+ −
#endif+ −
+ −
+ −
#if defined(Q_WS_WINCE) || defined(Q_WS_S60)+ −
d->ok->setFixedSize(0,0);+ −
#endif+ −
connect(d->ok, SIGNAL(clicked()), this, SLOT(accept()));+ −
d->ok->setFocus();+ −
grid->addWidget(d->ok, 2, 0, 1, 2, Qt::AlignCenter);+ −
grid->setColumnStretch(1, 42);+ −
grid->setRowStretch(0, 42);+ −
d->retranslateStrings();+ −
}+ −
+ −
+ −
/*!+ −
Destroys the error message dialog.+ −
*/+ −
+ −
QErrorMessage::~QErrorMessage()+ −
{+ −
if (this == qtMessageHandler) {+ −
qtMessageHandler = 0;+ −
QtMsgHandler tmp = qInstallMsgHandler(0);+ −
// in case someone else has later stuck in another...+ −
if (tmp != jump)+ −
qInstallMsgHandler(tmp);+ −
}+ −
}+ −
+ −
+ −
/*! \reimp */+ −
+ −
void QErrorMessage::done(int a)+ −
{+ −
Q_D(QErrorMessage);+ −
if (!d->again->isChecked() && !d->currentMessage.isEmpty() && d->currentType.isEmpty()) {+ −
d->doNotShow.insert(d->currentMessage);+ −
}+ −
if (!d->again->isChecked() && !d->currentType.isEmpty()) {+ −
d->doNotShowType.insert(d->currentType);+ −
}+ −
d->currentMessage.clear();+ −
d->currentType.clear();+ −
if (!d->nextPending()) {+ −
QDialog::done(a);+ −
if (this == qtMessageHandler && metFatal)+ −
exit(1);+ −
}+ −
}+ −
+ −
+ −
/*!+ −
Returns a pointer to a QErrorMessage object that outputs the+ −
default Qt messages. This function creates such an object, if there+ −
isn't one already.+ −
*/+ −
+ −
QErrorMessage * QErrorMessage::qtHandler()+ −
{+ −
if (!qtMessageHandler) {+ −
qtMessageHandler = new QErrorMessage(0);+ −
qAddPostRoutine(deleteStaticcQErrorMessage); // clean up+ −
qtMessageHandler->setWindowTitle(QApplication::applicationName());+ −
qInstallMsgHandler(jump);+ −
}+ −
return qtMessageHandler;+ −
}+ −
+ −
+ −
/*! \internal */+ −
+ −
bool QErrorMessagePrivate::nextPending()+ −
{+ −
while (!pending.isEmpty()) {+ −
QPair<QString,QString> pendingMessage = pending.dequeue();+ −
QString message = pendingMessage.first;+ −
QString type = pendingMessage.second;+ −
if (!message.isEmpty() && ((type.isEmpty() && !doNotShow.contains(message)) || (!type.isEmpty() && !doNotShowType.contains(type)))) {+ −
#ifndef QT_NO_TEXTHTMLPARSER+ −
errors->setHtml(message);+ −
#else+ −
errors->setPlainText(message);+ −
#endif+ −
currentMessage = message;+ −
currentType = type;+ −
return true;+ −
}+ −
}+ −
return false;+ −
}+ −
+ −
+ −
/*!+ −
Shows the given message, \a message, and returns immediately. If the user+ −
has requested for the message not to be shown again, this function does+ −
nothing.+ −
+ −
Normally, the message is displayed immediately. However, if there are+ −
pending messages, it will be queued to be displayed later.+ −
*/+ −
+ −
void QErrorMessage::showMessage(const QString &message)+ −
{+ −
Q_D(QErrorMessage);+ −
if (d->doNotShow.contains(message))+ −
return;+ −
d->pending.enqueue(qMakePair(message,QString()));+ −
if (!isVisible() && d->nextPending())+ −
show();+ −
}+ −
+ −
/*!+ −
\since 4.5+ −
\overload+ −
+ −
Shows the given message, \a message, and returns immediately. If the user+ −
has requested for messages of type, \a type, not to be shown again, this+ −
function does nothing.+ −
+ −
Normally, the message is displayed immediately. However, if there are+ −
pending messages, it will be queued to be displayed later.+ −
+ −
\sa showMessage()+ −
*/+ −
+ −
void QErrorMessage::showMessage(const QString &message, const QString &type)+ −
{+ −
Q_D(QErrorMessage);+ −
if (d->doNotShow.contains(message) && d->doNotShowType.contains(type))+ −
return;+ −
d->pending.push_back(qMakePair(message,type));+ −
if (!isVisible() && d->nextPending())+ −
show();+ −
}+ −
+ −
/*!+ −
\reimp+ −
*/+ −
void QErrorMessage::changeEvent(QEvent *e)+ −
{+ −
Q_D(QErrorMessage);+ −
if (e->type() == QEvent::LanguageChange) {+ −
d->retranslateStrings();+ −
}+ −
QDialog::changeEvent(e);+ −
}+ −
+ −
void QErrorMessagePrivate::retranslateStrings()+ −
{+ −
again->setText(QErrorMessage::tr("&Show this message again"));+ −
ok->setText(QErrorMessage::tr("&OK"));+ −
#ifdef QT_SOFTKEYS_ENABLED+ −
okAction->setText(ok->text());+ −
#endif+ −
}+ −
+ −
/*!+ −
\fn void QErrorMessage::message(const QString & message)+ −
+ −
Use showMessage(\a message) instead.+ −
*/+ −
+ −
QT_END_NAMESPACE+ −
+ −
#endif // QT_NO_ERRORMESSAGE+ −