File indexing completed on 2024-11-10 04:40:37
0001 /* 0002 SPDX-FileCopyrightText: 2007 Volker Krause <vkrause@kde.org> 0003 0004 SPDX-License-Identifier: LGPL-2.0-or-later 0005 */ 0006 0007 #include "changerecorder.h" 0008 #include "changerecorder_p.h" 0009 0010 #include <QSettings> 0011 0012 using namespace Akonadi; 0013 0014 ChangeRecorder::ChangeRecorder(QObject *parent) 0015 : Monitor(new ChangeRecorderPrivate(nullptr, this), parent) 0016 { 0017 } 0018 0019 ChangeRecorder::ChangeRecorder(ChangeRecorderPrivate *privateclass, QObject *parent) 0020 : Monitor(privateclass, parent) 0021 { 0022 } 0023 0024 ChangeRecorder::~ChangeRecorder() 0025 { 0026 } 0027 0028 void ChangeRecorder::setConfig(QSettings *settings) 0029 { 0030 Q_D(ChangeRecorder); 0031 if (settings) { 0032 d->settings = settings; 0033 Q_ASSERT(d->pendingNotifications.isEmpty()); 0034 d->loadNotifications(); 0035 } else if (d->settings) { 0036 if (d->enableChangeRecording) { 0037 d->saveNotifications(); 0038 } 0039 d->settings = settings; 0040 } 0041 } 0042 0043 void ChangeRecorder::replayNext() 0044 { 0045 Q_D(ChangeRecorder); 0046 0047 if (!d->enableChangeRecording) { 0048 return; 0049 } 0050 0051 if (!d->pendingNotifications.isEmpty()) { 0052 const auto msg = d->pendingNotifications.head(); 0053 if (d->ensureDataAvailable(msg)) { 0054 d->emitNotification(msg); 0055 } else if (d->translateAndCompress(d->pipeline, msg)) { 0056 // The msg is now in both pipeline and pendingNotifications. 0057 // When data is available, MonitorPrivate::flushPipeline will emitNotification. 0058 // When changeProcessed is called, we'll finally remove it from pendingNotifications. 0059 } else { 0060 // In the case of a move where both source and destination are 0061 // ignored, we ignore the message and process the next one. 0062 d->dequeueNotification(); 0063 replayNext(); 0064 return; 0065 } 0066 } else { 0067 // This is necessary when none of the notifications were accepted / processed 0068 // above, and so there is no one to call changeProcessed() and the ChangeReplay task 0069 // will be stuck forever in the ResourceScheduler. 0070 Q_EMIT nothingToReplay(); 0071 } 0072 } 0073 0074 bool ChangeRecorder::isEmpty() const 0075 { 0076 Q_D(const ChangeRecorder); 0077 return d->pendingNotifications.isEmpty(); 0078 } 0079 0080 void ChangeRecorder::changeProcessed() 0081 { 0082 Q_D(ChangeRecorder); 0083 0084 if (!d->enableChangeRecording) { 0085 return; 0086 } 0087 0088 // changerecordertest.cpp calls changeProcessed after receiving nothingToReplay, 0089 // so test for emptiness. Not sure real code does this though. 0090 // Q_ASSERT( !d->pendingNotifications.isEmpty() ) 0091 if (!d->pendingNotifications.isEmpty()) { 0092 d->dequeueNotification(); 0093 } 0094 } 0095 0096 void ChangeRecorder::setChangeRecordingEnabled(bool enable) 0097 { 0098 Q_D(ChangeRecorder); 0099 if (d->enableChangeRecording == enable) { 0100 return; 0101 } 0102 d->enableChangeRecording = enable; 0103 if (enable) { 0104 d->m_needFullSave = true; 0105 d->notificationsLoaded(); 0106 } else { 0107 d->dispatchNotifications(); 0108 } 0109 } 0110 0111 QString Akonadi::ChangeRecorder::dumpNotificationListToString() const 0112 { 0113 Q_D(const ChangeRecorder); 0114 return d->dumpNotificationListToString(); 0115 } 0116 0117 #include "moc_changerecorder.cpp"