mirror of
https://bitbucket.org/smil3y/kde-playground.git
synced 2025-02-23 10:22:50 +00:00
387 lines
12 KiB
C++
387 lines
12 KiB
C++
/*
|
|
Copyright (c) 2009 Volker Krause <vkrause@kde.org>
|
|
|
|
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 "notificationmanagerinterface.h"
|
|
|
|
#include <QtCore/QCoreApplication>
|
|
#include <QtDBus/QDBusConnection>
|
|
|
|
#include <KDebug>
|
|
#include <KLocale>
|
|
#include <KGlobal>
|
|
|
|
#include <Akonadi/ServerManager>
|
|
|
|
#include <akonadi/private/imapparser_p.h>
|
|
#include <boost/concept_check.hpp>
|
|
#include <akonadi/private/notificationmessagev3_p.h>
|
|
|
|
using namespace Akonadi;
|
|
|
|
class NotificationModel::Item {
|
|
public:
|
|
Item(int type_): type(type_) {}
|
|
virtual ~Item() {}
|
|
|
|
int type;
|
|
};
|
|
|
|
class NotificationModel::NotificationBlock: public NotificationModel::Item {
|
|
public:
|
|
NotificationBlock( const Akonadi::NotificationMessageV3::List &msgs );
|
|
~NotificationBlock();
|
|
|
|
QList<NotificationNode*> nodes;
|
|
QDateTime timestamp;
|
|
};
|
|
|
|
class NotificationModel::NotificationNode: public NotificationModel::Item {
|
|
public:
|
|
NotificationNode( const NotificationMessageV3 &msg_, NotificationBlock *parent_ );
|
|
~NotificationNode();
|
|
|
|
QByteArray sessionId;
|
|
NotificationMessageV2::Type type;
|
|
NotificationMessageV2::Operation operation;
|
|
QByteArray resource;
|
|
QByteArray destResource;
|
|
NotificationMessageV2::Id parentCollection;
|
|
NotificationMessageV2::Id destCollection;
|
|
QSet<QByteArray> parts;
|
|
QSet<QByteArray> addedFlags;
|
|
QSet<QByteArray> removedFlags;
|
|
QList<NotificationEntity*> entities;
|
|
NotificationBlock *parent;
|
|
};
|
|
|
|
class NotificationModel::NotificationEntity: public NotificationModel::Item {
|
|
public:
|
|
NotificationEntity( const NotificationMessageV2::Entity &entity, NotificationNode *parent_ );
|
|
|
|
NotificationMessageV2::Id id;
|
|
QString remoteId;
|
|
QString remoteRevision;
|
|
QString mimeType;
|
|
NotificationNode *parent;
|
|
};
|
|
|
|
|
|
NotificationModel::NotificationBlock::NotificationBlock( const NotificationMessageV3::List &msgs ) :
|
|
Item( 0 )
|
|
{
|
|
timestamp = QDateTime::currentDateTime();
|
|
Q_FOREACH ( const NotificationMessageV3 &msg, msgs ) {
|
|
nodes << new NotificationNode( msg, this );
|
|
}
|
|
}
|
|
|
|
NotificationModel::NotificationBlock::~NotificationBlock()
|
|
{
|
|
qDeleteAll( nodes );
|
|
}
|
|
|
|
|
|
NotificationModel::NotificationNode::NotificationNode( const NotificationMessageV3& msg, NotificationModel::NotificationBlock* parent_ ):
|
|
Item( 1 ),
|
|
sessionId( msg.sessionId() ),
|
|
type( msg.type() ),
|
|
operation( msg.operation() ),
|
|
resource( msg.resource() ),
|
|
destResource( msg.destinationResource() ),
|
|
parentCollection( msg.parentCollection() ),
|
|
destCollection( msg.parentDestCollection() ),
|
|
parts( msg.itemParts() ),
|
|
addedFlags( msg.addedFlags() ),
|
|
removedFlags( msg.removedFlags() ),
|
|
parent( parent_ )
|
|
{
|
|
Q_FOREACH ( const NotificationMessageV2::Entity &entity, msg.entities()) {
|
|
entities << new NotificationEntity( entity, this );
|
|
}
|
|
}
|
|
|
|
NotificationModel::NotificationNode::~NotificationNode()
|
|
{
|
|
qDeleteAll( entities );
|
|
}
|
|
|
|
|
|
NotificationModel::NotificationEntity::NotificationEntity( const NotificationMessageV2::Entity &entity, NotificationModel::NotificationNode* parent_ ):
|
|
Item( 2 ),
|
|
id( entity.id ),
|
|
remoteId( entity.remoteId ),
|
|
remoteRevision( entity.remoteRevision ),
|
|
mimeType( entity.mimeType ),
|
|
parent( parent_ )
|
|
{
|
|
}
|
|
|
|
NotificationModel::NotificationModel( QObject* parent ) :
|
|
QAbstractItemModel( parent ),
|
|
m_source( 0 )
|
|
{
|
|
NotificationMessageV2::registerDBusTypes();
|
|
|
|
QString service = QLatin1String( "org.freedesktop.Akonadi" );
|
|
if ( Akonadi::ServerManager::hasInstanceIdentifier() ) {
|
|
service += "." + Akonadi::ServerManager::instanceIdentifier();
|
|
}
|
|
m_manager = new org::freedesktop::Akonadi::NotificationManager( service,
|
|
QLatin1String( "/notifications" ),
|
|
QDBusConnection::sessionBus(), this );
|
|
if ( !m_manager ) {
|
|
kWarning( 5250 ) << "Unable to connect to notification manager";
|
|
return;
|
|
}
|
|
}
|
|
|
|
NotificationModel::~NotificationModel()
|
|
{
|
|
if ( m_source ) {
|
|
m_source->unsubscribe();
|
|
}
|
|
}
|
|
|
|
int NotificationModel::columnCount( const QModelIndex &parent ) const
|
|
{
|
|
Q_UNUSED( parent );
|
|
return 10;
|
|
}
|
|
|
|
int NotificationModel::rowCount( const QModelIndex& parent ) const
|
|
{
|
|
if ( !parent.isValid() )
|
|
return m_data.size();
|
|
|
|
Item *parentItem = static_cast<Item*>( parent.internalPointer() );
|
|
if ( parentItem ) {
|
|
if ( parentItem->type == 0 ) {
|
|
return static_cast<NotificationBlock*>( parentItem )->nodes.count();
|
|
} else if ( parentItem->type == 1 ) {
|
|
return static_cast<NotificationNode*>( parentItem )->entities.count();
|
|
}
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|
|
QModelIndex NotificationModel::index( int row, int column, const QModelIndex &parent ) const
|
|
{
|
|
if ( !parent.isValid() ) {
|
|
if ( row >= m_data.count() ) {
|
|
return QModelIndex();
|
|
}
|
|
return createIndex( row, column, m_data.at( row ) );
|
|
}
|
|
|
|
Item *parentItem = static_cast<Item*>( parent.internalPointer() );
|
|
if ( parentItem ) {
|
|
if ( parentItem ->type == 0 ) {
|
|
NotificationBlock *parentBlock = static_cast<NotificationBlock*>( parentItem );
|
|
return createIndex( row, column, parentBlock->nodes.at( row ) );
|
|
} else if ( parentItem->type == 1 ) {
|
|
NotificationNode *parentNode = static_cast<NotificationNode*>( parentItem );
|
|
return createIndex( row, column, parentNode->entities.at( row ) );
|
|
}
|
|
}
|
|
|
|
return QModelIndex();
|
|
}
|
|
|
|
QModelIndex NotificationModel::parent( const QModelIndex &child ) const
|
|
{
|
|
if ( !child.isValid() ) {
|
|
return QModelIndex();
|
|
}
|
|
|
|
Item *childItem = static_cast<Item*>( child.internalPointer() );
|
|
if ( childItem ) {
|
|
if ( childItem->type == 0 ) {
|
|
return QModelIndex();
|
|
} else if ( childItem->type == 1 ) {
|
|
NotificationNode *childNode = static_cast<NotificationNode*>( childItem );
|
|
return createIndex( m_data.indexOf( childNode->parent ), 0, childNode->parent );
|
|
} else if ( childItem->type == 2 ) {
|
|
NotificationEntity *childEntity = static_cast<NotificationEntity*>( childItem );
|
|
NotificationNode *parentNode = childEntity->parent;
|
|
return createIndex( parentNode->parent->nodes.indexOf( parentNode ), 0, childEntity->parent );
|
|
}
|
|
}
|
|
|
|
return QModelIndex();
|
|
}
|
|
|
|
QVariant NotificationModel::data( const QModelIndex &index, int role ) const
|
|
{
|
|
if ( !index.isValid() ) {
|
|
return QVariant();
|
|
}
|
|
|
|
Item *item = static_cast<Item*>( index.internalPointer() );
|
|
if ( !item ) {
|
|
return QVariant();
|
|
}
|
|
|
|
if ( item->type == 0 ) {
|
|
NotificationBlock *block = static_cast<NotificationBlock*>( item );
|
|
if ( role == Qt::DisplayRole ) {
|
|
switch ( index.column() ) {
|
|
case 0:
|
|
return QString( KGlobal::locale()->formatTime( block->timestamp.time(), true ) +
|
|
QString::fromLatin1( ".%1" ).arg( block->timestamp.time().msec(), 3, 10, QLatin1Char('0') ) );
|
|
case 1:
|
|
return block->nodes.count();
|
|
}
|
|
}
|
|
} else if ( item->type == 1 ) {
|
|
NotificationNode *node = static_cast<NotificationNode*>( item );
|
|
if ( role == Qt::DisplayRole ) {
|
|
switch ( index.column() ) {
|
|
case 0:
|
|
{
|
|
switch ( node->operation ) {
|
|
case NotificationMessageV2::Add: return QLatin1String( "Add" );
|
|
case NotificationMessageV2::Modify: return QLatin1String( "Modify" );
|
|
case NotificationMessageV2::ModifyFlags: return QLatin1String( "ModifyFlags" );
|
|
case NotificationMessageV2::ModifyTags: return QLatin1String( "ModifyTags" );
|
|
case NotificationMessageV2::Move: return QLatin1String( "Move" );
|
|
case NotificationMessageV2::Remove: return QLatin1String( "Delete" );
|
|
case NotificationMessageV2::Link: return QLatin1String( "Link" );
|
|
case NotificationMessageV2::Unlink: return QLatin1String( "Unlink" );
|
|
case NotificationMessageV2::Subscribe: return QLatin1String( "Subscribe" );
|
|
case NotificationMessageV2::Unsubscribe: return QLatin1String( "Unsubscribe" );
|
|
default: return QString( "Invalid" );
|
|
}
|
|
}
|
|
case 1:
|
|
{
|
|
switch ( node->type ) {
|
|
case NotificationMessageV2::Collections: return QLatin1String( "Collections" );
|
|
case NotificationMessageV2::Items: return QLatin1String( "Items" );
|
|
case NotificationMessageV2::Tags: return QLatin1String( "Tags" );
|
|
default: return QString( "Invalid" );
|
|
}
|
|
}
|
|
case 2:
|
|
return QString::fromUtf8( node->sessionId );
|
|
case 3:
|
|
return QString::fromUtf8( node->resource );
|
|
case 4:
|
|
return QString::fromUtf8( node->destResource );
|
|
case 5:
|
|
return QString::number( node->parentCollection );
|
|
case 6:
|
|
return QString::number( node->destCollection );
|
|
case 7:
|
|
return QString::fromUtf8( Akonadi::ImapParser::join( node->parts, ", " ) );
|
|
case 8:
|
|
return QString::fromUtf8( Akonadi::ImapParser::join( node->addedFlags, ", " ) );
|
|
case 9:
|
|
return QString::fromUtf8( Akonadi::ImapParser::join( node->removedFlags, ", " ) );
|
|
}
|
|
}
|
|
} else if ( item->type == 2 ) {
|
|
NotificationEntity *entity = static_cast<NotificationEntity*>( item );
|
|
if ( role == Qt::DisplayRole ) {
|
|
switch ( index.column() ) {
|
|
case 0:
|
|
return entity->id;
|
|
case 1:
|
|
return entity->remoteId;
|
|
case 2:
|
|
return entity->remoteRevision;
|
|
case 3:
|
|
return entity->mimeType;
|
|
}
|
|
}
|
|
}
|
|
|
|
return QVariant();
|
|
}
|
|
|
|
QVariant NotificationModel::headerData(int section, Qt::Orientation orientation, int role) const
|
|
{
|
|
if ( role == Qt::DisplayRole && orientation == Qt::Horizontal ) {
|
|
switch ( section ) {
|
|
case 0: return QString( "Operation / ID" );
|
|
case 1: return QString( "Type / RID" );
|
|
case 2: return QString( "Session / REV" );
|
|
case 3: return QString( "Resource / MimeType" );
|
|
case 4: return QString( "Destination Resource" );
|
|
case 5: return QString( "Parent" );
|
|
case 6: return QString( "Destination" );
|
|
case 7: return QString( "Parts" );
|
|
case 8: return QString( "Added Flags" );
|
|
case 9: return QString( "Removed Flags" );
|
|
}
|
|
}
|
|
return QAbstractItemModel::headerData(section, orientation, role);
|
|
}
|
|
|
|
|
|
void NotificationModel::slotNotify(const Akonadi::NotificationMessageV3::List& msgs)
|
|
{
|
|
beginInsertRows( QModelIndex(), m_data.size(), m_data.size() );
|
|
m_data.append( new NotificationBlock( msgs ) );
|
|
endInsertRows();
|
|
}
|
|
|
|
void NotificationModel::clear()
|
|
{
|
|
qDeleteAll( m_data );
|
|
m_data.clear();
|
|
reset();
|
|
}
|
|
|
|
void NotificationModel::setEnabled( bool enable )
|
|
{
|
|
if ( enable && !m_source ) {
|
|
const QString identifier = QString::fromLatin1("akonadiconsole_%1_notificationmodel").arg( QString::number( QCoreApplication::applicationPid() ) );
|
|
m_manager->subscribe( identifier );
|
|
|
|
QString service = QLatin1String( "org.freedesktop.Akonadi" );
|
|
if ( Akonadi::ServerManager::hasInstanceIdentifier() ) {
|
|
service += "." + Akonadi::ServerManager::instanceIdentifier();
|
|
}
|
|
m_source = new org::freedesktop::Akonadi::NotificationSource( service,
|
|
QLatin1String( "/subscriber/" ) + identifier,
|
|
QDBusConnection::sessionBus(), this );
|
|
if ( !m_source ) {
|
|
kWarning( 5250 ) << "Unable to connect to notification source";
|
|
return;
|
|
}
|
|
|
|
connect( m_source, SIGNAL(notifyV3(Akonadi::NotificationMessageV3::List)),
|
|
this, SLOT(slotNotify(Akonadi::NotificationMessageV3::List)) );
|
|
|
|
} else if ( !enable && m_source ) {
|
|
|
|
disconnect( m_source, SIGNAL(notifyV3(Akonadi::NotificationMessageV3::List)) );
|
|
m_source->unsubscribe();
|
|
m_source->deleteLater();
|
|
m_source = 0;
|
|
}
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|