diff --git a/include/iradiant.h b/include/iradiant.h index 672496e808..cc79a923b2 100644 --- a/include/iradiant.h +++ b/include/iradiant.h @@ -7,6 +7,8 @@ const char* const MODULE_RADIANT("Radiant"); +namespace applog { class ILogWriter; } + namespace radiant { @@ -18,6 +20,12 @@ class IRadiant public: typedef std::shared_ptr Ptr; + /** + * Central logging class of the module. Use this to + * attach your own ILogDevices to receive logging output. + */ + virtual applog::ILogWriter& getLogWriter() = 0; + virtual ~IRadiant() {} }; diff --git a/radiant/Radiant.cpp b/radiant/Radiant.cpp index 79afc901b4..db1cde087c 100644 --- a/radiant/Radiant.cpp +++ b/radiant/Radiant.cpp @@ -1,6 +1,9 @@ #include "iradiant.h" #include "module/CoreModule.h" +#include "log/LogStream.h" +#include "log/LogWriter.h" + namespace radiant { @@ -13,7 +16,20 @@ class Radiant : public: Radiant(ApplicationContext& context) : _context(context) - {} + { + // Set the stream references for rMessage(), redirect std::cout, etc. + applog::LogStream::InitialiseStreams(); + } + + ~Radiant() + { + applog::LogStream::ShutdownStreams(); + } + + applog::ILogWriter& getLogWriter() override + { + return applog::LogWriter::Instance(); + } }; } diff --git a/radiant/RadiantApp.cpp b/radiant/RadiantApp.cpp index 92a189ed3e..8c9bb0a35d 100644 --- a/radiant/RadiantApp.cpp +++ b/radiant/RadiantApp.cpp @@ -2,6 +2,7 @@ #include "i18n.h" #include "iradiant.h" +#include "version.h" #include "log/LogFile.h" #include "log/LogStream.h" @@ -26,6 +27,7 @@ #include #endif #include +#include #if defined (_DEBUG) && defined (WIN32) && defined (_MSC_VER) #include "crtdbg.h" @@ -34,6 +36,11 @@ // The startup event which will be queued in App::OnInit() wxDEFINE_EVENT(EV_RadiantStartup, wxCommandEvent); +namespace +{ + const char* const TIME_FMT = "%Y-%m-%d %H:%M:%S"; +} + bool RadiantApp::OnInit() { if (!wxApp::OnInit()) return false; @@ -67,8 +74,8 @@ bool RadiantApp::OnInit() throw ex; } - // The settings path is set, start logging now - applog::LogFile::create("darkradiant.log"); + // Attach the logfile to the core binary's logwriter + createLogFile(); #ifndef POSIX // Initialise the language based on the settings in the user settings folder @@ -101,19 +108,54 @@ bool RadiantApp::OnInit() return true; } -int RadiantApp::OnExit() +void RadiantApp::createLogFile() { - if (_coreModule) + _logFile.reset(new applog::LogFile(_context.getSettingsPath() + "darkradiant.log")); + + if (_logFile->isOpen()) { - _coreModule.reset(); + _coreModule->get()->getLogWriter().attach(_logFile.get()); + + rMessage() << "Started logging to " << _logFile->getFullPath() << std::endl; + + rMessage() << "This is " << RADIANT_APPNAME_FULL() << std::endl; + + std::time_t t = std::time(nullptr); + std::tm tm = *std::localtime(&t); + + // Write timestamp and thread information + rMessage() << "Today is " << std::put_time(&tm, TIME_FMT) << std::endl; + + // Output the wxWidgets version to the logfile + std::string wxVersion = string::to_string(wxMAJOR_VERSION) + "."; + wxVersion += string::to_string(wxMINOR_VERSION) + "."; + wxVersion += string::to_string(wxRELEASE_NUMBER); + + rMessage() << "wxWidgets Version: " << wxVersion << std::endl; + } + else + { + rConsoleError() << "Failed to create log file '" + << _logFile->getFullPath() << ", check write permissions in parent directory." + << std::endl; } +} +int RadiantApp::OnExit() +{ // Issue a shutdown() call to all the modules module::GlobalModuleRegistry().shutdownModules(); - // Close the logfile - applog::LogFile::close(); - applog::LogStream::ShutdownStreams(); + if (_coreModule) + { + // Close the log file + if (_logFile) + { + _coreModule->get()->getLogWriter().detach(_logFile.get()); + } + + _coreModule.reset(); + } return wxApp::OnExit(); } diff --git a/radiant/RadiantApp.h b/radiant/RadiantApp.h index 0a74c93a77..9f0e07efbd 100644 --- a/radiant/RadiantApp.h +++ b/radiant/RadiantApp.h @@ -3,6 +3,7 @@ #include #include "modulesystem/ApplicationContextImpl.h" #include "module/CoreModule.h" +#include "log/LogFile.h" /** * Main application class required by wxWidgets @@ -24,6 +25,8 @@ class RadiantApp : std::unique_ptr _coreModule; + std::unique_ptr _logFile; + public: bool OnInit() override; int OnExit() override; @@ -34,5 +37,6 @@ class RadiantApp : bool OnExceptionInMainLoop() override; private: + void createLogFile(); void onStartupEvent(wxCommandEvent& ev); }; diff --git a/radiant/log/LogFile.cpp b/radiant/log/LogFile.cpp index 0e9058cc19..1f8717f2e2 100644 --- a/radiant/log/LogFile.cpp +++ b/radiant/log/LogFile.cpp @@ -9,7 +9,6 @@ #include "string/convert.h" #include "LogWriter.h" -#include "modulesystem/ModuleRegistry.h" namespace applog { @@ -19,25 +18,10 @@ namespace const char* const TIME_FMT = "%Y-%m-%d %H:%M:%S"; } -LogFile::LogFile(const std::string& filename) : - _logFilename( - module::ModuleRegistry::Instance().getApplicationContext().getSettingsPath() + - filename - ), - _logStream(_logFilename.c_str()) -{ - if (_logStream.good()) - { - // Register this class as logdevice - LogWriter::Instance().attach(this); - } - else - { - rConsoleError() << "Failed to create log file '" - << _logFilename << ", check write permissions in parent directory." - << std::endl; - } -} +LogFile::LogFile(const std::string& fullPath) : + _logFilePath(fullPath), + _logStream(_logFilePath.c_str()) +{} LogFile::~LogFile() { @@ -63,6 +47,16 @@ LogFile::~LogFile() LogWriter::Instance().detach(this); } +bool LogFile::isOpen() +{ + return _logStream.good(); +} + +const std::string& LogFile::getFullPath() const +{ + return _logFilePath; +} + void LogFile::writeLog(const std::string& outputStr, ELogLevel level) { _buffer.append(outputStr); @@ -88,6 +82,7 @@ void LogFile::writeLog(const std::string& outputStr, ELogLevel level) } } +#if 0 // Creates the singleton logfile with the given filename void LogFile::create(const std::string& filename) { @@ -97,7 +92,7 @@ void LogFile::create(const std::string& filename) InstancePtr() = LogFilePtr(new LogFile(filename)); // Write the initialisation info to the logfile. - rMessage() << "Started logging to " << InstancePtr()->_logFilename << std::endl; + rMessage() << "Started logging to " << InstancePtr()->_logFilePath << std::endl; rMessage() << "This is " << RADIANT_APPNAME_FULL() << std::endl; @@ -128,5 +123,6 @@ LogFilePtr& LogFile::InstancePtr() { static LogFilePtr _instancePtr; return _instancePtr; } +#endif } // namespace applog diff --git a/radiant/log/LogFile.h b/radiant/log/LogFile.h index 92bc699493..56dc36dcdb 100644 --- a/radiant/log/LogFile.h +++ b/radiant/log/LogFile.h @@ -1,21 +1,16 @@ #pragma once #include -#include #include "ilogwriter.h" namespace applog { -// Shared_ptr forward declaration -class LogFile; -typedef std::shared_ptr LogFilePtr; - class LogFile : public ILogDevice { // The log file name including path - std::string _logFilename; + std::string _logFilePath; // We write line by line std::string _buffer; @@ -25,28 +20,23 @@ class LogFile : public: /** - * greebo: Pass only the file name to the constructor, - * the path is automatically loaded from the XMLRegistry. - * (The path in the registry key SETTINGS_PATH is used.) + * greebo: Pass the full path to the constructor */ - LogFile(const std::string& filename); + LogFile(const std::string& fullPath); virtual ~LogFile(); + // Returns true if the log stream was successfully opened + bool isOpen(); + + // Returns the full path to the log file + const std::string& getFullPath() const; + /** * Use this to write a string to the logfile. This usually gets * called by the LogWriter class, but it can be called independently. */ void writeLog(const std::string& outputStr, ELogLevel level) override; - - // Creates the singleton logfile with the given filename - static void create(const std::string& filename); - - // Closes the singleton log instance - static void close(); - - // The singleton InstancePtr(), is NULL when the logfile is closed - static LogFilePtr& InstancePtr(); }; } // namespace applog diff --git a/tools/msvc/DarkRadiantCore.vcxproj b/tools/msvc/DarkRadiantCore.vcxproj index 0cfebfc3cc..4d6dc88e8b 100644 --- a/tools/msvc/DarkRadiantCore.vcxproj +++ b/tools/msvc/DarkRadiantCore.vcxproj @@ -117,19 +117,15 @@ - true $(SolutionDir)\..\..\install\ - true $(SolutionDir)\..\..\install\ - false $(SolutionDir)\..\..\install\ - false $(SolutionDir)\..\..\install\ diff --git a/tools/msvc/modulelib.vcxproj b/tools/msvc/modulelib.vcxproj index 251c48a8c0..b488110de9 100644 --- a/tools/msvc/modulelib.vcxproj +++ b/tools/msvc/modulelib.vcxproj @@ -94,7 +94,7 @@ Level3 true _DEBUG;_CONSOLE;%(PreprocessorDefinitions) - true + ProgramDatabase Console @@ -106,7 +106,7 @@ Level3 true _DEBUG;_CONSOLE;%(PreprocessorDefinitions) - true + ProgramDatabase Console