1// Copyright (C) 2016 The Qt Company Ltd.
2// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
3
4#include "qqmlinfo.h"
5
6#include "qqmldata_p.h"
7#include "qqmlmetatype_p.h"
8#include "qqmlengine_p.h"
9#include "qqmlsourcecoordinate_p.h"
10
11#include <QCoreApplication>
12
13QT_BEGIN_NAMESPACE
14
15/*!
16 \class QQmlInfo
17 \inmodule QtQml
18 \brief The QQmlInfo class allows logging of QML-related messages.
19
20 QQmlInfo is an opaque handle for QML-related diagnostic messages. You can
21 use the \c{<<} operator to add content to the message. When the QQmlInfo
22 object is destroyed, it prints the resulting message along with information
23 on the context.
24
25 \sa qmlDebug, qmlInfo, qmlWarning
26*/
27
28/*!
29 \fn QQmlInfo qmlDebug(const QObject *object)
30 \relates QQmlInfo
31 \since 5.9
32
33 Prints debug messages that include the file and line number for the
34 specified QML \a object.
35
36//! [qqmlinfo-desc]
37 When QML types produce logging messages, it improves traceability
38 if they include the QML file and line number on which the
39 particular instance was instantiated.
40
41 To include the file and line number, an object must be passed. If
42 the file and line number is not available for that instance
43 (either it was not instantiated by the QML engine or location
44 information is disabled), "unknown location" will be used instead.
45//! [qqmlinfo-desc]
46
47 For example,
48
49 \code
50 qmlDebug(object) << "Internal state: 42";
51 \endcode
52
53 prints
54
55 \badcode
56 QML MyCustomType (unknown location): Internal state: 42
57 \endcode
58
59 \sa qmlInfo, qmlWarning
60*/
61
62/*!
63 \fn QQmlInfo qmlInfo(const QObject *object)
64 \relates QQmlInfo
65
66 Prints informational messages that include the file and line number for the
67 specified QML \a object.
68
69 \include qqmlinfo.cpp qqmlinfo-desc
70
71 For example,
72
73 \code
74 qmlInfo(object) << tr("component property is a write-once property");
75 \endcode
76
77 prints
78
79 \badcode
80 QML MyCustomType (unknown location): component property is a write-once property
81 \endcode
82
83 \note In versions prior to Qt 5.9, qmlInfo reported messages using a warning
84 QtMsgType. For Qt 5.9 and above, qmlInfo uses an info QtMsgType. To send
85 warnings, use qmlWarning.
86
87 \sa qmlDebug, qmlWarning
88*/
89
90/*!
91 \fn QQmlInfo qmlWarning(const QObject *object)
92 \relates QQmlInfo
93 \since 5.9
94
95 Prints warning messages that include the file and line number for the
96 specified QML \a object.
97
98 \include qqmlinfo.cpp qqmlinfo-desc
99
100 For example,
101
102 \code
103 qmlInfo(object) << tr("property cannot be set to 0");
104 \endcode
105
106 prints
107
108 \badcode
109 QML MyCustomType (unknown location): property cannot be set to 0
110 \endcode
111
112 \sa qmlDebug, qmlInfo
113*/
114
115/*!
116 \fn QQmlInfo qmlDebug(const QObject *object, const QQmlError &error)
117 \internal
118*/
119
120/*!
121 \fn QQmlInfo qmlDebug(const QObject *object, const QList<QQmlError> &errors)
122 \internal
123*/
124
125/*!
126 \fn QQmlInfo qmlInfo(const QObject *object, const QQmlError &error)
127 \internal
128*/
129
130/*!
131 \fn QQmlInfo qmlInfo(const QObject *object, const QList<QQmlError> &errors)
132 \internal
133*/
134
135/*!
136 \fn QQmlInfo qmlWarning(const QObject *object, const QQmlError &error)
137 \internal
138*/
139
140/*!
141 \fn QQmlInfo qmlWarning(const QObject *object, const QList<QQmlError> &errors)
142 \internal
143*/
144
145class QQmlInfoPrivate
146{
147public:
148 QQmlInfoPrivate(QtMsgType type)
149 : ref (1)
150 , msgType(type)
151 , object(nullptr)
152 {}
153
154 int ref;
155 QtMsgType msgType;
156 const QObject *object;
157 QString buffer;
158 QList<QQmlError> errors;
159};
160
161QQmlInfo::QQmlInfo(QQmlInfoPrivate *p)
162: QDebug(&p->buffer), d(p)
163{
164 nospace();
165}
166
167QQmlInfo::QQmlInfo(const QQmlInfo &other)
168: QDebug(other), d(other.d)
169{
170 d->ref++;
171}
172
173QQmlInfo::~QQmlInfo()
174{
175 if (0 == --d->ref) {
176 QList<QQmlError> errors = d->errors;
177
178 QQmlEngine *engine = nullptr;
179
180 if (!d->buffer.isEmpty()) {
181 QQmlError error;
182 error.setMessageType(d->msgType);
183
184 QObject *object = const_cast<QObject *>(d->object);
185
186 if (object) {
187 // Some objects (e.g. like attached objects created in C++) won't have an associated engine,
188 // but we can still try to look for a parent object that does.
189 QObject *objectWithEngine = object;
190 while (objectWithEngine) {
191 engine = qmlEngine(objectWithEngine);
192 if (engine)
193 break;
194 objectWithEngine = objectWithEngine->parent();
195 }
196
197 if (!objectWithEngine || objectWithEngine == object) {
198 d->buffer.prepend(s: QLatin1String("QML ") + QQmlMetaType::prettyTypeName(object) + QLatin1String(": "));
199 } else {
200 d->buffer.prepend(s: QLatin1String("QML ") + QQmlMetaType::prettyTypeName(object: objectWithEngine)
201 + QLatin1String(" (parent or ancestor of ") + QQmlMetaType::prettyTypeName(object) + QLatin1String("): "));
202 }
203
204 QQmlData *ddata = QQmlData::get(object: objectWithEngine ? objectWithEngine : object, create: false);
205 if (ddata && ddata->outerContext) {
206 error.setUrl(ddata->outerContext->url());
207 error.setLine(qmlConvertSourceCoordinate<quint16, int>(n: ddata->lineNumber));
208 error.setColumn(qmlConvertSourceCoordinate<quint16, int>(n: ddata->columnNumber));
209 }
210 }
211
212 error.setDescription(d->buffer);
213
214 errors.prepend(t: error);
215 }
216
217 QQmlEnginePrivate::warning(engine, errors);
218
219 delete d;
220 }
221}
222
223#define MESSAGE_FUNCS(FuncName, MessageLevel) \
224 QQmlInfo FuncName(const QObject *me) \
225 { \
226 QQmlInfoPrivate *d = new QQmlInfoPrivate(MessageLevel); \
227 d->object = me; \
228 return QQmlInfo(d); \
229 } \
230 QQmlInfo FuncName(const QObject *me, const QQmlError &error) \
231 { \
232 QQmlInfoPrivate *d = new QQmlInfoPrivate(MessageLevel); \
233 d->object = me; \
234 d->errors << error; \
235 return QQmlInfo(d); \
236 } \
237 QQmlInfo FuncName(const QObject *me, const QList<QQmlError> &errors) \
238 { \
239 QQmlInfoPrivate *d = new QQmlInfoPrivate(MessageLevel); \
240 d->object = me; \
241 d->errors = errors; \
242 return QQmlInfo(d); \
243 }
244
245MESSAGE_FUNCS(qmlDebug, QtMsgType::QtDebugMsg)
246MESSAGE_FUNCS(qmlInfo, QtMsgType::QtInfoMsg)
247MESSAGE_FUNCS(qmlWarning, QtMsgType::QtWarningMsg)
248
249QT_END_NAMESPACE
250

source code of qtdeclarative/src/qml/qml/qqmlinfo.cpp