kmail

expirejob.cpp
1
29#include "expirejob.h"
30#include "kmfolder.h"
31#include "globalsettings.h"
32#include "folderstorage.h"
33#include "broadcaststatus.h"
34using KPIM::BroadcastStatus;
35#include "kmcommands.h"
36
37#include <kdebug.h>
38#include <tdelocale.h>
39
40using namespace KMail;
41
42// Look at this number of messages in each slotDoWork call
43#define EXPIREJOB_NRMESSAGES 100
44// And wait this number of milliseconds before calling it again
45#define EXPIREJOB_TIMERINTERVAL 100
46
47/*
48 Testcases for folder expiry:
49 Automatic expiry:
50 - normal case (ensure folder has old mails and expiry settings, wait for auto-expiry)
51 - having the folder selected when the expiry job would run (gets delayed)
52 - selecting a folder while an expiry job is running for it (should interrupt)
53 - exiting kmail while an expiry job is running (should abort & delete things cleanly)
54 Manual expiry:
55 - RMB / expire (for one folder) [KMMainWidget::slotExpireFolder()]
56 - RMB on Local Folders / Expire All Folders [KMFolderMgr::expireAll()]
57 - Expire All Folders [KMMainWidget::slotExpireAll()]
58*/
59
60
61ExpireJob::ExpireJob( KMFolder* folder, bool immediate )
62 : ScheduledJob( folder, immediate ), mTimer( this ), mCurrentIndex( 0 ),
63 mFolderOpen( false ), mMoveToFolder( 0 )
64{
65}
66
67ExpireJob::~ExpireJob()
68{
69}
70
71void ExpireJob::kill()
72{
73 Q_ASSERT( mCancellable );
74 // We must close the folder if we opened it and got interrupted
75 if ( mFolderOpen && mSrcFolder && mSrcFolder->storage() )
76 mSrcFolder->storage()->close( "expirejob" );
77 FolderJob::kill();
78}
79
80void ExpireJob::execute()
81{
82 mMaxUnreadTime = -1;
83 mMaxReadTime = -1;
84 mCurrentIndex = 0;
85
86 int unreadDays, readDays;
87 mSrcFolder->daysToExpire( unreadDays, readDays );
88 if (unreadDays >= 0) {
89 kdDebug(5006) << "ExpireJob: deleting unread older than "<< unreadDays << " days" << endl;
90 mMaxUnreadTime = time(0) - unreadDays * 3600 * 24;
91 }
92 if (readDays >= 0) {
93 kdDebug(5006) << "ExpireJob: deleting read older than "<< readDays << " days" << endl;
94 mMaxReadTime = time(0) - readDays * 3600 * 24;
95 }
96
97 if ((mMaxUnreadTime == 0) && (mMaxReadTime == 0)) {
98 kdDebug(5006) << "ExpireJob: nothing to do" << endl;
99 delete this;
100 return;
101 }
102
103 FolderStorage* storage = mSrcFolder->storage();
104 mOpeningFolder = true; // Ignore open-notifications while opening the folder
105 storage->open( "expirejob" );
106 mOpeningFolder = false;
107 mFolderOpen = true;
108 mCurrentIndex = storage->count()-1;
109 kdDebug(5006) << "ExpireJob: starting to expire in folder " << mSrcFolder->location() << endl;
110 connect( &mTimer, TQ_SIGNAL( timeout() ), TQ_SLOT( slotDoWork() ) );
111 mTimer.start( EXPIREJOB_TIMERINTERVAL );
112 slotDoWork();
113 // do nothing here, we might be deleted!
114}
115
116void ExpireJob::slotDoWork()
117{
118 // No need to worry about mSrcFolder==0 here. The FolderStorage deletes the jobs on destruction.
119 FolderStorage* storage = mSrcFolder->storage();
120 int stopIndex = mImmediate ? 0 : TQMAX( 0, mCurrentIndex - EXPIREJOB_NRMESSAGES );
121#ifdef DEBUG_SCHEDULER
122 kdDebug(5006) << "ExpireJob: checking messages " << mCurrentIndex << " to " << stopIndex << endl;
123#endif
124 for( ; mCurrentIndex >= stopIndex; mCurrentIndex-- ) {
125 const KMMsgBase *mb = storage->getMsgBase( mCurrentIndex );
126#ifdef DEBUG_SCHEDULER
127 kdDebug(5006) << "ExpireJob: checking message " << mCurrentIndex << " existence" << endl;
128#endif
129 if (mb == 0)
130 continue;
131#ifdef DEBUG_SCHEDULER
132 kdDebug(5006) << "ExpireJob: checking message " << mCurrentIndex << " importance" << endl;
133#endif
134 if ( ( mb->isImportant() || mb->isTodo() || mb->isWatched() )
135 && GlobalSettings::self()->excludeImportantMailFromExpiry() )
136 continue;
137
138#ifdef DEBUG_SCHEDULER
139 kdDebug(5006) << "ExpireJob: checking message " << mCurrentIndex << " time" << endl;
140#endif
141 time_t maxTime = mb->isUnread() ? mMaxUnreadTime : mMaxReadTime;
142
143#ifdef DEBUG_SCHEDULER
144 kdDebug(5006) << "ExpireJob: checking message " << mCurrentIndex << " time (" << mb->date() << " vs " << maxTime << ")" << endl;
145#endif
146 if (mb->date() < maxTime) {
147 kdDebug(5006) << "ExpireJob: expiring message " << mCurrentIndex << " from folder " << mSrcFolder->location() << endl;
148 mRemovedMsgs.append( storage->getMsgBase( mCurrentIndex ) );
149 }
150 }
151 if ( stopIndex == 0 )
152 done();
153}
154
155void ExpireJob::done()
156{
157 mTimer.stop();
158
159 TQString str;
160 bool moving = false;
161
162 if ( !mRemovedMsgs.isEmpty() ) {
163 int count = mRemovedMsgs.count();
164 // The command shouldn't kill us because it opens the folder
165 mCancellable = false;
166 if ( mSrcFolder->expireAction() == KMFolder::ExpireDelete ) {
167 // Expire by deletion, i.e. move to null target folder
168 kdDebug(5006) << "ExpireJob: finished expiring in folder "
169 << mSrcFolder->location()
170 << " " << count << " messages to remove." << endl;
171 KMMoveCommand* cmd = new KMMoveCommand( 0, mRemovedMsgs );
172 connect( cmd, TQ_SIGNAL( completed( KMCommand * ) ),
173 this, TQ_SLOT( slotMessagesMoved( KMCommand * ) ) );
174 cmd->start();
175 moving = true;
176 str = i18n( "Removing 1 old message from folder %1...",
177 "Removing %n old messages from folder %1...", count )
178 .arg( mSrcFolder->label() );
179 } else {
180 // Expire by moving
181 mMoveToFolder =
182 kmkernel->findFolderById( mSrcFolder->expireToFolderId() );
183 if ( !mMoveToFolder ) {
184 str = i18n( "Cannot expire messages from folder %1: destination "
185 "folder %2 not found" )
186 .arg( mSrcFolder->label(), mSrcFolder->expireToFolderId() );
187 kdWarning(5006) << str << endl;
188 } else {
189 kdDebug(5006) << "ExpireJob: finished expiring in folder "
190 << mSrcFolder->location() << " "
191 << mRemovedMsgs.count() << " messages to move to "
192 << mMoveToFolder->label() << endl;
193 KMMoveCommand* cmd = new KMMoveCommand( mMoveToFolder, mRemovedMsgs );
194 connect( cmd, TQ_SIGNAL( completed( KMCommand * ) ),
195 this, TQ_SLOT( slotMessagesMoved( KMCommand * ) ) );
196 cmd->start();
197 moving = true;
198 str = i18n( "Moving 1 old message from folder %1 to folder %2...",
199 "Moving %n old messages from folder %1 to folder %2...",
200 count )
201 .arg( mSrcFolder->label(), mMoveToFolder->label() );
202 }
203 }
204 }
205 if ( !str.isEmpty() )
206 BroadcastStatus::instance()->setStatusMsg( str );
207
208 TDEConfigGroup group( KMKernel::config(), "Folder-" + mSrcFolder->idString() );
209 group.writeEntry( "Current", -1 ); // i.e. make it invalid, the serial number will be used
210
211 if ( !moving ) {
212 mSrcFolder->storage()->close( "expirejob" );
213 mFolderOpen = false;
214 delete this;
215 }
216}
217
218void ExpireJob::slotMessagesMoved( KMCommand *command )
219{
220 mSrcFolder->storage()->close( "expirejob" );
221 mFolderOpen = false;
222 TQString msg;
223 switch ( command->result() ) {
224 case KMCommand::OK:
225 if ( mSrcFolder->expireAction() == KMFolder::ExpireDelete ) {
226 msg = i18n( "Removed 1 old message from folder %1.",
227 "Removed %n old messages from folder %1.",
228 mRemovedMsgs.count() )
229 .arg( mSrcFolder->label() );
230 }
231 else {
232 msg = i18n( "Moved 1 old message from folder %1 to folder %2.",
233 "Moved %n old messages from folder %1 to folder %2.",
234 mRemovedMsgs.count() )
235 .arg( mSrcFolder->label(), mMoveToFolder->label() );
236 }
237 break;
238 case KMCommand::Failed:
239 if ( mSrcFolder->expireAction() == KMFolder::ExpireDelete ) {
240 msg = i18n( "Removing old messages from folder %1 failed." )
241 .arg( mSrcFolder->label() );
242 }
243 else {
244 msg = i18n( "Moving old messages from folder %1 to folder %2 failed." )
245 .arg( mSrcFolder->label(), mMoveToFolder->label() );
246 }
247 break;
248 case KMCommand::Canceled:
249 if ( mSrcFolder->expireAction() == KMFolder::ExpireDelete ) {
250 msg = i18n( "Removing old messages from folder %1 was canceled." )
251 .arg( mSrcFolder->label() );
252 }
253 else {
254 msg = i18n( "Moving old messages from folder %1 to folder %2 was "
255 "canceled." )
256 .arg( mSrcFolder->label(), mMoveToFolder->label() );
257 }
258 default: ;
259 }
260 BroadcastStatus::instance()->setStatusMsg( msg );
261
262 deleteLater();
263}
264
265#include "expirejob.moc"
The FolderStorage class is the bass class for the storage related aspects of a collection of mail (a ...
Definition: folderstorage.h:80
virtual int open(const char *owner)=0
Open folder for access.
virtual int count(bool cache=false) const
Number of messages in this folder.
virtual const KMMsgBase * getMsgBase(int idx) const =0
Provides access to the basic message fields that are also stored in the index.
Mail folder.
Definition: kmfolder.h:69
Base class for scheduled jobs.
Definition: jobscheduler.h:144
folderdiaquotatab.h
Definition: aboutdata.cpp:40