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"