src/platform/qt/LogController.cpp (view raw)
1/* Copyright (c) 2013-2015 Jeffrey Pfau
2 *
3 * This Source Code Form is subject to the terms of the Mozilla Public
4 * License, v. 2.0. If a copy of the MPL was not distributed with this
5 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
6#include "LogController.h"
7
8#include <QMessageBox>
9
10#include "ConfigController.h"
11
12using namespace QGBA;
13
14LogController LogController::s_global(mLOG_ALL);
15int LogController::s_qtCat{-1};
16
17LogController::LogController(int levels, QObject* parent)
18 : QObject(parent)
19{
20 mLogFilterInit(&m_filter);
21 mLogFilterSet(&m_filter, "gba.bios", mLOG_STUB | mLOG_FATAL);
22 mLogFilterSet(&m_filter, "core.status", mLOG_ALL & ~mLOG_DEBUG);
23 m_filter.defaultLevels = levels;
24 s_qtCat = mLogCategoryById("platform.qt");
25
26 if (this != &s_global) {
27 connect(&s_global, &LogController::logPosted, this, &LogController::postLog);
28 connect(this, static_cast<void (LogController::*)(int)>(&LogController::levelsSet), &s_global, static_cast<void (LogController::*)(int)>(&LogController::setLevels));
29 connect(this, static_cast<void (LogController::*)(int)>(&LogController::levelsEnabled), &s_global, static_cast<void (LogController::*)(int)>(&LogController::enableLevels));
30 connect(this, static_cast<void (LogController::*)(int)>(&LogController::levelsDisabled), &s_global, static_cast<void (LogController::*)(int)>(&LogController::disableLevels));
31 }
32}
33
34LogController::~LogController() {
35 mLogFilterDeinit(&m_filter);
36}
37
38int LogController::levels(int category) const {
39 return mLogFilterLevels(&m_filter, category);
40}
41
42LogController::Stream LogController::operator()(int category, int level) {
43 return Stream(this, category, level);
44}
45
46void LogController::load(const ConfigController* config) {
47 mLogFilterLoad(&m_filter, config->config());
48 if (!levels(mLogCategoryById("gba.bios"))) {
49 mLogFilterSet(&m_filter, "gba.bios", mLOG_STUB | mLOG_FATAL);
50 }
51 if (!levels(mLogCategoryById("core.status"))) {
52 mLogFilterSet(&m_filter, "core.status", mLOG_ALL & ~mLOG_DEBUG);
53 }
54 setLogFile(config->getOption("logFile"));
55 logToStdout(config->getOption("logToStdout").toInt());
56 logToFile(config->getOption("logToFile").toInt());
57}
58
59void LogController::save(ConfigController* config) const {
60 mLogFilterSave(&m_filter, config->config());
61}
62
63void LogController::postLog(int level, int category, const QString& string) {
64 if (!mLogFilterTest(&m_filter, category, static_cast<mLogLevel>(level))) {
65 return;
66 }
67 if (m_logToStdout || m_logToFile) {
68 QString line = tr("[%1] %2: %3").arg(LogController::toString(level)).arg(mLogCategoryName(category)).arg(string);
69
70 if (m_logToStdout) {
71 QTextStream out(stdout);
72 out << line << endl;
73 }
74 if (m_logToFile && m_logStream) {
75 *m_logStream << line << endl;
76 }
77 }
78 if (category == s_qtCat && level == mLOG_ERROR && this == &s_global) {
79 QMessageBox* dialog = new QMessageBox(QMessageBox::Critical, tr("An error occurred"), string, QMessageBox::Ok);
80 dialog->setAttribute(Qt::WA_DeleteOnClose);
81 dialog->show();
82 }
83 emit logPosted(level, category, string);
84}
85
86void LogController::setLevels(int levels) {
87 m_filter.defaultLevels = levels;
88 emit levelsSet(levels);
89}
90
91void LogController::enableLevels(int levels) {
92 m_filter.defaultLevels |= levels;
93 emit levelsEnabled(levels);
94}
95
96void LogController::disableLevels(int levels) {
97 m_filter.defaultLevels &= ~levels;
98 emit levelsDisabled(levels);
99}
100
101void LogController::setLevels(int levels, int category) {
102 auto id = mLogCategoryId(category);
103 mLogFilterSet(&m_filter, id, levels);
104 emit levelsSet(levels, category);
105}
106
107void LogController::enableLevels(int levels, int category) {
108 auto id = mLogCategoryId(category);
109 int newLevels = mLogFilterLevels(&m_filter, category) | levels;
110 mLogFilterSet(&m_filter, id, newLevels);
111 emit levelsEnabled(levels, category);
112}
113
114void LogController::disableLevels(int levels, int category) {
115 auto id = mLogCategoryId(category);
116 int newLevels = mLogFilterLevels(&m_filter, category) & ~levels;
117 mLogFilterSet(&m_filter, id, newLevels);
118 emit levelsDisabled(levels, category);
119}
120
121void LogController::clearLevels(int category) {
122 auto id = mLogCategoryId(category);
123 mLogFilterReset(&m_filter, id);
124}
125
126void LogController::logToFile(bool log) {
127 m_logToFile = log;
128}
129
130void LogController::logToStdout(bool log) {
131 m_logToStdout = log;
132}
133
134void LogController::setLogFile(const QString& file) {
135 m_logStream.reset();
136 if (file.isEmpty()) {
137 return;
138 }
139 m_logFile = std::make_unique<QFile>(file);
140 m_logFile->open(QIODevice::Append | QIODevice::Text);
141 m_logStream = std::make_unique<QTextStream>(m_logFile.get());
142}
143
144LogController* LogController::global() {
145 return &s_global;
146}
147
148QString LogController::toString(int level) {
149 switch (level) {
150 case mLOG_DEBUG:
151 return tr("DEBUG");
152 case mLOG_STUB:
153 return tr("STUB");
154 case mLOG_INFO:
155 return tr("INFO");
156 case mLOG_WARN:
157 return tr("WARN");
158 case mLOG_ERROR:
159 return tr("ERROR");
160 case mLOG_FATAL:
161 return tr("FATAL");
162 case mLOG_GAME_ERROR:
163 return tr("GAME ERROR");
164 }
165 return QString();
166}
167
168LogController::Stream::Stream(LogController* controller, int level, int category)
169 : m_level(level)
170 , m_category(category)
171 , m_log(controller)
172{
173}
174
175LogController::Stream::~Stream() {
176 m_log->postLog(m_level, m_category, m_queue.join(" "));
177}
178
179LogController::Stream& LogController::Stream::operator<<(const QString& string) {
180 m_queue.append(string);
181 return *this;
182}