summaryrefslogtreecommitdiff
path: root/logworker.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'logworker.cpp')
-rw-r--r--logworker.cpp273
1 files changed, 273 insertions, 0 deletions
diff --git a/logworker.cpp b/logworker.cpp
new file mode 100644
index 0000000..b165e4c
--- /dev/null
+++ b/logworker.cpp
@@ -0,0 +1,273 @@
+#include "logworker.h"
+
+// qt
+#include <QFile>
+#include <QMetaEnum>
+#include <QMutex>
+
+// cpp
+#include <iostream>
+
+// goodies
+#include "singleton.h"
+
+#define REGISTER_QT_MSG_TYPE(type) \
+ {QtMsgType::type, QString(#type).replace("Qt", "").replace("Msg", "")}
+
+namespace goodies
+{
+
+// TODO: to avoid errors replace me via magic_enum lib or any other compile-time
+// stuff when qt-distributed mingw will support it
+static QHash<QtMsgType, QString> qtMsgTypes = {
+ REGISTER_QT_MSG_TYPE(QtDebugMsg),
+ REGISTER_QT_MSG_TYPE(QtWarningMsg),
+ REGISTER_QT_MSG_TYPE(QtCriticalMsg),
+ REGISTER_QT_MSG_TYPE(QtFatalMsg),
+ REGISTER_QT_MSG_TYPE(QtInfoMsg)
+};
+
+QString appLogFileName()
+{
+ QString path =
+ QStandardPaths::writableLocation(QStandardPaths::AppDataLocation) +
+ QDir::separator() + "logs";
+
+ QDir dir(path);
+
+ if (!dir.exists())
+ {
+ if (!dir.mkpath(path))
+ {
+ // we'll get recursion here by using qWarning or some other
+ // QMessageLogger
+ std::cerr << "cannot create dir: " << path.toStdString()
+ << std::endl;
+ }
+ }
+
+ QString filename =
+ QDateTime::currentDateTime().toString("yyyy.MM.dd_hh.mm.ss.zzz") +
+ ".log";
+
+ return path + QDir::separator() + filename;
+}
+
+void myMessageHandler(
+ QtMsgType type,
+ const QMessageLogContext& context,
+ const QString& msg
+)
+{
+ goodies::defaultMessageHandler(type, context, msg);
+ // std::cout << msg.toStdString() << std::endl;
+ SINGLETON(LogWorker)->writeMessage(type, context, msg);
+}
+
+LogMsg::LogMsg(
+ QDateTime dateTime,
+ MessageType messageType,
+ QString message,
+ QObject* parent
+)
+ : G_Object(parent)
+ , INIT_FIELD(dateTime)
+ , INIT_FIELD(messageType)
+ , INIT_FIELD(message)
+{
+}
+
+LogWorker::LogWorker(const QString filepath)
+ : QAbstractListModel(nullptr)
+ , INIT_FIELD(filepath)
+ , m_file(filepath)
+ , m_fileStream(&m_file)
+{
+ QMutexLocker l(&m_mtx);
+
+ auto onIsLoggingEnabledChanged =
+ [&]() {
+ if (get_isLoggingEnabled())
+ {
+ if (!m_file.open(QFile::ReadWrite | QFile::Append))
+ {
+ qWarning()
+ << tr("cannot open log file for reading and writing: ")
+ << m_file.fileName();
+ set_isLoggingEnabled(false);
+ return;
+ }
+
+ qDebug() << "log file opened reading and writing";
+ }
+ else
+ {
+ if (!m_file.open(QFile::ReadOnly))
+ {
+ qWarning() << tr("cannot open log file for reading: ")
+ << m_file.fileName();
+ }
+
+ qDebug() << "log file opened for reading";
+ }
+ };
+
+ connect(
+ this,
+ qOverload<>(&LogWorker::isLoggingEnabledChanged),
+ onIsLoggingEnabledChanged
+ );
+ onIsLoggingEnabledChanged();
+}
+
+LogWorker::~LogWorker()
+{
+ QMutexLocker l(&m_mtx);
+}
+
+QString LogWorker::filepath() const
+{
+ return m_filepath;
+}
+
+void LogWorker::initialize(QApplication& app)
+{
+ // LogWorker uses app info to open log file
+ Q_UNUSED(app)
+ SINGLETON(LogWorker);
+ goodies::defaultMessageHandler = qInstallMessageHandler(myMessageHandler);
+}
+
+// LogWorker &LogWorker::operator<<(const QString &msg)
+//{
+// QMutexLocker l(&m_mtx);
+
+// if(!m_file.isOpen())
+// return *this;
+
+// auto date =
+// QDateTime::currentDateTime().toString("yyyy.MM.dd_hh.mm.ss.zzz");
+
+// auto m = date + ": " + msg;
+
+// m_fileStream << m << Qt::endl << Qt::flush;
+// beginInsertRows(QModelIndex(), m_messages.count(), m_messages.count());
+// m_messages << m;
+// endInsertRows();
+
+// auto delta = m_messages.count() - get_maxLinesCount();
+
+// if(get_maxLinesCount() > 0 && delta > 0)
+// {
+// beginRemoveRows(QModelIndex(), 0, delta - 1);
+// m_messages.erase(m_messages.begin(),
+// m_messages.begin() + delta);
+// endRemoveRows();
+// }
+
+// return *this;
+//}
+
+// void LogWorker::writeMessage(QString msg)
+//{
+// (*this) << msg;
+// }
+
+void LogWorker::writeMessage(
+ QtMsgType type,
+ const QMessageLogContext& context,
+ const QString& msg
+)
+{
+ QMutexLocker l(&m_mtx);
+
+ // extract filename from filepath (not tested on windows \\\\\\\ )
+ const char* file = context.file ? FILENAME(context.file) : "";
+ // convert QtSomethingMsg to Something
+ // auto typeName =
+ // QString::fromStdString(std::string(magic_enum::enum_name(type)))
+ // .replace("Qt", "").replace("Msg", "");
+ auto typeName = qtMsgTypes[type];
+ auto newLineOrSpace = msg.contains("\n") ? "\n" : " ";
+
+ if (!m_file.isOpen())
+ return;
+
+ // auto date =
+ // QDateTime::currentDateTime().toString("yyyy.MM.dd_hh.mm.ss.zzz");
+ auto dt = QDateTime::currentDateTime();
+
+ auto m = QString("%1:%2: %3: %4%5")
+ .arg(file)
+ .arg(context.line)
+ .arg(typeName)
+ .arg(newLineOrSpace)
+ .arg(msg);
+
+ auto full_m = dt.toString(Qt::ISODateWithMs) + ": " + m;
+
+ m_fileStream << full_m << Qt::endl << Qt::flush;
+
+ beginInsertRows(QModelIndex(), m_messages.count(), m_messages.count());
+ m_messages << LogMsg(dt, LogMsg::MessageType(type), msg);
+ endInsertRows();
+
+ auto delta = m_messages.count() - get_maxLinesCount();
+
+ if (get_maxLinesCount() > 0 && delta > 0)
+ {
+ beginRemoveRows(QModelIndex(), 0, delta - 1);
+ m_messages.erase(m_messages.begin(), m_messages.begin() + delta);
+ endRemoveRows();
+ }
+
+ // writeMessage(QString("%1:%2: %3:%4%5")
+ // .arg(file)
+ // .arg(context.line)
+ // .arg(typeName)
+ // .arg(newLineOrSpace)
+ // .arg(msg));
+}
+
+int LogWorker::rowCount(const QModelIndex& parent) const
+{
+ Q_UNUSED(parent)
+
+ return m_messages.count();
+}
+
+QVariant LogWorker::data(const QModelIndex& index, int role) const
+{
+ if (!index.isValid())
+ return QVariant();
+
+ // std::cout << Q_FUNC_INFO << std::endl;
+ if (role >= Qt::UserRole)
+ {
+ auto m = m_messages.at(index.row());
+
+ switch (role)
+ {
+ case Date:
+ return m.get_dateTime().toUTC();
+ break;
+ case MsgType:
+ return m.get_messageType();
+ break;
+ case Msg:
+ return m.get_message();
+ break;
+ default:
+ break;
+ }
+ return m_messages.at(index.row()).get_message();
+ }
+
+ return QVariant();
+}
+
+LogWorker::LogWorker(const LogWorker& other)
+{
+ Q_ASSERT_X(false, Q_FUNC_INFO, "don't call me");
+}
+} // namespace goodies