File indexing completed on 2024-05-12 05:12:46

0001 /*
0002     SPDX-FileCopyrightText: 2018 Daniel Vrátil <dvratil@kde.org>
0003 
0004     SPDX-License-Identifier: LGPL-2.0-or-later
0005 */
0006 
0007 #include "loggingmodel.h"
0008 
0009 #include <KLocalizedString>
0010 
0011 #include <QDateTime>
0012 #include <QDir>
0013 #include <QStandardItemModel>
0014 
0015 Q_DECLARE_METATYPE(LoggingModel::Message)
0016 
0017 LoggingModel::LoggingModel(QObject *parent)
0018     : QAbstractItemModel(parent)
0019 {
0020 }
0021 
0022 LoggingModel::~LoggingModel() = default;
0023 
0024 QString LoggingModel::cacheString(const QString &str, QSet<QString> &cache, QStandardItemModel *model)
0025 {
0026     auto it = cache.constFind(str);
0027     if (it == cache.constEnd()) {
0028         if (model) {
0029             auto item = new QStandardItem(str);
0030             item->setCheckState(Qt::Checked);
0031             model->appendRow(item);
0032         }
0033         cache.insert(str);
0034         return str;
0035     }
0036     return *it;
0037 }
0038 
0039 void LoggingModel::addMessage(qint64 timestamp,
0040                               const QString &app,
0041                               qint64 pid,
0042                               QtMsgType type,
0043                               const QString &category,
0044                               const QString &file,
0045                               const QString &function,
0046                               int line,
0047                               const QString &message)
0048 {
0049     beginInsertRows({}, mMessages.count(), mMessages.count());
0050     mMessages.push_back({timestamp,
0051                          cacheString(app, mAppCache, mAppFilterModel),
0052                          pid,
0053                          cacheString(category, mCategoryCache, mCategoryFilterModel),
0054                          cacheString(file, mFileCache),
0055                          cacheString(function, mFunctionCache),
0056                          message,
0057                          type,
0058                          line});
0059     endInsertRows();
0060 }
0061 
0062 void LoggingModel::setAppFilterModel(QStandardItemModel *appFilterModel)
0063 {
0064     mAppFilterModel = appFilterModel;
0065 }
0066 
0067 void LoggingModel::setCategoryFilterModel(QStandardItemModel *categoryFilterModel)
0068 {
0069     mCategoryFilterModel = categoryFilterModel;
0070 }
0071 
0072 int LoggingModel::rowCount(const QModelIndex &parent) const
0073 {
0074     return parent.isValid() ? 0 : mMessages.count();
0075 }
0076 
0077 int LoggingModel::columnCount(const QModelIndex &) const
0078 {
0079     return _ColumnCount;
0080 }
0081 
0082 QModelIndex LoggingModel::index(int row, int column, const QModelIndex &parent) const
0083 {
0084     if (parent.isValid() || row < 0 || row >= mMessages.count() || column < 0 || column >= _ColumnCount) {
0085         return {};
0086     }
0087 
0088     return createIndex(row, column);
0089 }
0090 
0091 QModelIndex LoggingModel::parent(const QModelIndex &) const
0092 {
0093     return {};
0094 }
0095 
0096 QVariant LoggingModel::headerData(int section, Qt::Orientation orientation, int role) const
0097 {
0098     if (orientation != Qt::Horizontal || role != Qt::DisplayRole) {
0099         return {};
0100     }
0101 
0102     switch (section) {
0103     case TimeColumn:
0104         return i18n("Time");
0105     case AppColumn:
0106         return i18n("Program");
0107     case TypeColumn:
0108         return i18n("Type");
0109     case CategoryColumn:
0110         return i18n("Category");
0111     case FileColumn:
0112         return i18n("File");
0113     case FunctionColumn:
0114         return i18n("Function");
0115     case MessageColumn:
0116         return i18n("Message");
0117     }
0118     return {};
0119 }
0120 
0121 QVariant LoggingModel::data(const QModelIndex &index, int role) const
0122 {
0123     if (!index.isValid() || index.row() >= mMessages.count() || index.column() >= _ColumnCount) {
0124         return {};
0125     }
0126 
0127     const auto message = mMessages.at(index.row());
0128     if (role == Qt::DisplayRole) {
0129         switch (index.column()) {
0130         case TimeColumn:
0131             return QDateTime::fromMSecsSinceEpoch(message.timestamp).toString(Qt::ISODateWithMs);
0132         case AppColumn:
0133             return QStringLiteral("%1(%2)").arg(message.app, QString::number(message.pid));
0134         case TypeColumn:
0135             switch (message.type) {
0136             case QtDebugMsg:
0137                 return i18n("Debug");
0138             case QtInfoMsg:
0139                 return i18n("Info");
0140             case QtWarningMsg:
0141                 return i18n("Warning");
0142             case QtCriticalMsg:
0143                 return i18n("Critical");
0144             case QtFatalMsg:
0145                 return i18n("Fatal");
0146             }
0147             return {};
0148         case CategoryColumn:
0149             return message.category;
0150         case FileColumn:
0151             if (!message.file.isEmpty()) {
0152                 const auto file = message.file.mid(message.file.lastIndexOf(QDir::separator()) + 1, -1);
0153                 if (message.line > 0) {
0154                     return i18n("%1:%2", file, QString::number(message.line));
0155                 } else {
0156                     return file;
0157                 }
0158             }
0159             return {};
0160         case FunctionColumn:
0161             return message.function;
0162         case MessageColumn:
0163             return message.message;
0164         }
0165     } else if (role == Qt::ToolTipRole) {
0166         switch (index.column()) {
0167         case FileColumn:
0168             if (!message.file.isEmpty()) {
0169                 if (message.line > 0) {
0170                     return i18n("%1:%2", message.file, QString::number(message.line));
0171                 } else {
0172                     return message.file;
0173                 }
0174             }
0175             return {};
0176         case FunctionColumn:
0177             return message.function;
0178         case MessageColumn:
0179             return message.message;
0180         }
0181     } else if (role == MessageRole) {
0182         return QVariant::fromValue(message);
0183     }
0184 
0185     return {};
0186 }
0187 
0188 #include "moc_loggingmodel.cpp"