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( ChangeNotificationDependenciesFactory *dependenciesFactory_, ChangeRecorder* parent ) : 00030 MonitorPrivate( dependenciesFactory_, 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 no one was listening to 00063 return someoneWasListening; 00064 } 00065 00066 QString notificationsFileName() const 00067 { 00068 return settings->fileName() + QLatin1String( "_changes.dat" ); 00069 } 00070 00071 void loadNotifications() 00072 { 00073 pendingNotifications.clear(); 00074 00075 const QString changesFileName = notificationsFileName(); 00076 00083 if ( !QFile::exists( changesFileName ) ) { 00084 QStringList list; 00085 settings->beginGroup( QLatin1String( "ChangeRecorder" ) ); 00086 const int size = settings->beginReadArray( QLatin1String( "change" ) ); 00087 00088 for ( int i = 0; i < size; ++i ) { 00089 settings->setArrayIndex( i ); 00090 NotificationMessage msg; 00091 msg.setSessionId( settings->value( QLatin1String( "sessionId" ) ).toByteArray() ); 00092 msg.setType( (NotificationMessage::Type)settings->value( QLatin1String( "type" ) ).toInt() ); 00093 msg.setOperation( (NotificationMessage::Operation)settings->value( QLatin1String( "op" ) ).toInt() ); 00094 msg.setUid( settings->value( QLatin1String( "uid" ) ).toLongLong() ); 00095 msg.setRemoteId( settings->value( QLatin1String( "rid" ) ).toString() ); 00096 msg.setResource( settings->value( QLatin1String( "resource" ) ).toByteArray() ); 00097 msg.setParentCollection( settings->value( QLatin1String( "parentCol" ) ).toLongLong() ); 00098 msg.setParentDestCollection( settings->value( QLatin1String( "parentDestCol" ) ).toLongLong() ); 00099 msg.setMimeType( settings->value( QLatin1String( "mimeType" ) ).toString() ); 00100 list = settings->value( QLatin1String( "itemParts" ) ).toStringList(); 00101 QSet<QByteArray> itemParts; 00102 Q_FOREACH( const QString &entry, list ) 00103 itemParts.insert( entry.toLatin1() ); 00104 msg.setItemParts( itemParts ); 00105 pendingNotifications << msg; 00106 } 00107 00108 settings->endArray(); 00109 00110 // save notifications to the new file... 00111 saveNotifications(); 00112 00113 // ...delete the legacy list... 00114 settings->remove( QString() ); 00115 settings->endGroup(); 00116 00117 // ...and continue as usually 00118 } 00119 00120 QFile file( changesFileName ); 00121 if ( !file.open( QIODevice::ReadOnly ) ) 00122 return; 00123 pendingNotifications = loadFrom( &file ); 00124 } 00125 00126 QQueue<NotificationMessage> loadFrom( QIODevice *device ) 00127 { 00128 QDataStream stream( device ); 00129 stream.setVersion( QDataStream::Qt_4_6 ); 00130 00131 qulonglong size; 00132 QByteArray sessionId, resource; 00133 int type, operation; 00134 qlonglong uid, parentCollection, parentDestCollection; 00135 QString remoteId, mimeType; 00136 QSet<QByteArray> itemParts; 00137 00138 QQueue<NotificationMessage> list; 00139 00140 stream >> size; 00141 for ( qulonglong i = 0; i < size; ++i ) { 00142 NotificationMessage msg; 00143 00144 stream >> sessionId; 00145 stream >> type; 00146 stream >> operation; 00147 stream >> uid; 00148 stream >> remoteId; 00149 stream >> resource; 00150 stream >> parentCollection; 00151 stream >> parentDestCollection; 00152 stream >> mimeType; 00153 stream >> itemParts; 00154 00155 msg.setSessionId( sessionId ); 00156 msg.setType( static_cast<NotificationMessage::Type>( type ) ); 00157 msg.setOperation( static_cast<NotificationMessage::Operation>( operation ) ); 00158 msg.setUid( uid ); 00159 msg.setRemoteId( remoteId ); 00160 msg.setResource( resource ); 00161 msg.setParentCollection( parentCollection ); 00162 msg.setParentDestCollection( parentDestCollection ); 00163 msg.setMimeType( mimeType ); 00164 msg.setItemParts( itemParts ); 00165 list << msg; 00166 } 00167 return list; 00168 } 00169 00170 QString dumpNotificationListToString() const 00171 { 00172 QString result; 00173 const QString changesFileName = notificationsFileName(); 00174 QFile file( changesFileName ); 00175 if ( file.open( QIODevice::ReadOnly ) ) { 00176 QDataStream stream( &file ); 00177 stream.setVersion( QDataStream::Qt_4_6 ); 00178 00179 qulonglong size; 00180 QByteArray sessionId, resource; 00181 int type, operation; 00182 qlonglong uid, parentCollection, parentDestCollection; 00183 QString remoteId, mimeType; 00184 QSet<QByteArray> itemParts; 00185 00186 QStringList list; 00187 00188 stream >> size; 00189 for ( qulonglong i = 0; i < size; ++i ) { 00190 stream >> sessionId; 00191 stream >> type; 00192 stream >> operation; 00193 stream >> uid; 00194 stream >> remoteId; 00195 stream >> resource; 00196 stream >> parentCollection; 00197 stream >> parentDestCollection; 00198 stream >> mimeType; 00199 stream >> itemParts; 00200 00201 QString typeString; 00202 switch ( type ) { 00203 case NotificationMessage::Collection: 00204 typeString = QLatin1String( "Collection" ); 00205 break; 00206 case NotificationMessage::Item: 00207 typeString = QLatin1String( "Item" ); 00208 break; 00209 default: 00210 typeString = QLatin1String( "InvalidType" ); 00211 break; 00212 }; 00213 00214 QString operationString; 00215 switch ( operation ) { 00216 case NotificationMessage::Add: 00217 operationString = QLatin1String( "Add" ); 00218 break; 00219 case NotificationMessage::Modify: 00220 operationString = QLatin1String( "Modify" ); 00221 break; 00222 case NotificationMessage::Move: 00223 operationString = QLatin1String( "Move" ); 00224 break; 00225 case NotificationMessage::Remove: 00226 operationString = QLatin1String( "Remove" ); 00227 break; 00228 case NotificationMessage::Link: 00229 operationString = QLatin1String( "Link" ); 00230 break; 00231 case NotificationMessage::Unlink: 00232 operationString = QLatin1String( "Unlink" ); 00233 break; 00234 case NotificationMessage::Subscribe: 00235 operationString = QLatin1String( "Subscribe" ); 00236 break; 00237 case NotificationMessage::Unsubscribe: 00238 operationString = QLatin1String( "Unsubscribe" ); 00239 break; 00240 default: 00241 operationString = QLatin1String( "InvalidOp" ); 00242 break; 00243 }; 00244 00245 QStringList itemPartsList; 00246 foreach( const QByteArray &b, itemParts ) 00247 itemPartsList.push_back( QString::fromLatin1(b) ); 00248 00249 const QString entry = QString::fromLatin1("session=%1 type=%2 operation=%3 uid=%4 remoteId=%5 resource=%6 parentCollection=%7 parentDestCollection=%8 mimeType=%9 itemParts=%10") 00250 .arg( QString::fromLatin1( sessionId ) ) 00251 .arg( typeString ) 00252 .arg( operationString ) 00253 .arg( uid ) 00254 .arg( remoteId ) 00255 .arg( QString::fromLatin1( resource ) ) 00256 .arg( parentCollection ) 00257 .arg( parentDestCollection ) 00258 .arg( mimeType ) 00259 .arg( itemPartsList.join(QLatin1String(", " )) ); 00260 00261 result += entry + QLatin1Char('\n'); 00262 } 00263 00264 } 00265 return result; 00266 } 00267 00268 void addToStream( QDataStream &stream, const NotificationMessage &msg ) 00269 { 00270 stream << msg.sessionId(); 00271 stream << int(msg.type()); 00272 stream << int(msg.operation()); 00273 stream << qulonglong(msg.uid()); 00274 stream << msg.remoteId(); 00275 stream << msg.resource(); 00276 stream << qulonglong(msg.parentCollection()); 00277 stream << qulonglong(msg.parentDestCollection()); 00278 stream << msg.mimeType(); 00279 stream << msg.itemParts(); 00280 } 00281 00282 void saveNotifications() 00283 { 00284 if ( !settings ) 00285 return; 00286 00287 QFile file( notificationsFileName() ); 00288 QFileInfo info( file ); 00289 if ( !QFile::exists( info.absolutePath() ) ) { 00290 QDir dir; 00291 dir.mkpath( info.absolutePath() ); 00292 } 00293 if ( !file.open( QIODevice::WriteOnly ) ) { 00294 qWarning() << "could not save notifications to file " << file.fileName(); 00295 return; 00296 } 00297 saveTo(&file); 00298 } 00299 00300 void saveTo( QIODevice *device ) 00301 { 00302 00303 QDataStream stream( device ); 00304 stream.setVersion( QDataStream::Qt_4_6 ); 00305 00306 stream << (qulonglong)(pipeline.count() + pendingNotifications.count()); 00307 00308 for ( int i = 0; i < pipeline.count(); ++i ) { 00309 const NotificationMessage msg = pipeline.at( i ); 00310 addToStream( stream, msg ); 00311 } 00312 00313 for ( int i = 0; i < pendingNotifications.count(); ++i ) { 00314 const NotificationMessage msg = pendingNotifications.at( i ); 00315 addToStream( stream, msg ); 00316 } 00317 } 00318 }; 00319 00320 #endif
This file is part of the KDE documentation.
Documentation copyright © 1996-2012 The KDE developers.
Generated on Mon Apr 30 2012 21:49:14 by doxygen 1.8.0 written by Dimitri van Heesch, © 1997-2006
Documentation copyright © 1996-2012 The KDE developers.
Generated on Mon Apr 30 2012 21:49:14 by doxygen 1.8.0 written by Dimitri van Heesch, © 1997-2006
KDE's Doxygen guidelines are available online.