diff --git a/src/notificationmodel.cpp b/src/notificationmodel.cpp index f73a5c2..c28de84 100644 --- a/src/notificationmodel.cpp +++ b/src/notificationmodel.cpp @@ -1,258 +1,258 @@ /* Copyright (c) 2009 Volker Krause This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ #include "notificationmodel.h" #include #include "akonadiconsole_debug.h" #include #include #include #include Q_DECLARE_METATYPE(Akonadi::ChangeNotification) using namespace Akonadi; NotificationModel::NotificationModel(QObject *parent) : QAbstractItemModel(parent), m_monitor(nullptr) { } NotificationModel::~NotificationModel() { setEnabled(false); } int NotificationModel::columnCount(const QModelIndex &parent) const { Q_UNUSED(parent); return _ColumnCount; } int NotificationModel::rowCount(const QModelIndex &parent) const { return parent.isValid() ? 0 : m_data.count(); } QModelIndex NotificationModel::index(int row, int column, const QModelIndex &parent) const { if (row < 0 || row >= m_data.count() || column < 0 || column > 9 || parent.isValid()) { return {}; } return createIndex(row, column); } QModelIndex NotificationModel::parent(const QModelIndex &child) const { Q_UNUSED(child); return {}; } QVariant NotificationModel::data(const QModelIndex &index, int role) const { if (!index.isValid()) { return QVariant(); } if (role == Qt::DisplayRole || role == Qt::ToolTipRole) { const auto msg = m_data.at(index.row()); switch (index.column()) { case DateColumn: - return msg.timestamp(); + return msg.timestamp().toString(Qt::ISODateWithMs); case TypeColumn: switch (msg.type()) { case ChangeNotification::Items: return QStringLiteral("Items"); case ChangeNotification::Collection: return QStringLiteral("Collection"); case ChangeNotification::Tag: return QStringLiteral("Tag"); case ChangeNotification::Relation: return QStringLiteral("Relation"); case ChangeNotification::Subscription: return QStringLiteral("Subscription"); } return QStringLiteral("Unknown"); case OperationColumn: switch (msg.type()) { case ChangeNotification::Items: switch (Protocol::cmdCast(msg.notification()).operation()) { case Protocol::ItemChangeNotification::Add: return QStringLiteral("Add"); case Protocol::ItemChangeNotification::Modify: return QStringLiteral("Modify"); case Protocol::ItemChangeNotification::Move: return QStringLiteral("Move"); case Protocol::ItemChangeNotification::Remove: return QStringLiteral("Remove"); case Protocol::ItemChangeNotification::Link: return QStringLiteral("Link"); case Protocol::ItemChangeNotification::Unlink: return QStringLiteral("Unlink"); case Protocol::ItemChangeNotification::ModifyFlags: return QStringLiteral("ModifyFlags"); case Protocol::ItemChangeNotification::ModifyTags: return QStringLiteral("ModifyTags"); case Protocol::ItemChangeNotification::ModifyRelations: return QStringLiteral("ModifyRelations"); case Protocol::ItemChangeNotification::InvalidOp: return QStringLiteral("InvalidOp"); } return {}; case ChangeNotification::Collection: switch (Protocol::cmdCast(msg.notification()).operation()) { case Protocol::CollectionChangeNotification::Add: return QStringLiteral("Add"); case Protocol::CollectionChangeNotification::Modify: return QStringLiteral("Modify"); case Protocol::CollectionChangeNotification::Move: return QStringLiteral("Move"); case Protocol::CollectionChangeNotification::Remove: return QStringLiteral("Remove"); case Protocol::CollectionChangeNotification::Subscribe: return QStringLiteral("Subscribe"); case Protocol::CollectionChangeNotification::Unsubscribe: return QStringLiteral("Unsubscribe"); case Protocol::CollectionChangeNotification::InvalidOp: return QStringLiteral("InvalidIp"); } return {}; case ChangeNotification::Tag: switch (Protocol::cmdCast(msg.notification()).operation()) { case Protocol::TagChangeNotification::Add: return QStringLiteral("Add"); case Protocol::TagChangeNotification::Modify: return QStringLiteral("Modify"); case Protocol::TagChangeNotification::Remove: return QStringLiteral("Remove"); case Protocol::TagChangeNotification::InvalidOp: return QStringLiteral("InvalidOp"); } return {}; case ChangeNotification::Relation: switch (Protocol::cmdCast(msg.notification()).operation()) { case Protocol::RelationChangeNotification::Add: return QStringLiteral("Add"); case Protocol::RelationChangeNotification::Remove: return QStringLiteral("Remove"); case Protocol::RelationChangeNotification::InvalidOp: return QStringLiteral("InvalidOp"); } return {}; case ChangeNotification::Subscription: switch (Protocol::cmdCast(msg.notification()).operation()) { case Akonadi::Protocol::SubscriptionChangeNotification::Add: return QStringLiteral("Add"); case Akonadi::Protocol::SubscriptionChangeNotification::Modify: return QStringLiteral("Modify"); case Akonadi::Protocol::SubscriptionChangeNotification::Remove: return QStringLiteral("Remove"); case Akonadi::Protocol::SubscriptionChangeNotification::InvalidOp: return QStringLiteral("InvalidOp"); } return {}; default: return QStringLiteral("Unknown"); } case IdsColumn: switch (msg.type()) { case ChangeNotification::Items: { QStringList rv; const auto items = Protocol::cmdCast(msg.notification()).items(); for (const auto &item : items) { rv.push_back(QString::number(item.id())); } return rv.join(QStringLiteral(", ")); } case ChangeNotification::Collection: return Protocol::cmdCast(msg.notification()).collection().id(); case ChangeNotification::Tag: return Protocol::cmdCast(msg.notification()).tag().id(); case ChangeNotification::Relation: case ChangeNotification::Subscription: return {}; } return {}; case SessionColumn: return msg.notification()->sessionId(); case ListenersColumn: { const auto listeners = msg.listeners(); QStringList rv; for (const auto &l : listeners) { rv.push_back(QString::fromUtf8(l)); } return rv.join(QStringLiteral(", ")); } } } else if (role == NotificationRole) { return QVariant::fromValue(m_data.at(index.row())); } return QVariant(); } QVariant NotificationModel::headerData(int section, Qt::Orientation orientation, int role) const { if (role == Qt::DisplayRole && orientation == Qt::Horizontal) { switch (section) { case DateColumn: return QStringLiteral("Date"); case TypeColumn: return QStringLiteral("Type"); case OperationColumn: return QStringLiteral("Operation"); case IdsColumn: return QStringLiteral("IDs"); case SessionColumn: return QStringLiteral("Session"); case ListenersColumn: return QStringLiteral("Listeners"); } } return QAbstractItemModel::headerData(section, orientation, role); } void NotificationModel::slotNotify(const Akonadi::ChangeNotification &ntf) { beginInsertRows(QModelIndex(), m_data.size(), m_data.size()); m_data.append(ntf); endInsertRows(); } void NotificationModel::clear() { beginResetModel(); m_data.clear(); endResetModel(); } void NotificationModel::setEnabled(bool enable) { if (enable) { m_monitor = new Akonadi::Monitor(this); m_monitor->setObjectName(QStringLiteral("notificationMonitor")); m_monitor->setTypeMonitored(Akonadi::Monitor::Notifications); connect(m_monitor, &Akonadi::Monitor::debugNotification, this, &NotificationModel::slotNotify); } else if (m_monitor) { m_monitor->deleteLater(); m_monitor = nullptr; } } diff --git a/src/notificationmonitor.cpp b/src/notificationmonitor.cpp index f0742dd..ef66988 100644 --- a/src/notificationmonitor.cpp +++ b/src/notificationmonitor.cpp @@ -1,589 +1,589 @@ /* Copyright (c) 2009 Volker Krause This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ #include "notificationmonitor.h" #include "notificationmodel.h" #include "utils.h" #include #include #include #include #include #include #include #include #include #include #include #include #include Q_DECLARE_METATYPE(Akonadi::ChangeNotification) NotificationMonitor::NotificationMonitor(QWidget *parent) : QWidget(parent) { m_model = new NotificationModel(this); m_model->setEnabled(false); // since it can be slow, default to off QVBoxLayout *layout = new QVBoxLayout(this); QCheckBox *enableCB = new QCheckBox(this); enableCB->setText(QStringLiteral("Enable notification monitor")); enableCB->setChecked(m_model->isEnabled()); connect(enableCB, &QCheckBox::toggled, m_model, &NotificationModel::setEnabled); layout->addWidget(enableCB); m_splitter = new QSplitter(this); layout->addWidget(m_splitter); m_treeView = new QTreeView(this); m_treeView->setModel(m_model); m_treeView->expandAll(); m_treeView->setAlternatingRowColors(true); m_treeView->setContextMenuPolicy(Qt::CustomContextMenu); m_treeView->header()->setSectionResizeMode(QHeaderView::ResizeToContents); connect(m_treeView, &QTreeView::customContextMenuRequested, this, &NotificationMonitor::contextMenu); connect(m_treeView->selectionModel(), &QItemSelectionModel::currentChanged, this, &NotificationMonitor::onNotificationSelected); m_splitter->addWidget(m_treeView); m_ntfView = new QTreeView(this); m_ntfView->setModel(new QStandardItemModel(this)); m_ntfView->setEditTriggers(QAbstractItemView::NoEditTriggers); m_splitter->addWidget(m_ntfView); onNotificationSelected({}); KConfigGroup config(KSharedConfig::openConfig(), "NotificationMonitor"); m_treeView->header()->restoreState(config.readEntry("tv", QByteArray())); m_ntfView->header()->restoreState(config.readEntry("ntfView", QByteArray())); m_splitter->restoreState(config.readEntry("splitter", QByteArray())); Akonadi::ControlGui::widgetNeedsAkonadi(this); } NotificationMonitor::~NotificationMonitor() { KConfigGroup config(KSharedConfig::openConfig(), "NotificationMonitor"); config.writeEntry("tv", m_treeView->header()->saveState()); config.writeEntry("ntfView", m_ntfView->header()->saveState()); config.writeEntry("splitter", m_splitter->saveState()); } void NotificationMonitor::contextMenu(const QPoint & /*pos*/) { QMenu menu; menu.addAction(QStringLiteral("Clear View"), m_model, &NotificationModel::clear); menu.exec(QCursor::pos()); } void NotificationMonitor::onNotificationSelected(const QModelIndex &index) { auto model = qobject_cast(m_ntfView->model()); const auto state = m_ntfView->header()->saveState(); model->clear(); model->setHorizontalHeaderLabels({ QStringLiteral("Properties"), QStringLiteral("Values") }); m_ntfView->header()->restoreState(state); const auto ntf = index.data(NotificationModel::NotificationRole).value(); if (!ntf.isValid()) { return; } - appendRow(model, QStringLiteral("Timestamp"), ntf.timestamp().toString(Qt::ISODate)); + appendRow(model, QStringLiteral("Timestamp"), ntf.timestamp().toString(Qt::ISODateWithMs)); appendRow(model, QStringLiteral("Type"), index.sibling(index.row(), NotificationModel::TypeColumn).data().toString()); appendRow(model, QStringLiteral("Listeners"), index.sibling(index.row(), NotificationModel::ListenersColumn).data().toString()); switch (ntf.type()) { case Akonadi::ChangeNotification::Items: populateItemNtfTree(model, Akonadi::Protocol::cmdCast(ntf.notification())); break; case Akonadi::ChangeNotification::Collection: populateCollectionNtfTree(model, Akonadi::Protocol::cmdCast(ntf.notification())); break; case Akonadi::ChangeNotification::Tag: populateTagNtfTree(model, Akonadi::Protocol::cmdCast(ntf.notification())); break; case Akonadi::ChangeNotification::Relation: populateRelationNtfTree(model, Akonadi::Protocol::cmdCast(ntf.notification())); break; case Akonadi::ChangeNotification::Subscription: populateSubscriptionNtfTree(model, Akonadi::Protocol::cmdCast(ntf.notification())); break; } m_ntfView->expandAll(); } void NotificationMonitor::populateItemNtfTree(QStandardItemModel *model, const Akonadi::Protocol::ItemChangeNotification &ntf) { QString operation; switch (ntf.operation()) { case Akonadi::Protocol::ItemChangeNotification::Add: operation = QStringLiteral("Add"); break; case Akonadi::Protocol::ItemChangeNotification::Modify: operation = QStringLiteral("Modify"); break; case Akonadi::Protocol::ItemChangeNotification::Move: operation = QStringLiteral("Move"); break; case Akonadi::Protocol::ItemChangeNotification::Remove: operation = QStringLiteral("Remove"); break; case Akonadi::Protocol::ItemChangeNotification::Link: operation = QStringLiteral("Link"); break; case Akonadi::Protocol::ItemChangeNotification::Unlink: operation = QStringLiteral("Unlink"); break; case Akonadi::Protocol::ItemChangeNotification::ModifyFlags: operation = QStringLiteral("ModifyFlags"); break; case Akonadi::Protocol::ItemChangeNotification::ModifyTags: operation = QStringLiteral("ModifyTags"); break; case Akonadi::Protocol::ItemChangeNotification::ModifyRelations: operation = QStringLiteral("ModifyRelations"); break; case Akonadi::Protocol::ItemChangeNotification::InvalidOp: operation = QStringLiteral("InvalidOp"); break; } appendRow(model, QStringLiteral("Operation"), operation); appendRow(model, QStringLiteral("Resource"), QString::fromUtf8(ntf.resource())); appendRow(model, QStringLiteral("Parent Collection"), QString::number(ntf.parentCollection())); appendRow(model, QStringLiteral("Parent Dest Col"), QString::number(ntf.parentDestCollection())); appendRow(model, QStringLiteral("Destination Resource"), QString::fromUtf8(ntf.destinationResource())); appendRow(model, QStringLiteral("Item Parts"), toString(ntf.itemParts())); appendRow(model, QStringLiteral("Added Flags"), toString(ntf.addedFlags())); appendRow(model, QStringLiteral("Removed Flags"), toString(ntf.removedFlags())); appendRow(model, QStringLiteral("Added Tags"), toString(ntf.addedTags()));; appendRow(model, QStringLiteral("Removed Tags"), toString(ntf.removedTags())); auto relationsItem = new QStandardItem(QStringLiteral("Added Relations")); const auto addedRelations = ntf.addedRelations(); for (const auto &addedRelation : addedRelations) { auto item = new QStandardItem(QStringLiteral("%lld-%lld %s").arg( QString::number(addedRelation.leftId), QString::number(addedRelation.rightId), addedRelation.type)); relationsItem->appendRow(item); } model->appendRow(relationsItem); relationsItem = new QStandardItem(QStringLiteral("Removed Relations")); const auto removedRelations = ntf.removedRelations(); for (const auto &removedRelation : removedRelations) { auto item = new QStandardItem(QStringLiteral("%lld-%lld %s").arg( QString::number(removedRelation.leftId), QString::number(removedRelation.rightId), removedRelation.type)); relationsItem->appendRow(item); } model->appendRow(relationsItem); appendRow(model, QStringLiteral("Must retrieve"), toString(ntf.mustRetrieve())); auto itemsItem = new QStandardItem(QStringLiteral("Items")); const auto &items = ntf.items(); for (const auto &item : items) { auto i = new QStandardItem(QString::number(item.id())); populateItemTree(i, item); itemsItem->appendRow(i); } model->appendRow(itemsItem); } QStandardItem *NotificationMonitor::populateAncestorTree(QStandardItem *parent, const Akonadi::Protocol::Ancestor &ancestor) { appendRow(parent, QStringLiteral("id"), QString::number(ancestor.id())); appendRow(parent, QStringLiteral("remoteId"), ancestor.remoteId()); appendRow(parent, QStringLiteral("name"), ancestor.name()); populateAttributesTree(parent, ancestor.attributes()); auto ancestorItem = new QStandardItem(QStringLiteral("Ancestor")); parent->appendRow(ancestorItem); return ancestorItem; } void NotificationMonitor::populateTagTree(QStandardItem *parent, const Akonadi::Protocol::FetchTagsResponse &tag) { appendRow(parent, QStringLiteral("ID"), QString::number(tag.id())); appendRow(parent, QStringLiteral("Parent ID"), QString::number(tag.parentId())); appendRow(parent, QStringLiteral("GID"), QString::fromUtf8(tag.gid())); appendRow(parent, QStringLiteral("Type"), QString::fromUtf8(tag.type())); appendRow(parent, QStringLiteral("Remote ID"), QString::fromUtf8(tag.remoteId())); populateAttributesTree(parent, tag.attributes()); } void NotificationMonitor::populateAttributesTree(QStandardItem *parent, const Akonadi::Protocol::Attributes &attributes) { auto attributesItem = new QStandardItem(QStringLiteral("Attributes")); for (auto it = attributes.cbegin(), end = attributes.cend(); it != end; ++it) { appendRow(attributesItem, QString::fromUtf8(it.key()), QString::fromUtf8(it.value())); } parent->appendRow(attributesItem); } void NotificationMonitor::populateItemTree(QStandardItem *parent, const Akonadi::Protocol::FetchItemsResponse &item) { appendRow(parent, QStringLiteral("Revision"), QString::number(item.revision())); appendRow(parent, QStringLiteral("ParentID"), QString::number(item.parentId())); appendRow(parent, QStringLiteral("RemoteID"), item.remoteId()); appendRow(parent, QStringLiteral("RemoteRev"), item.remoteRevision()); appendRow(parent, QStringLiteral("GID"), item.gid()); appendRow(parent, QStringLiteral("Size"), QString::number(item.size())); appendRow(parent, QStringLiteral("MimeType"), item.mimeType()); appendRow(parent, QStringLiteral("MTime"), item.mTime().toString(Qt::ISODate)); appendRow(parent, QStringLiteral("Flags"), toString(item.flags())); auto tagItem = new QStandardItem(QStringLiteral("Tags")); const auto tags = item.tags(); for (const auto tag : tags) { auto item = new QStandardItem(QString::number(tag.id())); populateTagTree(item, tag); tagItem->appendRow(item); } parent->appendRow(tagItem); appendRow(parent, QStringLiteral("VRefs"), toString(item.virtualReferences())); auto relationItem = new QStandardItem(QStringLiteral("Relations")); const auto relations = item.relations(); for (const auto relation : relations) { auto item = new QStandardItem(QStringLiteral("%lld-%lld %s").arg(QString::number(relation.left()), QString::number(relation.right()), QString::fromUtf8(relation.type()))); relationItem->appendRow(item); } parent->appendRow(relationItem); const auto ancestors = item.ancestors(); auto i = new QStandardItem(QStringLiteral("Ancestor")); parent->appendRow(i); for (const auto &ancestor : ancestors) { i = populateAncestorTree(i, ancestor); } auto partsItem = new QStandardItem(QStringLiteral("Parts")); const auto parts = item.parts(); for (const auto &part : parts) { auto item = new QStandardItem(QString::fromUtf8(part.payloadName())); QString type; switch (part.metaData().storageType()) { case Akonadi::Protocol::PartMetaData::External: type = QStringLiteral("External"); break; case Akonadi::Protocol::PartMetaData::Internal: type = QStringLiteral("Internal"); break; case Akonadi::Protocol::PartMetaData::Foreign: type = QStringLiteral("Foreign"); break; } appendRow(item, QStringLiteral("Size"), QString::number(part.metaData().size())); appendRow(item, QStringLiteral("Storage Type"), type); appendRow(item, QStringLiteral("Version"), QString::number(part.metaData().version())); appendRow(item, QStringLiteral("Data"), QString::fromUtf8( part.data().toHex())); partsItem->appendRow(item); } parent->appendRow(partsItem); } void NotificationMonitor::populateCollectionTree(QStandardItem *parent, const Akonadi::Protocol::FetchCollectionsResponse &collection) { appendRow(parent, QStringLiteral("ID"), QString::number(collection.id())); appendRow(parent, QStringLiteral("Parent ID"), QString::number(collection.parentId())); appendRow(parent, QStringLiteral("Name"), collection.name()); appendRow(parent, QStringLiteral("Mime Types"), toString(static_cast>(collection.mimeTypes()))); appendRow(parent, QStringLiteral("Remote ID"), collection.remoteId()); appendRow(parent, QStringLiteral("Remote Revision"), collection.remoteRevision()); auto statsItem = new QStandardItem(QStringLiteral("Statistics")); const auto stats = collection.statistics(); appendRow(statsItem, QStringLiteral("Count"), QString::number(stats.count())); appendRow(statsItem, QStringLiteral("Unseen"), QString::number(stats.unseen())); appendRow(statsItem, QStringLiteral("Size"), QString::number(stats.size())); parent->appendRow(statsItem); appendRow(parent, QStringLiteral("Search Query"), collection.searchQuery()); appendRow(parent, QStringLiteral("Search Collections"), toString(collection.searchCollections())); auto i = new QStandardItem(QStringLiteral("Ancestor")); parent->appendRow(i); const auto ancestors = collection.ancestors(); for (const auto &ancestor : ancestors) { i = populateAncestorTree(i, ancestor); } auto cpItem = new QStandardItem(QStringLiteral("Cache Policy")); const auto cp = collection.cachePolicy(); appendRow(cpItem, QStringLiteral("Inherit"), toString(cp.inherit())); appendRow(cpItem, QStringLiteral("Check Interval"), QString::number(cp.checkInterval())); appendRow(cpItem, QStringLiteral("Cache Timeout"), QString::number(cp.cacheTimeout())); appendRow(cpItem, QStringLiteral("Sync on Demand"), toString(cp.syncOnDemand())); appendRow(cpItem, QStringLiteral("Local Parts"), toString(static_cast>(cp.localParts()))); parent->appendRow(cpItem); populateAttributesTree(parent, collection.attributes()); appendRow(parent, QStringLiteral("Enabled"), toString(collection.enabled())); appendRow(parent, QStringLiteral("DisplayPref"), toString(collection.displayPref())); appendRow(parent, QStringLiteral("SyncPref"), toString(collection.syncPref())); appendRow(parent, QStringLiteral("IndexPref"), toString(collection.indexPref())); appendRow(parent, QStringLiteral("Referenced"), toString(collection.referenced())); appendRow(parent, QStringLiteral("Virtual"), toString(collection.isVirtual())); } void NotificationMonitor::populateCollectionNtfTree(QStandardItemModel *model, const Akonadi::Protocol::CollectionChangeNotification &ntf) { QString operation; switch (ntf.operation()) { case Akonadi::Protocol::CollectionChangeNotification::Add: operation = QStringLiteral("Add"); break; case Akonadi::Protocol::CollectionChangeNotification::Modify: operation = QStringLiteral("Modify"); break; case Akonadi::Protocol::CollectionChangeNotification::Move: operation = QStringLiteral("Move"); break; case Akonadi::Protocol::CollectionChangeNotification::Remove: operation = QStringLiteral("Remove"); break; case Akonadi::Protocol::CollectionChangeNotification::Subscribe: operation = QStringLiteral("Subscribe"); break; case Akonadi::Protocol::CollectionChangeNotification::Unsubscribe: operation = QStringLiteral("Unsubscribe"); break; case Akonadi::Protocol::CollectionChangeNotification::InvalidOp: operation = QStringLiteral("InvalidIp"); break; } appendRow(model, QStringLiteral("Operation"), operation); appendRow(model, QStringLiteral("Resource"), QString::fromUtf8(ntf.resource())); appendRow(model, QStringLiteral("Parent Collection"), QString::number(ntf.parentCollection())); appendRow(model, QStringLiteral("Parent Dest Collection"), QString::number(ntf.parentDestCollection())); appendRow(model, QStringLiteral("Destination Resource"), QString::fromUtf8(ntf.destinationResource())); appendRow(model, QStringLiteral("Changed Parts"), toString(ntf.changedParts())); auto item = new QStandardItem(QStringLiteral("Collection")); populateCollectionTree(item, ntf.collection()); model->appendRow(item); } void NotificationMonitor::populateRelationNtfTree(QStandardItemModel *model, const Akonadi::Protocol::RelationChangeNotification &ntf) { QString operation; switch (ntf.operation()) { case Akonadi::Protocol::RelationChangeNotification::Add: operation = QStringLiteral("Add"); break; case Akonadi::Protocol::RelationChangeNotification::Remove: operation = QStringLiteral("Remove"); break; case Akonadi::Protocol::RelationChangeNotification::InvalidOp: operation = QStringLiteral("InvalidOp"); break; } appendRow(model, QStringLiteral("Operation"), operation); auto item = new QStandardItem(QStringLiteral("Relation")); const auto rel = ntf.relation(); appendRow(item, QStringLiteral("Left ID"), QString::number(rel.left())); appendRow(item, QStringLiteral("Left MimeType"), QString::fromUtf8(rel.leftMimeType())); appendRow(item, QStringLiteral("Right ID"), QString::number(rel.right())); appendRow(item, QStringLiteral("Right MimeType"), QString::fromUtf8(rel.rightMimeType())); appendRow(item, QStringLiteral("Remote ID"), QString::fromUtf8(rel.remoteId())); model->appendRow(item); } void NotificationMonitor::populateTagNtfTree(QStandardItemModel *model, const Akonadi::Protocol::TagChangeNotification &ntf) { QString operation; switch (ntf.operation()) { case Akonadi::Protocol::TagChangeNotification::Add: operation = QStringLiteral("Add"); break; case Akonadi::Protocol::TagChangeNotification::Modify: operation = QStringLiteral("Modify"); break; case Akonadi::Protocol::TagChangeNotification::Remove: operation = QStringLiteral("Remove"); break; case Akonadi::Protocol::TagChangeNotification::InvalidOp: operation = QStringLiteral("InvalidOp"); break; } appendRow(model, QStringLiteral("Operation"), operation); appendRow(model, QStringLiteral("Resource"), QString::fromUtf8(ntf.resource())); auto tagItem = new QStandardItem(QStringLiteral("Tag")); populateTagTree(tagItem, ntf.tag()); model->appendRow(tagItem); } void NotificationMonitor::populateSubscriptionNtfTree(QStandardItemModel *model, const Akonadi::Protocol::SubscriptionChangeNotification &ntf) { QString operation; switch (ntf.operation()) { case Akonadi::Protocol::SubscriptionChangeNotification::Add: operation = QStringLiteral("Add"); break; case Akonadi::Protocol::SubscriptionChangeNotification::Modify: operation = QStringLiteral("Modify"); break; case Akonadi::Protocol::SubscriptionChangeNotification::Remove: operation = QStringLiteral("Remove"); break; case Akonadi::Protocol::SubscriptionChangeNotification::InvalidOp: operation = QStringLiteral("InvalidOp"); break; } appendRow(model, QStringLiteral("Operation"), operation); appendRow(model, QStringLiteral("Subscriber"), QString::fromUtf8(ntf.subscriber())); appendRow(model, QStringLiteral("Monitored Collections"), toString(ntf.collections())); appendRow(model, QStringLiteral("Monitored Items"), toString(ntf.items())); appendRow(model, QStringLiteral("Monitored Tags"), toString(ntf.tags())); QStringList types; const auto typesSet = ntf.types(); for (const auto &type : typesSet) { switch (type) { case Akonadi::Protocol::ModifySubscriptionCommand::ItemChanges: types.push_back(QStringLiteral("Items")); break; case Akonadi::Protocol::ModifySubscriptionCommand::CollectionChanges: types.push_back(QStringLiteral("Collections")); break; case Akonadi::Protocol::ModifySubscriptionCommand::TagChanges: types.push_back(QStringLiteral("Tags")); break; case Akonadi::Protocol::ModifySubscriptionCommand::RelationChanges: types.push_back(QStringLiteral("Relations")); break; case Akonadi::Protocol::ModifySubscriptionCommand::SubscriptionChanges: types.push_back(QStringLiteral("Subscriptions")); break; case Akonadi::Protocol::ModifySubscriptionCommand::ChangeNotifications: types.push_back(QStringLiteral("Changes")); break; case Akonadi::Protocol::ModifySubscriptionCommand::NoType: types.push_back(QStringLiteral("No Type")); break; } } appendRow(model, QStringLiteral("Monitored Types"), types.join(QStringLiteral(", "))); appendRow(model, QStringLiteral("Monitored Mime Types"), toString(ntf.mimeTypes())); appendRow(model, QStringLiteral("Monitored Resources"), toString(ntf.resources())); appendRow(model, QStringLiteral("Ignored Sessions"), toString(ntf.ignoredSessions())); appendRow(model, QStringLiteral("All Monitored"), toString(ntf.allMonitored())); appendRow(model, QStringLiteral("Exclusive"), toString(ntf.exclusive())); auto item = new QStandardItem(QStringLiteral("Item Fetch Scope")); const auto ifs = ntf.itemFetchScope(); appendRow(item, QStringLiteral("Requested Parts"), toString(ifs.requestedParts())); - appendRow(item, QStringLiteral("Changed Since"), ifs.changedSince().toString(Qt::ISODate)); + appendRow(item, QStringLiteral("Changed Since"), ifs.changedSince().toString(Qt::ISODateWithMs)); appendRow(item, QStringLiteral("Tag Fetch Scope"), toString(ifs.tagFetchScope())); QString ancestorDepth; switch (ifs.ancestorDepth()) { case Akonadi::Protocol::ItemFetchScope::NoAncestor: ancestorDepth = QStringLiteral("No Ancestor"); break; case Akonadi::Protocol::ItemFetchScope::ParentAncestor: ancestorDepth = QStringLiteral("Parent Ancestor"); break; case Akonadi::Protocol::ItemFetchScope::AllAncestors: ancestorDepth = QStringLiteral("All Ancestors"); break; } appendRow(item, QStringLiteral("Ancestor Depth"), ancestorDepth); appendRow(item, QStringLiteral("Cache Only"), toString(ifs.cacheOnly())); appendRow(item, QStringLiteral("Check Cached Payload Parts Only"), toString(ifs.checkCachedPayloadPartsOnly())); appendRow(item, QStringLiteral("Full Payload"), toString(ifs.fullPayload())); appendRow(item, QStringLiteral("All Attributes"), toString(ifs.allAttributes())); appendRow(item, QStringLiteral("Fetch Size"), toString(ifs.fetchSize())); appendRow(item, QStringLiteral("Fetch MTime"), toString(ifs.fetchMTime())); appendRow(item, QStringLiteral("Fetch Remote Revision"), toString(ifs.fetchRemoteRevision())); appendRow(item, QStringLiteral("Ignore Errors"), toString(ifs.ignoreErrors())); appendRow(item, QStringLiteral("Fetch Flags"), toString(ifs.fetchFlags())); appendRow(item, QStringLiteral("Fetch RemoteID"), toString(ifs.fetchRemoteId())); appendRow(item, QStringLiteral("Fetch GID"), toString(ifs.fetchGID())); appendRow(item, QStringLiteral("Fetch Tags"), toString(ifs.fetchTags())); appendRow(item, QStringLiteral("Fetch Relations"), toString(ifs.fetchRelations())); appendRow(item, QStringLiteral("Fetch VRefs"), toString(ifs.fetchVirtualReferences())); model->appendRow(item); item = new QStandardItem(QStringLiteral("Collection Fetch Scope")); const auto cfs = ntf.collectionFetchScope(); QString listFilter; switch (cfs.listFilter()) { case Akonadi::Protocol::CollectionFetchScope::NoFilter: listFilter = QStringLiteral("No Filter"); break; case Akonadi::Protocol::CollectionFetchScope::Display: listFilter = QStringLiteral("Display"); break; case Akonadi::Protocol::CollectionFetchScope::Enabled: listFilter = QStringLiteral("Enabled"); break; case Akonadi::Protocol::CollectionFetchScope::Index: listFilter = QStringLiteral("Index"); break; case Akonadi::Protocol::CollectionFetchScope::Sync: listFilter = QStringLiteral("Sync"); break; } appendRow(item, QStringLiteral("List Filter"), listFilter); appendRow(item, QStringLiteral("Include Statistics"), toString(cfs.includeStatistics())); appendRow(item, QStringLiteral("Resource"), cfs.resource()); appendRow(item, QStringLiteral("Content Mime Types"), cfs.contentMimeTypes().join(QStringLiteral(", "))); appendRow(item, QStringLiteral("Attributes"), toString(cfs.attributes())); appendRow(item, QStringLiteral("Fetch ID Only"), toString(cfs.fetchIdOnly())); QString ancestorRetrieval; switch (cfs.ancestorRetrieval()) { case Akonadi::Protocol::CollectionFetchScope::All: ancestorRetrieval = QStringLiteral("All"); break; case Akonadi::Protocol::CollectionFetchScope::Parent: ancestorRetrieval = QStringLiteral("Parent"); break; case Akonadi::Protocol::CollectionFetchScope::None: ancestorRetrieval = QStringLiteral("None"); break; } appendRow(item, QStringLiteral("Ancestor Retrieval"), ancestorRetrieval); appendRow(item, QStringLiteral("Ancestor Fetch ID Only"), toString(cfs.ancestorFetchIdOnly())); appendRow(item, QStringLiteral("Ancestor Attributes"), toString(cfs.ancestorAttributes())); appendRow(item, QStringLiteral("Ignore Retrieval Errors"), toString(cfs.ignoreRetrievalErrors())); model->appendRow(item); }