2 Copyright (c) 2009 Volker Krause <vkrause@kde.org>
4 This program is free software; you can redistribute it and/or modify
5 it under the terms of the GNU General Public License as published by
6 the Free Software Foundation; either version 2 of the License, or
7 (at your option) any later version.
9 This program is distributed in the hope that it will be useful,
10 but WITHOUT ANY WARRANTY; without even the implied warranty of
11 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 GNU General Public License for more details.
14 You should have received a copy of the GNU General Public License
15 along with this program; if not, write to the Free Software
16 Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301,
20 #include "notificationmodel.h"
22 #include <QCoreApplication>
24 #include <QtDBus/QDBusConnection>
25 #include <QtDBus/QDBusPendingCall>
29 #include "akonadiconsole_debug.h"
30 #include <AkonadiCore/ServerManager>
32 #include <akonadi/private/imapparser_p.h>
33 #include <akonadi/private/protocol_p.h>
34 #include <QMetaMethod>
36 using namespace Akonadi
;
38 class NotificationModel::Item
41 Item(int type_
): type(type_
) {}
47 class NotificationModel::NotificationBlock
: public NotificationModel::Item
50 NotificationBlock(const Akonadi::Protocol::ChangeNotification::List
&msgs
);
53 QList
<NotificationNode
*> nodes
;
57 class NotificationModel::NotificationNode
: public NotificationModel::Item
60 NotificationNode(const Protocol::ChangeNotification
&msg_
, NotificationBlock
*parent_
);
64 Protocol::ChangeNotification::Type type
;
65 Protocol::ChangeNotification::Operation operation
;
67 QByteArray destResource
;
68 Protocol::ChangeNotification::Id parentCollection
;
69 Protocol::ChangeNotification::Id destCollection
;
70 QSet
<QByteArray
> parts
;
71 QSet
<QByteArray
> addedFlags
;
72 QSet
<QByteArray
> removedFlags
;
73 QList
<NotificationEntity
*> entities
;
74 NotificationBlock
*parent
;
77 class NotificationModel::NotificationEntity
: public NotificationModel::Item
80 NotificationEntity(const Protocol::ChangeNotification::Entity
&entity
, NotificationNode
*parent_
);
82 Protocol::ChangeNotification::Id id
;
84 QString remoteRevision
;
86 NotificationNode
*parent
;
89 NotificationModel::NotificationBlock::NotificationBlock(const Protocol::ChangeNotification::List
&msgs
) :
92 timestamp
= QDateTime::currentDateTime();
93 Q_FOREACH (const Protocol::ChangeNotification
&msg
, msgs
) {
94 nodes
<< new NotificationNode(msg
, this);
98 NotificationModel::NotificationBlock::~NotificationBlock()
103 NotificationModel::NotificationNode::NotificationNode(const Protocol::ChangeNotification
&msg
, NotificationModel::NotificationBlock
*parent_
):
105 sessionId(msg
.sessionId()),
107 operation(msg
.operation()),
108 resource(msg
.resource()),
109 destResource(msg
.destinationResource()),
110 parentCollection(msg
.parentCollection()),
111 destCollection(msg
.parentDestCollection()),
112 parts(msg
.itemParts()),
113 addedFlags(msg
.addedFlags()),
114 removedFlags(msg
.removedFlags()),
117 Q_FOREACH (const Protocol::ChangeNotification::Entity
&entity
, msg
.entities()) {
118 entities
<< new NotificationEntity(entity
, this);
122 NotificationModel::NotificationNode::~NotificationNode()
124 qDeleteAll(entities
);
127 NotificationModel::NotificationEntity::NotificationEntity(const Protocol::ChangeNotification::Entity
&entity
, NotificationModel::NotificationNode
*parent_
):
130 remoteId(entity
.remoteId
),
131 remoteRevision(entity
.remoteRevision
),
132 mimeType(entity
.mimeType
),
137 NotificationModel::NotificationModel(QObject
*parent
) :
138 QAbstractItemModel(parent
)
140 QString service
= QStringLiteral("org.freedesktop.Akonadi");
141 if (Akonadi::ServerManager::hasInstanceIdentifier()) {
142 service
+= QLatin1String(".") + Akonadi::ServerManager::instanceIdentifier();
144 m_manager
= new QDBusInterface(service
, QStringLiteral("/notifications/debug"),
145 QStringLiteral("org.freedesktop.Akonadi.NotificationManager"),
146 QDBusConnection::sessionBus(),
148 if (!m_manager
->isValid()) {
149 qCWarning(AKONADICONSOLE_LOG
) << "Unable to connect to notification manager";
153 connect(m_manager
, SIGNAL(debugNotify(QVector
<QByteArray
>)),
154 this, SLOT(slotNotify(QVector
<QByteArray
>)));
158 NotificationModel::~NotificationModel()
163 int NotificationModel::columnCount(const QModelIndex
&parent
) const
169 int NotificationModel::rowCount(const QModelIndex
&parent
) const
171 if (!parent
.isValid()) {
172 return m_data
.size();
175 Item
*parentItem
= static_cast<Item
*>(parent
.internalPointer());
177 if (parentItem
->type
== 0) {
178 return static_cast<NotificationBlock
*>(parentItem
)->nodes
.count();
179 } else if (parentItem
->type
== 1) {
180 return static_cast<NotificationNode
*>(parentItem
)->entities
.count();
187 QModelIndex
NotificationModel::index(int row
, int column
, const QModelIndex
&parent
) const
189 if (!parent
.isValid()) {
190 if (row
>= m_data
.count()) {
191 return QModelIndex();
193 return createIndex(row
, column
, m_data
.at(row
));
196 Item
*parentItem
= static_cast<Item
*>(parent
.internalPointer());
198 if (parentItem
->type
== 0) {
199 NotificationBlock
*parentBlock
= static_cast<NotificationBlock
*>(parentItem
);
200 return createIndex(row
, column
, parentBlock
->nodes
.at(row
));
201 } else if (parentItem
->type
== 1) {
202 NotificationNode
*parentNode
= static_cast<NotificationNode
*>(parentItem
);
203 return createIndex(row
, column
, parentNode
->entities
.at(row
));
207 return QModelIndex();
210 QModelIndex
NotificationModel::parent(const QModelIndex
&child
) const
212 if (!child
.isValid()) {
213 return QModelIndex();
216 Item
*childItem
= static_cast<Item
*>(child
.internalPointer());
218 if (childItem
->type
== 0) {
219 return QModelIndex();
220 } else if (childItem
->type
== 1) {
221 NotificationNode
*childNode
= static_cast<NotificationNode
*>(childItem
);
222 return createIndex(m_data
.indexOf(childNode
->parent
), 0, childNode
->parent
);
223 } else if (childItem
->type
== 2) {
224 NotificationEntity
*childEntity
= static_cast<NotificationEntity
*>(childItem
);
225 NotificationNode
*parentNode
= childEntity
->parent
;
226 return createIndex(parentNode
->parent
->nodes
.indexOf(parentNode
), 0, childEntity
->parent
);
230 return QModelIndex();
233 QVariant
NotificationModel::data(const QModelIndex
&index
, int role
) const
235 if (!index
.isValid()) {
239 Item
*item
= static_cast<Item
*>(index
.internalPointer());
244 if (item
->type
== 0) {
245 NotificationBlock
*block
= static_cast<NotificationBlock
*>(item
);
246 if (role
== Qt::DisplayRole
) {
247 switch (index
.column()) {
249 return QString(QLocale().toString(block
->timestamp
.time()) +
250 QStringLiteral(".%1").arg(block
->timestamp
.time().msec(), 3, 10, QLatin1Char('0')));
252 return block
->nodes
.count();
255 } else if (item
->type
== 1) {
256 NotificationNode
*node
= static_cast<NotificationNode
*>(item
);
257 if (role
== Qt::DisplayRole
) {
258 switch (index
.column()) {
260 switch (node
->operation
) {
261 case Protocol::ChangeNotification::Add
: return QStringLiteral("Add");
262 case Protocol::ChangeNotification::Modify
: return QStringLiteral("Modify");
263 case Protocol::ChangeNotification::ModifyFlags
: return QStringLiteral("ModifyFlags");
264 case Protocol::ChangeNotification::ModifyTags
: return QStringLiteral("ModifyTags");
265 case Protocol::ChangeNotification::Move
: return QStringLiteral("Move");
266 case Protocol::ChangeNotification::Remove
: return QStringLiteral("Delete");
267 case Protocol::ChangeNotification::Link
: return QStringLiteral("Link");
268 case Protocol::ChangeNotification::Unlink
: return QStringLiteral("Unlink");
269 case Protocol::ChangeNotification::Subscribe
: return QStringLiteral("Subscribe");
270 case Protocol::ChangeNotification::Unsubscribe
: return QStringLiteral("Unsubscribe");
271 default: return QStringLiteral("Invalid");
275 switch (node
->type
) {
276 case Protocol::ChangeNotification::Collections
: return QStringLiteral("Collections");
277 case Protocol::ChangeNotification::Items
: return QStringLiteral("Items");
278 case Protocol::ChangeNotification::Tags
: return QStringLiteral("Tags");
279 default: return QStringLiteral("Invalid");
283 return QString::fromUtf8(node
->sessionId
);
285 return QString::fromUtf8(node
->resource
);
287 return QString::fromUtf8(node
->destResource
);
289 return QString::number(node
->parentCollection
);
291 return QString::number(node
->destCollection
);
293 return QString::fromUtf8(Akonadi::ImapParser::join(node
->parts
, ", "));
295 return QString::fromUtf8(Akonadi::ImapParser::join(node
->addedFlags
, ", "));
297 return QString::fromUtf8(Akonadi::ImapParser::join(node
->removedFlags
, ", "));
300 } else if (item
->type
== 2) {
301 NotificationEntity
*entity
= static_cast<NotificationEntity
*>(item
);
302 if (role
== Qt::DisplayRole
) {
303 switch (index
.column()) {
307 return entity
->remoteId
;
309 return entity
->remoteRevision
;
311 return entity
->mimeType
;
319 QVariant
NotificationModel::headerData(int section
, Qt::Orientation orientation
, int role
) const
321 if (role
== Qt::DisplayRole
&& orientation
== Qt::Horizontal
) {
323 case 0: return QStringLiteral("Operation / ID");
324 case 1: return QStringLiteral("Type / RID");
325 case 2: return QStringLiteral("Session / REV");
326 case 3: return QStringLiteral("Resource / MimeType");
327 case 4: return QStringLiteral("Destination Resource");
328 case 5: return QStringLiteral("Parent");
329 case 6: return QStringLiteral("Destination");
330 case 7: return QStringLiteral("Parts");
331 case 8: return QStringLiteral("Added Flags");
332 case 9: return QStringLiteral("Removed Flags");
335 return QAbstractItemModel::headerData(section
, orientation
, role
);
338 void NotificationModel::slotNotify(const QVector
<QByteArray
> &data
)
340 Protocol::ChangeNotification::List ntfs
;
341 ntfs
.reserve(data
.size());
342 Q_FOREACH (const QByteArray
&d
, data
) {
343 QBuffer
buffer(const_cast<QByteArray
*>(&d
));
344 buffer
.open(QIODevice::ReadOnly
);
345 ntfs
<< Protocol::deserialize(&buffer
);
348 beginInsertRows(QModelIndex(), m_data
.size(), m_data
.size());
349 m_data
.append(new NotificationBlock(ntfs
));
353 void NotificationModel::clear()
360 void NotificationModel::setEnabled(bool enable
)
363 m_manager
->asyncCall(QStringLiteral("enableDebug"), enable
);