kmail

folderstorage.cpp
1/*
2 Virtual base class for mail storage.
3
4 This file is part of KMail.
5
6 Copyright (c) 2004 Bo Thorsen <bo@sonofthor.dk>
7
8 This library is free software; you can redistribute it and/or
9 modify it under the terms of the GNU Library General Public
10 License as published by the Free Software Foundation; either
11 version 2 of the License, or (at your option) any later version.
12
13 This library is distributed in the hope that it will be useful,
14 but WITHOUT ANY WARRANTY; without even the implied warranty of
15 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
16 Library General Public License for more details.
17
18 You should have received a copy of the GNU Library General Public License
19 along with this library; see the file COPYING.LIB. If not, write to
20 the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
21 Boston, MA 02110-1301, USA.
22
23 In addition, as a special exception, the copyright holders give
24 permission to link the code of this program with any edition of
25 the TQt library by Trolltech AS, Norway (or with modified versions
26 of TQt that use the same license as TQt), and distribute linked
27 combinations including the two. You must obey the GNU General
28 Public License in all respects for all of the code used other than
29 TQt. If you modify this file, you may extend this exception to
30 your version of the file, but you are not obligated to do so. If
31 you do not wish to do so, delete this exception statement from
32 your version.
33*/
34
35#include <config.h>
36
37#include "folderstorage.h"
38#include "kmfolder.h"
39#include "kmkernel.h"
40
41#include "kmfolderimap.h" //for the nasty imap hacks, FIXME
42#include "undostack.h"
43#include "kmmsgdict.h"
44#include "kmfoldermgr.h"
45#include "kmcommands.h"
46#include "listjob.h"
47using KMail::ListJob;
48#include "kmsearchpattern.h"
49#include "globalsettings.h"
50
51#include <tdelocale.h>
52#include <tdeconfig.h>
53#include <kdebug.h>
54
55#include <tqfile.h>
56#include <tqregexp.h>
57
58#include <mimelib/mimepp.h>
59#include <errno.h>
60
61//-----------------------------------------------------------------------------
62
63FolderStorage::FolderStorage( KMFolder* folder, const char* aName )
64 : TQObject( folder, aName ), mFolder( folder ), mEmitChangedTimer( 0L )
65{
66 mOpenCount = 0;
67 mQuiet = 0;
68 mChanged = false;
69 mAutoCreateIndex = true;
70 mExportsSernums = false;
71 mDirty = false;
72 mUnreadMsgs = -1;
73 mGuessedUnreadMsgs = -1;
74 mTotalMsgs = -1;
75 mSize = -1;
76 needsCompact = false;
77 mConvertToUtf8 = false;
78 mCompactable = true;
79 mNoContent = false;
80 mNoChildren = false;
81 mRDict = 0;
82 mDirtyTimer = new TQTimer(this, "mDirtyTimer");
83 connect(mDirtyTimer, TQ_SIGNAL(timeout()),
84 this, TQ_SLOT(updateIndex()));
85
86 mHasChildren = HasNoChildren;
87 mContentsType = KMail::ContentsTypeMail;
88
89 connect(this, TQ_SIGNAL(closed(KMFolder*)), mFolder, TQ_SIGNAL(closed()));
90}
91
92//-----------------------------------------------------------------------------
93FolderStorage::~FolderStorage()
94{
95 mJobList.setAutoDelete( true );
96 TQObject::disconnect( TQ_SIGNAL(destroyed(TQObject*)), this, 0 );
97 mJobList.clear();
98 KMMsgDict::deleteRentry(mRDict);
99}
100
101
102void FolderStorage::close( const char* owner, bool aForced )
103{
104 if (mOpenCount <= 0) return;
105 if (mOpenCount > 0) mOpenCount--;
106 if (mOpenCount > 0 && !aForced) return;
107
108 // kdWarning() << "Really closing: " << folder()->prettyURL() << kdBacktrace() << endl;
109 reallyDoClose(owner);
110}
111
112//-----------------------------------------------------------------------------
113TQString FolderStorage::dotEscape(const TQString& aStr)
114{
115 if (aStr[0] != '.') return aStr;
116 return aStr.left(aStr.find(TQRegExp("[^\\.]"))) + aStr;
117}
118
119void FolderStorage::addJob( FolderJob* job ) const
120{
121 TQObject::connect( job, TQ_SIGNAL(destroyed(TQObject*)),
122 TQ_SLOT(removeJob(TQObject*)) );
123 mJobList.append( job );
124}
125
126void FolderStorage::removeJob( TQObject* job )
127{
128 mJobList.remove( static_cast<FolderJob*>( job ) );
129}
130
131
132//-----------------------------------------------------------------------------
134{
135 TQString sLocation(const_cast<FolderStorage*>(this)->folder()->path());
136
137 if (!sLocation.isEmpty()) sLocation += '/';
138 sLocation += dotEscape(fileName());
139
140 return sLocation;
141}
142
144{
145 return mFolder->name();
146}
147
148
149
150//-----------------------------------------------------------------------------
152{
153 mAutoCreateIndex = autoIndex;
154}
155
156//-----------------------------------------------------------------------------
158{
159 mDirty = f;
161 mDirtyTimer->changeInterval( mDirtyTimerInterval );
162 else
163 mDirtyTimer->stop();
164}
165
166//-----------------------------------------------------------------------------
168{
169 KMMsgBase* msgBase;
170 int i;
171
172 for (i=0; i< count(); ++i)
173 {
174 if (!(msgBase = getMsgBase(i))) continue;
175 if (msgBase->isNew())
176 {
177 msgBase->setStatus(KMMsgStatusUnread);
178 msgBase->setDirty(true);
179 }
180 }
181}
182
184{
185 KMMsgBase* msgBase;
186 SerNumList serNums;
187
188 for (int i=count()-1; i>=0; --i)
189 {
190 msgBase = getMsgBase(i);
191 assert(msgBase);
192 if (msgBase->isNew() || msgBase->isUnread())
193 {
194 serNums.append( msgBase->getMsgSerNum() );
195 }
196 }
197 if (serNums.empty())
198 return;
199
200 KMCommand *command = new KMSeStatusCommand( KMMsgStatusRead, serNums );
201 command->start();
202}
203
204//-----------------------------------------------------------------------------
205void FolderStorage::quiet(bool beQuiet)
206{
207
208 if (beQuiet)
209 {
210 /* Allocate the timer here to don't have one timer for each folder. BTW,
211 * a timer is created when a folder is checked
212 */
213 if ( !mEmitChangedTimer) {
214 mEmitChangedTimer= new TQTimer( this, "mEmitChangedTimer" );
215 connect( mEmitChangedTimer, TQ_SIGNAL( timeout() ),
216 this, TQ_SLOT( slotEmitChangedTimer() ) );
217 }
218 mQuiet++;
219 } else {
220 mQuiet--;
221 if (mQuiet <= 0)
222 {
223 delete mEmitChangedTimer;
224 mEmitChangedTimer=0L;
225
226 mQuiet = 0;
227 if (mChanged) {
228 emit changed();
229 // Don't hurt emit this if the mUnreadMsg really don't change
230 // We emit it here, because this signal is delayed if mQuiet >0
231 emit numUnreadMsgsChanged( folder() );
232 }
233 mChanged = false;
234 }
235 }
236}
237
238//-----------------------------------------------------------------------------
239
241int operator<( KMMsgBase & m1, KMMsgBase & m2 )
242{
243 return (m1.date() < m2.date());
244}
245
247int operator==( KMMsgBase & m1, KMMsgBase & m2 )
248{
249 return (m1.date() == m2.date());
250}
251
252
253//-----------------------------------------------------------------------------
255{
256 int i, msgnb=0;
257 time_t msgTime, maxTime;
258 const KMMsgBase* mb;
259 TQValueList<int> rmvMsgList;
260
261 maxTime = time(0) - days * 3600 * 24;
262
263 for (i=count()-1; i>=0; i--) {
264 mb = getMsgBase(i);
265 assert(mb);
266 msgTime = mb->date();
267
268 if (msgTime < maxTime) {
269 //kdDebug(5006) << "deleting msg " << i << " : " << mb->subject() << " - " << mb->dateStr(); // << endl;
270 removeMsg( i );
271 msgnb++;
272 }
273 }
274 return msgnb;
275}
276
277//------------------------------------------
279{
280 emit changed();
281 mChanged=false;
282}
283//-----------------------------------------------------------------------------
285{
286 TQ_UINT32 serNum = KMMsgDict::instance()->getMsgSerNum( folder() , idx );
287 if (!mQuiet) {
288 emit msgAdded(idx);
289 } else {
292 if ( !mEmitChangedTimer->isActive() ) {
293 mEmitChangedTimer->start( 3000 );
294 }
295 mChanged=true;
296 }
297 emit msgAdded( folder(), serNum );
298}
299
300//-----------------------------------------------------------------------------
301bool FolderStorage::canAddMsgNow(KMMessage* aMsg, int* aIndex_ret)
302{
303 if (aIndex_ret) *aIndex_ret = -1;
304 KMFolder *msgParent = aMsg->parent();
305 // If the message has a parent and is in transfer, bail out. If it does not
306 // have a parent we want to be able to add it even if it is in transfer.
307 if (aMsg->transferInProgress() && msgParent)
308 return false;
309 if (!aMsg->isComplete() && msgParent && msgParent->folderType() == KMFolderTypeImap)
310 {
311 FolderJob *job = msgParent->createJob(aMsg);
312 connect(job, TQ_SIGNAL(messageRetrieved(KMMessage*)),
313 TQ_SLOT(reallyAddMsg(KMMessage*)));
314 job->start();
315 aMsg->setTransferInProgress( true );
316 return false;
317 }
318 return true;
319}
320
321
322//-----------------------------------------------------------------------------
324{
325 if (!aMsg) // the signal that is connected can call with aMsg=0
326 return;
327 aMsg->setTransferInProgress( false );
328 aMsg->setComplete( true );
329 KMFolder *aFolder = aMsg->parent();
330 int index;
331 ulong serNum = aMsg->getMsgSerNum();
332 bool undo = aMsg->enableUndo();
333 addMsg(aMsg, &index);
334 if (index < 0) return;
335 unGetMsg(index);
336 if (undo)
337 {
338 kmkernel->undoStack()->pushSingleAction( serNum, aFolder, folder() );
339 }
340}
341
342
343//-----------------------------------------------------------------------------
345{
346 if ( !aMsg ) return; // messageRetrieved(0) is always possible
347 aMsg->setParent( 0 );
348 aMsg->setTransferInProgress( false );
349 addMsg( aMsg );
350 unGetMsg( count() - 1 );
351}
352
353int FolderStorage::find( const KMMessage * msg ) const {
354 return find( &msg->toMsgBase() );
355}
356
357//-----------------------------------------------------------------------------
358void FolderStorage::removeMsg(const TQPtrList<KMMsgBase>& msgList, bool imapQuiet)
359{
360 for( TQPtrListIterator<KMMsgBase> it( msgList ); *it; ++it )
361 {
362 int idx = find(it.current());
363 assert( idx != -1);
364 removeMsg(idx, imapQuiet);
365 }
366}
367
368//-----------------------------------------------------------------------------
369void FolderStorage::removeMsg(const TQPtrList<KMMessage>& msgList, bool imapQuiet)
370{
371 for( TQPtrListIterator<KMMessage> it( msgList ); *it; ++it )
372 {
373 int idx = find(it.current());
374 assert( idx != -1);
375 removeMsg(idx, imapQuiet);
376 }
377}
378
379//-----------------------------------------------------------------------------
380void FolderStorage::removeMsg(int idx, bool)
381{
382 //assert(idx>=0);
383 if(idx < 0)
384 {
385 kdDebug(5006) << "FolderStorage::removeMsg() : idx < 0\n" << endl;
386 return;
387 }
388
389 KMMsgBase* mb = getMsgBase(idx);
390
391 TQ_UINT32 serNum = KMMsgDict::instance()->getMsgSerNum( folder(), idx );
392 if (serNum != 0)
393 emit msgRemoved( folder(), serNum );
394 mb = takeIndexEntry( idx );
395
396 setDirty( true );
397 needsCompact=true; // message is taken from here - needs to be compacted
398
399 if (mb->isUnread() || mb->isNew() ||
400 (folder() == kmkernel->outboxFolder())) {
401 --mUnreadMsgs;
402 if ( !mQuiet ) {
403// kdDebug( 5006 ) << "FolderStorage::msgStatusChanged" << endl;
404 emit numUnreadMsgsChanged( folder() );
405 }else{
406 if ( !mEmitChangedTimer->isActive() ) {
407// kdDebug( 5006 )<< "EmitChangedTimer started" << endl;
408 mEmitChangedTimer->start( 3000 );
409 }
410 mChanged = true;
411 }
412 }
413 --mTotalMsgs;
414
415 mSize = -1;
416 TQString msgIdMD5 = mb->msgIdMD5();
417 emit msgRemoved( idx, msgIdMD5 );
418 emit msgRemoved( folder() );
419}
420
421
422//-----------------------------------------------------------------------------
424{
425 KMMsgBase* mb;
426 KMMessage* msg;
427
428 assert(idx>=0 && idx<=count());
429
430 mb = getMsgBase(idx);
431 if (!mb) return 0;
432 if (!mb->isMessage()) readMsg(idx);
433 TQ_UINT32 serNum = KMMsgDict::instance()->getMsgSerNum( folder(), idx );
434 emit msgRemoved( folder(), serNum );
435
436 msg = (KMMessage*)takeIndexEntry(idx);
437
438 if (msg->isUnread() || msg->isNew() ||
439 ( folder() == kmkernel->outboxFolder() )) {
440 --mUnreadMsgs;
441 if ( !mQuiet ) {
442 emit numUnreadMsgsChanged( folder() );
443 }else{
444 if ( !mEmitChangedTimer->isActive() ) {
445 mEmitChangedTimer->start( 3000 );
446 }
447 mChanged = true;
448 }
449 }
450 --mTotalMsgs;
451 msg->setParent(0);
452 setDirty( true );
453 mSize = -1;
454 needsCompact=true; // message is taken from here - needs to be compacted
455 TQString msgIdMD5 = msg->msgIdMD5();
456 emit msgRemoved( idx, msgIdMD5 );
457 emit msgRemoved( folder() );
458
459 return msg;
460}
461
462void FolderStorage::take(TQPtrList<KMMessage> msgList)
463{
464 for ( KMMessage* msg = msgList.first(); msg; msg = msgList.next() )
465 {
466 if (msg->parent())
467 {
468 int idx = msg->parent()->find(msg);
469 if ( idx >= 0 )
470 take(idx);
471 }
472 }
473}
474
475
476//-----------------------------------------------------------------------------
478{
479 if ( mOpenCount <= 0 ) {
480 kdWarning(5006) << "FolderStorage::getMsg was called on a closed folder: " << folder()->prettyURL() << endl;
481 return 0;
482 }
483 if ( idx < 0 || idx >= count() ) {
484 kdWarning(5006) << "FolderStorage::getMsg was asked for an invalid index. idx =" << idx << " count()=" << count() << endl;
485 return 0;
486 }
487
488 KMMsgBase* mb = getMsgBase(idx);
489 if (!mb) {
490 kdWarning(5006) << "FolderStorage::getMsg, getMsgBase failed for index: " << idx << endl;
491 return 0;
492 }
493
494 KMMessage *msg = 0;
495 bool undo = mb->enableUndo();
496 if (mb->isMessage()) {
497 msg = ((KMMessage*)mb);
498 } else {
499 TQString mbSubject = mb->subject();
500 msg = readMsg(idx);
501 // sanity check
502 if (mCompactable && (!msg || (msg->subject().isEmpty() != mbSubject.isEmpty()))) {
503 kdDebug(5006) << "Error: " << location() <<
504 " Index file is inconsistent with folder file. This should never happen." << endl;
505
506 // We can't recreate the index at this point, since that would invalidate the current
507 // message list and delete KMMsgBase or KMMessage objects that are in use.
508 // Do it later in KMFolderIndex::readIndexHeader() instead.
509 mCompactable = false; // Don't compact
510 writeConfig();
511 }
512
513 }
514 // Either isMessage and we had a sernum, or readMsg gives us one
515 // (via insertion into mMsgList). sernum == 0 may still occur due to
516 // an outdated or corrupt IMAP cache.
517 if ( msg->getMsgSerNum() == 0 ) {
518 kdWarning(5006) << "FolderStorage::getMsg, message has no sernum, index: " << idx << endl;
519 return 0;
520 }
521 msg->setEnableUndo(undo);
522 msg->setComplete( true );
523 return msg;
524}
525
526//-----------------------------------------------------------------------------
528{
529 if(!(idx >= 0 && idx <= count())) {
530 kdDebug(5006) << k_funcinfo << "Invalid index " << idx << "!" << endl;
531 return 0;
532 }
533
534 KMMsgBase* mb = getMsgBase(idx);
535 if (!mb) {
536 kdDebug(5006) << k_funcinfo << "getMsgBase() for " << idx << " failed!" << endl;
537 return 0;
538 }
539
540 unsigned long sernum = mb->getMsgSerNum();
541
542 KMMessage *msg = 0;
543 bool undo = mb->enableUndo();
544 if (mb->isMessage()) {
545 // the caller will delete it, so we must make a copy it
546 msg = new KMMessage(*(KMMessage*)mb);
547 msg->setMsgSerNum(sernum);
548 msg->setComplete( true );
549 } else {
550 // ## Those two lines need to be moved to a virtual method for KMFolderSearch, like readMsg
551 msg = new KMMessage(*(KMMsgInfo*)mb);
552 msg->setMsgSerNum(sernum); // before fromDwString so that readyToShow uses the right sernum
553 msg->setComplete( true );
554 const DwString msgString = getDwString( idx );
555 if ( msgString.size() <= 0 ) {
556 kdDebug(5006) << k_funcinfo << " Calling getDwString() failed!" << endl;
557 }
558 msg->fromDwString( msgString );
559 }
560 msg->setEnableUndo(undo);
561 return msg;
562}
563
564
565//-----------------------------------------------------------------------------
566KMMsgInfo* FolderStorage::unGetMsg(int idx)
567{
568 KMMsgBase* mb;
569
570 if(!(idx >= 0 && idx <= count()))
571 return 0;
572
573 mb = getMsgBase(idx);
574 if (!mb) return 0;
575
576
577 if (mb->isMessage()) {
578 // Remove this message from all jobs' list it might still be on.
579 // setIndexEntry deletes the message.
580 KMMessage *msg = static_cast<KMMessage*>(mb);
581 if ( msg->transferInProgress() ) return 0;
583 return setIndexEntry( idx, msg );
584 }
585
586 return 0;
587}
588
589
590//-----------------------------------------------------------------------------
592{
593 KMMsgBase* mb;
594 if (!(idx >= 0 && idx <= count())) return false;
595 mb = getMsgBase(idx);
596 return (mb && mb->isMessage());
597}
598
599//-----------------------------------------------------------------------------
600FolderJob* FolderStorage::createJob( KMMessage *msg, FolderJob::JobType jt,
601 KMFolder *folder, TQString partSpecifier,
602 const AttachmentStrategy *as ) const
603{
604 FolderJob * job = doCreateJob( msg, jt, folder, partSpecifier, as );
605 if ( job )
606 addJob( job );
607 return job;
608}
609
610//-----------------------------------------------------------------------------
611FolderJob* FolderStorage::createJob( TQPtrList<KMMessage>& msgList, const TQString& sets,
612 FolderJob::JobType jt, KMFolder *folder ) const
613{
614 FolderJob * job = doCreateJob( msgList, sets, jt, folder );
615 if ( job )
616 addJob( job );
617 return job;
618}
619
620//-----------------------------------------------------------------------------
621int FolderStorage::moveMsg(KMMessage* aMsg, int* aIndex_ret)
622{
623 assert(aMsg != 0);
624 KMFolder* msgParent = aMsg->parent();
625
626 if (msgParent)
627 msgParent->open("moveMsgSrc");
628
629 open("moveMsgDest");
630 int rc = addMsg(aMsg, aIndex_ret);
631 close("moveMsgDest");
632
633 if (msgParent)
634 msgParent->close("moveMsgSrc");
635
636 return rc;
637}
638
639//-----------------------------------------------------------------------------
640int FolderStorage::moveMsg(TQPtrList<KMMessage> msglist, int* aIndex_ret)
641{
642 KMMessage* aMsg = msglist.first();
643 assert(aMsg != 0);
644 KMFolder* msgParent = aMsg->parent();
645
646 if (msgParent)
647 msgParent->open("foldermovemsg");
648
649 TQValueList<int> index;
650 open("moveMsg");
651 int rc = addMsg(msglist, index);
652 close("moveMsg");
653 // FIXME: we want to have a TQValueList to pass it back, so change this method
654 if ( !index.isEmpty() )
655 aIndex_ret = &index.first();
656
657 if (msgParent)
658 msgParent->close("foldermovemsg");
659
660 return rc;
661}
662
663
664//-----------------------------------------------------------------------------
665int FolderStorage::rename(const TQString& newName, KMFolderDir *newParent)
666{
667 TQString oldLoc, oldIndexLoc, oldIdsLoc, newLoc, newIndexLoc, newIdsLoc;
668 TQString oldSubDirLoc, newSubDirLoc;
669 TQString oldName;
670 int rc=0;
671 KMFolderDir *oldParent;
672
673 assert(!newName.isEmpty());
674
675 oldLoc = location();
676 oldIndexLoc = indexLocation();
677 oldSubDirLoc = folder()->subdirLocation();
678 oldIdsLoc = KMMsgDict::instance()->getFolderIdsLocation( *this );
679 TQString oldConfigString = "Folder-" + folder()->idString();
680
681 close("rename", true);
682
683 oldName = folder()->fileName();
684 oldParent = folder()->parent();
685 if (newParent)
686 folder()->setParent( newParent );
687
688 folder()->setName(newName);
689 newLoc = location();
690 newIndexLoc = indexLocation();
691 newSubDirLoc = folder()->subdirLocation();
692 newIdsLoc = KMMsgDict::instance()->getFolderIdsLocation( *this );
693
694 if (::rename(TQFile::encodeName(oldLoc), TQFile::encodeName(newLoc))) {
695 folder()->setName(oldName);
696 folder()->setParent(oldParent);
697 rc = errno;
698 }
699 else {
700 // rename/move index file and index.sorted file
701 if (!oldIndexLoc.isEmpty()) {
702 ::rename(TQFile::encodeName(oldIndexLoc), TQFile::encodeName(newIndexLoc));
703 ::rename(TQFile::encodeName(oldIndexLoc) + ".sorted",
704 TQFile::encodeName(newIndexLoc) + ".sorted");
705 }
706
707 // rename/move serial number file
708 if (!oldIdsLoc.isEmpty())
709 ::rename(TQFile::encodeName(oldIdsLoc), TQFile::encodeName(newIdsLoc));
710
711 // rename/move the subfolder directory
712 KMFolderDir* child = 0;
713 if( folder() )
714 child = folder()->child();
715
716 if (!::rename(TQFile::encodeName(oldSubDirLoc), TQFile::encodeName(newSubDirLoc) )) {
717 // now that the subfolder directory has been renamed and/or moved also
718 // change the name that is stored in the corresponding KMFolderNode
719 // (provide that the name actually changed)
720 if( child && ( oldName != newName ) ) {
721 child->setName( "." + TQFile::encodeName(newName) + ".directory" );
722 }
723 }
724
725 // if the folder is being moved then move its node and, if necessary, also
726 // the associated subfolder directory node to the new parent
727 if (newParent) {
728 if (oldParent->findRef( folder() ) != -1)
729 oldParent->take();
730 newParent->inSort( folder() );
731 if ( child ) {
732 if ( child->parent()->findRef( child ) != -1 )
733 child->parent()->take();
734 newParent->inSort( child );
735 child->setParent( newParent );
736 }
737 }
738 }
739
740 writeConfig();
741
742 // delete the old entry as we get two entries with the same ID otherwise
743 if ( oldConfigString != "Folder-" + folder()->idString() )
744 KMKernel::config()->deleteGroup( oldConfigString );
745
746 emit locationChanged( oldLoc, newLoc );
747 emit nameChanged();
748 kmkernel->folderMgr()->contentsChanged();
749 emit closed(folder()); // let the ticket owners regain
750 return rc;
751}
752
753
754//-----------------------------------------------------------------------------
756{
757 assert(!folder()->name().isEmpty());
758
759 clearIndex( true, mExportsSernums ); // delete and remove from dict if necessary
760 close("remove", true);
761
762 if ( mExportsSernums ) {
763 KMMsgDict::mutableInstance()->removeFolderIds( *this );
764 mExportsSernums = false; // do not writeFolderIds after removal
765 }
766 unlink(TQFile::encodeName(indexLocation()) + ".sorted");
767 unlink(TQFile::encodeName(indexLocation()));
768
769 int rc = removeContents();
770
771 needsCompact = false; //we are dead - no need to compact us
772
773 // Erase settings, otherwise they might interfer when recreating the folder
774 TDEConfig* config = KMKernel::config();
775 config->deleteGroup( "Folder-" + folder()->idString() );
776
777 emit closed(folder());
778 emit removed(folder(), (rc ? false : true));
779}
780
781
782//-----------------------------------------------------------------------------
784{
785 assert(!folder()->name().isEmpty());
786
787 clearIndex( true, mExportsSernums ); // delete and remove from dict, if needed
788 close( "expunge", true );
789
790 if ( mExportsSernums )
791 KMMsgDict::mutableInstance()->removeFolderIds( *this );
792 if ( mAutoCreateIndex )
793 truncateIndex();
794 else unlink(TQFile::encodeName(indexLocation()));
795
796 int rc = expungeContents();
797 if (rc) return rc;
798
799 mDirty = false;
800 needsCompact = false; //we're cleared and truncated no need to compact
801
802 mUnreadMsgs = 0;
803 mTotalMsgs = 0;
804 mSize = 0;
805 emit numUnreadMsgsChanged( folder() );
806 if ( mAutoCreateIndex ) // FIXME Heh? - Till
807 writeConfig();
808 emit changed();
809 emit expunged( folder() );
810
811 return 0;
812}
813
814//-----------------------------------------------------------------------------
815TQString FolderStorage::label() const
816{
817 return folder()->label();
818}
819
820int FolderStorage::count(bool cache) const
821{
822 if (cache && mTotalMsgs != -1)
823 return mTotalMsgs;
824 else
825 return -1;
826}
827
828//-----------------------------------------------------------------------------
830{
831 if (mGuessedUnreadMsgs > -1)
832 return mGuessedUnreadMsgs;
833 if (mUnreadMsgs > -1)
834 return mUnreadMsgs;
835
836 readConfig();
837
838 if (mUnreadMsgs > -1)
839 return mUnreadMsgs;
840
841 open("countunread"); // will update unreadMsgs
842 int unread = mUnreadMsgs;
843 close("countunread");
844 return (unread > 0) ? unread : 0;
845}
846
848{
849 if ( mSize != -1 ) {
850 return mSize;
851 } else {
852 return doFolderSize();
853 }
854}
855
856
857/*virtual*/
859{
860 return false;
861}
862
863//-----------------------------------------------------------------------------
864void FolderStorage::msgStatusChanged(const KMMsgStatus oldStatus,
865 const KMMsgStatus newStatus, int idx)
866{
867 int oldUnread = 0;
868 int newUnread = 0;
869
870 if (((oldStatus & KMMsgStatusUnread || oldStatus & KMMsgStatusNew) &&
871 !(oldStatus & KMMsgStatusIgnored)) ||
872 (folder() == kmkernel->outboxFolder()))
873 oldUnread = 1;
874 if (((newStatus & KMMsgStatusUnread || newStatus & KMMsgStatusNew) &&
875 !(newStatus & KMMsgStatusIgnored)) ||
876 (folder() == kmkernel->outboxFolder()))
877 newUnread = 1;
878 int deltaUnread = newUnread - oldUnread;
879
880 mDirtyTimer->changeInterval(mDirtyTimerInterval);
881 if (deltaUnread != 0) {
882 if (mUnreadMsgs < 0) mUnreadMsgs = 0;
883 mUnreadMsgs += deltaUnread;
884 if ( !mQuiet ) {
885 emit numUnreadMsgsChanged( folder() );
886 }else{
887 if ( !mEmitChangedTimer->isActive() ) {
888 mEmitChangedTimer->start( 3000 );
889 }
890 mChanged = true;
891 }
892 TQ_UINT32 serNum = KMMsgDict::instance()->getMsgSerNum(folder(), idx);
893 emit msgChanged( folder(), serNum, deltaUnread );
894 }
895}
896
897//-----------------------------------------------------------------------------
898void FolderStorage::headerOfMsgChanged(const KMMsgBase* aMsg, int idx)
899{
900 if (idx < 0)
901 idx = aMsg->parent()->find( aMsg );
902
903 if (idx >= 0 )
904 {
905 if ( !mQuiet )
906 emit msgHeaderChanged(folder(), idx);
907 else{
908 if ( !mEmitChangedTimer->isActive() ) {
909 mEmitChangedTimer->start( 3000 );
910 }
911 mChanged = true;
912 }
913 } else
914 mChanged = true;
915}
916
917//-----------------------------------------------------------------------------
919{
920 //kdDebug(5006)<<"#### READING CONFIG = "<< name() <<endl;
921 TDEConfig* config = KMKernel::config();
922 TDEConfigGroupSaver saver(config, "Folder-" + folder()->idString());
923 if (mUnreadMsgs == -1)
924 mUnreadMsgs = config->readNumEntry("UnreadMsgs", -1);
925 if (mTotalMsgs == -1)
926 mTotalMsgs = config->readNumEntry("TotalMsgs", -1);
927 mCompactable = config->readBoolEntry("Compactable", true);
928 if ( mSize == -1 )
929 mSize = config->readNum64Entry("FolderSize", -1);
930
931 int type = config->readNumEntry( "ContentsType", 0 );
932 if ( type < 0 || type > KMail::ContentsTypeLast ) type = 0;
933 setContentsType( static_cast<KMail::FolderContentsType>( type ) );
934
935 if( folder() ) folder()->readConfig( config );
936}
937
938//-----------------------------------------------------------------------------
940{
941 TDEConfig* config = KMKernel::config();
942 TDEConfigGroupSaver saver(config, "Folder-" + folder()->idString());
943 config->writeEntry("UnreadMsgs",
944 mGuessedUnreadMsgs == -1 ? mUnreadMsgs : mGuessedUnreadMsgs);
945 config->writeEntry("TotalMsgs", mTotalMsgs);
946 config->writeEntry("Compactable", mCompactable);
947 config->writeEntry("ContentsType", mContentsType);
948 config->writeEntry("FolderSize", mSize);
949
950 // Write the KMFolder parts
951 if( folder() ) folder()->writeConfig( config );
952
953 GlobalSettings::self()->requestSync();
954}
955
956//-----------------------------------------------------------------------------
958{
959 open("countunreadmsg");
960 close("countunreadmsg");
961 emit numUnreadMsgsChanged( folder() );
962}
963
965{
966 mExportsSernums = true;
968}
969
971{
973 mExportsSernums = false;
974}
975
977{
978 if ( !mExportsSernums ) return;
979 if ( KMMsgDict::mutableInstance()->readFolderIds( *this ) == -1 ) {
981 }
982 if ( !KMMsgDict::mutableInstance()->hasFolderIds( *this ) ) {
984 }
985}
986
988{
989 if ( !mExportsSernums ) return;
990 unlink(TQFile::encodeName( indexLocation()) + ".sorted");
991 unlink(TQFile::encodeName( indexLocation()) + ".ids");
993 KMMsgDict::mutableInstance()->writeFolderIds( *this );
994 emit invalidated( folder() );
995}
996
997
998//-----------------------------------------------------------------------------
1000{
1001 if ( !mExportsSernums ) return -1;
1002 return KMMsgDict::mutableInstance()->writeFolderIds( *this );
1003}
1004
1005//-----------------------------------------------------------------------------
1007{
1008 if ( !mExportsSernums ) return -1;
1009 return KMMsgDict::mutableInstance()->touchFolderIds( *this );
1010}
1011
1012//-----------------------------------------------------------------------------
1014{
1015 if ( !mExportsSernums ) return -1;
1016 int ret = 0;
1017 if ( count() == 1 ) {
1018 ret = KMMsgDict::mutableInstance()->writeFolderIds( *this );
1019 } else {
1020 ret = KMMsgDict::mutableInstance()->appendToFolderIds( *this, idx );
1021 }
1022 return ret;
1023}
1024
1025void FolderStorage::replaceMsgSerNum( unsigned long sernum, KMMsgBase* msg, int idx )
1026{
1027 if ( !mExportsSernums ) return;
1028 KMMsgDict::mutableInstance()->replace( sernum, msg, idx );
1029}
1030
1031void FolderStorage::setRDict( KMMsgDictREntry *rentry ) const
1032{
1033 if ( ! mExportsSernums )
1034 kdDebug(5006) << "WTF, this FolderStorage should be invisible to the msgdict, who is calling us?" << kdBacktrace() << endl;
1035 assert( mExportsSernums ); // otherwise things are very wrong
1036 if ( rentry == mRDict )
1037 return;
1038 KMMsgDict::deleteRentry( mRDict );
1039 mRDict = rentry;
1040}
1041
1042//-----------------------------------------------------------------------------
1043void FolderStorage::setStatus(int idx, KMMsgStatus status, bool toggle)
1044{
1045 KMMsgBase *msg = getMsgBase(idx);
1046 if ( msg ) {
1047 if (toggle)
1048 msg->toggleStatus(status, idx);
1049 else
1050 msg->setStatus(status, idx);
1051 }
1052}
1053
1054
1055//-----------------------------------------------------------------------------
1056void FolderStorage::setStatus(TQValueList<int>& ids, KMMsgStatus status, bool toggle)
1057{
1058 for ( TQValueList<int>::Iterator it = ids.begin(); it != ids.end(); ++it )
1059 {
1060 FolderStorage::setStatus(*it, status, toggle);
1061 }
1062}
1063
1065{
1066 if ( !msg || msg->transferInProgress() )
1067 return;
1068
1069 TQPtrListIterator<FolderJob> it( mJobList );
1070 while ( it.current() )
1071 {
1072 //FIXME: the questions is : should we iterate through all
1073 //messages in jobs? I don't think so, because it would
1074 //mean canceling the jobs that work with other messages
1075 if ( it.current()->msgList().first() == msg )
1076 {
1077 FolderJob* job = it.current();
1078 mJobList.remove( job );
1079 delete job;
1080 } else
1081 ++it;
1082 }
1083}
1084
1085//-----------------------------------------------------------------------------
1086void FolderStorage::removeJobs()
1087{
1088 mJobList.setAutoDelete( true );
1089 mJobList.clear();
1090 mJobList.setAutoDelete( false );
1091}
1092
1093
1094
1095//-----------------------------------------------------------------------------
1097{
1098 if ( folder() && folder()->child() )
1099 {
1100 if ( kmkernel->folderMgr()->folderCount( folder()->child() ) > 0 )
1101 setHasChildren( HasChildren );
1102 else
1103 setHasChildren( HasNoChildren );
1104 }
1105}
1106
1107//-----------------------------------------------------------------------------
1108void FolderStorage::setNoChildren( bool aNoChildren )
1109{
1110 mNoChildren = aNoChildren;
1111 if ( aNoChildren )
1112 setHasChildren( HasNoChildren );
1113}
1114
1115//-----------------------------------------------------------------------------
1116void FolderStorage::setContentsType( KMail::FolderContentsType type, bool quiet )
1117{
1118 if ( type != mContentsType ) {
1119 mContentsType = type;
1120 if ( !quiet )
1121 emit contentsTypeChanged( type );
1122 }
1123}
1124
1125//-----------------------------------------------------------------------------
1127{
1128 mSearchPattern = pattern;
1129 mCurrentSearchedMsg = 0;
1130 if ( pattern )
1132}
1133
1135{
1136 if ( !mSearchPattern )
1137 return;
1138 TQValueList<TQ_UINT32> matchingSerNums;
1139 const int end = TQMIN( mCurrentSearchedMsg + 15, count() );
1140 for ( int i = mCurrentSearchedMsg; i < end; ++i )
1141 {
1142 TQ_UINT32 serNum = KMMsgDict::instance()->getMsgSerNum( folder(), i );
1143 if ( mSearchPattern->matches( serNum ) )
1144 matchingSerNums.append( serNum );
1145 }
1146 mCurrentSearchedMsg = end;
1147 bool complete = ( end >= count() );
1148 emit searchResult( folder(), matchingSerNums, mSearchPattern, complete );
1149 if ( !complete )
1150 TQTimer::singleShot( 0, this, TQ_SLOT(slotProcessNextSearchBatch()) );
1151}
1152
1153//-----------------------------------------------------------------------------
1154void FolderStorage::search( const KMSearchPattern* pattern, TQ_UINT32 serNum )
1155{
1156 bool matches = pattern && pattern->matches( serNum );
1157
1158 emit searchDone( folder(), serNum, pattern, matches );
1159}
1160
1161//-----------------------------------------------------------------------------
1162int FolderStorage::addMsg( TQPtrList<KMMessage>& msgList, TQValueList<int>& index_ret )
1163{
1164 int ret = 0;
1165 int index;
1166 for ( TQPtrListIterator<KMMessage> it( msgList ); *it; ++it )
1167 {
1168 int aret = addMsg( *it, &index );
1169 index_ret << index;
1170 if ( aret != 0 ) // error condition
1171 ret = aret;
1172 }
1173 return ret;
1174}
1175
1176//-----------------------------------------------------------------------------
1178{
1179 return ( folder()->isSystemFolder() ) ? false : true;
1180}
1181
1182
1183/*virtual*/
1184KMAccount* FolderStorage::account() const
1185{
1186 return 0;
1187}
1188
1189bool FolderStorage::mailCheckInProgress() const
1190{
1191 return false;
1192}
1193
1195{
1196 return !isReadOnly();
1197}
1198
1199void FolderStorage::setNoContent(bool aNoContent)
1200{
1201 const bool changed = aNoContent != mNoContent;
1202 mNoContent = aNoContent;
1203 if ( changed )
1204 emit noContentChanged();
1205}
1206
1207#include "folderstorage.moc"
The FolderStorage class is the bass class for the storage related aspects of a collection of mail (a ...
Definition: folderstorage.h:80
virtual bool isMessage(int idx)
Checks if the message is already "gotten" with getMsg.
virtual int countUnread()
Number of new or unread messages in this folder.
virtual void ignoreJobsForMessage(KMMessage *)
Removes and deletes all jobs associated with the particular message.
void nameChanged()
Emitted when the name of the folder changes.
virtual DwString getDwString(int idx)=0
Read a message and returns a DwString.
virtual void markNewAsUnread()
Mark all new messages as unread.
int writeFolderIdsFile() const
Writes the message serial number file.
virtual int open(const char *owner)=0
Open folder for access.
virtual TQString indexLocation() const =0
Returns full path to index file.
virtual KMMessage * take(int idx)
Detach message from this folder.
virtual int count(bool cache=false) const
Number of messages in this folder.
void invalidated(KMFolder *)
Emitted when the serial numbers of this folder were invalidated.
void emitMsgAddedSignals(int idx)
Called by derived classes implementation of addMsg.
void msgHeaderChanged(KMFolder *, int)
Emitted when a field of the header of a specific message changed.
virtual bool isMoveable() const
Returns true if this folder can be moved.
void slotEmitChangedTimer()
Emit changed signal if mQuite <=0.
virtual int updateIndex()=0
Incrementally update the index if possible else call writeIndex.
virtual int expungeOldMsg(int days)
Delete messages in the folder that are older than days.
virtual KMMessage * readTemporaryMsg(int idx)
Load message from file and do NOT store it, only return it.
virtual int rename(const TQString &newName, KMFolderDir *aParent=0)
Physically rename the folder.
virtual void setContentsType(KMail::FolderContentsType type, bool quiet=false)
Set the type of contents held in this folder (mail, calendar, etc.)
virtual void msgStatusChanged(const KMMsgStatus oldStatus, const KMMsgStatus newStatus, int idx)
Called by KMMsgBase::setStatus when status of a message has changed required to keep the number unrea...
int appendToFolderIdsFile(int idx=-1)
Append message to end of message serial number file.
void registerWithMessageDict()
Triggers registration with the message dict, which will cause the dict to ask the FolderStorage to fi...
virtual TQString fileName() const
Returns the filename of the folder (reimplemented in KMFolderImap)
void msgRemoved(KMFolder *, TQ_UINT32 sernum)
Emitted before a message is removed from the folder.
virtual int find(const KMMsgBase *msg) const =0
Returns the index of the given message or -1 if not found.
virtual void reallyAddMsg(KMMessage *aMsg)
Add the message to the folder after it has been retrieved from an IMAP server.
bool needsCompact
sven: true if on destruct folder needs to be compacted.
virtual KMMessage * readMsg(int idx)=0
Load message from file and store it at given index.
void msgChanged(KMFolder *, TQ_UINT32 sernum, int delta)
Emitted, when the status of a message is changed.
void expunged(KMFolder *)
Emitted after an expunge.
virtual FolderJob * createJob(KMMessage *msg, FolderJob::JobType jt=FolderJob::tGetMessage, KMFolder *folder=0, TQString partSpecifier=TQString(), const AttachmentStrategy *as=0) const
These methods create respective FolderJob (You should derive FolderJob for each derived KMFolder).
virtual void setHasChildren(ChildrenState state)
Specify if the folder has children.
int touchFolderIdsFile()
Touches the message serial number file.
void addJob(FolderJob *) const
Add job for this folder.
virtual void readConfig()
Read the config file.
virtual const KMMsgBase * getMsgBase(int idx) const =0
Provides access to the basic message fields that are also stored in the index.
static TQString dotEscape(const TQString &)
Escape a leading dot.
FolderStorage(KMFolder *folder, const char *name=0)
Usually a parent is given.
virtual void markUnreadAsRead()
Mark all new and unread messages as read.
void numUnreadMsgsChanged(KMFolder *)
Emitted when number of unread messages has changed.
void replaceMsgSerNum(unsigned long sernum, KMMsgBase *msg, int idx)
Replaces the serial number for the message msg at index idx with sernum.
void changed()
Emitted when the status, name, or associated accounts of this folder changed.
virtual void setStatus(int idx, KMMsgStatus status, bool toggle=false)
Set the status of the message at index idx to status.
void invalidateFolder()
Called when serial numbers for a folder are invalidated, invalidates/recreates data structures depend...
TQPtrList< FolderJob > mJobList
List of jobs created by this folder.
virtual int expunge()
Delete entire folder.
virtual FolderJob * doCreateJob(KMMessage *msg, FolderJob::JobType jt, KMFolder *folder, TQString partSpecifier, const AttachmentStrategy *as) const =0
These two methods actually create the jobs.
bool mExportsSernums
Has this storage exported its serial numbers to the global message dict for lookup?
virtual void correctUnreadMsgsCount()
A cludge to help make sure the count of unread messges is kept in sync.
virtual void reallyAddCopyOfMsg(KMMessage *aMsg)
Add a copy of the message to the folder after it has been retrieved from an IMAP server.
virtual int expungeContents()=0
Called by KMFolder::expunge() to delete the actual contents.
virtual void updateChildrenState()
Updates the hasChildren() state.
void searchDone(KMFolder *, TQ_UINT32, const KMSearchPattern *, bool)
Emitted when a search for a single message is completed The serial number and a bool matching yes/no ...
virtual void removeMsg(int i, bool imapQuiet=false)
Remove (first occurrence of) given message from the folder.
void readFolderIdsFile()
Read the on-disk cache of serial numbers of messages in this store and fill those into the global mes...
virtual bool canAddMsgNow(KMMessage *aMsg, int *aIndex_ret)
Returns FALSE, if the message has to be retrieved from an IMAP account first.
void setDirty(bool f)
Change the dirty flag.
void headerOfMsgChanged(const KMMsgBase *, int idx)
Tell the folder that a header field that is usually used for the index (subject, from,...
KMail::FolderContentsType mContentsType
Type of contents in this folder.
virtual void search(const KMSearchPattern *)
Search for messages The end is signaled with searchDone()
virtual void remove()
Removes the folder physically from disk and empties the contents of the folder in memory.
virtual bool canDeleteMessages() const
Can messages in this folder be deleted?
void close(const char *owner, bool force=false)
Close folder.
virtual KMMsgInfo * unGetMsg(int idx)
Replace KMMessage with KMMsgInfo and delete KMMessage
virtual int removeContents()=0
Called by KMFolder::remove() to delete the actual contents.
void noContentChanged()
Emitted when the no content state of the folder changes.
bool mDirty
if the index is dirty it will be recreated upon close()
virtual void writeConfig()
Write the config file.
void locationChanged(const TQString &, const TQString &)
Emitted when the location on disk of the folder changes.
virtual int moveMsg(KMMessage *msg, int *index_return=0)
Detaches the given message from it's current folder and adds it to this folder.
virtual int addMsg(KMMessage *msg, int *index_return=0)=0
Add the given message to the folder.
void removed(KMFolder *, bool)
Emitted when a folder was removed.
void slotProcessNextSearchBatch()
Process the next search batch.
void msgAdded(int idx)
Emitted when a message is added from the folder.
virtual void setAutoCreateIndex(bool)
Allow/disallow automatic creation of a table of contents file.
void searchResult(KMFolder *, TQValueList< TQ_UINT32 >, const KMSearchPattern *, bool complete)
Emitted when a search delivers results The matching serial numbers are included If complete is true t...
TQString label() const
Returns the label of the folder for visualization.
bool mCompactable
false if index file is out of sync with mbox file
virtual void setNoChildren(bool aNoChildren)
Specify, that the folder can't have children.
void setRDict(KMMsgDictREntry *rentry) const
Sets the reverse-dictionary for this folder.
KMMsgDictREntry * mRDict
Points at the reverse dictionary for this folder.
TQString location() const
Returns full path to folder file.
void contentsTypeChanged(KMail::FolderContentsType type)
Emitted when the contents type (calendar, mail, tasks, ..) of the folderstorage changes.
virtual void fillMessageDict()
Inserts messages into the message dictionary.
virtual bool isReadOnly() const =0
Is the folder read-only?
virtual KMMessage * getMsg(int idx)
Read message at given index.
int mUnreadMsgs
number of unread messages, -1 if not yet set
bool mAutoCreateIndex
is the automatic creation of a index file allowed ?
void closed(KMFolder *)
Emitted when the folder was closed and ticket owners have to reopen.
virtual bool isCloseToQuota() const
Return whether the folder is close to its quota limit, which can be reflected in the UI.
TQ_INT64 folderSize() const
Total size of the contents of this folder.
virtual void quiet(bool beQuiet)
If set to quiet the folder will not emit msgAdded(idx) signal.
void deregisterFromMessageDict()
Triggers deregistration from the message dict, which will cause the dict to ask the FolderStorage to ...
virtual void setNoContent(bool aNoContent)
Specify, that the folder can't contain mails.
KMail list that manages the contents of one directory that may contain folders and/or other directori...
Definition: kmfolderdir.h:16
Mail folder.
Definition: kmfolder.h:69
TQString subdirLocation() const
Returns full path to sub directory file.
Definition: kmfolder.cpp:253
TQString idString() const
Returns a string that can be used to identify this folder.
Definition: kmfolder.cpp:705
virtual TQString prettyURL() const
URL of the node for visualization purposes.
Definition: kmfolder.cpp:593
virtual TQString label() const
Returns the label of the folder for visualization.
Definition: kmfolder.cpp:581
TQString fileName() const
Returns the filename of the folder (reimplemented in KMFolderImap)
Definition: kmfolder.cpp:238
FolderJob * createJob(KMMessage *msg, FolderJob::JobType jt=FolderJob::tGetMessage, KMFolder *folder=0, TQString partSpecifier=TQString(), const AttachmentStrategy *as=0) const
These methods create respective FolderJob (You should derive FolderJob for each derived KMFolder).
Definition: kmfolder.cpp:346
void close(const char *owner, bool force=false)
Close folder.
Definition: kmfolder.cpp:489
void readConfig(TDEConfig *config)
This is used by the storage to read the folder specific configuration.
Definition: kmfolder.cpp:161
KMFolderType folderType() const
Returns the type of this folder.
Definition: kmfolder.cpp:233
int open(const char *owner)
Open folder for access.
Definition: kmfolder.cpp:479
void writeConfig(TDEConfig *config) const
This is used by the storage to save the folder specific configuration.
Definition: kmfolder.cpp:200
KMFolderDir * child() const
Returns the folder directory associated with this node or 0 if no such directory exists.
Definition: kmfolder.h:157
This is a Mime Message.
Definition: kmmessage.h:68
void setTransferInProgress(bool value, bool force=false)
Set that the message shall not be deleted because it is still required.
Definition: kmmessage.cpp:243
TQString subject() const
Get or set the 'Subject' header field.
Definition: kmmessage.cpp:2049
void fromDwString(const DwString &str, bool setStatus=false)
Parse the string and create this message from it.
Definition: kmmessage.cpp:402
KMMsgBase & toMsgBase()
Get KMMsgBase for this object.
Definition: kmmessage.h:114
bool transferInProgress() const
Return, if the message should not be deleted.
Definition: kmmessage.cpp:236
void setMsgSerNum(unsigned long newMsgSerNum=0)
Sets the message serial number.
Definition: kmmessage.cpp:223
void setComplete(bool v)
Set if the message is a complete message.
Definition: kmmessage.h:869
bool isComplete() const
Return true if the complete message is available without referring to the backing store.
Definition: kmmessage.h:867
unsigned long getMsgSerNum(KMFolder *folder, int index) const
Find the message serial number for the message located at index index in folder folder.
Definition: kmmsgdict.cpp:345
static const KMMsgDict * instance()
Access the globally unique MessageDict.
Definition: kmmsgdict.cpp:167
This class is an abstraction of a search over messages.
bool matches(const KMMessage *msg, bool ignoreBody=false) const
The central function of this class.
Generic folder list job for (d)imap accounts.
Definition: listjob.h:55