File indexing completed on 2024-12-08 11:02:06
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 }