Index: sources/storage/logger.cpp =================================================================== diff -u -r62efc6d8ead9b39b47859fdc9c0661f30b5941d0 -rc6a09899d2e46dc0bda5a6b994aa257953626f97 --- sources/storage/logger.cpp (.../logger.cpp) (revision 62efc6d8ead9b39b47859fdc9c0661f30b5941d0) +++ sources/storage/logger.cpp (.../logger.cpp) (revision c6a09899d2e46dc0bda5a6b994aa257953626f97) @@ -13,9 +13,234 @@ */ #include "logger.h" +// Qt +#include +#include +#include +#include +#include +#include + +// Project +#include "storageglobals.h" +#include "filehandler.h" +#include "threads.h" + using namespace Storage; -Logger::Logger(QObject *parent) : QObject(parent) +Logger::Logger(QObject *parent) : QObject(parent) { } + +/*! + * \brief Logger::init + * \details Initializes the Class. + * \return False if it has been called before. + */ +bool Logger::init() { + if ( _init ) return false; + _init = true; + // runs in thread + checkLogPath(); + initConnections(); + + LOG_EVENT(QObject::tr("%1 Initialized").arg(metaObject()->className())); + + return true; } + +/*! + * \brief Logger::init + * \details Initialized the Class by calling the init() method first + * And initializes the thread vThread by calling initThread + * on success init(). + * \param vThread - the thread + * \return returns the return value of the init() method + */ +bool Logger::init(QThread &vThread) +{ + if ( ! init() ) return false; + initThread(vThread); + return true; +} + +/*! + * \brief Logger quit + * \details quits the class + * Calls quitThread + */ +void Logger::quit() +{ + quitThread(); +} + +void Logger::onLog(const QString &vContent, LogType vLogType) +{ + log(vContent,vLogType); +} + +/*! + * \brief Logger::initConnections + * \details Initializes the required signal/slot connection between this class and other objects + * to be able to communicate. + * \note No connection has been defined yet. + */ +void Logger::initConnections() +{ + connect(&_exportWatcher, SIGNAL(finished()), + this , SLOT(onExport())); + + connect(this, SIGNAL(didLog(QString,LogType)), + this, SLOT( onLog(QString,LogType))); +} + +/*! + * \brief Logger::initThread + * \details Moves this object into the thread vThread. + * And checks that this method is called from main thread. + * Also connects quitThread to application aboutToQuit. + * \param vThread - the thread + */ +void Logger::initThread(QThread &vThread) +{ + // runs in main thread + Q_ASSERT_X(QThread::currentThread() == qApp->thread() , __func__, "The Class initialization must be done in Main Thread" ); + _thread = &vThread; + _thread->setObjectName(QString("%1_Thread").arg(metaObject()->className())); + connect(qApp, SIGNAL(aboutToQuit()), this, SLOT(quit())); + _thread->start(); + moveToThread(_thread); +} + +/*! + * \brief Logger::quitThread + * \details Moves this object to main thread to be handled by QApplicaiton + * And to be destroyed there. + */ +void Logger::quitThread() +{ + if (! _thread) return; + + // runs in thread + moveToThread(qApp->thread()); +} + +/*! + * \brief Logger::checkLogPath + * \details Sets the log paths and creates them if didn't exist. + */ +void Logger::checkLogPath() +{ + setLogBasePath(); // try to use /media/sd_card on device + if (! setLogPath()) { // check and create log folders & if unsuccessful then + setLogBasePath(true); // try to use application folder + setLogPath ( ); // check and create log folders // Note: it may require to check for write access regarding device setup + } +} + +/*! + * \brief Logger::setLogBasePath + * \details Tries to the set the log path to the default log path (Log_Base_Path_Name) + * Will set the application folder as the base log path if can't set the log path to the default. + * Will log the event in that case. + * \param vUseApplicationDirPath + */ +void Logger::setLogBasePath(bool vUseApplicationDirPath) +{ + if (vUseApplicationDirPath) { + _dir.setPath(qApp->applicationDirPath()); + LOG_EVENT(tr("Application Dir Path used for events logging (%1)").arg(_dir.path())); + } else { + _dir.setPath(Log_Base_Path_Name); + } +} + +/*! + * \brief Logger::setLogPath + * \details set the log path for each of the Datum, Event, Error log types + * \return False if can not st the log paths. + */ +bool Logger::setLogPath() +{ + bool ok = true; + ok = ok && setLogPath(LogType::eLogEvent); + ok = ok && setLogPath(LogType::eLogError); + ok = ok && setLogPath(LogType::eLogDatum); + return ok; +} + +/*! + * \brief Logger::setLogPath + * \details Sets the log path for the log type vLogType + * Creates the folder if not exists. + * \param vLogType - log type + * \return returns false if the path doesn't exist and folder can't be created. + */ +bool Logger::setLogPath(LogType vLogType) +{ + _logPathNames[vLogType] = _dir.path() + "/" + _logBasePathNames[vLogType]; + if ( ! _dir.exists(_logBasePathNames[vLogType]) ) { + if ( ! _dir.mkpath(_logBasePathNames[vLogType]) ) { + LOG_ERROR(tr("Can't create %1 log path (%2)") + .arg(_logPrefix[vLogType]) + .arg(_logPathNames[vLogType]) + ); + return false; + } + } + return true; +} + +/*! + * \brief Logger::log + * \details Logs the content vContent in log type of vLogType. + * \param vContent - Log content + * \param vLogType - Log type + * \note This method is not thread-safe so is private and needs to be called by concurrentLog + * Which uses QtConcurrent::run to run in thread and thread-safe. + */ +void Logger::log(const QString &vContent, Logger::LogType vLogType) +{ + QString date = QDate::currentDate().toString(_dateFormat); + QString mContent; + + switch (vLogType) { + case eLogEvent: + case eLogError: + case eLogDatum: + break; + default: + LOG_ERROR(tr("Incorrect type of logging").arg(vLogType)); + } + mContent += _logPrefix[vLogType]; + mContent += _prefixSeparator; + mContent += QTime::currentTime().toString(_timeFormat); + mContent += _timeSeparator + vContent; + QString fileName = date + _dateSeparator + Log_File_Name; + _logFileName = _logPathNames[vLogType] + fileName; + FileHandler::write(_logFileName, mContent + "\r\n", true); + if (vLogType == eLogError) { + qDebug().noquote() << mContent; + } +} + +/*! + * \brief Logger::concurrentExport + * \details Exports the log files from log folder (Storage::Log_Base_Path_Name_Location) + * into USB drive folder (Storage::USB_Mount_Point) + * \return always returns true for now. + * \note This method uses QtConcurrent run to execute the FileHandler copyFolder method. + */ +bool Logger::concurrentExport() +{ + QString mSource = Storage::Log_Base_Path_Name_Location; + QString mDestination = Storage::USB_Mount_Point; + QFuture future = QtConcurrent::run(&FileHandler::copyFolder, mSource, mDestination); + _exportWatcher.setFuture(future); + return true; +} + +void Logger::onExport() +{ + emit didExport(); +}