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"