akonadi
changerecorder_p.h
00001 /* 00002 Copyright (c) 2007 Volker Krause <vkrause@kde.org> 00003 00004 This library is free software; you can redistribute it and/or modify it 00005 under the terms of the GNU Library General Public License as published by 00006 the Free Software Foundation; either version 2 of the License, or (at your 00007 option) any later version. 00008 00009 This library is distributed in the hope that it will be useful, but WITHOUT 00010 ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 00011 FITNESS FOR A PARTICULAR PURPOSE. See the GNU Library General Public 00012 License for more details. 00013 00014 You should have received a copy of the GNU Library General Public License 00015 along with this library; see the file COPYING.LIB. If not, write to the 00016 Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 00017 02110-1301, USA. 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; // we fill the pipeline ourselves when using change recording 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 ); // with change recording disabled this will automatically take care of dispatching notification messages 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 ); // skip notifications noone was listening to 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 // save notifications to the new file... 00106 saveNotifications(); 00107 00108 // ...delete the legacy list... 00109 settings->remove( QString() ); 00110 settings->endGroup(); 00111 00112 // ...and continue as usually 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