Added Logging Category support to QML
New Logging Categories can be defined by using the LoggingCategory type and define a name for the category When the id of a valid LoggingCategory is provided as the first argument to console.log and friends the LoggingCategory is used instead of the default "qml" LoggingCategory [ChangeLog][QML Elements] Added a LoggingCategory type and added support for it to the console object Change-Id: Ifaeed5f71de6ea6d8172d8c838d6e7789c4d6b9d Reviewed-by: Simon Hausmann <simon.hausmann@qt.io>
This commit is contained in:
parent
a3aad1a470
commit
eea2754976
|
@ -49,7 +49,8 @@ SOURCES += \
|
|||
$$PWD/qqmlfileselector.cpp \
|
||||
$$PWD/qqmlobjectcreator.cpp \
|
||||
$$PWD/qqmldirparser.cpp \
|
||||
$$PWD/qqmldelayedcallqueue.cpp
|
||||
$$PWD/qqmldelayedcallqueue.cpp \
|
||||
$$PWD/qqmlloggingcategory.cpp
|
||||
|
||||
HEADERS += \
|
||||
$$PWD/qqmlglobal_p.h \
|
||||
|
@ -121,7 +122,8 @@ HEADERS += \
|
|||
$$PWD/qqmlfileselector.h \
|
||||
$$PWD/qqmlobjectcreator_p.h \
|
||||
$$PWD/qqmldirparser_p.h \
|
||||
$$PWD/qqmldelayedcallqueue_p.h
|
||||
$$PWD/qqmldelayedcallqueue_p.h \
|
||||
$$PWD/qqmlloggingcategory_p.h
|
||||
|
||||
include(ftw/ftw.pri)
|
||||
include(v8/v8.pri)
|
||||
|
|
|
@ -89,6 +89,7 @@
|
|||
#include <private/qqmlobjectmodel_p.h>
|
||||
#include <private/qquickworkerscript_p.h>
|
||||
#include <private/qqmlinstantiator_p.h>
|
||||
#include <private/qqmlloggingcategory_p.h>
|
||||
|
||||
#ifdef Q_OS_WIN // for %APPDATA%
|
||||
# include <qt_windows.h>
|
||||
|
@ -184,6 +185,7 @@ void QQmlEnginePrivate::registerBaseTypes(const char *uri, int versionMajor, int
|
|||
qmlRegisterType<QQmlInstantiator>(uri, versionMajor, (versionMinor < 1 ? 1 : versionMinor), "Instantiator"); //Only available in >=2.1
|
||||
qmlRegisterCustomType<QQmlConnections>(uri, versionMajor, versionMinor,"Connections", new QQmlConnectionsParser);
|
||||
qmlRegisterType<QQmlInstanceModel>();
|
||||
qmlRegisterType<QQmlLoggingCategory>(uri, versionMajor, (versionMinor < 8 ? 8 : versionMinor), "LoggingCategory"); //Only available in >=2.8
|
||||
}
|
||||
|
||||
|
||||
|
|
|
@ -0,0 +1,128 @@
|
|||
/****************************************************************************
|
||||
**
|
||||
** Copyright (C) 2016 Pelagicore AG
|
||||
** Contact: https://www.qt.io/licensing/
|
||||
**
|
||||
** This file is part of the QtQml module of the Qt Toolkit.
|
||||
**
|
||||
** $QT_BEGIN_LICENSE:LGPL$
|
||||
** Commercial License Usage
|
||||
** Licensees holding valid commercial Qt licenses may use this file in
|
||||
** accordance with the commercial license agreement provided with the
|
||||
** Software or, alternatively, in accordance with the terms contained in
|
||||
** a written agreement between you and The Qt Company. For licensing terms
|
||||
** and conditions see https://www.qt.io/terms-conditions. For further
|
||||
** information use the contact form at https://www.qt.io/contact-us.
|
||||
**
|
||||
** GNU Lesser General Public License Usage
|
||||
** Alternatively, this file may be used under the terms of the GNU Lesser
|
||||
** General Public License version 3 as published by the Free Software
|
||||
** Foundation and appearing in the file LICENSE.LGPL3 included in the
|
||||
** packaging of this file. Please review the following information to
|
||||
** ensure the GNU Lesser General Public License version 3 requirements
|
||||
** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
|
||||
**
|
||||
** GNU General Public License Usage
|
||||
** Alternatively, this file may be used under the terms of the GNU
|
||||
** General Public License version 2.0 or (at your option) the GNU General
|
||||
** Public license version 3 or any later version approved by the KDE Free
|
||||
** Qt Foundation. The licenses are as published by the Free Software
|
||||
** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
|
||||
** included in the packaging of this file. Please review the following
|
||||
** information to ensure the GNU General Public License requirements will
|
||||
** be met: https://www.gnu.org/licenses/gpl-2.0.html and
|
||||
** https://www.gnu.org/licenses/gpl-3.0.html.
|
||||
**
|
||||
** $QT_END_LICENSE$
|
||||
**
|
||||
****************************************************************************/
|
||||
|
||||
#include "qqmlloggingcategory_p.h"
|
||||
|
||||
#include <QtQml/qqmlinfo.h>
|
||||
|
||||
/*!
|
||||
\qmltype LoggingCategory
|
||||
\ingroup qml-utility-elements
|
||||
\inqmlmodule QtQml
|
||||
\brief Defines a logging category in QML
|
||||
\since 5.8
|
||||
|
||||
A logging category can be passed to console.log() and friends as the first argument.
|
||||
If supplied to to the logger the LoggingCategory's name will be used as Logging Category
|
||||
otherwise the default logging category will be used.
|
||||
|
||||
\qml
|
||||
import QtQuick 2.8
|
||||
|
||||
Item {
|
||||
LoggingCategory {
|
||||
id: category
|
||||
name: "com.qt.category"
|
||||
}
|
||||
|
||||
Component.onCompleted: {
|
||||
console.log(category, "message");
|
||||
}
|
||||
}
|
||||
\endqml
|
||||
|
||||
\note As the creation of objects is expensive, it is encouraged to put the needed
|
||||
LoggingCategory definitions into a singleton and import this where needed.
|
||||
|
||||
\sa QLoggingCategory
|
||||
*/
|
||||
|
||||
/*!
|
||||
\qmlproperty string QtQml::LoggingCategory::name
|
||||
|
||||
Holds the name of the logging category.
|
||||
|
||||
\note This property needs to be set when declaring the LoggingCategory
|
||||
and cannot be changed later.
|
||||
|
||||
\sa QLoggingCategory::name()
|
||||
*/
|
||||
|
||||
QQmlLoggingCategory::QQmlLoggingCategory(QObject *parent)
|
||||
: QObject(parent)
|
||||
, m_initialized(false)
|
||||
{
|
||||
}
|
||||
|
||||
QQmlLoggingCategory::~QQmlLoggingCategory()
|
||||
{
|
||||
}
|
||||
|
||||
QString QQmlLoggingCategory::name() const
|
||||
{
|
||||
return QString::fromUtf8(m_name);
|
||||
}
|
||||
|
||||
QLoggingCategory *QQmlLoggingCategory::category() const
|
||||
{
|
||||
return m_category.data();
|
||||
}
|
||||
|
||||
void QQmlLoggingCategory::classBegin()
|
||||
{
|
||||
}
|
||||
|
||||
void QQmlLoggingCategory::componentComplete()
|
||||
{
|
||||
m_initialized = true;
|
||||
if (m_name.isNull())
|
||||
qmlInfo(this) << QString(QLatin1String("Declaring the name of the LoggingCategory is mandatory and cannot be changed later !"));
|
||||
}
|
||||
|
||||
void QQmlLoggingCategory::setName(const QString &name)
|
||||
{
|
||||
if (m_initialized) {
|
||||
qmlInfo(this) << QString(QLatin1String("The name of a LoggingCategory cannot be changed after the Item is created"));
|
||||
return;
|
||||
}
|
||||
|
||||
m_name = name.toUtf8();
|
||||
QScopedPointer<QLoggingCategory> category(new QLoggingCategory(m_name.constData()));
|
||||
m_category.swap(category);
|
||||
}
|
|
@ -0,0 +1,89 @@
|
|||
/****************************************************************************
|
||||
**
|
||||
** Copyright (C) 2016 Pelagicore AG
|
||||
** Contact: https://www.qt.io/licensing/
|
||||
**
|
||||
** This file is part of the QtQml module of the Qt Toolkit.
|
||||
**
|
||||
** $QT_BEGIN_LICENSE:LGPL$
|
||||
** Commercial License Usage
|
||||
** Licensees holding valid commercial Qt licenses may use this file in
|
||||
** accordance with the commercial license agreement provided with the
|
||||
** Software or, alternatively, in accordance with the terms contained in
|
||||
** a written agreement between you and The Qt Company. For licensing terms
|
||||
** and conditions see https://www.qt.io/terms-conditions. For further
|
||||
** information use the contact form at https://www.qt.io/contact-us.
|
||||
**
|
||||
** GNU Lesser General Public License Usage
|
||||
** Alternatively, this file may be used under the terms of the GNU Lesser
|
||||
** General Public License version 3 as published by the Free Software
|
||||
** Foundation and appearing in the file LICENSE.LGPL3 included in the
|
||||
** packaging of this file. Please review the following information to
|
||||
** ensure the GNU Lesser General Public License version 3 requirements
|
||||
** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
|
||||
**
|
||||
** GNU General Public License Usage
|
||||
** Alternatively, this file may be used under the terms of the GNU
|
||||
** General Public License version 2.0 or (at your option) the GNU General
|
||||
** Public license version 3 or any later version approved by the KDE Free
|
||||
** Qt Foundation. The licenses are as published by the Free Software
|
||||
** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
|
||||
** included in the packaging of this file. Please review the following
|
||||
** information to ensure the GNU General Public License requirements will
|
||||
** be met: https://www.gnu.org/licenses/gpl-2.0.html and
|
||||
** https://www.gnu.org/licenses/gpl-3.0.html.
|
||||
**
|
||||
** $QT_END_LICENSE$
|
||||
**
|
||||
****************************************************************************/
|
||||
|
||||
#ifndef QQMLLOGGINGCATEGORY_P_H
|
||||
#define QQMLLOGGINGCATEGORY_P_H
|
||||
|
||||
//
|
||||
// W A R N I N G
|
||||
// -------------
|
||||
//
|
||||
// This file is not part of the Qt API. It exists purely as an
|
||||
// implementation detail. This header file may change from version to
|
||||
// version without notice, or even be removed.
|
||||
//
|
||||
// We mean it.
|
||||
//
|
||||
|
||||
#include <QtCore/qobject.h>
|
||||
#include <QtCore/qstring.h>
|
||||
#include <QtCore/qloggingcategory.h>
|
||||
|
||||
#include <QtQml/qqmlparserstatus.h>
|
||||
|
||||
QT_BEGIN_NAMESPACE
|
||||
|
||||
class QQmlLoggingCategory : public QObject, public QQmlParserStatus
|
||||
{
|
||||
Q_OBJECT
|
||||
Q_INTERFACES(QQmlParserStatus)
|
||||
|
||||
Q_PROPERTY(QString name READ name WRITE setName)
|
||||
|
||||
public:
|
||||
QQmlLoggingCategory(QObject *parent = 0);
|
||||
virtual ~QQmlLoggingCategory();
|
||||
|
||||
QString name() const;
|
||||
void setName(const QString &name);
|
||||
|
||||
QLoggingCategory *category() const;
|
||||
|
||||
void classBegin() override;
|
||||
void componentComplete() override;
|
||||
|
||||
private:
|
||||
QByteArray m_name;
|
||||
QScopedPointer<QLoggingCategory> m_category;
|
||||
bool m_initialized;
|
||||
};
|
||||
|
||||
QT_END_NAMESPACE
|
||||
|
||||
#endif // QQMLLOGGINGCATEGORY_H
|
|
@ -42,6 +42,7 @@
|
|||
#include <QtQml/qqmlcomponent.h>
|
||||
#include <private/qqmlengine_p.h>
|
||||
#include <private/qqmlcomponent_p.h>
|
||||
#include <private/qqmlloggingcategory_p.h>
|
||||
#include <private/qqmlstringconverters_p.h>
|
||||
#include <private/qqmllocale_p.h>
|
||||
#include <private/qv8engine_p.h>
|
||||
|
@ -76,6 +77,8 @@
|
|||
#include <QtCore/qcoreapplication.h>
|
||||
#include <QtCore/qloggingcategory.h>
|
||||
|
||||
#include <QDebug>
|
||||
|
||||
QT_BEGIN_NAMESPACE
|
||||
|
||||
using namespace QV4;
|
||||
|
@ -1464,11 +1467,26 @@ static QString jsStack(QV4::ExecutionEngine *engine) {
|
|||
static QV4::ReturnedValue writeToConsole(ConsoleLogTypes logType, CallContext *ctx,
|
||||
bool printStack = false)
|
||||
{
|
||||
QLoggingCategory *loggingCategory = 0;
|
||||
QString result;
|
||||
QV4::ExecutionEngine *v4 = ctx->d()->engine;
|
||||
|
||||
for (int i = 0; i < ctx->argc(); ++i) {
|
||||
if (i != 0)
|
||||
int start = 0;
|
||||
if (ctx->argc() > 0) {
|
||||
if (const QObjectWrapper* wrapper = ctx->args()[0].as<QObjectWrapper>()) {
|
||||
if (QQmlLoggingCategory* category = qobject_cast<QQmlLoggingCategory*>(wrapper->object())) {
|
||||
if (category->category())
|
||||
loggingCategory = category->category();
|
||||
else
|
||||
V4THROW_ERROR("A QmlLoggingCatgory was provided without a valid name");
|
||||
start = 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
for (int i = start; i < ctx->argc(); ++i) {
|
||||
if (i != start)
|
||||
result.append(QLatin1Char(' '));
|
||||
|
||||
if (ctx->args()[i].as<ArrayObject>())
|
||||
|
@ -1485,7 +1503,8 @@ static QV4::ReturnedValue writeToConsole(ConsoleLogTypes logType, CallContext *c
|
|||
static QLoggingCategory qmlLoggingCategory("qml");
|
||||
static QLoggingCategory jsLoggingCategory("js");
|
||||
|
||||
QLoggingCategory *loggingCategory = v4->qmlEngine() ? &qmlLoggingCategory : &jsLoggingCategory;
|
||||
if (!loggingCategory)
|
||||
loggingCategory = v4->qmlEngine() ? &qmlLoggingCategory : &jsLoggingCategory;
|
||||
QV4::StackFrame frame = v4->currentStackFrame();
|
||||
const QByteArray baSource = frame.source.toUtf8();
|
||||
const QByteArray baFunction = frame.function.toUtf8();
|
||||
|
|
|
@ -0,0 +1,65 @@
|
|||
/****************************************************************************
|
||||
**
|
||||
** Copyright (C) 2016 Pelagicore AG
|
||||
** Contact: https://www.qt.io/licensing/
|
||||
**
|
||||
** This file is part of the QtQml module of the Qt Toolkit.
|
||||
**
|
||||
** $QT_BEGIN_LICENSE:LGPL$
|
||||
** Commercial License Usage
|
||||
** Licensees holding valid commercial Qt licenses may use this file in
|
||||
** accordance with the commercial license agreement provided with the
|
||||
** Software or, alternatively, in accordance with the terms contained in
|
||||
** a written agreement between you and The Qt Company. For licensing terms
|
||||
** and conditions see https://www.qt.io/terms-conditions. For further
|
||||
** information use the contact form at https://www.qt.io/contact-us.
|
||||
**
|
||||
** GNU Lesser General Public License Usage
|
||||
** Alternatively, this file may be used under the terms of the GNU Lesser
|
||||
** General Public License version 3 as published by the Free Software
|
||||
** Foundation and appearing in the file LICENSE.LGPL3 included in the
|
||||
** packaging of this file. Please review the following information to
|
||||
** ensure the GNU Lesser General Public License version 3 requirements
|
||||
** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
|
||||
**
|
||||
** GNU General Public License Usage
|
||||
** Alternatively, this file may be used under the terms of the GNU
|
||||
** General Public License version 2.0 or (at your option) the GNU General
|
||||
** Public license version 3 or any later version approved by the KDE Free
|
||||
** Qt Foundation. The licenses are as published by the Free Software
|
||||
** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
|
||||
** included in the packaging of this file. Please review the following
|
||||
** information to ensure the GNU General Public License requirements will
|
||||
** be met: https://www.gnu.org/licenses/gpl-2.0.html and
|
||||
** https://www.gnu.org/licenses/gpl-3.0.html.
|
||||
**
|
||||
** $QT_END_LICENSE$
|
||||
**
|
||||
****************************************************************************/
|
||||
|
||||
import QtQuick 2.8
|
||||
|
||||
Item {
|
||||
id:root
|
||||
|
||||
LoggingCategory {
|
||||
id: testCategory
|
||||
name: "qt.test"
|
||||
}
|
||||
|
||||
LoggingCategory {
|
||||
id: emptyCategory
|
||||
}
|
||||
|
||||
Component.onCompleted: {
|
||||
console.debug(testCategory, "console.debug");
|
||||
console.log(testCategory, "console.log");
|
||||
console.info(testCategory, "console.info");
|
||||
console.warn(testCategory, "console.warn");
|
||||
console.error(testCategory, "console.error");
|
||||
|
||||
testCategory.name = "qt.test2";
|
||||
|
||||
console.error(emptyCategory, "console.error");
|
||||
}
|
||||
}
|
|
@ -40,6 +40,7 @@ public:
|
|||
|
||||
private slots:
|
||||
void logging();
|
||||
void categorized_logging();
|
||||
void tracing();
|
||||
void profiling();
|
||||
void testAssert();
|
||||
|
@ -87,6 +88,41 @@ void tst_qqmlconsole::logging()
|
|||
delete object;
|
||||
}
|
||||
|
||||
void tst_qqmlconsole::categorized_logging()
|
||||
{
|
||||
QUrl testUrl = testFileUrl("categorized_logging.qml");
|
||||
QQmlTestMessageHandler messageHandler;
|
||||
messageHandler.setIncludeCategoriesEnabled(true);
|
||||
|
||||
QLoggingCategory testCategory("qt.test");
|
||||
testCategory.setEnabled(QtDebugMsg, true);
|
||||
QVERIFY(testCategory.isDebugEnabled());
|
||||
QVERIFY(testCategory.isWarningEnabled());
|
||||
QVERIFY(testCategory.isCriticalEnabled());
|
||||
|
||||
QQmlComponent component(&engine, testUrl);
|
||||
QObject *object = component.create();
|
||||
QVERIFY2(object != 0, component.errorString().toUtf8());
|
||||
|
||||
QVERIFY(messageHandler.messages().contains("qt.test: console.info"));
|
||||
QVERIFY(messageHandler.messages().contains("qt.test: console.warn"));
|
||||
QVERIFY(messageHandler.messages().contains("qt.test: console.error"));
|
||||
|
||||
QString emptyCategory = "default: " + QString::fromLatin1("%1:%2:%3: ").arg(testUrl.toString()).arg(50).arg(5) +
|
||||
"QML LoggingCategory: Declaring the name of the LoggingCategory is mandatory and cannot be changed later !";
|
||||
QVERIFY(messageHandler.messages().contains(emptyCategory));
|
||||
|
||||
QString changedCategory = "default: " + QString::fromLatin1("%1:%2:%3: ").arg(testUrl.toString()).arg(45).arg(5) +
|
||||
"QML LoggingCategory: The name of a LoggingCategory cannot be changed after the Item is created";
|
||||
QVERIFY(messageHandler.messages().contains(changedCategory));
|
||||
|
||||
QString useEmptyCategory = "default: " + QString::fromLatin1("%1:%2: ").arg(testUrl.toString()).arg(63) +
|
||||
"Error: A QmlLoggingCatgory was provided without a valid name";
|
||||
QVERIFY(messageHandler.messages().contains(useEmptyCategory));
|
||||
|
||||
delete object;
|
||||
}
|
||||
|
||||
void tst_qqmlconsole::tracing()
|
||||
{
|
||||
QUrl testUrl = testFileUrl("tracing.qml");
|
||||
|
|
|
@ -101,11 +101,15 @@ Q_GLOBAL_STATIC(QMutex, qQmlTestMessageHandlerMutex)
|
|||
|
||||
QQmlTestMessageHandler *QQmlTestMessageHandler::m_instance = 0;
|
||||
|
||||
void QQmlTestMessageHandler::messageHandler(QtMsgType, const QMessageLogContext &, const QString &message)
|
||||
void QQmlTestMessageHandler::messageHandler(QtMsgType, const QMessageLogContext &context, const QString &message)
|
||||
{
|
||||
QMutexLocker locker(qQmlTestMessageHandlerMutex());
|
||||
if (QQmlTestMessageHandler::m_instance)
|
||||
QQmlTestMessageHandler::m_instance->m_messages.push_back(message);
|
||||
if (QQmlTestMessageHandler::m_instance) {
|
||||
if (QQmlTestMessageHandler::m_instance->m_includeCategories)
|
||||
QQmlTestMessageHandler::m_instance->m_messages.push_back(QString("%1: %2").arg(context.category, message));
|
||||
else
|
||||
QQmlTestMessageHandler::m_instance->m_messages.push_back(message);
|
||||
}
|
||||
}
|
||||
|
||||
QQmlTestMessageHandler::QQmlTestMessageHandler()
|
||||
|
@ -114,6 +118,7 @@ QQmlTestMessageHandler::QQmlTestMessageHandler()
|
|||
Q_ASSERT(!QQmlTestMessageHandler::m_instance);
|
||||
QQmlTestMessageHandler::m_instance = this;
|
||||
m_oldHandler = qInstallMessageHandler(messageHandler);
|
||||
m_includeCategories = false;
|
||||
}
|
||||
|
||||
QQmlTestMessageHandler::~QQmlTestMessageHandler()
|
||||
|
|
|
@ -87,12 +87,15 @@ public:
|
|||
|
||||
void clear() { m_messages.clear(); }
|
||||
|
||||
void setIncludeCategoriesEnabled(bool enabled) { m_includeCategories = enabled; }
|
||||
|
||||
private:
|
||||
static void messageHandler(QtMsgType, const QMessageLogContext &, const QString &message);
|
||||
static void messageHandler(QtMsgType, const QMessageLogContext &context, const QString &message);
|
||||
|
||||
static QQmlTestMessageHandler *m_instance;
|
||||
QStringList m_messages;
|
||||
QtMessageHandler m_oldHandler;
|
||||
bool m_includeCategories;
|
||||
};
|
||||
|
||||
#endif // QQMLTESTUTILS_H
|
||||
|
|
Loading…
Reference in New Issue