Loading files
This file is pinned to the selected release. Download the original to open it in your design tool.
76de63d66This file is pinned to the selected release. Download the original to open it in your design tool.
/*
* LibrePCB - Professional EDA for everyone!
* Copyright (C) 2013 LibrePCB Developers, see AUTHORS.md for contributors.
* https://librepcb.org/
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program 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 General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
/*******************************************************************************
* Includes
******************************************************************************/
#include "debug.h"
#include "fileio/filepath.h"
#include <QtCore>
/*******************************************************************************
* Namespace
******************************************************************************/
namespace librepcb {
/*******************************************************************************
* Constructors / Destructor
******************************************************************************/
Debug::Debug()
: mDebugLevelStderr(DebugLevel_t::All),
mDebugLevelLogFile(DebugLevel_t::Nothing),
mStderrStream(new QTextStream(stderr)),
mLogFilepath(),
mLogFile(0) {
// determine the filename of the log file which will be used if logging is
// enabled
QString datetime =
QDateTime::currentDateTime().toString("yyyy-MM-dd_hh-mm-ss");
QString dataDir =
QStandardPaths::writableLocation(QStandardPaths::DataLocation);
if (!dataDir.isEmpty())
mLogFilepath.setPath(dataDir % "/logs/" % datetime % ".log");
// install the message handler for Qt's debug functions (qDebug(), ...)
qInstallMessageHandler(messageHandler);
}
Debug::~Debug() {
delete mStderrStream;
mStderrStream = 0;
if (mLogFile) {
mLogFile->close();
delete mLogFile;
mLogFile = 0;
}
}
/*******************************************************************************
* General Methods
******************************************************************************/
void Debug::setDebugLevelStderr(DebugLevel_t level) {
mDebugLevelStderr = level;
}
void Debug::setDebugLevelLogFile(DebugLevel_t level) {
if (level == mDebugLevelLogFile) return;
if ((mDebugLevelLogFile == DebugLevel_t::Nothing) &&
(level != DebugLevel_t::Nothing)) {
// enable logging to file
QDir().mkpath(mLogFilepath.getParentDir().toStr());
mLogFile = new QFile(mLogFilepath.toStr());
bool success = mLogFile->open(QFile::WriteOnly);
if (success) {
mDebugLevelLogFile = level; // activate logging to file immediately!
qDebug() << "Enabled logging to file:" << mLogFilepath.toNative();
} else {
qWarning() << "Cannot enable logging to file" << mLogFilepath.toNative();
qWarning() << "Error message:" << mLogFile->errorString();
delete mLogFile;
mLogFile = 0;
}
} else if ((mDebugLevelLogFile != DebugLevel_t::Nothing) &&
(level == DebugLevel_t::Nothing) && (mLogFile)) {
// disable logging to file
mLogFile->close();
delete mLogFile;
mLogFile = 0;
}
mDebugLevelLogFile = level;
}
Debug::DebugLevel_t Debug::getDebugLevelStderr() const {
return mDebugLevelStderr;
}
Debug::DebugLevel_t Debug::getDebugLevelLogFile() const {
return mDebugLevelLogFile;
}
const FilePath& Debug::getLogFilepath() const {
return mLogFilepath;
}
void Debug::print(DebugLevel_t level, const QString& msg, const char* file,
int line) {
QMutexLocker locker(&mMutex);
if ((mDebugLevelStderr < level) &&
((mDebugLevelLogFile < level) || (!mLogFile)))
return; // if there is nothing to print, we will return immediately from
// this function
const char* levelStr =
"---------"; // the debug level string has always 9 characters
switch (level) {
case DebugLevel_t::DebugMsg:
levelStr = "DEBUG-MSG";
break;
case DebugLevel_t::Info:
levelStr = " INFO ";
break;
case DebugLevel_t::Warning:
levelStr = " WARNING ";
break;
case DebugLevel_t::Exception:
levelStr = "EXCEPTION";
break;
case DebugLevel_t::Critical:
levelStr = "CRITICAL ";
break;
case DebugLevel_t::Fatal:
levelStr = " FATAL ";
break;
default:
break;
}
QString logMsg = QString("[%1] %2 (%3:%4)")
.arg(levelStr, msg.toLocal8Bit().constData(), file)
.arg(line);
if (mDebugLevelStderr >= level) {
// write to stderr
*mStderrStream << logMsg << endl;
}
if ((mDebugLevelLogFile >= level) && (mLogFile)) {
// write to the log file
QTextStream logFileStream(mLogFile);
logFileStream << logMsg << endl;
}
}
/*******************************************************************************
* The message handler for qDebug(), qWarning(), qCritical() and qFatal()
******************************************************************************/
void Debug::messageHandler(QtMsgType type, const QMessageLogContext& context,
const QString& msg) {
switch (type) {
case QtDebugMsg:
instance()->print(DebugLevel_t::DebugMsg, msg, context.file,
context.line);
break;
case QtInfoMsg:
instance()->print(DebugLevel_t::Info, msg, context.file, context.line);
break;
case QtWarningMsg:
instance()->print(DebugLevel_t::Warning, msg, context.file, context.line);
break;
case QtCriticalMsg:
instance()->print(DebugLevel_t::Critical, msg, context.file,
context.line);
break;
case QtFatalMsg:
instance()->print(DebugLevel_t::Fatal, msg, context.file, context.line);
abort(); // fatal error --> quit the whole application!
default:
Q_ASSERT(false);
instance()->print(DebugLevel_t::Critical,
QString("unhandled case: %1").arg(type), __FILE__,
__LINE__);
break;
}
}
/*******************************************************************************
* End of File
******************************************************************************/
} // namespace librepcb