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

0001 /*
0002     SPDX-FileCopyrightText: 2009 Volker Krause <vkrause@kde.org>
0003 
0004     SPDX-License-Identifier: GPL-2.0-or-later
0005 */
0006 
0007 #include "notificationmodel.h"
0008 
0009 #include "akonadiconsole_debug.h"
0010 #include <Akonadi/ServerManager>
0011 
0012 #include <KLocalizedString>
0013 
0014 #include <QMetaMethod>
0015 #include <akonadi/private/imapparser_p.h>
0016 #include <akonadi/private/protocol_p.h>
0017 
0018 Q_DECLARE_METATYPE(Akonadi::ChangeNotification)
0019 
0020 using namespace Akonadi;
0021 
0022 NotificationModel::NotificationModel(QObject *parent)
0023     : QAbstractItemModel(parent)
0024 {
0025 }
0026 
0027 NotificationModel::~NotificationModel()
0028 {
0029     setEnabled(false);
0030 }
0031 
0032 int NotificationModel::columnCount(const QModelIndex &parent) const
0033 {
0034     Q_UNUSED(parent)
0035     return _ColumnCount;
0036 }
0037 
0038 int NotificationModel::rowCount(const QModelIndex &parent) const
0039 {
0040     return parent.isValid() ? 0 : m_data.count();
0041 }
0042 
0043 QModelIndex NotificationModel::index(int row, int column, const QModelIndex &parent) const
0044 {
0045     if (row < 0 || row >= m_data.count() || column < 0 || column > 9 || parent.isValid()) {
0046         return {};
0047     }
0048 
0049     return createIndex(row, column);
0050 }
0051 
0052 QModelIndex NotificationModel::parent(const QModelIndex &child) const
0053 {
0054     Q_UNUSED(child)
0055     return {};
0056 }
0057 
0058 QVariant NotificationModel::data(const QModelIndex &index, int role) const
0059 {
0060     if (!index.isValid()) {
0061         return {};
0062     }
0063 
0064     if (role == Qt::DisplayRole || role == Qt::ToolTipRole) {
0065         const auto msg = m_data.at(index.row());
0066         switch (index.column()) {
0067         case DateColumn:
0068             return msg.timestamp().toString(Qt::ISODateWithMs);
0069         case TypeColumn:
0070             switch (msg.type()) {
0071             case ChangeNotification::Items:
0072                 return i18n("Items");
0073             case ChangeNotification::Collection:
0074                 return i18n("Collection");
0075             case ChangeNotification::Tag:
0076                 return i18n("Tag");
0077             case ChangeNotification::Relation:
0078                 return i18n("Relation");
0079             case ChangeNotification::Subscription:
0080                 return i18n("Subscription");
0081             }
0082             return QStringLiteral("Unknown");
0083         case OperationColumn:
0084             switch (msg.type()) {
0085             case ChangeNotification::Items:
0086                 switch (Protocol::cmdCast<Protocol::ItemChangeNotification>(msg.notification()).operation()) {
0087                 case Protocol::ItemChangeNotification::Add:
0088                     return i18n("Add");
0089                 case Protocol::ItemChangeNotification::Modify:
0090                     return i18n("Modify");
0091                 case Protocol::ItemChangeNotification::Move:
0092                     return i18n("Move");
0093                 case Protocol::ItemChangeNotification::Remove:
0094                     return i18n("Remove");
0095                 case Protocol::ItemChangeNotification::Link:
0096                     return i18n("Link");
0097                 case Protocol::ItemChangeNotification::Unlink:
0098                     return i18n("Unlink");
0099                 case Protocol::ItemChangeNotification::ModifyFlags:
0100                     return i18n("ModifyFlags");
0101                 case Protocol::ItemChangeNotification::ModifyTags:
0102                     return i18n("ModifyTags");
0103                 case Protocol::ItemChangeNotification::ModifyRelations:
0104                     return i18n("ModifyRelations");
0105                 case Protocol::ItemChangeNotification::InvalidOp:
0106                     return i18n("InvalidOp");
0107                 }
0108                 return {};
0109             case ChangeNotification::Collection:
0110                 switch (Protocol::cmdCast<Protocol::CollectionChangeNotification>(msg.notification()).operation()) {
0111                 case Protocol::CollectionChangeNotification::Add:
0112                     return i18n("Add");
0113                 case Protocol::CollectionChangeNotification::Modify:
0114                     return i18n("Modify");
0115                 case Protocol::CollectionChangeNotification::Move:
0116                     return i18n("Move");
0117                 case Protocol::CollectionChangeNotification::Remove:
0118                     return i18n("Remove");
0119                 case Protocol::CollectionChangeNotification::Subscribe:
0120                     return i18n("Subscribe");
0121                 case Protocol::CollectionChangeNotification::Unsubscribe:
0122                     return i18n("Unsubscribe");
0123                 case Protocol::CollectionChangeNotification::InvalidOp:
0124                     return i18n("InvalidIp");
0125                 }
0126                 return {};
0127             case ChangeNotification::Tag:
0128                 switch (Protocol::cmdCast<Protocol::TagChangeNotification>(msg.notification()).operation()) {
0129                 case Protocol::TagChangeNotification::Add:
0130                     return i18n("Add");
0131                 case Protocol::TagChangeNotification::Modify:
0132                     return i18n("Modify");
0133                 case Protocol::TagChangeNotification::Remove:
0134                     return i18n("Remove");
0135                 case Protocol::TagChangeNotification::InvalidOp:
0136                     return i18n("InvalidOp");
0137                 }
0138                 return {};
0139             case ChangeNotification::Relation:
0140                 switch (Protocol::cmdCast<Protocol::RelationChangeNotification>(msg.notification()).operation()) {
0141                 case Protocol::RelationChangeNotification::Add:
0142                     return i18n("Add");
0143                 case Protocol::RelationChangeNotification::Remove:
0144                     return i18n("Remove");
0145                 case Protocol::RelationChangeNotification::InvalidOp:
0146                     return i18n("InvalidOp");
0147                 }
0148                 return {};
0149             case ChangeNotification::Subscription:
0150                 switch (Protocol::cmdCast<Protocol::SubscriptionChangeNotification>(msg.notification()).operation()) {
0151                 case Akonadi::Protocol::SubscriptionChangeNotification::Add:
0152                     return i18n("Add");
0153                 case Akonadi::Protocol::SubscriptionChangeNotification::Modify:
0154                     return i18n("Modify");
0155                 case Akonadi::Protocol::SubscriptionChangeNotification::Remove:
0156                     return i18n("Remove");
0157                 case Akonadi::Protocol::SubscriptionChangeNotification::InvalidOp:
0158                     return i18n("InvalidOp");
0159                 }
0160                 return {};
0161             default:
0162                 return i18n("Unknown");
0163             }
0164         case IdsColumn:
0165             switch (msg.type()) {
0166             case ChangeNotification::Items: {
0167                 QStringList rv;
0168                 const auto items = Protocol::cmdCast<Protocol::ItemChangeNotification>(msg.notification()).items();
0169                 for (const auto &item : items) {
0170                     rv.push_back(QString::number(item.id()));
0171                 }
0172                 return rv.join(QLatin1StringView(", "));
0173             }
0174             case ChangeNotification::Collection:
0175                 return Protocol::cmdCast<Protocol::CollectionChangeNotification>(msg.notification()).collection().id();
0176             case ChangeNotification::Tag:
0177                 return Protocol::cmdCast<Protocol::TagChangeNotification>(msg.notification()).tag().id();
0178             case ChangeNotification::Relation:
0179             case ChangeNotification::Subscription:
0180                 return {};
0181             }
0182             return {};
0183         case SessionColumn:
0184             return msg.notification()->sessionId();
0185         case ListenersColumn: {
0186             const auto listeners = msg.listeners();
0187             QStringList rv;
0188             for (const auto &l : listeners) {
0189                 rv.push_back(QString::fromUtf8(l));
0190             }
0191             return rv.join(QLatin1StringView(", "));
0192         }
0193         }
0194     } else if (role == NotificationRole) {
0195         return QVariant::fromValue(m_data.at(index.row()));
0196     }
0197 
0198     return {};
0199 }
0200 
0201 QVariant NotificationModel::headerData(int section, Qt::Orientation orientation, int role) const
0202 {
0203     if (role == Qt::DisplayRole && orientation == Qt::Horizontal) {
0204         switch (section) {
0205         case DateColumn:
0206             return i18n("Date");
0207         case TypeColumn:
0208             return i18n("Type");
0209         case OperationColumn:
0210             return i18n("Operation");
0211         case IdsColumn:
0212             return i18n("IDs");
0213         case SessionColumn:
0214             return i18n("Session");
0215         case ListenersColumn:
0216             return i18n("Listeners");
0217         }
0218     }
0219     return QAbstractItemModel::headerData(section, orientation, role);
0220 }
0221 
0222 void NotificationModel::slotNotify(const Akonadi::ChangeNotification &ntf)
0223 {
0224     beginInsertRows(QModelIndex(), m_data.size(), m_data.size());
0225     m_data.append(ntf);
0226     endInsertRows();
0227 }
0228 
0229 void NotificationModel::clear()
0230 {
0231     beginResetModel();
0232     m_data.clear();
0233     endResetModel();
0234 }
0235 
0236 void NotificationModel::setEnabled(bool enable)
0237 {
0238     if (enable) {
0239         m_monitor = new Akonadi::Monitor(this);
0240         m_monitor->setObjectName(QLatin1StringView("notificationMonitor"));
0241         m_monitor->setTypeMonitored(Akonadi::Monitor::Notifications);
0242         connect(m_monitor, &Akonadi::Monitor::debugNotification, this, &NotificationModel::slotNotify);
0243     } else if (m_monitor) {
0244         m_monitor->deleteLater();
0245         m_monitor = nullptr;
0246     }
0247 }
0248 
0249 #include "moc_notificationmodel.cpp"