Files
create/src/Gui/ReportView.cpp
2025-11-11 13:49:01 +01:00

955 lines
29 KiB
C++

/***************************************************************************
* Copyright (c) 2004 Werner Mayer <wmayer[at]users.sourceforge.net> *
* *
* This file is part of the FreeCAD CAx development system. *
* *
* This library is free software; you can redistribute it and/or *
* modify it under the terms of the GNU Library General Public *
* License as published by the Free Software Foundation; either *
* version 2 of the License, or (at your option) any later version. *
* *
* This library is distributed in the hope that it will be useful, *
* but WITHOUT ANY WARRANTY; without even the implied warranty of *
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
* GNU Library General Public License for more details. *
* *
* You should have received a copy of the GNU Library General Public *
* License along with this library; see the file COPYING.LIB. If not, *
* write to the Free Software Foundation, Inc., 59 Temple Place, *
* Suite 330, Boston, MA 02111-1307, USA *
* *
***************************************************************************/
#include <QApplication>
#include <QContextMenuEvent>
#include <QGridLayout>
#include <QMenu>
#include <QTextCursor>
#include <QTextStream>
#include <QTime>
#include <Base/Interpreter.h>
#include <Base/Color.h>
#include "ReportView.h"
#include "Application.h"
#include "BitmapFactory.h"
#include "DockWindowManager.h"
#include "FileDialog.h"
#include "PythonConsole.h"
#include "PythonConsolePy.h"
#include "Tools.h"
using namespace Gui;
using namespace Gui::DockWnd;
/* TRANSLATOR Gui::DockWnd::ReportView */
/**
* Constructs a ReportView which is a child of 'parent', with the
* name 'name' and widget flags set to 'f'
*/
ReportView::ReportView(QWidget* parent)
: QWidget(parent)
{
setObjectName(QLatin1String("ReportOutput"));
resize(529, 162);
auto tabLayout = new QGridLayout(this);
tabLayout->setSpacing(0);
tabLayout->setContentsMargins(0, 0, 0, 0);
tabWidget = new QTabWidget(this);
tabWidget->setObjectName(QStringLiteral("tabWidget"));
tabWidget->setTabPosition(QTabWidget::South);
tabWidget->setTabShape(QTabWidget::Rounded);
tabLayout->addWidget(tabWidget, 0, 0);
// create the output window for 'Report view'
tabOutput = new ReportOutput();
tabOutput->setWindowTitle(tr("Output"));
tabOutput->setWindowIcon(BitmapFactory().pixmap("MacroEditor"));
int output = tabWidget->addTab(tabOutput, tabOutput->windowTitle());
tabWidget->setTabIcon(output, tabOutput->windowIcon());
// create the python console
tabPython = new PythonConsole();
tabPython->setWordWrapMode(QTextOption::NoWrap);
tabPython->setWindowTitle(tr("Python Console"));
tabPython->setWindowIcon(BitmapFactory().iconFromTheme("applications-python"));
int python = tabWidget->addTab(tabPython, tabPython->windowTitle());
tabWidget->setTabIcon(python, tabPython->windowIcon());
tabWidget->setCurrentIndex(0);
// raise the tab page set in the preferences
ParameterGrp::handle hGrp = WindowParameter::getDefaultParameter()->GetGroup("General");
int index = hGrp->GetInt("AutoloadTab", 0);
tabWidget->setCurrentIndex(index);
}
/**
* Destroys the object and frees any allocated resources
*/
ReportView::~ReportView() = default;
void ReportView::changeEvent(QEvent* e)
{
QWidget::changeEvent(e);
if (e->type() == QEvent::LanguageChange) {
tabOutput->setWindowTitle(tr("Output"));
tabPython->setWindowTitle(tr("Python Console"));
for (int i = 0; i < tabWidget->count(); i++) {
tabWidget->setTabText(i, tabWidget->widget(i)->windowTitle());
}
}
}
// ----------------------------------------------------------
namespace Gui
{
struct TextBlockData: public QTextBlockUserData
{
struct State
{
int length;
ReportHighlighter::Paragraph type;
};
QVector<State> block;
};
} // namespace Gui
ReportHighlighter::ReportHighlighter(QTextEdit* edit)
: QSyntaxHighlighter(edit)
, type(Message)
{
QPalette pal = edit->palette();
txtCol = pal.windowText().color();
logCol = Qt::blue;
warnCol = QColor(255, 170, 0);
errCol = Qt::red;
}
ReportHighlighter::~ReportHighlighter() = default;
void ReportHighlighter::highlightBlock(const QString& text)
{
if (text.isEmpty()) {
return;
}
auto ud = static_cast<TextBlockData*>(this->currentBlockUserData());
if (!ud) {
ud = new TextBlockData;
this->setCurrentBlockUserData(ud);
}
TextBlockData::State b;
b.length = text.length();
b.type = this->type;
ud->block.append(b);
QVector<TextBlockData::State> block = ud->block;
int start = 0;
for (const auto& it : block) {
switch (it.type) {
case Message:
setFormat(start, it.length - start, txtCol);
break;
case Warning:
setFormat(start, it.length - start, warnCol);
break;
case Error:
setFormat(start, it.length - start, errCol);
break;
case LogText:
setFormat(start, it.length - start, logCol);
break;
case Critical:
setFormat(start, it.length - start, criticalCol);
break;
default:
break;
}
start = it.length;
}
}
void ReportHighlighter::setParagraphType(ReportHighlighter::Paragraph t)
{
type = t;
}
void ReportHighlighter::setTextColor(const QColor& col)
{
txtCol = col;
}
void ReportHighlighter::setLogColor(const QColor& col)
{
logCol = col;
}
void ReportHighlighter::setWarningColor(const QColor& col)
{
warnCol = col;
}
void ReportHighlighter::setErrorColor(const QColor& col)
{
errCol = col;
}
void ReportHighlighter::setCriticalColor(const QColor& col)
{
criticalCol = col;
}
// ----------------------------------------------------------------------------
namespace Gui
{
class ReportOutputParameter
{
public:
static bool showOnLogMessage()
{
return getGroup()->GetBool("checkShowReportViewOnLogMessage", false);
}
static void toggleShowOnLogMessage()
{
bool show = showOnLogMessage();
getGroup()->SetBool("checkShowReportViewOnLogMessage", !show);
}
static bool showOnMessage()
{
return getGroup()->GetBool("checkShowReportViewOnNormalMessage", false);
}
static void toggleShowOnMessage()
{
bool show = showOnMessage();
getGroup()->SetBool("checkShowReportViewOnNormalMessage", !show);
}
static bool showOnWarning()
{
return getGroup()->GetBool("checkShowReportViewOnWarning", false);
}
static void toggleShowOnWarning()
{
bool show = showOnWarning();
getGroup()->SetBool("checkShowReportViewOnWarning", !show);
}
static bool showOnError()
{
return getGroup()->GetBool("checkShowReportViewOnError", false);
}
static void toggleShowOnError()
{
bool show = showOnError();
getGroup()->SetBool("checkShowReportViewOnError", !show);
}
static bool showOnCritical()
{
return getGroup()->GetBool("checkShowReportViewOnCritical", false);
}
static void toggleShowOnCritical()
{
bool show = showOnMessage();
getGroup()->SetBool("checkShowReportViewOnCritical", !show);
}
private:
static ParameterGrp::handle getGroup()
{
return App::GetApplication()
.GetUserParameter()
.GetGroup("BaseApp")
->GetGroup("Preferences")
->GetGroup("OutputWindow");
}
};
} // namespace Gui
// ----------------------------------------------------------
/**
* The CustomReportEvent class is used to send report events in the methods Log(),
* Error(), Warning() and Message() of the ReportOutput class to itself instead of
* printing the messages directly in its text view.
*
* This makes the methods Log(), Error(), Warning() and Message() thread-safe.
* @author Werner Mayer
*/
class CustomReportEvent: public QEvent
{
public:
CustomReportEvent(ReportHighlighter::Paragraph p, const QString& s)
: QEvent(QEvent::Type(QEvent::User))
{
par = p;
msg = s;
}
~CustomReportEvent() override = default;
const QString& message() const
{
return msg;
}
ReportHighlighter::Paragraph messageType() const
{
return par;
}
private:
ReportHighlighter::Paragraph par;
QString msg;
};
// ----------------------------------------------------------
/**
* The ReportOutputObserver class is used to check if messages sent to the
* report view are warnings or errors, and if so and if the user has not
* disabled this in preferences, the report view is toggled on so the
* user always gets the warnings/errors
*/
ReportOutputObserver::ReportOutputObserver(ReportOutput* report)
: QObject(report)
{
this->reportView = report;
}
void ReportOutputObserver::showReportView()
{
// get the QDockWidget parent of the report view
DockWindowManager::instance()->activate(reportView);
}
bool ReportOutputObserver::eventFilter(QObject* obj, QEvent* event)
{
if (event->type() == QEvent::User && obj == reportView.data()) {
auto cr = dynamic_cast<CustomReportEvent*>(event);
if (cr) {
ReportHighlighter::Paragraph msgType = cr->messageType();
if (msgType == ReportHighlighter::Warning) {
if (ReportOutputParameter::showOnWarning()) {
showReportView();
}
}
else if (msgType == ReportHighlighter::Error) {
if (ReportOutputParameter::showOnError()) {
showReportView();
}
}
else if (msgType == ReportHighlighter::Message) {
if (ReportOutputParameter::showOnMessage()) {
showReportView();
}
}
else if (msgType == ReportHighlighter::LogText) {
if (ReportOutputParameter::showOnLogMessage()) {
showReportView();
}
}
else if (msgType == ReportHighlighter::Critical) {
if (ReportOutputParameter::showOnCritical()) {
showReportView();
}
}
}
return false; // true would prevent the messages reaching the report view
}
// standard event processing
return QObject::eventFilter(obj, event);
}
// ----------------------------------------------------------
class ReportOutput::Data
{
public:
Data()
{
if (!default_stdout) {
Base::PyGILStateLocker lock;
default_stdout = PySys_GetObject("stdout");
replace_stdout = new OutputStdout();
redirected_stdout = false;
}
if (!default_stderr) {
Base::PyGILStateLocker lock;
default_stderr = PySys_GetObject("stderr");
replace_stderr = new OutputStderr();
redirected_stderr = false;
}
}
~Data()
{
if (replace_stdout) {
Base::PyGILStateLocker lock;
Py_DECREF(replace_stdout);
replace_stdout = nullptr;
}
if (replace_stderr) {
Base::PyGILStateLocker lock;
Py_DECREF(replace_stderr);
replace_stderr = nullptr;
}
}
// make them static because redirection should done only once
static bool redirected_stdout;
static PyObject* default_stdout;
static PyObject* replace_stdout;
static bool redirected_stderr;
static PyObject* default_stderr;
static PyObject* replace_stderr;
#ifdef FC_DEBUG
long logMessageSize = 0;
#else
long logMessageSize = 2048;
#endif
};
bool ReportOutput::Data::redirected_stdout = false;
PyObject* ReportOutput::Data::default_stdout = nullptr;
PyObject* ReportOutput::Data::replace_stdout = nullptr;
bool ReportOutput::Data::redirected_stderr = false;
PyObject* ReportOutput::Data::default_stderr = nullptr;
PyObject* ReportOutput::Data::replace_stderr = nullptr;
/* TRANSLATOR Gui::DockWnd::ReportOutput */
/**
* Constructs a ReportOutput which is a child of 'parent', with the
* name 'name' and widget flags set to 'f'
*/
ReportOutput::ReportOutput(QWidget* parent)
: QTextEdit(parent)
, WindowParameter("OutputWindow")
, d(new Data)
, gotoEnd(false)
, blockStart(true)
{
bLog = false;
reportHl = new ReportHighlighter(this);
restoreFont();
setReadOnly(true);
clear();
setHorizontalScrollBarPolicy(Qt::ScrollBarAlwaysOff);
Base::Console().attachObserver(this);
getWindowParameter()->Attach(this);
getWindowParameter()->NotifyAll();
// do this explicitly because the keys below might not yet be part of a group
getWindowParameter()->Notify("RedirectPythonOutput");
getWindowParameter()->Notify("RedirectPythonErrors");
_prefs = WindowParameter::getDefaultParameter()->GetGroup("Editor");
_prefs->Attach(this);
_prefs->Notify("FontSize");
messageSize = _prefs->GetInt("LogMessageSize", d->logMessageSize);
// scroll to bottom at startup to make sure that last appended text is visible
ensureCursorVisible();
}
/**
* Destroys the object and frees any allocated resources
*/
ReportOutput::~ReportOutput()
{
getWindowParameter()->Detach(this);
_prefs->Detach(this);
Base::Console().detachObserver(this);
delete reportHl;
delete d;
}
void ReportOutput::restoreFont()
{
QFont font;
auto hPrefGrp = App::GetApplication().GetParameterGroupByPath(
"User parameter:BaseApp/Preferences/Editor"
);
int fontSize = hPrefGrp->GetInt("FontSize", 10);
auto serifFont = hPrefGrp->GetASCII("Font");
if (serifFont.empty()) {
font = QFontDatabase::systemFont(QFontDatabase::FixedFont);
font.setPointSize(fontSize);
}
else {
font = QFont(QString::fromStdString(serifFont), fontSize);
}
setFont(font);
}
void ReportOutput::sendLog(
const std::string& notifiername,
const std::string& msg,
Base::LogStyle level,
Base::IntendedRecipient recipient,
Base::ContentType content
)
{
// Do not log translated messages, or messages intended only to the user to the Report View
if (recipient == Base::IntendedRecipient::User || content == Base::ContentType::Translated) {
return;
}
ReportHighlighter::Paragraph style = ReportHighlighter::LogText;
switch (level) {
case Base::LogStyle::Warning:
style = ReportHighlighter::Warning;
break;
case Base::LogStyle::Message:
style = ReportHighlighter::Message;
break;
case Base::LogStyle::Error:
style = ReportHighlighter::Error;
break;
case Base::LogStyle::Log:
style = ReportHighlighter::LogText;
break;
case Base::LogStyle::Critical:
style = ReportHighlighter::Critical;
break;
default:
break;
}
QString qMsg;
if (!notifiername.empty()) {
qMsg = QStringLiteral("%1: %2").arg(
QString::fromUtf8(notifiername.c_str()),
QString::fromUtf8(msg.c_str())
);
}
else {
qMsg = QString::fromUtf8(msg.c_str());
}
// This truncates log messages that are too long
if (style == ReportHighlighter::LogText) {
if (messageSize > 0 && qMsg.size() > messageSize) {
qMsg.truncate(messageSize);
qMsg += QStringLiteral("...\n");
}
}
// Send the event to itself to allow thread-safety. Qt will delete it when done.
auto ev = new CustomReportEvent(style, qMsg);
QApplication::postEvent(this, ev);
}
void ReportOutput::customEvent(QEvent* ev)
{
// Appends the text stored in the event to the text view
if (ev->type() == QEvent::User) {
auto ce = static_cast<CustomReportEvent*>(ev);
reportHl->setParagraphType(ce->messageType());
bool showTimecode = getWindowParameter()->GetBool("checkShowReportTimecode", true);
QString text = ce->message();
// The time code can only be set when the cursor is at the block start
if (showTimecode && blockStart) {
QTime time = QTime::currentTime();
text.prepend(time.toString(QLatin1String("hh:mm:ss ")));
}
QTextCursor cursor(this->document());
cursor.beginEditBlock();
cursor.movePosition(QTextCursor::End);
cursor.insertText(text);
cursor.endEditBlock();
blockStart = cursor.atBlockStart();
if (gotoEnd) {
setTextCursor(cursor);
}
ensureCursorVisible();
}
}
bool ReportOutput::event(QEvent* event)
{
if (event && event->type() == QEvent::ShortcutOverride) {
auto kevent = static_cast<QKeyEvent*>(event);
if (kevent == QKeySequence::Copy || kevent == QKeySequence::SelectAll) {
kevent->accept();
}
}
return QTextEdit::event(event);
}
void ReportOutput::changeEvent(QEvent* ev)
{
if (ev->type() == QEvent::StyleChange) {
QPalette pal = qApp->palette();
QColor color = pal.windowText().color();
unsigned int text = Base::Color::asPackedRGB<QColor>(color);
auto value = static_cast<unsigned long>(text);
// if this parameter is not already set use the style's window text color
value = getWindowParameter()->GetUnsigned("colorText", value);
getWindowParameter()->SetUnsigned("colorText", value);
}
QTextEdit::changeEvent(ev);
}
void ReportOutput::contextMenuEvent(QContextMenuEvent* e)
{
bool bShowOnLog = ReportOutputParameter::showOnLogMessage();
bool bShowOnNormal = ReportOutputParameter::showOnMessage();
bool bShowOnWarn = ReportOutputParameter::showOnWarning();
bool bShowOnError = ReportOutputParameter::showOnError();
bool bShowOnCritical = ReportOutputParameter::showOnCritical();
auto menu = new QMenu(this);
auto optionMenu = new QMenu(menu);
optionMenu->setTitle(tr("Options"));
menu->addMenu(optionMenu);
menu->addSeparator();
auto displayMenu = new QMenu(optionMenu);
displayMenu->setTitle(tr("Display Message Types"));
optionMenu->addMenu(displayMenu);
QAction* logMsg
= displayMenu->addAction(tr("Normal Messages"), this, &ReportOutput::onToggleNormalMessage);
logMsg->setCheckable(true);
logMsg->setChecked(bMsg);
QAction* logAct
= displayMenu->addAction(tr("Log Messages"), this, &ReportOutput::onToggleLogMessage);
logAct->setCheckable(true);
logAct->setChecked(bLog);
QAction* wrnAct = displayMenu->addAction(tr("Warnings"), this, &ReportOutput::onToggleWarning);
wrnAct->setCheckable(true);
wrnAct->setChecked(bWrn);
QAction* errAct = displayMenu->addAction(tr("Errors"), this, &ReportOutput::onToggleError);
errAct->setCheckable(true);
errAct->setChecked(bErr);
QAction* logCritical
= displayMenu->addAction(tr("Critical Messages"), this, &ReportOutput::onToggleCritical);
logCritical->setCheckable(true);
logCritical->setChecked(bCritical);
auto showOnMenu = new QMenu(optionMenu);
showOnMenu->setTitle(tr("Show Report View On"));
optionMenu->addMenu(showOnMenu);
QAction* showNormAct = showOnMenu->addAction(
tr("Normal Messages"),
this,
&ReportOutput::onToggleShowReportViewOnNormalMessage
);
showNormAct->setCheckable(true);
showNormAct->setChecked(bShowOnNormal);
QAction* showLogAct = showOnMenu->addAction(
tr("Log Messages"),
this,
&ReportOutput::onToggleShowReportViewOnLogMessage
);
showLogAct->setCheckable(true);
showLogAct->setChecked(bShowOnLog);
QAction* showWrnAct
= showOnMenu->addAction(tr("Warnings"), this, &ReportOutput::onToggleShowReportViewOnWarning);
showWrnAct->setCheckable(true);
showWrnAct->setChecked(bShowOnWarn);
QAction* showErrAct
= showOnMenu->addAction(tr("Errors"), this, &ReportOutput::onToggleShowReportViewOnError);
showErrAct->setCheckable(true);
showErrAct->setChecked(bShowOnError);
QAction* showCriticalAct = showOnMenu->addAction(
tr("Critical Messages"),
this,
SLOT(onToggleShowReportViewOnCritical())
);
showCriticalAct->setCheckable(true);
showCriticalAct->setChecked(bShowOnCritical);
optionMenu->addSeparator();
QAction* stdoutAct = optionMenu->addAction(
tr("Redirect Python Output"),
this,
&ReportOutput::onToggleRedirectPythonStdout
);
stdoutAct->setCheckable(true);
stdoutAct->setChecked(d->redirected_stdout);
QAction* stderrAct = optionMenu->addAction(
tr("Redirect Python Errors"),
this,
&ReportOutput::onToggleRedirectPythonStderr
);
stderrAct->setCheckable(true);
stderrAct->setChecked(d->redirected_stderr);
optionMenu->addSeparator();
QAction* botAct = optionMenu->addAction(tr("Go to End"), this, &ReportOutput::onToggleGoToEnd);
botAct->setCheckable(true);
botAct->setChecked(gotoEnd);
// Use Qt's internal translation of the Copy & Select All commands
const char* context = "QWidgetTextControl";
QString copyStr = QCoreApplication::translate(context, "&Copy");
QAction* copy = menu->addAction(copyStr, this, &ReportOutput::copy);
copy->setShortcut(QKeySequence(QKeySequence::Copy));
copy->setEnabled(textCursor().hasSelection());
QIcon icon = QIcon::fromTheme(QStringLiteral("edit-copy"));
if (!icon.isNull()) {
copy->setIcon(icon);
}
menu->addSeparator();
QString selectStr = QCoreApplication::translate(context, "Select All");
QAction* select = menu->addAction(selectStr, this, &ReportOutput::selectAll);
select->setShortcut(QKeySequence(QKeySequence::SelectAll));
menu->addAction(tr("Clear"), this, &ReportOutput::clear);
menu->addSeparator();
menu->addAction(tr("Save As…"), this, &ReportOutput::onSaveAs);
menu->exec(e->globalPos());
delete menu;
}
void ReportOutput::onSaveAs()
{
QString fn = QFileDialog::getSaveFileName(
this,
tr("Save Report Output"),
QString(),
QStringLiteral("%1 (*.txt *.log)").arg(tr("Plain text files"))
);
if (!fn.isEmpty()) {
QFileInfo fi(fn);
if (fi.completeSuffix().isEmpty()) {
fn += QLatin1String(".log");
}
QFile f(fn);
if (f.open(QIODevice::WriteOnly)) {
QTextStream t(&f);
t << toPlainText();
f.close();
}
}
}
bool ReportOutput::isError() const
{
return bErr;
}
bool ReportOutput::isWarning() const
{
return bWrn;
}
bool ReportOutput::isLogMessage() const
{
return bLog;
}
bool ReportOutput::isNormalMessage() const
{
return bMsg;
}
bool ReportOutput::isCritical() const
{
return bCritical;
}
void ReportOutput::onToggleError()
{
bErr = bErr ? false : true;
getWindowParameter()->SetBool("checkError", bErr);
}
void ReportOutput::onToggleWarning()
{
bWrn = bWrn ? false : true;
getWindowParameter()->SetBool("checkWarning", bWrn);
}
void ReportOutput::onToggleLogMessage()
{
bLog = bLog ? false : true;
getWindowParameter()->SetBool("checkLogging", bLog);
}
void ReportOutput::onToggleNormalMessage()
{
bMsg = bMsg ? false : true;
getWindowParameter()->SetBool("checkMessage", bMsg);
}
void ReportOutput::onToggleCritical()
{
bCritical = bCritical ? false : true;
getWindowParameter()->SetBool("checkCritical", bCritical);
}
void ReportOutput::onToggleShowReportViewOnWarning()
{
ReportOutputParameter::toggleShowOnWarning();
}
void ReportOutput::onToggleShowReportViewOnError()
{
ReportOutputParameter::toggleShowOnError();
}
void ReportOutput::onToggleShowReportViewOnNormalMessage()
{
ReportOutputParameter::toggleShowOnMessage();
}
void ReportOutput::onToggleShowReportViewOnCritical()
{
ReportOutputParameter::toggleShowOnCritical();
}
void ReportOutput::onToggleShowReportViewOnLogMessage()
{
ReportOutputParameter::toggleShowOnLogMessage();
}
void ReportOutput::onToggleRedirectPythonStdout()
{
if (d->redirected_stdout) {
d->redirected_stdout = false;
Base::PyGILStateLocker lock;
PySys_SetObject("stdout", d->default_stdout);
}
else {
d->redirected_stdout = true;
Base::PyGILStateLocker lock;
PySys_SetObject("stdout", d->replace_stdout);
}
getWindowParameter()->SetBool("RedirectPythonOutput", d->redirected_stdout);
}
void ReportOutput::onToggleRedirectPythonStderr()
{
if (d->redirected_stderr) {
d->redirected_stderr = false;
Base::PyGILStateLocker lock;
PySys_SetObject("stderr", d->default_stderr);
}
else {
d->redirected_stderr = true;
Base::PyGILStateLocker lock;
PySys_SetObject("stderr", d->replace_stderr);
}
getWindowParameter()->SetBool("RedirectPythonErrors", d->redirected_stderr);
}
void ReportOutput::onToggleGoToEnd()
{
gotoEnd = gotoEnd ? false : true;
getWindowParameter()->SetBool("checkGoToEnd", gotoEnd);
}
void ReportOutput::OnChange(Base::Subject<const char*>& rCaller, const char* sReason)
{
ParameterGrp& rclGrp = ((ParameterGrp&)rCaller);
if (strcmp(sReason, "checkLogging") == 0) {
bLog = rclGrp.GetBool(sReason, bLog);
}
else if (strcmp(sReason, "checkWarning") == 0) {
bWrn = rclGrp.GetBool(sReason, bWrn);
}
else if (strcmp(sReason, "checkError") == 0) {
bErr = rclGrp.GetBool(sReason, bErr);
}
else if (strcmp(sReason, "checkMessage") == 0) {
bMsg = rclGrp.GetBool(sReason, bMsg);
}
else if (strcmp(sReason, "checkCritical") == 0) {
bMsg = rclGrp.GetBool(sReason, bMsg);
}
else if (strcmp(sReason, "colorText") == 0) {
unsigned long col = rclGrp.GetUnsigned(sReason);
reportHl->setTextColor(Base::Color::fromPackedRGB<QColor>(col));
}
else if (strcmp(sReason, "colorCriticalText") == 0) {
unsigned long col = rclGrp.GetUnsigned(sReason);
reportHl->setTextColor(QColor((col >> 24) & 0xff, (col >> 16) & 0xff, (col >> 8) & 0xff));
}
else if (strcmp(sReason, "colorLogging") == 0) {
unsigned long col = rclGrp.GetUnsigned(sReason);
reportHl->setLogColor(Base::Color::fromPackedRGB<QColor>(col));
}
else if (strcmp(sReason, "colorWarning") == 0) {
unsigned long col = rclGrp.GetUnsigned(sReason);
reportHl->setWarningColor(Base::Color::fromPackedRGB<QColor>(col));
}
else if (strcmp(sReason, "colorError") == 0) {
unsigned long col = rclGrp.GetUnsigned(sReason);
reportHl->setErrorColor(Base::Color::fromPackedRGB<QColor>(col));
}
else if (strcmp(sReason, "checkGoToEnd") == 0) {
gotoEnd = rclGrp.GetBool(sReason, gotoEnd);
}
else if (strcmp(sReason, "FontSize") == 0 || strcmp(sReason, "Font") == 0) {
int fontSize = rclGrp.GetInt("FontSize", 10);
QFont font;
auto fontName = rclGrp.GetASCII("Font");
if (fontName.empty()) {
font = QFontDatabase::systemFont(QFontDatabase::FixedFont);
font.setPointSize(fontSize);
}
else {
font = QFont(QString::fromStdString(fontName), fontSize);
}
setFont(font);
QFontMetrics metric(font);
int width = QtTools::horizontalAdvance(metric, QLatin1String("0000"));
setTabStopDistance(width);
}
else if (strcmp(sReason, "RedirectPythonOutput") == 0) {
bool checked = rclGrp.GetBool(sReason, true);
if (checked != d->redirected_stdout) {
onToggleRedirectPythonStdout();
}
}
else if (strcmp(sReason, "RedirectPythonErrors") == 0) {
bool checked = rclGrp.GetBool(sReason, true);
if (checked != d->redirected_stderr) {
onToggleRedirectPythonStderr();
}
}
else if (strcmp(sReason, "LogMessageSize") == 0) {
messageSize = rclGrp.GetInt(sReason, d->logMessageSize);
}
}
#include "moc_ReportView.cpp"