00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020 #ifndef AKONADI_CHANGERECORDER_P_H
00021 #define AKONADI_CHANGERECORDER_P_H
00022
00023 #include "akonadiprivate_export.h"
00024 #include "monitor_p.h"
00025
00026 class AKONADI_TESTS_EXPORT Akonadi::ChangeRecorderPrivate : public Akonadi::MonitorPrivate
00027 {
00028 public:
00029 ChangeRecorderPrivate( ChangeRecorder* parent ) :
00030 MonitorPrivate( parent ),
00031 settings( 0 ),
00032 enableChangeRecording( true )
00033 {
00034 }
00035
00036 Q_DECLARE_PUBLIC( ChangeRecorder )
00037 QSettings *settings;
00038 bool enableChangeRecording;
00039
00040 virtual int pipelineSize() const
00041 {
00042 if ( enableChangeRecording )
00043 return 0;
00044 return MonitorPrivate::pipelineSize();
00045 }
00046
00047 virtual void slotNotify( const NotificationMessage::List &msgs )
00048 {
00049 Q_Q( ChangeRecorder );
00050 const int oldChanges = pendingNotifications.size();
00051 MonitorPrivate::slotNotify( msgs );
00052 if ( enableChangeRecording && pendingNotifications.size() != oldChanges ) {
00053 saveNotifications();
00054 emit q->changesAdded();
00055 }
00056 }
00057
00058 virtual bool emitNotification(const Akonadi::NotificationMessage& msg)
00059 {
00060 const bool someoneWasListening = MonitorPrivate::emitNotification( msg );
00061 if ( !someoneWasListening && enableChangeRecording )
00062 QMetaObject::invokeMethod( q_ptr, "replayNext", Qt::QueuedConnection );
00063 return someoneWasListening;
00064 }
00065
00066 void loadNotifications()
00067 {
00068 pendingNotifications.clear();
00069
00070 const QString changesFileName = settings->fileName() + QLatin1String( "_changes.dat" );
00071
00078 if ( !QFile::exists( changesFileName ) ) {
00079 QStringList list;
00080 settings->beginGroup( QLatin1String( "ChangeRecorder" ) );
00081 const int size = settings->beginReadArray( QLatin1String( "change" ) );
00082
00083 for ( int i = 0; i < size; ++i ) {
00084 settings->setArrayIndex( i );
00085 NotificationMessage msg;
00086 msg.setSessionId( settings->value( QLatin1String( "sessionId" ) ).toByteArray() );
00087 msg.setType( (NotificationMessage::Type)settings->value( QLatin1String( "type" ) ).toInt() );
00088 msg.setOperation( (NotificationMessage::Operation)settings->value( QLatin1String( "op" ) ).toInt() );
00089 msg.setUid( settings->value( QLatin1String( "uid" ) ).toLongLong() );
00090 msg.setRemoteId( settings->value( QLatin1String( "rid" ) ).toString() );
00091 msg.setResource( settings->value( QLatin1String( "resource" ) ).toByteArray() );
00092 msg.setParentCollection( settings->value( QLatin1String( "parentCol" ) ).toLongLong() );
00093 msg.setParentDestCollection( settings->value( QLatin1String( "parentDestCol" ) ).toLongLong() );
00094 msg.setMimeType( settings->value( QLatin1String( "mimeType" ) ).toString() );
00095 list = settings->value( QLatin1String( "itemParts" ) ).toStringList();
00096 QSet<QByteArray> itemParts;
00097 Q_FOREACH( const QString &entry, list )
00098 itemParts.insert( entry.toLatin1() );
00099 msg.setItemParts( itemParts );
00100 pendingNotifications << msg;
00101 }
00102
00103 settings->endArray();
00104
00105
00106 saveNotifications();
00107
00108
00109 settings->remove( QString() );
00110 settings->endGroup();
00111
00112
00113 }
00114
00115 QFile file( changesFileName );
00116 if ( !file.open( QIODevice::ReadOnly ) )
00117 return;
00118
00119 QDataStream stream( &file );
00120 stream.setVersion( QDataStream::Qt_4_6 );
00121
00122 qulonglong size;
00123 QByteArray sessionId, resource;
00124 int type, operation;
00125 qlonglong uid, parentCollection, parentDestCollection;
00126 QString remoteId, mimeType;
00127 QSet<QByteArray> itemParts;
00128
00129 stream >> size;
00130 for ( qulonglong i = 0; i < size; ++i ) {
00131 NotificationMessage msg;
00132
00133 stream >> sessionId;
00134 stream >> type;
00135 stream >> operation;
00136 stream >> uid;
00137 stream >> remoteId;
00138 stream >> resource;
00139 stream >> parentCollection;
00140 stream >> parentDestCollection;
00141 stream >> mimeType;
00142 stream >> itemParts;
00143
00144 msg.setSessionId( sessionId );
00145 msg.setType( static_cast<NotificationMessage::Type>( type ) );
00146 msg.setOperation( static_cast<NotificationMessage::Operation>( operation ) );
00147 msg.setUid( uid );
00148 msg.setRemoteId( remoteId );
00149 msg.setResource( resource );
00150 msg.setParentCollection( parentCollection );
00151 msg.setParentDestCollection( parentDestCollection );
00152 msg.setMimeType( mimeType );
00153 msg.setItemParts( itemParts );
00154 pendingNotifications << msg;
00155 }
00156 }
00157
00158 void saveNotifications()
00159 {
00160 if ( !settings )
00161 return;
00162
00163 QFile file( settings->fileName() + QLatin1String( "_changes.dat" ) );
00164 QFileInfo info( file );
00165 if ( !QFile::exists( info.absolutePath() ) ) {
00166 QDir dir;
00167 dir.mkpath( info.absolutePath() );
00168 }
00169 if ( !file.open( QIODevice::WriteOnly ) ) {
00170 qWarning() << "could not save notifications to file " << file.fileName();
00171 return;
00172 }
00173
00174 QDataStream stream( &file );
00175 stream.setVersion( QDataStream::Qt_4_6 );
00176
00177 stream << (qulonglong)pendingNotifications.count();
00178
00179 for ( int i = 0; i < pendingNotifications.count(); ++i ) {
00180 const NotificationMessage msg = pendingNotifications.at( i );
00181
00182 stream << msg.sessionId();
00183 stream << msg.type();
00184 stream << msg.operation();
00185 stream << msg.uid();
00186 stream << msg.remoteId();
00187 stream << msg.resource();
00188 stream << msg.parentCollection();
00189 stream << msg.parentDestCollection();
00190 stream << msg.mimeType();
00191 stream << msg.itemParts();
00192 }
00193
00194 file.close();
00195 }
00196 };
00197
00198 #endif