1 /* Copyright (c) 2013-2014 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 "LogView.h"
7 
8 #include "LogController.h"
9 
10 #include <QTextBlock>
11 #include <QTextCursor>
12 
13 using namespace QGBA;
14 
LogView(LogController * log,QWidget * parent)15 LogView::LogView(LogController* log, QWidget* parent)
16 	: QWidget(parent)
17 {
18 	m_ui.setupUi(this);
19 	connect(m_ui.levelDebug, &QAbstractButton::toggled, [this](bool set) {
20 		setLevel(mLOG_DEBUG, set);
21 	});
22 	connect(m_ui.levelStub, &QAbstractButton::toggled, [this](bool set) {
23 		setLevel(mLOG_STUB, set);
24 	});
25 	connect(m_ui.levelInfo, &QAbstractButton::toggled, [this](bool set) {
26 		setLevel(mLOG_INFO, set);
27 	});
28 	connect(m_ui.levelWarn, &QAbstractButton::toggled, [this](bool set) {
29 		setLevel(mLOG_WARN, set);
30 	});
31 	connect(m_ui.levelError, &QAbstractButton::toggled, [this](bool set) {
32 		setLevel(mLOG_ERROR, set);
33 	});
34 	connect(m_ui.levelFatal, &QAbstractButton::toggled, [this](bool set) {
35 		setLevel(mLOG_FATAL, set);
36 	});
37 	connect(m_ui.levelGameError, &QAbstractButton::toggled, [this](bool set) {
38 		setLevel(mLOG_GAME_ERROR, set);
39 	});
40 	connect(m_ui.clear, &QAbstractButton::clicked, this, &LogView::clear);
41 	connect(m_ui.maxLines, static_cast<void (QSpinBox::*)(int)>(&QSpinBox::valueChanged),
42 	        this, &LogView::setMaxLines);
43 	m_ui.maxLines->setValue(DEFAULT_LINE_LIMIT);
44 
45 	connect(log, &LogController::logPosted, this, &LogView::postLog);
46 	connect(log, static_cast<void (LogController::*)(int)>(&LogController::levelsSet), this, &LogView::setLevels);
47 	connect(log, static_cast<void (LogController::*)(int)>(&LogController::levelsEnabled), [this](int level) {
48 		bool s = blockSignals(true);
49 		setLevel(level, true);
50 		blockSignals(s);
51 	});
52 	connect(log, static_cast<void (LogController::*)(int)>(&LogController::levelsDisabled), [this](int level) {
53 		bool s = blockSignals(true);
54 		setLevel(level, false);
55 		blockSignals(s);
56 	});
57 	connect(this, &LogView::levelsEnabled, log, static_cast<void (LogController::*)(int)>(&LogController::enableLevels));
58 	connect(this, &LogView::levelsDisabled, log, static_cast<void (LogController::*)(int)>(&LogController::disableLevels));
59 }
60 
postLog(int level,int category,const QString & log)61 void LogView::postLog(int level, int category, const QString& log) {
62 	QString line = QString("[%1] %2:\t%3").arg(LogController::toString(level)).arg(mLogCategoryName(category)).arg(log);
63 	// TODO: Log to file
64 	m_pendingLines.enqueue(line);
65 	++m_lines;
66 	if (m_lines > m_lineLimit) {
67 		clearLine();
68 	}
69 	update();
70 }
71 
clear()72 void LogView::clear() {
73 	m_ui.view->clear();
74 	m_lines = 0;
75 }
76 
setLevels(int levels)77 void LogView::setLevels(int levels) {
78 	m_ui.levelDebug->setCheckState(levels & mLOG_DEBUG ? Qt::Checked : Qt::Unchecked);
79 	m_ui.levelStub->setCheckState(levels & mLOG_STUB ? Qt::Checked : Qt::Unchecked);
80 	m_ui.levelInfo->setCheckState(levels & mLOG_INFO ? Qt::Checked : Qt::Unchecked);
81 	m_ui.levelWarn->setCheckState(levels & mLOG_WARN ? Qt::Checked : Qt::Unchecked);
82 	m_ui.levelError->setCheckState(levels & mLOG_ERROR ? Qt::Checked : Qt::Unchecked);
83 	m_ui.levelFatal->setCheckState(levels & mLOG_FATAL ? Qt::Checked : Qt::Unchecked);
84 	m_ui.levelGameError->setCheckState(levels & mLOG_GAME_ERROR ? Qt::Checked : Qt::Unchecked);
85 }
86 
setLevel(int level,bool set)87 void LogView::setLevel(int level, bool set) {
88 	if (level & mLOG_DEBUG) {
89 		m_ui.levelDebug->setCheckState(set ? Qt::Checked : Qt::Unchecked);
90 	}
91 	if (level & mLOG_STUB) {
92 		m_ui.levelStub->setCheckState(set ? Qt::Checked : Qt::Unchecked);
93 	}
94 	if (level & mLOG_INFO) {
95 		m_ui.levelInfo->setCheckState(set ? Qt::Checked : Qt::Unchecked);
96 	}
97 	if (level & mLOG_WARN) {
98 		m_ui.levelWarn->setCheckState(set ? Qt::Checked : Qt::Unchecked);
99 	}
100 	if (level & mLOG_ERROR) {
101 		m_ui.levelError->setCheckState(set ? Qt::Checked : Qt::Unchecked);
102 	}
103 	if (level & mLOG_FATAL) {
104 		m_ui.levelFatal->setCheckState(set ? Qt::Checked : Qt::Unchecked);
105 	}
106 	if (level & mLOG_GAME_ERROR) {
107 		m_ui.levelGameError->setCheckState(set ? Qt::Checked : Qt::Unchecked);
108 	}
109 
110 	if (set) {
111 		emit levelsEnabled(level);
112 	} else {
113 		emit levelsDisabled(level);
114 	}
115 }
116 
setMaxLines(int limit)117 void LogView::setMaxLines(int limit) {
118 	m_lineLimit = limit;
119 	while (m_lines > m_lineLimit) {
120 		clearLine();
121 	}
122 }
123 
paintEvent(QPaintEvent * event)124 void LogView::paintEvent(QPaintEvent* event) {
125 	while (!m_pendingLines.isEmpty()) {
126 		m_ui.view->appendPlainText(m_pendingLines.dequeue());
127 	}
128 	QWidget::paintEvent(event);
129 }
130 
clearLine()131 void LogView::clearLine() {
132 	if (m_ui.view->document()->isEmpty()) {
133 		m_pendingLines.dequeue();
134 	} else {
135 		QTextCursor cursor(m_ui.view->document());
136 		cursor.setPosition(0);
137 		cursor.select(QTextCursor::BlockUnderCursor);
138 		cursor.removeSelectedText();
139 		cursor.deleteChar();
140 	}
141 	--m_lines;
142 }
143