File indexing completed on 2024-12-08 05:03:26

0001 /*************************************************************************
0002  *     Copyright (C) 2014 by Renaud Guezennec                            *
0003  *                                                                       *
0004  *     https://rolisteam.org/                                         *
0005  *                                                                       *
0006  *   Rolisteam is free software; you can redistribute it and/or modify   *
0007  *   it under the terms of the GNU General Public License as published   *
0008  *   by the Free Software Foundation; either version 2 of the License,   *
0009  *   or (at your option) any later version.                              *
0010  *                                                                       *
0011  *   This program is distributed in the hope that it will be useful,     *
0012  *   but WITHOUT ANY WARRANTY; without even the implied warranty of      *
0013  *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the       *
0014  *   GNU General Public License for more details.                        *
0015  *                                                                       *
0016  *   You should have received a copy of the GNU General Public License   *
0017  *   along with this program; if not, write to the                       *
0018  *   Free Software Foundation, Inc.,                                     *
0019  *   59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.           *
0020  *************************************************************************/
0021 #include <common/logcontroller.h>
0022 
0023 #include <QDateTime>
0024 #include <QJsonDocument>
0025 #include <QJsonObject>
0026 #include <QMetaMethod>
0027 #include <QMetaObject>
0028 #include <QMutexLocker>
0029 #include <QTime>
0030 #include <iostream>
0031 
0032 #ifdef QT_WIDGETS_LIB
0033 #include <QAction>
0034 #include <QWidget>
0035 #endif
0036 
0037 LogController* controller= nullptr;
0038 
0039 namespace helper
0040 {
0041 namespace log
0042 {
0043 QString humanReadableDiceResult(const QString& json)
0044 {
0045     QJsonDocument doc= QJsonDocument::fromJson(json.toUtf8());
0046     auto obj= doc.object();
0047 
0048     QStringList list;
0049     std::transform(std::begin(obj), std::end(obj), std::back_inserter(list),
0050                    [obj](const QJsonValueRef& ref) { return ref.toString(); });
0051     /*auto command= obj[Core::jsonDice::JSON_COMMAND].toString();
0052     auto error= obj[Core::jsonDice::JSON_ERROR].toString();
0053     auto scalar= obj[Core::jsonDice::JSON_SCALAR].toString();*/
0054 
0055     list << QString(json.toUtf8().toBase64());
0056     return list.join(";");
0057 }
0058 } // namespace log
0059 } // namespace helper
0060 
0061 void messageHandler(QtMsgType type, const QMessageLogContext& context, const QString& msg)
0062 {
0063     static QMutex mutex;
0064     QMutexLocker lock(&mutex);
0065 
0066     if(nullptr == controller)
0067         return;
0068 
0069     QByteArray localMsg= msg.toLocal8Bit();
0070     auto msgFormated= QStringLiteral("%1 (%2:%3), %4")
0071                           .arg(QString(localMsg.constData()), QString(context.file), QString::number(context.line),
0072                                QString(context.function));
0073     LogController::LogLevel cLevel= LogController::Error;
0074     switch(type)
0075     {
0076     case QtDebugMsg:
0077         cLevel= LogController::Debug;
0078         std::cout << msg.toStdString() << std::endl;
0079         break;
0080     case QtInfoMsg:
0081         cLevel= LogController::Info;
0082         std::cout << msg.toStdString() << std::endl;
0083         break;
0084     case QtWarningMsg:
0085         cLevel= LogController::Warning;
0086         std::cout << msg.toStdString() << std::endl;
0087         break;
0088     case QtCriticalMsg:
0089     case QtFatalMsg:
0090         cLevel= LogController::Error;
0091         std::cerr << msg.toStdString() << std::endl;
0092         break;
0093     }
0094 
0095     // controller->manageMessage(msgFormated,cLevel);
0096     QMetaObject::invokeMethod(controller, "manageMessage", Qt::QueuedConnection, Q_ARG(QString, msgFormated),Q_ARG(QString, QString::fromLocal8Bit(context.category)),
0097                               Q_ARG(LogController::LogLevel, cLevel));
0098     QMetaObject::invokeMethod(controller, "logToFile", Qt::QueuedConnection, Q_ARG(QString, msg),
0099                               Q_ARG(LogController::LogLevel, cLevel),
0100                               Q_ARG(QString, QString::fromLocal8Bit(context.category)));
0101 }
0102 
0103 LogController::LogController(bool attachMessage, QObject* parent) : QObject(parent)
0104 {
0105     qRegisterMetaType<LogController::LogLevel>("LogController::LogLevel");
0106     setMessageHandler(attachMessage);
0107 }
0108 
0109 LogController::~LogController()
0110 {
0111     controller= nullptr;
0112 }
0113 
0114 void LogController::setMessageHandler(bool attachMessage)
0115 {
0116     // #ifndef QT_DEBUG
0117     if((controller == nullptr) && (attachMessage))
0118     {
0119         qInstallMessageHandler(messageHandler);
0120         controller= this;
0121     }
0122     else
0123     {
0124         qInstallMessageHandler(nullptr);
0125         controller= nullptr;
0126     }
0127     /*#else
0128         Q_UNUSED(attachMessage)
0129     #endif*/
0130 }
0131 LogController::StorageModes LogController::currentModes() const
0132 {
0133     return m_currentModes;
0134 }
0135 
0136 void LogController::setCurrentModes(const StorageModes& currentModes)
0137 {
0138     m_currentModes= currentModes;
0139 }
0140 
0141 LogController::LogLevel LogController::logLevel() const
0142 {
0143     return m_logLevel;
0144 }
0145 
0146 void LogController::setLogLevel(const LogLevel& currentLevel)
0147 {
0148     if(currentLevel == m_logLevel)
0149         return;
0150 
0151     m_logLevel= currentLevel;
0152     emit logLevelChanged();
0153 }
0154 
0155 void LogController::listenObjects(const QObject* object)
0156 {
0157 #ifdef QT_WIDGETS_LIB
0158     const auto widget= dynamic_cast<const QWidget*>(object);
0159     if(widget != nullptr)
0160     {
0161         QList<QAction*> actions= widget->actions();
0162         for(QAction* action : actions)
0163         {
0164             connect(action, &QAction::triggered, this, &LogController::actionActivated, Qt::QueuedConnection);
0165         }
0166     }
0167 #endif
0168     Q_UNUSED(object)
0169     /*if(m_signalInspection)
0170     {
0171         auto metaObject = object->metaObject();
0172 
0173         for(int i = 0; i < metaObject->methodCount(); ++i)
0174         {
0175             auto meth = metaObject->method(i);
0176            // qDebug() << meth.name();
0177             if(meth.methodType() == QMetaMethod::Signal && meth.access() == QMetaMethod::Public)
0178             {
0179                 connect(object,meth.name(),this,SLOT(actionActivated()),Qt::QueuedConnection);
0180             }
0181         }
0182     }*/
0183 #ifdef QT_WIDGETS_LIB
0184     if(widget != nullptr)
0185     {
0186         QObjectList children= widget->children();
0187         for(QObject* obj : children)
0188         {
0189             listenObjects(obj);
0190         }
0191     }
0192 #endif
0193 }
0194 
0195 void LogController::actionActivated()
0196 {
0197 #ifdef QT_WIDGETS_LIB
0198     auto act= qobject_cast<QAction*>(sender());
0199     manageMessage(QStringLiteral("[Action] - %1 - %2").arg(act->text(), act->objectName()), Info);
0200 #endif
0201 }
0202 
0203 void LogController::signalActivated()
0204 {
0205     auto obj= sender();
0206     auto index= senderSignalIndex();
0207     auto meta= obj->metaObject();
0208     auto method= meta->method(index);
0209     manageMessage(QStringLiteral("[signal] - %1").arg(QString::fromUtf8(method.name())), QStringLiteral("Signal"), Info);
0210 }
0211 
0212 QString LogController::typeToText(LogController::LogLevel type)
0213 {
0214     static QHash<LogController::LogLevel, QString> list
0215         = {{LogController::Debug, "Debug"},  {LogController::Error, "Error"},      {LogController::Warning, "Warning"},
0216            {LogController::Info, "Info"},    {LogController::Features, "Feature"}, {LogController::Hidden, "Feature"},
0217            {LogController::Search, "Search"}};
0218     return list.value(type);
0219 }
0220 
0221 void LogController::setCurrentPath(const QString& path)
0222 {
0223     if(m_currentFile == path)
0224         return;
0225     m_currentFile= path;
0226     emit currentPathChanged();
0227 }
0228 
0229 bool LogController::signalInspection() const
0230 {
0231     return m_signalInspection;
0232 }
0233 
0234 QString LogController::currentPath() const
0235 {
0236     return m_currentFile;
0237 }
0238 
0239 void LogController::setSignalInspection(bool signalInspection)
0240 {
0241     m_signalInspection= signalInspection;
0242 }
0243 
0244 void LogController::setListenOutSide(bool val)
0245 {
0246     m_listenOutSide= val;
0247 }
0248 
0249 void LogController::manageMessage(QString message, const QString& category, LogController::LogLevel type)
0250 {
0251     static QMutex mutex;
0252     QMutexLocker locker(&mutex);
0253     Q_UNUSED(locker)
0254 
0255     QString str("%1 - %2 - %3");
0256     str= str.arg(QTime::currentTime().toString("hh:mm:ss"), typeToText(type), message);
0257 
0258     QString timestamps;
0259     timestamps= QDateTime::currentDateTime().toString("yyyy-MM-dd hh:mm:ss.zzz");
0260 
0261     if(type == Hidden)
0262     {
0263         emit showMessage(str, type);
0264         return;
0265     }
0266 
0267     if(type == Search || (m_currentModes & Network))
0268     {
0269         emit sendOffMessage(str, typeToText(type), category, timestamps);
0270     }
0271 
0272     if(type > m_logLevel)
0273         return;
0274 
0275     if(m_currentModes & Console)
0276     {
0277         if(type == Error)
0278             std::cerr << str.toStdString() << std::endl;
0279         else
0280             std::cout << str.toStdString() << std::endl;
0281     }
0282 
0283     if(m_currentModes & Gui)
0284     {
0285         emit showMessage(str, type);
0286     }
0287 }
0288 
0289 void LogController::logToFile(const QString& msg, const LogController::LogLevel& type, const QString& log)
0290 {
0291     if(m_currentModes & File && !m_currentFile.isEmpty())
0292     {
0293         auto realMsg
0294             = QString("%1;%2;%3;%4")
0295                   .arg(QDateTime::currentDateTime().toString("yyyy-MM-dd hh:mm:ss.zzz"), log, typeToText(type), msg);
0296 
0297         QFile output(m_currentFile);
0298         if(output.open(QIODevice::WriteOnly | QIODevice::Append))
0299         {
0300             QTextStream text(&output);
0301             text << realMsg << "\n";
0302         }
0303     }
0304 }