# # # add_file "guitone/src/util/DebugLog.cpp" # content [061f8dd3f473df0360dd67bad76e70f8a891462d] # # add_file "guitone/src/util/DebugLog.h" # content [15ae25ff50330f9a76933a81f344875cd72554d8] # # patch "guitone/guitone.pro" # from [3448c02855a8ee7961b5514502c00941e9ac635f] # to [89ffc63cab6945f7c72dd91d072bfa7425ae9d33] # # patch "guitone/res/forms/preferences.ui" # from [9e93e317aee87b3c5cb3d798e7a1ded37a8b0ff9] # to [b2a58b08e11a292a2f334514e2c24dfedcc7cd21] # # patch "guitone/src/main.cpp" # from [65dc8121bc3e89b4fd1b370a51554f9c81ec9306] # to [41f57d259c796164c7939ec5c3b779593016afbd] # # patch "guitone/src/util/Settings.cpp" # from [53eb2f27d05b118d6f65287cfd578b2e08f31ef9] # to [23ac3899da46d0555b39a375b966dc69322cdb20] # # patch "guitone/src/util/Settings.h" # from [3be69fcb30460f05f876b8d990cc5f2964a82231] # to [da27ac6c5551cfd88073109df8624bf22e548556] # # patch "guitone/src/view/dialogs/Preferences.cpp" # from [4aa186cb30ad6ca40b84ce3d0af9ffb3d7ec5dc2] # to [aee8e3701cad4b88fcc8f8d32f0fe836d7083b00] # ============================================================ --- guitone/src/util/DebugLog.cpp 061f8dd3f473df0360dd67bad76e70f8a891462d +++ guitone/src/util/DebugLog.cpp 061f8dd3f473df0360dd67bad76e70f8a891462d @@ -0,0 +1,198 @@ +/************************************************************************** +* Copyright (C) 2007 by Thomas Keller * +* address@hidden * +* * +* 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 2 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, write to the * +* Free Software Foundation, Inc., * +* 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * +***************************************************************************/ + +#include "DebugLog.h" +#include "Settings.h" +#include +#include +#include + +#include +#include + +DebugLog* DebugLog::instance = 0; + +DebugLog* DebugLog::singleton() +{ + if (!instance) + { + instance = new DebugLog(); + } + return instance; +} + +DebugLog::DebugLog() +{ + consoleLogging = Settings::getConsoleLogEnabled(); + fileLogging = Settings::getFileLogEnabled(); + int level = Settings::getLogLevel(); + if (level >= Fatal && level <= Debug) logLevel = static_cast(level); + + if (fileLogging && !openLogfile()) + { + critical(QString("Cannot open logfile '%1' for writing, " + "disable file logging.").arg(logFilePath())); + fileLogging = false; + } +} + +DebugLog::~DebugLog() +{ + if (logFile.isOpen()) closeLogfile(); +} + +bool DebugLog::openLogfile() +{ + logFile.setFileName(logFilePath()); + + QFlags flags = + QIODevice::WriteOnly | QIODevice::Append | + QIODevice::Text | QIODevice::Unbuffered; + + if (!logFile.open(flags)) return false; + + return true; +} + +void DebugLog::log(Type t, QString msg) +{ + if (!fileLogging && !consoleLogging) return; + + if (logLevel == Fatal && t > Fatal) return; + if (logLevel == Critical && t > Critical) return; + if (logLevel == Warn && t > Warn) return; + if (logLevel == Debug && t > Debug) return; + + QMap errors; + errors[0] = "fatal"; + errors[1] = "critical"; + errors[2] = "warning"; + errors[3] = "debug"; + + // do not use Q_ASSERT here since this calls qFatal and results in + // an endless loop + assert(t <= errors.size()); + + QDateTime current = QDateTime::currentDateTime(); + + QString logStr; + logStr.append( + QString("%1: %2: %3\n") + .arg(current.toString("yyyy-MM-dd hh:mm:ss")) + .arg(errors[t-1]) + .arg(msg) + ); + + QByteArray utf8_msg = logStr.toUtf8(); + + // print the message on console + if (consoleLogging) + { + fprintf(stderr, utf8_msg.constData()); + } + + // print the message to the logfile + if (fileLogging && logFile.isOpen()) + { + logFile.write(utf8_msg); + } +} + +void DebugLog::closeLogfile() +{ + if (logFile.isOpen()) logFile.close(); +} + +void DebugLog::debug(QString msg) +{ + singleton()->log(Debug, msg); +} + +void DebugLog::warn(QString msg) +{ + singleton()->log(Warn, msg); +} + +void DebugLog::critical(QString msg) +{ + singleton()->log(Critical, msg); +} + +void DebugLog::fatal(QString msg) +{ + singleton()->log(Fatal, msg); +} + +void DebugLog::setConsoleLogEnabled(bool enabled) +{ + DebugLog * log = singleton(); + log->consoleLogging = enabled; + Settings::setConsoleLogEnabled(enabled); +} + +bool DebugLog::getConsoleLogEnabled() +{ + return singleton()->consoleLogging; +} + +void DebugLog::setFileLogEnabled(bool enabled) +{ + DebugLog * log = singleton(); + if (log->fileLogging && !enabled) + { + log->closeLogfile(); + } + else if (!log->fileLogging && enabled) + { + if (!log->openLogfile()) + { + log->critical(QString("Cannot open logfile '%1' for writing, " + "disable file logging.").arg(logFilePath())); + enabled = false; + } + } + log->fileLogging = enabled; + Settings::setFileLogEnabled(enabled); +} + +bool DebugLog::getFileLogEnabled() +{ + return singleton()->fileLogging; +} + +void DebugLog::setLogLevel(int level) +{ + if (level < Fatal || level > Debug) return; + singleton()->logLevel = static_cast(level); + Settings::setLogLevel(level); +} + +int DebugLog::getLogLevel() +{ + return static_cast(singleton()->logLevel); +} + +QString DebugLog::logFilePath() +{ + QString path(QDir::homePath()); + path.append(QDir::separator()).append("guitone.log"); + return path; +} + ============================================================ --- guitone/src/util/DebugLog.h 15ae25ff50330f9a76933a81f344875cd72554d8 +++ guitone/src/util/DebugLog.h 15ae25ff50330f9a76933a81f344875cd72554d8 @@ -0,0 +1,75 @@ +/*************************************************************************** + * Copyright (C) 2007 by Thomas Keller * + * address@hidden * + * * + * 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 2 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, write to the * + * Free Software Foundation, Inc., * + * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * + ***************************************************************************/ + +#ifndef DEBUG_LOG_H +#define DEBUG_LOG_H + +#include +#include + +class DebugLog : public QObject +{ +public: + // higher levels include lower ones, i.e. + // 'warn' also prints out 'critical' and 'fatal'; + // 'debug' prints out everything we have + enum Level {Fatal = 1, Critical, Warn, Debug }; + // as we have different Levels each level's name is also + // the name for a specific log type + typedef Level Type; + + static void setFileLogEnabled(bool); + static void setConsoleLogEnabled(bool); + static void setLogLevel(int); + + static bool getFileLogEnabled(); + static bool getConsoleLogEnabled(); + static int getLogLevel(); + + static QString logFilePath(); + + static void debug(QString); + inline static void debug(const char * msg) { return debug(QString::fromUtf8(msg)); } + static void warn(QString); + inline static void warn(const char * msg) { return warn(QString::fromUtf8(msg)); } + static void critical(QString); + inline static void critical(const char * msg) { return critical(QString::fromUtf8(msg)); } + static void fatal(QString); + inline static void fatal(const char * msg) { return fatal(QString::fromUtf8(msg)); } + +private: + + DebugLog(); + ~DebugLog(); + bool openLogfile(); + void closeLogfile(); + void log(Type, QString); + + bool consoleLogging; + bool fileLogging; + Level logLevel; + QFile logFile; + + static DebugLog * singleton(); + static DebugLog * instance; +}; + + +#endif ============================================================ --- guitone/guitone.pro 3448c02855a8ee7961b5514502c00941e9ac635f +++ guitone/guitone.pro 89ffc63cab6945f7c72dd91d072bfa7425ae9d33 @@ -51,7 +51,8 @@ HEADERS += src/view/MainWindow.h \ src/util/DiffParser.h \ src/util/SignalWaiter.h \ src/util/OpenFile.h \ - src/util/TreeBuilder.h + src/util/TreeBuilder.h \ + src/util/DebugLog.h SOURCES += src/view/MainWindow.cpp \ src/view/TreeView.cpp \ src/view/Splitter.cpp \ @@ -92,6 +93,7 @@ SOURCES += src/view/MainWindow.cpp \ src/util/SignalWaiter.cpp \ src/util/OpenFile.cpp \ src/util/TreeBuilder.cpp \ + src/util/DebugLog.cpp \ src/main.cpp FORMS += res/forms/switch_workspace.ui \ ============================================================ --- guitone/res/forms/preferences.ui 9e93e317aee87b3c5cb3d798e7a1ded37a8b0ff9 +++ guitone/res/forms/preferences.ui b2a58b08e11a292a2f334514e2c24dfedcc7cd21 @@ -5,8 +5,8 @@ 0 0 - 393 - 141 + 343 + 248 @@ -17,6 +17,12 @@ 0 + + + 16777215 + 248 + + Qt::NoContextMenu @@ -52,7 +58,7 @@ Path to monotone executable - + 9 @@ -93,6 +99,81 @@ + + + Logging + + + + 9 + + + 6 + + + + + 0 + + + 6 + + + + + enable console logging + + + true + + + + + + + enable file logging (%1) + + + + + + + 0 + + + 6 + + + + + Log level + + + + + + + + + + Qt::Horizontal + + + + 40 + 20 + + + + + + + + + + + + 0 ============================================================ --- guitone/src/main.cpp 65dc8121bc3e89b4fd1b370a51554f9c81ec9306 +++ guitone/src/main.cpp 41f57d259c796164c7939ec5c3b779593016afbd @@ -19,13 +19,34 @@ ***************************************************************************/ #include "MainWindow.h" +#include "DebugLog.h" #include #include #include +void guitoneMsgHandler(QtMsgType type, const char *msg) +{ + switch (type) + { + case QtDebugMsg: + DebugLog::debug(msg); + break; + case QtWarningMsg: + DebugLog::warn(msg); + break; + case QtCriticalMsg: + DebugLog::critical(msg); + break; + case QtFatalMsg: + DebugLog::fatal(msg); + abort(); + } +} + int main(int argc, char** argv) { + qInstallMsgHandler(guitoneMsgHandler); QApplication app(argc,argv); QCoreApplication::setOrganizationName("Thomas Keller"); ============================================================ --- guitone/src/util/Settings.cpp 53eb2f27d05b118d6f65287cfd578b2e08f31ef9 +++ guitone/src/util/Settings.cpp 23ac3899da46d0555b39a375b966dc69322cdb20 @@ -57,8 +57,7 @@ void Settings::sync() void Settings::sync() { - Settings *settings = singleton(); - settings->QSettings::sync(); + singleton()->QSettings::sync(); } QString Settings::getMtnBinaryPath() @@ -68,11 +67,40 @@ void Settings::setMtnBinaryPath(QString void Settings::setMtnBinaryPath(QString path) { - Settings *settings = singleton(); - settings->setValue("MtnExePath", path); + singleton()->setValue("MtnExePath", path); } -// TODO: implement suppport for column moving here +bool Settings::getConsoleLogEnabled() +{ + return singleton()->value("ConsoleLogEnabled", true).toBool(); +} + +void Settings::setConsoleLogEnabled(bool enabled) +{ + singleton()->setValue("ConsoleLogEnabled", enabled); +} + +bool Settings::getFileLogEnabled() +{ + return singleton()->value("FileLogEnabled", false).toBool(); +} + +void Settings::setFileLogEnabled(bool enabled) +{ + singleton()->setValue("FileLogEnabled", enabled); +} + +int Settings::getLogLevel() +{ + // 4 is debug, see DebugLog.h + return singleton()->value("LogLevel", 4).toInt(); +} + +void Settings::setLogLevel(int verbosity) +{ + singleton()->setValue("LogLevel", verbosity); +} + void Settings::saveHeaderViewState(QHeaderView *view, QString name) { QStringList cols; ============================================================ --- guitone/src/util/Settings.h 3be69fcb30460f05f876b8d990cc5f2964a82231 +++ guitone/src/util/Settings.h da27ac6c5551cfd88073109df8624bf22e548556 @@ -31,20 +31,33 @@ public: public: static void setBool(const QString &, bool); static bool getBool(const QString &, bool); - static void setWindowGeometry(const QByteArray &, const QString &); + + static void setWindowGeometry(const QByteArray &, const QString &); static QByteArray getWindowGeometry(const QString &); - static QStringList getItemList(const QString &); + + static QStringList getItemList(const QString &); static void setItemList(const QString &, const QStringList &); static void addItemToList(const QString&, const QString &, int); static void removeItemFromList(const QString &, const QString &); + static QString getMtnBinaryPath(); static void setMtnBinaryPath(QString); + + static bool getConsoleLogEnabled(); + static void setConsoleLogEnabled(bool); + static bool getFileLogEnabled(); + static void setFileLogEnabled(bool); + static int getLogLevel(); + static void setLogLevel(int); + static void saveHeaderViewState(QHeaderView *, QString); static void restoreHeaderViewState(QHeaderView *, QString); + static QByteArray getSplitterState(QString); static void setSplitterState(const QByteArray &, QString); - static void sync(); + static void sync(); + private: Settings(); ~Settings(void); ============================================================ --- guitone/src/view/dialogs/Preferences.cpp 4aa186cb30ad6ca40b84ce3d0af9ffb3d7ec5dc2 +++ guitone/src/view/dialogs/Preferences.cpp aee8e3701cad4b88fcc8f8d32f0fe836d7083b00 @@ -21,6 +21,7 @@ #include "Preferences.h" #include "Monotone.h" #include "Settings.h" +#include "DebugLog.h" #include #include @@ -33,6 +34,20 @@ Preferences::Preferences(QWidget* parent mtnExecutablePath->setText(Settings::getMtnBinaryPath()); + enableConsoleLog->setCheckState(DebugLog::getConsoleLogEnabled() ? + Qt::Checked : Qt::Unchecked); + enableFileLog->setCheckState(DebugLog::getFileLogEnabled() ? + Qt::Checked : Qt::Unchecked); + + enableFileLog->setText(enableFileLog->text().arg(DebugLog::logFilePath())); + + logLevel->addItem(tr("Low (fatal errors)"), 1); + logLevel->addItem(tr("Medium (critical errors)"), 2); + logLevel->addItem(tr("High (warnings)"), 3); + logLevel->addItem(tr("All (debug messages)"), 4); + + logLevel->setCurrentIndex(DebugLog::getLogLevel()-1); + connect( selectMtnExecutable, SIGNAL(clicked()), this, SLOT(openFileBrowser()) @@ -80,6 +95,15 @@ void Preferences::accept() Settings::setMtnBinaryPath(newPath); } + + bool consoleEnabled = enableConsoleLog->isChecked(); + bool fileEnabled = enableFileLog->isChecked(); + int level = logLevel->itemData(logLevel->currentIndex()).toInt(); + + DebugLog::setConsoleLogEnabled(consoleEnabled); + DebugLog::setFileLogEnabled(fileEnabled); + DebugLog::setLogLevel(level); + done(QDialog::Accepted); }