1/****************************************************************************
2**
3** Copyright (C) 2016 The Qt Company Ltd.
4** Contact: https://www.qt.io/licensing/
5**
6** This file is part of the QtQml module of the Qt Toolkit.
7**
8** $QT_BEGIN_LICENSE:LGPL$
9** Commercial License Usage
10** Licensees holding valid commercial Qt licenses may use this file in
11** accordance with the commercial license agreement provided with the
12** Software or, alternatively, in accordance with the terms contained in
13** a written agreement between you and The Qt Company. For licensing terms
14** and conditions see https://www.qt.io/terms-conditions. For further
15** information use the contact form at https://www.qt.io/contact-us.
16**
17** GNU Lesser General Public License Usage
18** Alternatively, this file may be used under the terms of the GNU Lesser
19** General Public License version 3 as published by the Free Software
20** Foundation and appearing in the file LICENSE.LGPL3 included in the
21** packaging of this file. Please review the following information to
22** ensure the GNU Lesser General Public License version 3 requirements
23** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
24**
25** GNU General Public License Usage
26** Alternatively, this file may be used under the terms of the GNU
27** General Public License version 2.0 or (at your option) the GNU General
28** Public license version 3 or any later version approved by the KDE Free
29** Qt Foundation. The licenses are as published by the Free Software
30** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
31** included in the packaging of this file. Please review the following
32** information to ensure the GNU General Public License requirements will
33** be met: https://www.gnu.org/licenses/gpl-2.0.html and
34** https://www.gnu.org/licenses/gpl-3.0.html.
35**
36** $QT_END_LICENSE$
37**
38****************************************************************************/
39
40#include "qqmlinfo.h"
41
42#include "qqmldata_p.h"
43#include "qqmlcontext.h"
44#include "qqmlcontext_p.h"
45#include "qqmlmetatype_p.h"
46#include "qqmlengine_p.h"
47#include "qqmlsourcecoordinate_p.h"
48
49#include <QCoreApplication>
50
51QT_BEGIN_NAMESPACE
52
53/*!
54 \namespace QtQml
55 \inmodule QtQml
56 \brief Provides functions for producing logging messages for QML types.
57*/
58
59/*!
60 \fn QQmlInfo QtQml::qmlDebug(const QObject *object)
61 \since 5.9
62
63 Prints debug messages that include the file and line number for the
64 specified QML \a object.
65
66//! [qqmlinfo-desc]
67 When QML types produce logging messages, it improves traceability
68 if they include the QML file and line number on which the
69 particular instance was instantiated.
70
71 To include the file and line number, an object must be passed. If
72 the file and line number is not available for that instance
73 (either it was not instantiated by the QML engine or location
74 information is disabled), "unknown location" will be used instead.
75//! [qqmlinfo-desc]
76
77 For example,
78
79 \code
80 qmlDebug(object) << "Internal state: 42";
81 \endcode
82
83 prints
84
85 \badcode
86 QML MyCustomType (unknown location): Internal state: 42
87 \endcode
88
89 \sa QtQml::qmlInfo, QtQml::qmlWarning
90*/
91
92/*!
93 \fn QQmlInfo QtQml::qmlInfo(const QObject *object)
94
95 Prints informational 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("component property is a write-once property");
104 \endcode
105
106 prints
107
108 \badcode
109 QML MyCustomType (unknown location): component property is a write-once property
110 \endcode
111
112 \note In versions prior to Qt 5.9, qmlInfo reported messages using a warning
113 QtMsgType. For Qt 5.9 and above, qmlInfo uses an info QtMsgType. To send
114 warnings, use qmlWarning.
115
116 \sa QtQml::qmlDebug, QtQml::qmlWarning
117*/
118
119/*!
120 \fn QQmlInfo QtQml::qmlWarning(const QObject *object)
121 \since 5.9
122
123 Prints warning messages that include the file and line number for the
124 specified QML \a object.
125
126 \include qqmlinfo.cpp qqmlinfo-desc
127
128 For example,
129
130 \code
131 qmlInfo(object) << tr("property cannot be set to 0");
132 \endcode
133
134 prints
135
136 \badcode
137 QML MyCustomType (unknown location): property cannot be set to 0
138 \endcode
139
140 \sa QtQml::qmlDebug, QtQml::qmlInfo
141*/
142
143/*!
144 \fn QQmlInfo QtQml::qmlDebug(const QObject *object, const QQmlError &error)
145 \internal
146*/
147
148/*!
149 \fn QQmlInfo QtQml::qmlDebug(const QObject *object, const QList<QQmlError> &errors)
150 \internal
151*/
152
153/*!
154 \fn QQmlInfo QtQml::qmlInfo(const QObject *object, const QQmlError &error)
155 \internal
156*/
157
158/*!
159 \fn QQmlInfo QtQml::qmlInfo(const QObject *object, const QList<QQmlError> &errors)
160 \internal
161*/
162
163/*!
164 \fn QQmlInfo QtQml::qmlWarning(const QObject *object, const QQmlError &error)
165 \internal
166*/
167
168/*!
169 \fn QQmlInfo QtQml::qmlWarning(const QObject *object, const QList<QQmlError> &errors)
170 \internal
171*/
172
173class QQmlInfoPrivate
174{
175public:
176 QQmlInfoPrivate(QtMsgType type)
177 : ref (1)
178 , msgType(type)
179 , object(nullptr)
180 {}
181
182 int ref;
183 QtMsgType msgType;
184 const QObject *object;
185 QString buffer;
186 QList<QQmlError> errors;
187};
188
189QQmlInfo::QQmlInfo(QQmlInfoPrivate *p)
190: QDebug(&p->buffer), d(p)
191{
192 nospace();
193}
194
195QQmlInfo::QQmlInfo(const QQmlInfo &other)
196: QDebug(other), d(other.d)
197{
198 d->ref++;
199}
200
201QQmlInfo::~QQmlInfo()
202{
203 if (0 == --d->ref) {
204 QList<QQmlError> errors = d->errors;
205
206 QQmlEngine *engine = nullptr;
207
208 if (!d->buffer.isEmpty()) {
209 QQmlError error;
210 error.setMessageType(d->msgType);
211
212 QObject *object = const_cast<QObject *>(d->object);
213
214 if (object) {
215 // Some objects (e.g. like attached objects created in C++) won't have an associated engine,
216 // but we can still try to look for a parent object that does.
217 QObject *objectWithEngine = object;
218 while (objectWithEngine) {
219 engine = qmlEngine(objectWithEngine);
220 if (engine)
221 break;
222 objectWithEngine = objectWithEngine->parent();
223 }
224
225 if (!objectWithEngine || objectWithEngine == object) {
226 d->buffer.prepend(s: QLatin1String("QML ") + QQmlMetaType::prettyTypeName(object) + QLatin1String(": "));
227 } else {
228 d->buffer.prepend(s: QLatin1String("QML ") + QQmlMetaType::prettyTypeName(object: objectWithEngine)
229 + QLatin1String(" (parent or ancestor of ") + QQmlMetaType::prettyTypeName(object) + QLatin1String("): "));
230 }
231
232 QQmlData *ddata = QQmlData::get(object: objectWithEngine ? objectWithEngine : object, create: false);
233 if (ddata && ddata->outerContext) {
234 error.setUrl(ddata->outerContext->url());
235 error.setLine(qmlConvertSourceCoordinate<quint16, int>(n: ddata->lineNumber));
236 error.setColumn(qmlConvertSourceCoordinate<quint16, int>(n: ddata->columnNumber));
237 }
238 }
239
240 error.setDescription(d->buffer);
241
242 errors.prepend(t: error);
243 }
244
245 QQmlEnginePrivate::warning(engine, errors);
246
247 delete d;
248 }
249}
250
251namespace QtQml {
252
253#define MESSAGE_FUNCS(FuncName, MessageLevel) \
254 QQmlInfo FuncName(const QObject *me) \
255 { \
256 QQmlInfoPrivate *d = new QQmlInfoPrivate(MessageLevel); \
257 d->object = me; \
258 return QQmlInfo(d); \
259 } \
260 QQmlInfo FuncName(const QObject *me, const QQmlError &error) \
261 { \
262 QQmlInfoPrivate *d = new QQmlInfoPrivate(MessageLevel); \
263 d->object = me; \
264 d->errors << error; \
265 return QQmlInfo(d); \
266 } \
267 QQmlInfo FuncName(const QObject *me, const QList<QQmlError> &errors) \
268 { \
269 QQmlInfoPrivate *d = new QQmlInfoPrivate(MessageLevel); \
270 d->object = me; \
271 d->errors = errors; \
272 return QQmlInfo(d); \
273 }
274
275MESSAGE_FUNCS(qmlDebug, QtMsgType::QtDebugMsg)
276MESSAGE_FUNCS(qmlInfo, QtMsgType::QtInfoMsg)
277MESSAGE_FUNCS(qmlWarning, QtMsgType::QtWarningMsg)
278
279
280} // namespace QtQml
281
282#if QT_DEPRECATED_SINCE(5, 1)
283
284// Also define symbols outside namespace to keep binary compatibility with Qt 5.0
285
286QQmlInfo qmlInfo(const QObject *me)
287{
288 return QtQml::qmlInfo(me);
289}
290
291QQmlInfo qmlInfo(const QObject *me, const QQmlError &error)
292{
293 return QtQml::qmlInfo(me, error);
294}
295
296QQmlInfo qmlInfo(const QObject *me, const QList<QQmlError> &errors)
297{
298 return QtQml::qmlInfo(me, errors);
299}
300
301#endif // QT_DEPRECATED_SINCE(5, 1)
302
303QT_END_NAMESPACE
304

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