QQmlInfo: Add qmlDebug & qmlWarning functions alongside qmlInfo

This way, we can correctly write to multiple levels of QDebug with QML context
information. A followup change will port all existing callers, and
subsequently change qmlInfo's message level to QtInfoMsg.

[ChangeLog][QtQml] Introduced qmlDebug & qmlWarning functions to qqmlinfo.h, in
addition to the pre-existing qmlInfo function. As a side effect, QQmlError has
also gained messageType() and setMessageType().

Change-Id: I04ced5952c5c3c58293a89a6767c7b545c03cc0a
Reviewed-by: Simon Hausmann <simon.hausmann@qt.io>
This commit is contained in:
Robin Burchell 2017-01-05 20:19:18 +01:00
parent 971314dbb5
commit 5a5f140e60
6 changed files with 185 additions and 28 deletions

View File

@ -1914,9 +1914,29 @@ void QQmlEnginePrivate::sendExit(int retCode)
static void dumpwarning(const QQmlError &error)
{
QMessageLogger(error.url().toString().toLatin1().constData(),
error.line(), 0).warning().nospace()
<< qPrintable(error.toString());
switch (error.messageType()) {
case QtDebugMsg:
QMessageLogger(error.url().toString().toLatin1().constData(),
error.line(), 0).debug().nospace()
<< qPrintable(error.toString());
break;
case QtInfoMsg:
QMessageLogger(error.url().toString().toLatin1().constData(),
error.line(), 0).info().nospace()
<< qPrintable(error.toString());
break;
case QtWarningMsg:
case QtFatalMsg: // fatal does not support streaming, and furthermore, is actually fatal. Probably not desirable for QML.
QMessageLogger(error.url().toString().toLatin1().constData(),
error.line(), 0).warning().nospace()
<< qPrintable(error.toString());
break;
case QtCriticalMsg:
QMessageLogger(error.url().toString().toLatin1().constData(),
error.line(), 0).critical().nospace()
<< qPrintable(error.toString());
break;
}
}
static void dumpwarning(const QList<QQmlError> &errors)

View File

@ -85,11 +85,12 @@ public:
QString description;
quint16 line;
quint16 column;
QtMsgType messageType;
QObject *object;
};
QQmlErrorPrivate::QQmlErrorPrivate()
: line(0), column(0), object()
: line(0), column(0), messageType(QtMsgType::QtWarningMsg), object()
{
}
@ -125,6 +126,7 @@ QQmlError &QQmlError::operator=(const QQmlError &other)
d->line = other.d->line;
d->column = other.d->column;
d->object = other.d->object;
d->messageType = other.d->messageType;
}
return *this;
}
@ -238,6 +240,29 @@ void QQmlError::setObject(QObject *object)
d->object = object;
}
/*!
\since 5.9
Returns the message type.
*/
QtMsgType QQmlError::messageType() const
{
if (d) return d->messageType;
else return QtMsgType::QtWarningMsg;
}
/*!
\since 5.9
Sets the \a messageType for this message. The message type determines which
QDebug handlers are responsible for recieving the message.
*/
void QQmlError::setMessageType(QtMsgType messageType)
{
if (!d) d = new QQmlErrorPrivate;
d->messageType = messageType;
}
/*!
Returns the error as a human readable string.
*/

View File

@ -47,6 +47,7 @@
QT_BEGIN_NAMESPACE
// ### Qt 6: should this be called QQmlMessage, since it can have a message type?
class QDebug;
class QQmlErrorPrivate;
class Q_QML_EXPORT QQmlError
@ -69,6 +70,8 @@ public:
void setColumn(int);
QObject *object() const;
void setObject(QObject *);
QtMsgType messageType() const;
void setMessageType(QtMsgType messageType);
QString toString() const;
private:

View File

@ -49,14 +49,46 @@
QT_BEGIN_NAMESPACE
/*!
\fn QQmlInfo QtQml::qmlDebug(const QObject *object)
\relates QQmlEngine
\since 5.9
Prints debug messages that include the file and line number for the
specified QML \a object.
When QML types produce logging messages, it improves traceability
if they include the QML file and line number on which the
particular instance was instantiated.
To include the file and line number, an object must be passed. If
the file and line number is not available for that instance
(either it was not instantiated by the QML engine or location
information is disabled), "unknown location" will be used instead.
For example,
\code
qmlDebug(object) << "Internal state: 42";
\endcode
prints
\code
QML MyCustomType (unknown location): Internal state: 42
\endcode
\sa QtQml::qmlInfo, QtQml::qmlWarning
*/
/*!
\fn QQmlInfo QtQml::qmlInfo(const QObject *object)
\relates QQmlEngine
Prints warning messages that include the file and line number for the
Prints informational messages that include the file and line number for the
specified QML \a object.
When QML types display warning messages, it improves traceability
When QML types produce logging messages, it improves traceability
if they include the QML file and line number on which the
particular instance was instantiated.
@ -76,14 +108,58 @@ QT_BEGIN_NAMESPACE
\code
QML MyCustomType (unknown location): component property is a write-once property
\endcode
\note In versions prior to Qt 5.9, qmlInfo reported messages using a warning
QtMsgType. For Qt 5.9 and above, qmlInfo uses an info QtMsgType. To send
warnings, use qmlWarning.
\sa QtQml::qmlDebug, QtQml::qmlWarning
*/
/*!
\fn QQmlInfo QtQml::qmlWarning(const QObject *object)
\relates QQmlEngine
\since 5.9
Prints warning messages that include the file and line number for the
specified QML \a object.
When QML types produce logging messages, it improves traceability
if they include the QML file and line number on which the
particular instance was instantiated.
To include the file and line number, an object must be passed. If
the file and line number is not available for that instance
(either it was not instantiated by the QML engine or location
information is disabled), "unknown location" will be used instead.
For example,
\code
qmlInfo(object) << tr("property cannot be set to 0");
\endcode
prints
\code
QML MyCustomType (unknown location): property cannot be set to 0
\endcode
\sa QtQml::qmlDebug, QtQml::qmlInfo
*/
class QQmlInfoPrivate
{
public:
QQmlInfoPrivate() : ref (1), object(0) {}
QQmlInfoPrivate(QtMsgType type)
: ref (1)
, msgType(type)
, object(nullptr)
{}
int ref;
QtMsgType msgType;
const QObject *object;
QString buffer;
QList<QQmlError> errors;
@ -110,6 +186,7 @@ QQmlInfo::~QQmlInfo()
if (!d->buffer.isEmpty()) {
QQmlError error;
error.setMessageType(d->msgType);
QObject *object = const_cast<QObject *>(d->object);
@ -139,28 +216,32 @@ QQmlInfo::~QQmlInfo()
namespace QtQml {
QQmlInfo qmlInfo(const QObject *me)
{
QQmlInfoPrivate *d = new QQmlInfoPrivate;
d->object = me;
return QQmlInfo(d);
}
#define MESSAGE_FUNCS(FuncName, MessageLevel) \
QQmlInfo FuncName(const QObject *me) \
{ \
QQmlInfoPrivate *d = new QQmlInfoPrivate(MessageLevel); \
d->object = me; \
return QQmlInfo(d); \
} \
QQmlInfo FuncName(const QObject *me, const QQmlError &error) \
{ \
QQmlInfoPrivate *d = new QQmlInfoPrivate(MessageLevel); \
d->object = me; \
d->errors << error; \
return QQmlInfo(d); \
} \
QQmlInfo FuncName(const QObject *me, const QList<QQmlError> &errors) \
{ \
QQmlInfoPrivate *d = new QQmlInfoPrivate(MessageLevel); \
d->object = me; \
d->errors = errors; \
return QQmlInfo(d); \
}
QQmlInfo qmlInfo(const QObject *me, const QQmlError &error)
{
QQmlInfoPrivate *d = new QQmlInfoPrivate;
d->object = me;
d->errors << error;
return QQmlInfo(d);
}
MESSAGE_FUNCS(qmlDebug, QtMsgType::QtDebugMsg)
MESSAGE_FUNCS(qmlInfo, QtMsgType::QtWarningMsg) // XXX: temporary, switch to QtInfoMsg when callers are ported
MESSAGE_FUNCS(qmlWarning, QtMsgType::QtWarningMsg)
QQmlInfo qmlInfo(const QObject *me, const QList<QQmlError> &errors)
{
QQmlInfoPrivate *d = new QQmlInfoPrivate;
d->object = me;
d->errors = errors;
return QQmlInfo(d);
}
} // namespace QtQml

View File

@ -48,11 +48,19 @@ QT_BEGIN_NAMESPACE
class QQmlInfo;
// declared in namespace to avoid symbol conflicts with QtDeclarative
namespace QtQml {
// declared in namespace to avoid symbol conflicts with QtDeclarative
Q_QML_EXPORT QQmlInfo qmlDebug(const QObject *me);
Q_QML_EXPORT QQmlInfo qmlDebug(const QObject *me, const QQmlError &error);
Q_QML_EXPORT QQmlInfo qmlDebug(const QObject *me, const QList<QQmlError> &errors);
Q_QML_EXPORT QQmlInfo qmlInfo(const QObject *me);
Q_QML_EXPORT QQmlInfo qmlInfo(const QObject *me, const QQmlError &error);
Q_QML_EXPORT QQmlInfo qmlInfo(const QObject *me, const QList<QQmlError> &errors);
Q_QML_EXPORT QQmlInfo qmlWarning(const QObject *me);
Q_QML_EXPORT QQmlInfo qmlWarning(const QObject *me, const QQmlError &error);
Q_QML_EXPORT QQmlInfo qmlWarning(const QObject *me, const QList<QQmlError> &errors);
}
QT_WARNING_PUSH
QT_WARNING_DISABLE_CLANG("-Wheader-hygiene")
@ -93,9 +101,15 @@ public:
#endif
private:
friend Q_QML_EXPORT QQmlInfo QtQml::qmlDebug(const QObject *me);
friend Q_QML_EXPORT QQmlInfo QtQml::qmlDebug(const QObject *me, const QQmlError &error);
friend Q_QML_EXPORT QQmlInfo QtQml::qmlDebug(const QObject *me, const QList<QQmlError> &errors);
friend Q_QML_EXPORT QQmlInfo QtQml::qmlInfo(const QObject *me);
friend Q_QML_EXPORT QQmlInfo QtQml::qmlInfo(const QObject *me, const QQmlError &error);
friend Q_QML_EXPORT QQmlInfo QtQml::qmlInfo(const QObject *me, const QList<QQmlError> &errors);
friend Q_QML_EXPORT QQmlInfo QtQml::qmlWarning(const QObject *me);
friend Q_QML_EXPORT QQmlInfo QtQml::qmlWarning(const QObject *me, const QQmlError &error);
friend Q_QML_EXPORT QQmlInfo QtQml::qmlWarning(const QObject *me, const QList<QQmlError> &errors);
QQmlInfo(QQmlInfoPrivate *);
QQmlInfoPrivate *d;

View File

@ -49,6 +49,7 @@ private slots:
void nonQmlContextedObject();
void types();
void chaining();
void messageTypes();
private:
QQmlEngine engine;
@ -202,6 +203,19 @@ void tst_qqmlinfo::chaining()
<< QUrl("http://www.qt-project.org");
}
// Ensure that messages of different types are sent with the correct QtMsgType.
void tst_qqmlinfo::messageTypes()
{
QTest::ignoreMessage(QtDebugMsg, "<Unknown File>: debug");
qmlDebug(0) << QLatin1String("debug");
QTest::ignoreMessage(QtWarningMsg, "<Unknown File>: info");
qmlInfo(0) << QLatin1String("info");
QTest::ignoreMessage(QtWarningMsg, "<Unknown File>: warning");
qmlWarning(0) << QLatin1String("warning");
}
QTEST_MAIN(tst_qqmlinfo)
#include "tst_qqmlinfo.moc"