File indexing completed on 2024-05-19 05:13:16

0001 /*
0002     SPDX-FileCopyrightText: 2018 Sandro Knauß <sknauss@kde.org>
0003 
0004     SPDX-License-Identifier: LGPL-2.0-or-later
0005 */
0006 
0007 #include "debugmodel.h"
0008 
0009 #include <KLocalizedString>
0010 
0011 #include <QColor>
0012 #include <QStandardItemModel>
0013 
0014 #ifndef COMPILE_WITH_UNITY_CMAKE_SUPPORT
0015 Q_DECLARE_METATYPE(DebugModel::Message)
0016 #endif
0017 
0018 DebugModel::DebugModel(QObject *parent)
0019     : QAbstractItemModel(parent)
0020 {
0021 }
0022 
0023 DebugModel::~DebugModel() = default;
0024 
0025 QString DebugModel::displaySender(const QString &identifer) const
0026 {
0027     if (mSenderCache[identifer].isEmpty()) {
0028         return identifer;
0029     } else {
0030         return QString(mSenderCache[identifer] + QStringLiteral(" (") + identifer + QStringLiteral(")"));
0031     }
0032 }
0033 
0034 QString DebugModel::cacheString(const QString &str, QMap<QString, QString> &cache, QStandardItemModel *model)
0035 {
0036     auto pos = str.lastIndexOf(QLatin1Char('('));
0037     auto identifier = str;
0038     QString name;
0039     if (pos != -1) {
0040         identifier = str.mid(pos + 1, str.size() - pos - 2);
0041         name = str.mid(0, pos - 1);
0042     }
0043     if (!cache.contains(identifier)) {
0044         cache.insert(identifier, name);
0045         if (model) {
0046             auto item = new QStandardItem(displaySender(identifier));
0047             item->setData(identifier, IdentifierRole);
0048             item->setCheckState(Qt::Checked);
0049             model->appendRow(item);
0050         }
0051         return identifier;
0052     } else if (cache[identifier].isEmpty()) {
0053         cache[identifier] = name;
0054         const auto item = model->findItems(identifier).constFirst();
0055         item->setData(displaySender(identifier), Qt::DisplayRole);
0056     }
0057     return identifier;
0058 }
0059 
0060 void DebugModel::addMessage(const QString &sender, DebugModel::Direction direction, const QString &message)
0061 {
0062     beginInsertRows({}, mMessages.count(), mMessages.count());
0063     mMessages.push_back({cacheString(sender, mSenderCache, mSenderFilterModel), direction, message});
0064     endInsertRows();
0065 }
0066 
0067 bool DebugModel::removeRows(int row, int count, const QModelIndex &parent)
0068 {
0069     if (parent.isValid()) {
0070         return false;
0071     }
0072 
0073     beginRemoveRows(parent, row, row + count - 1);
0074     mMessages.remove(row, count);
0075 
0076     QList<QString> toDelete;
0077 
0078     // find elements that needs to be deleted.
0079     for (const auto &identifer : mSenderCache.keys()) {
0080         bool found = false;
0081         for (const auto &msg : std::as_const(mMessages)) {
0082             if (msg.sender == identifer) {
0083                 found = true;
0084                 break;
0085             }
0086         }
0087         if (!found) {
0088             toDelete.push_back(identifer);
0089         }
0090     }
0091 
0092     // Update senderCache and senderFilterModel
0093     for (const auto &i : toDelete) {
0094         const auto &item = mSenderFilterModel->findItems(displaySender(i));
0095         if (!item.isEmpty()) {
0096             const auto &index = item.first()->index();
0097             mSenderFilterModel->removeRows(index.row(), 1);
0098         }
0099         mSenderCache.remove(i);
0100     }
0101     endRemoveRows();
0102     return true;
0103 }
0104 
0105 void DebugModel::setSenderFilterModel(QStandardItemModel *senderFilterModel)
0106 {
0107     mSenderFilterModel = senderFilterModel;
0108 }
0109 
0110 int DebugModel::rowCount(const QModelIndex &parent) const
0111 {
0112     return parent.isValid() ? 0 : mMessages.count();
0113 }
0114 
0115 int DebugModel::columnCount(const QModelIndex &) const
0116 {
0117     return _ColumnCount;
0118 }
0119 
0120 QModelIndex DebugModel::index(int row, int column, const QModelIndex &parent) const
0121 {
0122     if (parent.isValid() || row < 0 || row >= mMessages.count() || column < 0 || column >= _ColumnCount) {
0123         return {};
0124     }
0125 
0126     return createIndex(row, column);
0127 }
0128 
0129 QModelIndex DebugModel::parent(const QModelIndex &) const
0130 {
0131     return {};
0132 }
0133 
0134 QVariant DebugModel::headerData(int section, Qt::Orientation orientation, int role) const
0135 {
0136     if (orientation != Qt::Horizontal || role != Qt::DisplayRole) {
0137         return {};
0138     }
0139 
0140     switch (section) {
0141     case SenderColumn:
0142         return i18n("Sender");
0143     case DirectionColumn:
0144         return i18n("Direction");
0145     case MessageColumn:
0146         return i18n("Message");
0147     }
0148     return {};
0149 }
0150 
0151 QVariant DebugModel::data(const QModelIndex &index, int role) const
0152 {
0153     if (!index.isValid() || index.row() >= mMessages.count() || index.column() >= _ColumnCount) {
0154         return {};
0155     }
0156 
0157     const auto message = mMessages.at(index.row());
0158     if (role == Qt::DisplayRole) {
0159         switch (index.column()) {
0160         case SenderColumn:
0161             return displaySender(message.sender);
0162         case DirectionColumn:
0163             switch (message.direction) {
0164             case ClientToServer:
0165                 return QStringLiteral("<-");
0166             case ServerToClient:
0167                 return QStringLiteral("->");
0168             }
0169             return {};
0170         case MessageColumn:
0171             return message.message;
0172         }
0173     } else if (role == Qt::ToolTipRole) {
0174         switch (index.column()) {
0175         case MessageColumn:
0176             return message.message;
0177         }
0178     } else if (role == Qt::ForegroundRole && index.column() != MessageColumn) {
0179         if (message.direction == ClientToServer) {
0180             return QColor(Qt::red);
0181         } else {
0182             return QColor(Qt::green);
0183         }
0184     } else if (role == MessageRole) {
0185         return QVariant::fromValue(message);
0186     } else if (role == IdentifierRole) {
0187         return message.sender;
0188     }
0189 
0190     return {};
0191 }
0192 
0193 #include "moc_debugmodel.cpp"