mirror of
https://bitbucket.org/smil3y/kde-playground.git
synced 2025-02-23 18:32:51 +00:00
433 lines
11 KiB
C++
433 lines
11 KiB
C++
![]() |
/*
|
||
|
Copyright (c) 2007 Volker Krause <vkrause@kde.org>
|
||
|
|
||
|
This library is free software; you can redistribute it and/or modify it
|
||
|
under the terms of the GNU Library General Public License as published by
|
||
|
the Free Software Foundation; either version 2 of the License, or (at your
|
||
|
option) any later version.
|
||
|
|
||
|
This library 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 Library General Public
|
||
|
License for more details.
|
||
|
|
||
|
You should have received a copy of the GNU Library General Public License
|
||
|
along with this library; see the file COPYING.LIB. If not, write to the
|
||
|
Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
|
||
|
02110-1301, USA.
|
||
|
*/
|
||
|
|
||
|
#include "notificationmessage_p.h"
|
||
|
#include "imapparser_p.h"
|
||
|
|
||
|
#include <QtCore/QDebug>
|
||
|
#include <QtCore/QHash>
|
||
|
#include <QtDBus/QDBusMetaType>
|
||
|
|
||
|
using namespace Akonadi;
|
||
|
|
||
|
class NotificationMessage::Private : public QSharedData
|
||
|
{
|
||
|
public:
|
||
|
Private()
|
||
|
: QSharedData()
|
||
|
, type( NotificationMessage::InvalidType )
|
||
|
, operation( NotificationMessage::InvalidOp )
|
||
|
, uid( -1 )
|
||
|
, parentCollection( -1 )
|
||
|
, parentDestCollection( -1 )
|
||
|
{
|
||
|
}
|
||
|
|
||
|
Private( const Private &other )
|
||
|
: QSharedData( other )
|
||
|
{
|
||
|
sessionId = other.sessionId;
|
||
|
type = other.type;
|
||
|
operation = other.operation;
|
||
|
uid = other.uid;
|
||
|
remoteId = other.remoteId;
|
||
|
resource = other.resource;
|
||
|
destResource = other.destResource;
|
||
|
parentCollection = other.parentCollection;
|
||
|
parentDestCollection = other.parentDestCollection;
|
||
|
mimeType = other.mimeType;
|
||
|
parts = other.parts;
|
||
|
}
|
||
|
|
||
|
bool compareWithoutOpAndParts( const Private &other ) const
|
||
|
{
|
||
|
return uid == other.uid
|
||
|
&& type == other.type
|
||
|
&& sessionId == other.sessionId
|
||
|
&& remoteId == other.remoteId
|
||
|
&& resource == other.resource
|
||
|
&& destResource == other.destResource
|
||
|
&& parentCollection == other.parentCollection
|
||
|
&& parentDestCollection == other.parentDestCollection
|
||
|
&& mimeType == other.mimeType;
|
||
|
}
|
||
|
|
||
|
bool operator==( const Private &other ) const
|
||
|
{
|
||
|
return operation == other.operation && parts == other.parts && compareWithoutOpAndParts( other );
|
||
|
}
|
||
|
|
||
|
QByteArray sessionId;
|
||
|
NotificationMessage::Type type;
|
||
|
NotificationMessage::Operation operation;
|
||
|
Id uid;
|
||
|
QString remoteId;
|
||
|
QByteArray resource;
|
||
|
QByteArray destResource;
|
||
|
Id parentCollection;
|
||
|
Id parentDestCollection;
|
||
|
QString mimeType;
|
||
|
QSet<QByteArray> parts;
|
||
|
};
|
||
|
|
||
|
NotificationMessage::NotificationMessage()
|
||
|
: d( new Private )
|
||
|
{
|
||
|
}
|
||
|
|
||
|
NotificationMessage::NotificationMessage( const NotificationMessage &other )
|
||
|
: d( other.d )
|
||
|
{
|
||
|
}
|
||
|
|
||
|
NotificationMessage::~NotificationMessage()
|
||
|
{
|
||
|
}
|
||
|
|
||
|
NotificationMessage &NotificationMessage::operator=( const NotificationMessage &other )
|
||
|
{
|
||
|
if ( this != &other ) {
|
||
|
d = other.d;
|
||
|
}
|
||
|
|
||
|
return *this;
|
||
|
}
|
||
|
|
||
|
bool NotificationMessage::operator==( const NotificationMessage &other ) const
|
||
|
{
|
||
|
return d == other.d;
|
||
|
}
|
||
|
|
||
|
void NotificationMessage::registerDBusTypes()
|
||
|
{
|
||
|
qDBusRegisterMetaType<Akonadi::NotificationMessage>();
|
||
|
qDBusRegisterMetaType<Akonadi::NotificationMessage::List>();
|
||
|
}
|
||
|
|
||
|
QByteArray NotificationMessage::sessionId() const
|
||
|
{
|
||
|
return d->sessionId;
|
||
|
}
|
||
|
|
||
|
void NotificationMessage::setSessionId( const QByteArray &sessionId )
|
||
|
{
|
||
|
d->sessionId = sessionId;
|
||
|
}
|
||
|
|
||
|
NotificationMessage::Type NotificationMessage::type() const
|
||
|
{
|
||
|
return d->type;
|
||
|
}
|
||
|
|
||
|
void NotificationMessage::setType( Type type )
|
||
|
{
|
||
|
d->type = type;
|
||
|
}
|
||
|
|
||
|
NotificationMessage::Operation NotificationMessage::operation() const
|
||
|
{
|
||
|
return d->operation;
|
||
|
}
|
||
|
|
||
|
void NotificationMessage::setOperation( Operation operation )
|
||
|
{
|
||
|
d->operation = operation;
|
||
|
}
|
||
|
|
||
|
NotificationMessage::Id NotificationMessage::uid() const
|
||
|
{
|
||
|
return d->uid;
|
||
|
}
|
||
|
|
||
|
void NotificationMessage::setUid( Id uid )
|
||
|
{
|
||
|
d->uid = uid;
|
||
|
}
|
||
|
|
||
|
QString NotificationMessage::remoteId() const
|
||
|
{
|
||
|
return d->remoteId;
|
||
|
}
|
||
|
|
||
|
void NotificationMessage::setRemoteId( const QString &remoteId )
|
||
|
{
|
||
|
d->remoteId = remoteId;
|
||
|
}
|
||
|
|
||
|
QByteArray NotificationMessage::resource() const
|
||
|
{
|
||
|
return d->resource;
|
||
|
}
|
||
|
|
||
|
void NotificationMessage::setResource( const QByteArray &resource )
|
||
|
{
|
||
|
d->resource = resource;
|
||
|
}
|
||
|
|
||
|
NotificationMessage::Id NotificationMessage::parentCollection() const
|
||
|
{
|
||
|
return d->parentCollection;
|
||
|
}
|
||
|
|
||
|
NotificationMessage::Id NotificationMessage::parentDestCollection() const
|
||
|
{
|
||
|
return d->parentDestCollection;
|
||
|
}
|
||
|
|
||
|
void NotificationMessage::setParentCollection( Id parent )
|
||
|
{
|
||
|
d->parentCollection = parent;
|
||
|
}
|
||
|
|
||
|
void NotificationMessage::setParentDestCollection( Id parent )
|
||
|
{
|
||
|
d->parentDestCollection = parent;
|
||
|
}
|
||
|
|
||
|
void NotificationMessage::setDestinationResource( const QByteArray &destResource )
|
||
|
{
|
||
|
d->destResource = destResource;
|
||
|
}
|
||
|
|
||
|
QByteArray NotificationMessage::destinationResource() const
|
||
|
{
|
||
|
return d->destResource;
|
||
|
}
|
||
|
|
||
|
QString NotificationMessage::mimeType() const
|
||
|
{
|
||
|
return d->mimeType;
|
||
|
}
|
||
|
|
||
|
void NotificationMessage::setMimeType( const QString &mimeType )
|
||
|
{
|
||
|
d->mimeType = mimeType;
|
||
|
}
|
||
|
|
||
|
QSet<QByteArray> NotificationMessage::itemParts() const
|
||
|
{
|
||
|
return d->parts;
|
||
|
}
|
||
|
|
||
|
void NotificationMessage::setItemParts( const QSet<QByteArray> &parts )
|
||
|
{
|
||
|
d->parts = parts;
|
||
|
}
|
||
|
|
||
|
QString NotificationMessage::toString() const
|
||
|
{
|
||
|
QString rv;
|
||
|
// some tests before making the string
|
||
|
if ( type() == InvalidType ) {
|
||
|
return QLatin1String( "Error: Type is not set" );
|
||
|
}
|
||
|
if ( uid() == -1 ) {
|
||
|
return QLatin1String( "Error: uid is not set" );
|
||
|
}
|
||
|
if ( remoteId().isEmpty() ) {
|
||
|
return QLatin1String( "Error: remoteId is empty" );
|
||
|
}
|
||
|
if ( operation() == InvalidOp ) {
|
||
|
return QLatin1String( "Error: operation is not set" );
|
||
|
}
|
||
|
|
||
|
switch ( type() ) {
|
||
|
case Item:
|
||
|
rv += QLatin1String( "Item " );
|
||
|
break;
|
||
|
case Collection:
|
||
|
rv += QLatin1String( "Collection " );
|
||
|
break;
|
||
|
case InvalidType:
|
||
|
// already done above
|
||
|
break;
|
||
|
}
|
||
|
|
||
|
rv += QString::fromLatin1( "(%1, %2) " ).arg( uid() ).arg( remoteId() );
|
||
|
|
||
|
if ( parentCollection() >= 0 ) {
|
||
|
if ( parentDestCollection() >= 0 ) {
|
||
|
rv += QString::fromLatin1( "from " );
|
||
|
} else {
|
||
|
rv += QString::fromLatin1( "in " );
|
||
|
}
|
||
|
rv += QString::fromLatin1( "collection %1 " ).arg( parentCollection() );
|
||
|
} else {
|
||
|
rv += QLatin1String( "unspecified parent collection " );
|
||
|
}
|
||
|
|
||
|
rv += QString::fromLatin1( "mimetype %1 " ).arg( mimeType().isEmpty() ? QLatin1String( "unknown" ) : mimeType() );
|
||
|
|
||
|
switch ( operation() ) {
|
||
|
case Add:
|
||
|
rv += QLatin1String( "added" );
|
||
|
break;
|
||
|
case Modify:
|
||
|
rv += QLatin1String( "modified parts (" );
|
||
|
rv += QString::fromLatin1( ImapParser::join( itemParts().toList(), ", " ) );
|
||
|
rv += QLatin1String( ")" );
|
||
|
break;
|
||
|
case Move:
|
||
|
rv += QLatin1String( "moved" );
|
||
|
break;
|
||
|
case Remove:
|
||
|
rv += QLatin1String( "removed" );
|
||
|
break;
|
||
|
case Link:
|
||
|
rv += QLatin1String( "linked" );
|
||
|
break;
|
||
|
case Unlink:
|
||
|
rv += QLatin1String( "unlinked" );
|
||
|
break;
|
||
|
case Subscribe:
|
||
|
rv += QLatin1String( "subscribed" );
|
||
|
break;
|
||
|
case Unsubscribe:
|
||
|
rv += QLatin1String( "unsubscribed" );
|
||
|
break;
|
||
|
case InvalidOp:
|
||
|
// already done above
|
||
|
break;
|
||
|
}
|
||
|
|
||
|
if ( parentDestCollection() >= 0 ) {
|
||
|
rv += QString::fromLatin1( " to collection %1" ).arg( parentDestCollection() );
|
||
|
}
|
||
|
|
||
|
return rv;
|
||
|
}
|
||
|
|
||
|
void NotificationMessage::appendAndCompress( NotificationMessage::List &list, const NotificationMessage &msg )
|
||
|
{
|
||
|
bool appended;
|
||
|
appendAndCompress( list, msg, &appended );
|
||
|
}
|
||
|
|
||
|
void NotificationMessage::appendAndCompress( NotificationMessage::List &list, const NotificationMessage &msg, bool *appended )
|
||
|
{
|
||
|
// fast-path for stuff that is not considered during O(n) compression below
|
||
|
if ( msg.operation() != Add && msg.operation() != Link && msg.operation() != Unlink && msg.operation() != Subscribe && msg.operation() != Unsubscribe && msg.operation() != Move ) {
|
||
|
NotificationMessage::List::Iterator end = list.end();
|
||
|
for ( NotificationMessage::List::Iterator it = list.begin(); it != end; ) {
|
||
|
if ( msg.d.constData()->compareWithoutOpAndParts( *( ( *it ).d.constData() ) ) ) {
|
||
|
// same operation: merge changed parts and drop the new one
|
||
|
if ( msg.operation() == ( *it ).operation() ) {
|
||
|
( *it ).setItemParts( ( *it ).itemParts() + msg.itemParts() );
|
||
|
*appended = false;
|
||
|
return;
|
||
|
}
|
||
|
// new one is a modification, the existing one not, so drop the new one
|
||
|
else if ( msg.operation() == Modify ) {
|
||
|
*appended = false;
|
||
|
return;
|
||
|
}
|
||
|
// new on is a deletion, erase the existing modification ones (and keep going, in case there are more)
|
||
|
else if ( msg.operation() == Remove && ( *it ).operation() == Modify ) {
|
||
|
it = list.erase( it );
|
||
|
end = list.end();
|
||
|
}
|
||
|
// keep looking
|
||
|
else {
|
||
|
++it;
|
||
|
}
|
||
|
} else {
|
||
|
++it;
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
*appended = true;
|
||
|
list.append( msg );
|
||
|
}
|
||
|
|
||
|
QDBusArgument &operator<<( QDBusArgument &arg, const NotificationMessage &msg )
|
||
|
{
|
||
|
arg.beginStructure();
|
||
|
arg << msg.sessionId();
|
||
|
arg << msg.type();
|
||
|
arg << msg.operation();
|
||
|
arg << msg.uid();
|
||
|
arg << msg.remoteId();
|
||
|
arg << msg.resource();
|
||
|
arg << msg.parentCollection();
|
||
|
arg << msg.parentDestCollection();
|
||
|
arg << msg.mimeType();
|
||
|
|
||
|
QStringList itemParts;
|
||
|
if ( msg.operation() == NotificationMessage::Move ) {
|
||
|
// encode destination resource in parts, as a backward compat hack
|
||
|
itemParts.push_back( QString::fromLatin1( msg.destinationResource() ) );
|
||
|
} else {
|
||
|
Q_FOREACH ( const QByteArray &itemPart, msg.itemParts() ) {
|
||
|
itemParts.append( QString::fromLatin1( itemPart ) );
|
||
|
}
|
||
|
}
|
||
|
|
||
|
arg << itemParts;
|
||
|
arg.endStructure();
|
||
|
return arg;
|
||
|
}
|
||
|
|
||
|
const QDBusArgument &operator>>( const QDBusArgument &arg, NotificationMessage &msg )
|
||
|
{
|
||
|
arg.beginStructure();
|
||
|
QByteArray b;
|
||
|
arg >> b;
|
||
|
msg.setSessionId( b );
|
||
|
int i;
|
||
|
arg >> i;
|
||
|
msg.setType( static_cast<NotificationMessage::Type>( i ) );
|
||
|
arg >> i;
|
||
|
msg.setOperation( static_cast<NotificationMessage::Operation>( i ) );
|
||
|
NotificationMessage::Id id;
|
||
|
arg >> id;
|
||
|
msg.setUid( id );
|
||
|
QString s;
|
||
|
arg >> s;
|
||
|
msg.setRemoteId( s );
|
||
|
arg >> b;
|
||
|
msg.setResource( b );
|
||
|
arg >> id;
|
||
|
msg.setParentCollection( id );
|
||
|
arg >> id;
|
||
|
msg.setParentDestCollection( id );
|
||
|
arg >> s;
|
||
|
msg.setMimeType( s );
|
||
|
QStringList l;
|
||
|
arg >> l;
|
||
|
|
||
|
QSet<QByteArray> itemParts;
|
||
|
if ( msg.operation() == NotificationMessage::Move && l.size() >= 1 ) {
|
||
|
// decode destination resource, which is stored in parts as a backward compat hack
|
||
|
msg.setDestinationResource( l.first().toLatin1() );
|
||
|
} else {
|
||
|
Q_FOREACH ( const QString &itemPart, l ) {
|
||
|
itemParts.insert( itemPart.toLatin1() );
|
||
|
}
|
||
|
}
|
||
|
|
||
|
msg.setItemParts( itemParts );
|
||
|
arg.endStructure();
|
||
|
return arg;
|
||
|
}
|
||
|
|
||
|
uint qHash( const Akonadi::NotificationMessage &msg )
|
||
|
{
|
||
|
return qHash( msg.uid() + ( msg.type() << 31 ) + ( msg.operation() << 28 ) );
|
||
|
}
|