forked from qt-creator/qt-creator
Core: Refactor logging viewer
* All log categories that were ever used are captured. * Fixed various small issues. * Allow disabling individual logging types. * Add Splitter between messages and categories. * No longer needs to interpret or change QT_LOGGING_RULES. Change-Id: I33be4754d550064bc66274f655a59e7af67ae487 Reviewed-by: <github-actions-qt-creator@cristianadam.eu> Reviewed-by: Christian Stenger <christian.stenger@qt.io>
This commit is contained in:
@@ -209,8 +209,6 @@ add_qtc_plugin(Core
|
|||||||
locator/spotlightlocatorfilter.h
|
locator/spotlightlocatorfilter.h
|
||||||
locator/urllocatorfilter.cpp
|
locator/urllocatorfilter.cpp
|
||||||
locator/urllocatorfilter.h
|
locator/urllocatorfilter.h
|
||||||
loggingmanager.cpp
|
|
||||||
loggingmanager.h
|
|
||||||
loggingviewer.cpp
|
loggingviewer.cpp
|
||||||
loggingviewer.h
|
loggingviewer.h
|
||||||
manhattanstyle.cpp
|
manhattanstyle.cpp
|
||||||
|
|||||||
@@ -9,18 +9,18 @@
|
|||||||
#include "icore.h"
|
#include "icore.h"
|
||||||
#include "idocument.h"
|
#include "idocument.h"
|
||||||
#include "iwizardfactory.h"
|
#include "iwizardfactory.h"
|
||||||
|
#include "loggingviewer.h"
|
||||||
#include "modemanager.h"
|
#include "modemanager.h"
|
||||||
#include "session.h"
|
#include "session.h"
|
||||||
#include "settingsdatabase.h"
|
#include "settingsdatabase.h"
|
||||||
#include "themechooser.h"
|
#include "themechooser.h"
|
||||||
|
|
||||||
#include "actionmanager/actionmanager.h"
|
#include "actionmanager/actionmanager.h"
|
||||||
|
#include "coreconstants.h"
|
||||||
#include "documentmanager.h"
|
#include "documentmanager.h"
|
||||||
#include "editormanager/editormanager.h"
|
#include "fileutils.h"
|
||||||
#include "find/findplugin.h"
|
#include "find/findplugin.h"
|
||||||
#include "locator/locator.h"
|
#include "locator/locator.h"
|
||||||
#include "coreconstants.h"
|
|
||||||
#include "fileutils.h"
|
|
||||||
|
|
||||||
#include <extensionsystem/pluginerroroverview.h>
|
#include <extensionsystem/pluginerroroverview.h>
|
||||||
#include <extensionsystem/pluginmanager.h>
|
#include <extensionsystem/pluginmanager.h>
|
||||||
@@ -490,6 +490,7 @@ QString CorePlugin::msgCrashpadInformation()
|
|||||||
|
|
||||||
ExtensionSystem::IPlugin::ShutdownFlag CorePlugin::aboutToShutdown()
|
ExtensionSystem::IPlugin::ShutdownFlag CorePlugin::aboutToShutdown()
|
||||||
{
|
{
|
||||||
|
LoggingViewer::hideLoggingView();
|
||||||
Find::aboutToShutdown();
|
Find::aboutToShutdown();
|
||||||
m_locator->aboutToShutdown();
|
m_locator->aboutToShutdown();
|
||||||
ICore::aboutToShutdown();
|
ICore::aboutToShutdown();
|
||||||
|
|||||||
@@ -102,8 +102,6 @@ QtcPlugin {
|
|||||||
"iwizardfactory.h",
|
"iwizardfactory.h",
|
||||||
"jsexpander.cpp",
|
"jsexpander.cpp",
|
||||||
"jsexpander.h",
|
"jsexpander.h",
|
||||||
"loggingmanager.cpp",
|
|
||||||
"loggingmanager.h",
|
|
||||||
"loggingviewer.cpp",
|
"loggingviewer.cpp",
|
||||||
"loggingviewer.h",
|
"loggingviewer.h",
|
||||||
"manhattanstyle.cpp",
|
"manhattanstyle.cpp",
|
||||||
|
|||||||
@@ -1,304 +0,0 @@
|
|||||||
// Copyright (C) 2021 The Qt Company Ltd.
|
|
||||||
// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
|
|
||||||
|
|
||||||
#include "loggingmanager.h"
|
|
||||||
|
|
||||||
#include <utils/environment.h>
|
|
||||||
#include <utils/filepath.h>
|
|
||||||
|
|
||||||
#include <QCoreApplication>
|
|
||||||
#include <QDateTime>
|
|
||||||
#include <QLibraryInfo>
|
|
||||||
#include <QRegularExpression>
|
|
||||||
#include <QSettings>
|
|
||||||
#include <QStandardPaths>
|
|
||||||
|
|
||||||
//
|
|
||||||
// WARNING! Do not use qDebug(), qWarning() or similar inside this file -
|
|
||||||
// same applies for indirect usages (e.g. QTC_ASSERT() and the like).
|
|
||||||
// Using static functions of QLoggingCategory may cause dead locks as well.
|
|
||||||
//
|
|
||||||
|
|
||||||
using namespace Utils;
|
|
||||||
|
|
||||||
namespace Core {
|
|
||||||
namespace Internal {
|
|
||||||
|
|
||||||
static QtMessageHandler s_originalMessageHandler = nullptr;
|
|
||||||
|
|
||||||
static LoggingViewManager *s_instance = nullptr;
|
|
||||||
|
|
||||||
static QString levelToString(QtMsgType t)
|
|
||||||
{
|
|
||||||
switch (t) {
|
|
||||||
case QtMsgType::QtCriticalMsg: return {"critical"};
|
|
||||||
case QtMsgType::QtDebugMsg: return {"debug"};
|
|
||||||
case QtMsgType::QtInfoMsg: return {"info"};
|
|
||||||
case QtMsgType::QtWarningMsg: return {"warning"};
|
|
||||||
default:
|
|
||||||
return {"fatal"}; // wrong but we don't care
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
static QtMsgType parseLevel(const QString &level)
|
|
||||||
{
|
|
||||||
switch (level.at(0).toLatin1()) {
|
|
||||||
case 'c': return QtMsgType::QtCriticalMsg;
|
|
||||||
case 'd': return QtMsgType::QtDebugMsg;
|
|
||||||
case 'i': return QtMsgType::QtInfoMsg;
|
|
||||||
case 'w': return QtMsgType::QtWarningMsg;
|
|
||||||
default:
|
|
||||||
return QtMsgType::QtFatalMsg; // wrong but we don't care
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
static bool parseLine(const QString &line, FilterRuleSpec *filterRule)
|
|
||||||
{
|
|
||||||
const QStringList parts = line.split('=');
|
|
||||||
if (parts.size() != 2)
|
|
||||||
return false;
|
|
||||||
|
|
||||||
const QString category = parts.at(0);
|
|
||||||
static const QRegularExpression regex("^(.+?)(\\.(debug|info|warning|critical))?$");
|
|
||||||
const QRegularExpressionMatch match = regex.match(category);
|
|
||||||
if (!match.hasMatch())
|
|
||||||
return false;
|
|
||||||
|
|
||||||
const QString categoryName = match.captured(1);
|
|
||||||
if (categoryName.size() > 2) {
|
|
||||||
if (categoryName.mid(1, categoryName.size() - 2).contains('*'))
|
|
||||||
return false;
|
|
||||||
} else if (categoryName.size() == 2) {
|
|
||||||
if (categoryName.count('*') == 2)
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
filterRule->category = categoryName;
|
|
||||||
|
|
||||||
if (match.capturedLength(2) == 0)
|
|
||||||
filterRule->level = std::nullopt;
|
|
||||||
else
|
|
||||||
filterRule->level = std::make_optional(parseLevel(match.captured(2).mid(1)));
|
|
||||||
|
|
||||||
const QString enabled = parts.at(1);
|
|
||||||
if (enabled == "true" || enabled == "false") {
|
|
||||||
filterRule->enabled = (enabled == "true");
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
static QList<FilterRuleSpec> fetchOriginalRules()
|
|
||||||
{
|
|
||||||
QList<FilterRuleSpec> rules;
|
|
||||||
|
|
||||||
auto appendRulesFromFile = [&rules](const QString &fileName) {
|
|
||||||
QSettings iniSettings(fileName, QSettings::IniFormat);
|
|
||||||
iniSettings.beginGroup("Rules");
|
|
||||||
const QStringList keys = iniSettings.allKeys();
|
|
||||||
for (const QString &key : keys) {
|
|
||||||
const QString value = iniSettings.value(key).toString();
|
|
||||||
FilterRuleSpec filterRule;
|
|
||||||
if (parseLine(key + "=" + value, &filterRule))
|
|
||||||
rules.append(filterRule);
|
|
||||||
}
|
|
||||||
iniSettings.endGroup();
|
|
||||||
};
|
|
||||||
|
|
||||||
Utils::FilePath iniFile = Utils::FilePath::fromString(
|
|
||||||
QLibraryInfo::path(QLibraryInfo::DataPath)).pathAppended("qtlogging.ini");
|
|
||||||
if (iniFile.exists())
|
|
||||||
appendRulesFromFile(iniFile.toString());
|
|
||||||
|
|
||||||
const QString qtProjectString = QStandardPaths::locate(QStandardPaths::GenericConfigLocation,
|
|
||||||
"QtProject/qtlogging.ini");
|
|
||||||
if (!qtProjectString.isEmpty())
|
|
||||||
appendRulesFromFile(qtProjectString);
|
|
||||||
|
|
||||||
iniFile = Utils::FilePath::fromString(qtcEnvironmentVariable("QT_LOGGING_CONF"));
|
|
||||||
if (iniFile.exists())
|
|
||||||
appendRulesFromFile(iniFile.toString());
|
|
||||||
|
|
||||||
if (qtcEnvironmentVariableIsSet("QT_LOGGING_RULES")) {
|
|
||||||
const QStringList rulesStrings = qtcEnvironmentVariable("QT_LOGGING_RULES").split(';');
|
|
||||||
for (const QString &rule : rulesStrings) {
|
|
||||||
FilterRuleSpec filterRule;
|
|
||||||
if (parseLine(rule, &filterRule))
|
|
||||||
rules.append(filterRule);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return rules;
|
|
||||||
}
|
|
||||||
|
|
||||||
LoggingViewManager::LoggingViewManager(QObject *parent)
|
|
||||||
: QObject(parent)
|
|
||||||
, m_originalLoggingRules(qtcEnvironmentVariable("QT_LOGGING_RULES"))
|
|
||||||
{
|
|
||||||
qRegisterMetaType<Core::Internal::LoggingCategoryEntry>();
|
|
||||||
s_instance = this;
|
|
||||||
s_originalMessageHandler = qInstallMessageHandler(logMessageHandler);
|
|
||||||
m_enabled = true;
|
|
||||||
m_originalRules = fetchOriginalRules();
|
|
||||||
prefillCategories();
|
|
||||||
QLoggingCategory::setFilterRules("*=true");
|
|
||||||
}
|
|
||||||
|
|
||||||
LoggingViewManager::~LoggingViewManager()
|
|
||||||
{
|
|
||||||
m_enabled = false;
|
|
||||||
qInstallMessageHandler(s_originalMessageHandler);
|
|
||||||
s_originalMessageHandler = nullptr;
|
|
||||||
qputenv("QT_LOGGING_RULES", m_originalLoggingRules.toLocal8Bit());
|
|
||||||
QLoggingCategory::setFilterRules("*=false");
|
|
||||||
resetFilterRules();
|
|
||||||
s_instance = nullptr;
|
|
||||||
}
|
|
||||||
|
|
||||||
LoggingViewManager *LoggingViewManager::instance()
|
|
||||||
{
|
|
||||||
return s_instance;
|
|
||||||
}
|
|
||||||
|
|
||||||
void LoggingViewManager::logMessageHandler(QtMsgType type, const QMessageLogContext &context,
|
|
||||||
const QString &mssg)
|
|
||||||
{
|
|
||||||
if (!s_instance->m_enabled) {
|
|
||||||
if (s_instance->enabledInOriginalRules(context, type))
|
|
||||||
s_originalMessageHandler(type, context, mssg);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!context.category) {
|
|
||||||
s_originalMessageHandler(type, context, mssg);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
const QString category = QString::fromLocal8Bit(context.category);
|
|
||||||
auto it = s_instance->m_categories.find(category);
|
|
||||||
if (it == s_instance->m_categories.end()) {
|
|
||||||
if (!s_instance->m_listQtInternal && category.startsWith("qt."))
|
|
||||||
return;
|
|
||||||
LoggingCategoryEntry entry;
|
|
||||||
entry.level = QtMsgType::QtDebugMsg;
|
|
||||||
entry.enabled = (category == "default") || s_instance->enabledInOriginalRules(context, type);
|
|
||||||
it = s_instance->m_categories.insert(category, entry);
|
|
||||||
emit s_instance->foundNewCategory(category, entry);
|
|
||||||
}
|
|
||||||
|
|
||||||
const LoggingCategoryEntry entry = it.value();
|
|
||||||
if (entry.enabled && enabled(type, entry.level)) {
|
|
||||||
const QString timestamp = QDateTime::currentDateTime().toString("HH:mm:ss.zzz");
|
|
||||||
emit s_instance->receivedLog(timestamp, category,
|
|
||||||
LoggingViewManager::messageTypeToString(type), mssg);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
bool LoggingViewManager::isCategoryEnabled(const QString &category)
|
|
||||||
{
|
|
||||||
auto entry = m_categories.find(category);
|
|
||||||
if (entry == m_categories.end()) // shall not happen - paranoia
|
|
||||||
return false;
|
|
||||||
|
|
||||||
return entry.value().enabled;
|
|
||||||
}
|
|
||||||
|
|
||||||
void LoggingViewManager::setCategoryEnabled(const QString &category, bool enabled)
|
|
||||||
{
|
|
||||||
auto entry = m_categories.find(category);
|
|
||||||
if (entry == m_categories.end()) // shall not happen - paranoia
|
|
||||||
return;
|
|
||||||
|
|
||||||
entry->enabled = enabled;
|
|
||||||
}
|
|
||||||
|
|
||||||
void LoggingViewManager::setLogLevel(const QString &category, QtMsgType type)
|
|
||||||
{
|
|
||||||
auto entry = m_categories.find(category);
|
|
||||||
if (entry == m_categories.end()) // shall not happen - paranoia
|
|
||||||
return;
|
|
||||||
|
|
||||||
entry->level = type;
|
|
||||||
}
|
|
||||||
|
|
||||||
void LoggingViewManager::setListQtInternal(bool listQtInternal)
|
|
||||||
{
|
|
||||||
m_listQtInternal = listQtInternal;
|
|
||||||
}
|
|
||||||
|
|
||||||
void LoggingViewManager::appendOrUpdate(const QString &category, const LoggingCategoryEntry &entry)
|
|
||||||
{
|
|
||||||
auto it = m_categories.find(category);
|
|
||||||
bool append = it == m_categories.end();
|
|
||||||
m_categories.insert(category, entry);
|
|
||||||
if (append)
|
|
||||||
emit foundNewCategory(category, entry);
|
|
||||||
else
|
|
||||||
emit updatedCategory(category, entry);
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Does not check categories for being present, will perform early exit if m_categories is not empty
|
|
||||||
*/
|
|
||||||
void LoggingViewManager::prefillCategories()
|
|
||||||
{
|
|
||||||
if (!m_categories.isEmpty())
|
|
||||||
return;
|
|
||||||
|
|
||||||
for (int i = 0, end = m_originalRules.size(); i < end; ++i) {
|
|
||||||
const FilterRuleSpec &rule = m_originalRules.at(i);
|
|
||||||
if (rule.category.startsWith('*') || rule.category.endsWith('*'))
|
|
||||||
continue;
|
|
||||||
|
|
||||||
bool enabled = rule.enabled;
|
|
||||||
// check following rules whether they might overwrite
|
|
||||||
for (int j = i + 1; j < end; ++j) {
|
|
||||||
const FilterRuleSpec &secondRule = m_originalRules.at(j);
|
|
||||||
const QRegularExpression regex(
|
|
||||||
QRegularExpression::wildcardToRegularExpression(secondRule.category));
|
|
||||||
if (!regex.match(rule.category).hasMatch())
|
|
||||||
continue;
|
|
||||||
|
|
||||||
if (secondRule.level.has_value() && rule.level != secondRule.level)
|
|
||||||
continue;
|
|
||||||
|
|
||||||
enabled = secondRule.enabled;
|
|
||||||
}
|
|
||||||
LoggingCategoryEntry entry;
|
|
||||||
entry.level = rule.level.value_or(QtMsgType::QtInfoMsg);
|
|
||||||
entry.enabled = enabled;
|
|
||||||
m_categories.insert(rule.category, entry);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void LoggingViewManager::resetFilterRules()
|
|
||||||
{
|
|
||||||
for (const FilterRuleSpec &rule : std::as_const(m_originalRules)) {
|
|
||||||
const QString level = rule.level.has_value() ? '.' + levelToString(rule.level.value())
|
|
||||||
: QString();
|
|
||||||
const QString ruleString = rule.category + level + '=' + (rule.enabled ? "true" : "false");
|
|
||||||
QLoggingCategory::setFilterRules(ruleString);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
bool LoggingViewManager::enabledInOriginalRules(const QMessageLogContext &context, QtMsgType type)
|
|
||||||
{
|
|
||||||
if (!context.category)
|
|
||||||
return false;
|
|
||||||
const QString category = QString::fromUtf8(context.category);
|
|
||||||
bool result = false;
|
|
||||||
for (const FilterRuleSpec &rule : std::as_const(m_originalRules)) {
|
|
||||||
const QRegularExpression regex(
|
|
||||||
QRegularExpression::wildcardToRegularExpression(rule.category));
|
|
||||||
if (regex.match(category).hasMatch()) {
|
|
||||||
if (rule.level.has_value()) {
|
|
||||||
if (rule.level.value() == type)
|
|
||||||
result = rule.enabled;
|
|
||||||
} else {
|
|
||||||
result = rule.enabled;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
} // namespace Internal
|
|
||||||
} // namespace Core
|
|
||||||
@@ -1,121 +0,0 @@
|
|||||||
// Copyright (C) 2021 The Qt Company Ltd.
|
|
||||||
// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
|
|
||||||
|
|
||||||
#pragma once
|
|
||||||
|
|
||||||
#include <QColor>
|
|
||||||
#include <QLoggingCategory>
|
|
||||||
#include <QMap>
|
|
||||||
#include <QObject>
|
|
||||||
|
|
||||||
#include <optional>
|
|
||||||
|
|
||||||
namespace Core {
|
|
||||||
namespace Internal {
|
|
||||||
|
|
||||||
struct FilterRuleSpec
|
|
||||||
{
|
|
||||||
QString category;
|
|
||||||
std::optional<QtMsgType> level;
|
|
||||||
bool enabled;
|
|
||||||
};
|
|
||||||
|
|
||||||
class LoggingCategoryEntry
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
QtMsgType level = QtDebugMsg;
|
|
||||||
bool enabled = false;
|
|
||||||
QColor color;
|
|
||||||
};
|
|
||||||
|
|
||||||
class LoggingViewManager : public QObject
|
|
||||||
{
|
|
||||||
Q_OBJECT
|
|
||||||
public:
|
|
||||||
static inline QString messageTypeToString(QtMsgType type)
|
|
||||||
{
|
|
||||||
switch (type) {
|
|
||||||
case QtDebugMsg: return {"Debug"};
|
|
||||||
case QtInfoMsg: return {"Info"};
|
|
||||||
case QtCriticalMsg: return {"Critical"};
|
|
||||||
case QtWarningMsg: return {"Warning"};
|
|
||||||
case QtFatalMsg: return {"Fatal"};
|
|
||||||
default: return {"Unknown"};
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
static inline QtMsgType messageTypeFromString(const QString &type)
|
|
||||||
{
|
|
||||||
if (type.isEmpty())
|
|
||||||
return QtDebugMsg;
|
|
||||||
|
|
||||||
// shortcut - only handle expected
|
|
||||||
switch (type.at(0).toLatin1()) {
|
|
||||||
case 'I':
|
|
||||||
return QtInfoMsg;
|
|
||||||
case 'C':
|
|
||||||
return QtCriticalMsg;
|
|
||||||
case 'W':
|
|
||||||
return QtWarningMsg;
|
|
||||||
case 'D':
|
|
||||||
default:
|
|
||||||
return QtDebugMsg;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
explicit LoggingViewManager(QObject *parent = nullptr);
|
|
||||||
~LoggingViewManager();
|
|
||||||
|
|
||||||
static LoggingViewManager *instance();
|
|
||||||
|
|
||||||
static inline bool enabled(QtMsgType current, QtMsgType stored)
|
|
||||||
{
|
|
||||||
if (stored == QtMsgType::QtInfoMsg)
|
|
||||||
return true;
|
|
||||||
if (current == stored)
|
|
||||||
return true;
|
|
||||||
if (stored == QtMsgType::QtDebugMsg)
|
|
||||||
return current != QtMsgType::QtInfoMsg;
|
|
||||||
if (stored == QtMsgType::QtWarningMsg)
|
|
||||||
return current == QtMsgType::QtCriticalMsg || current == QtMsgType::QtFatalMsg;
|
|
||||||
if (stored == QtMsgType::QtCriticalMsg)
|
|
||||||
return current == QtMsgType::QtFatalMsg;
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
static void logMessageHandler(QtMsgType type, const QMessageLogContext &context,
|
|
||||||
const QString &mssg);
|
|
||||||
|
|
||||||
void setEnabled(bool enabled) { m_enabled = enabled; }
|
|
||||||
bool isEnabled() const { return m_enabled; }
|
|
||||||
bool isCategoryEnabled(const QString &category);
|
|
||||||
void setCategoryEnabled(const QString &category, bool enabled);
|
|
||||||
void setLogLevel(const QString &category, QtMsgType type);
|
|
||||||
void setListQtInternal(bool listQtInternal);
|
|
||||||
QList<FilterRuleSpec> originalRules() const { return m_originalRules; }
|
|
||||||
|
|
||||||
QMap<QString, LoggingCategoryEntry> categories() const { return m_categories; }
|
|
||||||
void appendOrUpdate(const QString &category, const LoggingCategoryEntry &entry);
|
|
||||||
|
|
||||||
signals:
|
|
||||||
void receivedLog(const QString ×tamp, const QString &type, const QString &category,
|
|
||||||
const QString &msg);
|
|
||||||
void foundNewCategory(const QString &category, const LoggingCategoryEntry &entry);
|
|
||||||
void updatedCategory(const QString &category, const LoggingCategoryEntry &entry);
|
|
||||||
|
|
||||||
private:
|
|
||||||
void prefillCategories();
|
|
||||||
void resetFilterRules();
|
|
||||||
bool enabledInOriginalRules(const QMessageLogContext &context, QtMsgType type);
|
|
||||||
|
|
||||||
QMap<QString, LoggingCategoryEntry> m_categories;
|
|
||||||
const QString m_originalLoggingRules;
|
|
||||||
QList<FilterRuleSpec> m_originalRules;
|
|
||||||
bool m_enabled = false;
|
|
||||||
bool m_listQtInternal = false;
|
|
||||||
};
|
|
||||||
|
|
||||||
} // namespace Internal
|
|
||||||
} // namespace Core
|
|
||||||
|
|
||||||
Q_DECLARE_METATYPE(Core::Internal::LoggingCategoryEntry)
|
|
||||||
File diff suppressed because it is too large
Load Diff
@@ -3,14 +3,13 @@
|
|||||||
|
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
namespace Core {
|
namespace Core::Internal {
|
||||||
namespace Internal {
|
|
||||||
|
|
||||||
class LoggingViewer
|
class LoggingViewer
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
static void showLoggingView();
|
static void showLoggingView();
|
||||||
|
static void hideLoggingView();
|
||||||
};
|
};
|
||||||
|
|
||||||
} // Internal
|
} // namespace Core::Internal
|
||||||
} // Core
|
|
||||||
|
|||||||
Reference in New Issue
Block a user