00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032
00033
00034
00035 #include <config.h>
00036
00037 #include "folderstorage.h"
00038 #include "kmfolder.h"
00039 #include "kmkernel.h"
00040
00041 #include "kmfolderimap.h"
00042 #include "undostack.h"
00043 #include "kmmsgdict.h"
00044 #include "kmfoldermgr.h"
00045 #include "kmcommands.h"
00046 #include "listjob.h"
00047 using KMail::ListJob;
00048 #include "kmsearchpattern.h"
00049 #include "globalsettings.h"
00050
00051 #include <klocale.h>
00052 #include <kconfig.h>
00053 #include <kdebug.h>
00054
00055 #include <qfile.h>
00056 #include <qregexp.h>
00057
00058 #include <mimelib/mimepp.h>
00059 #include <errno.h>
00060
00061
00062
00063 FolderStorage::FolderStorage( KMFolder* folder, const char* aName )
00064 : QObject( folder, aName ), mFolder( folder ), mEmitChangedTimer( 0L )
00065 {
00066 mOpenCount = 0;
00067 mQuiet = 0;
00068 mChanged = false;
00069 mAutoCreateIndex = true;
00070 mExportsSernums = false;
00071 mDirty = false;
00072 mUnreadMsgs = -1;
00073 mGuessedUnreadMsgs = -1;
00074 mTotalMsgs = -1;
00075 needsCompact = false;
00076 mConvertToUtf8 = false;
00077 mCompactable = true;
00078 mNoContent = false;
00079 mNoChildren = false;
00080 mRDict = 0;
00081 mDirtyTimer = new QTimer(this, "mDirtyTimer");
00082 connect(mDirtyTimer, SIGNAL(timeout()),
00083 this, SLOT(updateIndex()));
00084
00085 mHasChildren = HasNoChildren;
00086 mContentsType = KMail::ContentsTypeMail;
00087
00088 connect(this, SIGNAL(closed(KMFolder*)), mFolder, SIGNAL(closed()));
00089 }
00090
00091
00092 FolderStorage::~FolderStorage()
00093 {
00094 mJobList.setAutoDelete( true );
00095 QObject::disconnect( SIGNAL(destroyed(QObject*)), this, 0 );
00096 mJobList.clear();
00097 KMMsgDict::deleteRentry(mRDict);
00098 }
00099
00100
00101 void FolderStorage::close( const char * owner, bool aForced )
00102 {
00103 if (mOpenCount <= 0) return;
00104 if (mOpenCount > 0) mOpenCount--;
00105 if (mOpenCount > 0 && !aForced) return;
00106 reallyDoClose( owner );
00107 }
00108
00109
00110 QString FolderStorage::dotEscape(const QString& aStr)
00111 {
00112 if (aStr[0] != '.') return aStr;
00113 return aStr.left(aStr.find(QRegExp("[^\\.]"))) + aStr;
00114 }
00115
00116 void FolderStorage::addJob( FolderJob* job ) const
00117 {
00118 QObject::connect( job, SIGNAL(destroyed(QObject*)),
00119 SLOT(removeJob(QObject*)) );
00120 mJobList.append( job );
00121 }
00122
00123 void FolderStorage::removeJob( QObject* job )
00124 {
00125 mJobList.remove( static_cast<FolderJob*>( job ) );
00126 }
00127
00128
00129
00130 QString FolderStorage::location() const
00131 {
00132 QString sLocation(const_cast<FolderStorage*>(this)->folder()->path());
00133
00134 if (!sLocation.isEmpty()) sLocation += '/';
00135 sLocation += dotEscape(fileName());
00136
00137 return sLocation;
00138 }
00139
00140 QString FolderStorage::fileName() const
00141 {
00142 return mFolder->name();
00143 }
00144
00145
00146
00147
00148 void FolderStorage::setAutoCreateIndex(bool autoIndex)
00149 {
00150 mAutoCreateIndex = autoIndex;
00151 }
00152
00153
00154 void FolderStorage::setDirty(bool f)
00155 {
00156 mDirty = f;
00157 if (mDirty && mAutoCreateIndex)
00158 mDirtyTimer->changeInterval( mDirtyTimerInterval );
00159 else
00160 mDirtyTimer->stop();
00161 }
00162
00163
00164 void FolderStorage::markNewAsUnread()
00165 {
00166 KMMsgBase* msgBase;
00167 int i;
00168
00169 for (i=0; i< count(); ++i)
00170 {
00171 if (!(msgBase = getMsgBase(i))) continue;
00172 if (msgBase->isNew())
00173 {
00174 msgBase->setStatus(KMMsgStatusUnread);
00175 msgBase->setDirty(true);
00176 }
00177 }
00178 }
00179
00180 void FolderStorage::markUnreadAsRead()
00181 {
00182 KMMsgBase* msgBase;
00183 SerNumList serNums;
00184
00185 for (int i=count()-1; i>=0; --i)
00186 {
00187 msgBase = getMsgBase(i);
00188 assert(msgBase);
00189 if (msgBase->isNew() || msgBase->isUnread())
00190 {
00191 serNums.append( msgBase->getMsgSerNum() );
00192 }
00193 }
00194 if (serNums.empty())
00195 return;
00196
00197 KMCommand *command = new KMSetStatusCommand( KMMsgStatusRead, serNums );
00198 command->start();
00199 }
00200
00201
00202 void FolderStorage::quiet(bool beQuiet)
00203 {
00204
00205 if (beQuiet)
00206 {
00207
00208
00209
00210 if ( !mEmitChangedTimer) {
00211 mEmitChangedTimer= new QTimer( this, "mEmitChangedTimer" );
00212 connect( mEmitChangedTimer, SIGNAL( timeout() ),
00213 this, SLOT( slotEmitChangedTimer() ) );
00214 }
00215 mQuiet++;
00216 } else {
00217 mQuiet--;
00218 if (mQuiet <= 0)
00219 {
00220 delete mEmitChangedTimer;
00221 mEmitChangedTimer=0L;
00222
00223 mQuiet = 0;
00224 if (mChanged) {
00225 emit changed();
00226
00227
00228 emit numUnreadMsgsChanged( folder() );
00229 }
00230 mChanged = false;
00231 }
00232 }
00233 }
00234
00235
00236
00238 int operator<( KMMsgBase & m1, KMMsgBase & m2 )
00239 {
00240 return (m1.date() < m2.date());
00241 }
00242
00244 int operator==( KMMsgBase & m1, KMMsgBase & m2 )
00245 {
00246 return (m1.date() == m2.date());
00247 }
00248
00249
00250
00251 int FolderStorage::expungeOldMsg(int days)
00252 {
00253 int i, msgnb=0;
00254 time_t msgTime, maxTime;
00255 const KMMsgBase* mb;
00256 QValueList<int> rmvMsgList;
00257
00258 maxTime = time(0) - days * 3600 * 24;
00259
00260 for (i=count()-1; i>=0; i--) {
00261 mb = getMsgBase(i);
00262 assert(mb);
00263 msgTime = mb->date();
00264
00265 if (msgTime < maxTime) {
00266
00267 removeMsg( i );
00268 msgnb++;
00269 }
00270 }
00271 return msgnb;
00272 }
00273
00274
00275 void FolderStorage::slotEmitChangedTimer()
00276 {
00277 emit changed();
00278 mChanged=false;
00279 }
00280
00281 void FolderStorage::emitMsgAddedSignals(int idx)
00282 {
00283 Q_UINT32 serNum = KMMsgDict::instance()->getMsgSerNum( folder() , idx );
00284 if (!mQuiet) {
00285 emit msgAdded(idx);
00286 } else {
00289 if ( !mEmitChangedTimer->isActive() ) {
00290 mEmitChangedTimer->start( 3000 );
00291 }
00292 mChanged=true;
00293 }
00294 emit msgAdded( folder(), serNum );
00295 }
00296
00297
00298 bool FolderStorage::canAddMsgNow(KMMessage* aMsg, int* aIndex_ret)
00299 {
00300 if (aIndex_ret) *aIndex_ret = -1;
00301 KMFolder *msgParent = aMsg->parent();
00302
00303
00304 if (aMsg->transferInProgress() && msgParent)
00305 return false;
00306 if (!aMsg->isComplete() && msgParent && msgParent->folderType() == KMFolderTypeImap)
00307 {
00308 FolderJob *job = msgParent->createJob(aMsg);
00309 connect(job, SIGNAL(messageRetrieved(KMMessage*)),
00310 SLOT(reallyAddMsg(KMMessage*)));
00311 job->start();
00312 aMsg->setTransferInProgress( true );
00313 return false;
00314 }
00315 return true;
00316 }
00317
00318
00319
00320 void FolderStorage::reallyAddMsg(KMMessage* aMsg)
00321 {
00322 if (!aMsg)
00323 return;
00324 aMsg->setTransferInProgress( false );
00325 aMsg->setComplete( true );
00326 KMFolder *aFolder = aMsg->parent();
00327 int index;
00328 ulong serNum = aMsg->getMsgSerNum();
00329 bool undo = aMsg->enableUndo();
00330 addMsg(aMsg, &index);
00331 if (index < 0) return;
00332 unGetMsg(index);
00333 if (undo)
00334 {
00335 kmkernel->undoStack()->pushSingleAction( serNum, aFolder, folder() );
00336 }
00337 }
00338
00339
00340
00341 void FolderStorage::reallyAddCopyOfMsg(KMMessage* aMsg)
00342 {
00343 if ( !aMsg ) return;
00344 aMsg->setParent( 0 );
00345 aMsg->setTransferInProgress( false );
00346 addMsg( aMsg );
00347 unGetMsg( count() - 1 );
00348 }
00349
00350 int FolderStorage::find( const KMMessage * msg ) const {
00351 return find( &msg->toMsgBase() );
00352 }
00353
00354
00355 void FolderStorage::removeMsg(const QPtrList<KMMsgBase>& msgList, bool imapQuiet)
00356 {
00357 for( QPtrListIterator<KMMsgBase> it( msgList ); *it; ++it )
00358 {
00359 int idx = find(it.current());
00360 assert( idx != -1);
00361 removeMsg(idx, imapQuiet);
00362 }
00363 }
00364
00365
00366 void FolderStorage::removeMsg(const QPtrList<KMMessage>& msgList, bool imapQuiet)
00367 {
00368 for( QPtrListIterator<KMMessage> it( msgList ); *it; ++it )
00369 {
00370 int idx = find(it.current());
00371 assert( idx != -1);
00372 removeMsg(idx, imapQuiet);
00373 }
00374 }
00375
00376
00377 void FolderStorage::removeMsg(int idx, bool)
00378 {
00379
00380 if(idx < 0)
00381 {
00382 kdDebug(5006) << "FolderStorage::removeMsg() : idx < 0\n" << endl;
00383 return;
00384 }
00385
00386 KMMsgBase* mb = getMsgBase(idx);
00387
00388 Q_UINT32 serNum = KMMsgDict::instance()->getMsgSerNum( folder(), idx );
00389 if (serNum != 0)
00390 emit msgRemoved( folder(), serNum );
00391 mb = takeIndexEntry( idx );
00392
00393 setDirty( true );
00394 needsCompact=true;
00395
00396 if (mb->isUnread() || mb->isNew() ||
00397 (folder() == kmkernel->outboxFolder())) {
00398 --mUnreadMsgs;
00399 if ( !mQuiet ) {
00400
00401 emit numUnreadMsgsChanged( folder() );
00402 }else{
00403 if ( !mEmitChangedTimer->isActive() ) {
00404
00405 mEmitChangedTimer->start( 3000 );
00406 }
00407 mChanged = true;
00408 }
00409 }
00410 --mTotalMsgs;
00411
00412 QString msgIdMD5 = mb->msgIdMD5();
00413 emit msgRemoved( idx, msgIdMD5 );
00414 emit msgRemoved( folder() );
00415 }
00416
00417
00418
00419 KMMessage* FolderStorage::take(int idx)
00420 {
00421 KMMsgBase* mb;
00422 KMMessage* msg;
00423
00424 assert(idx>=0 && idx<=count());
00425
00426 mb = getMsgBase(idx);
00427 if (!mb) return 0;
00428 if (!mb->isMessage()) readMsg(idx);
00429 Q_UINT32 serNum = KMMsgDict::instance()->getMsgSerNum( folder(), idx );
00430 emit msgRemoved( folder(), serNum );
00431
00432 msg = (KMMessage*)takeIndexEntry(idx);
00433
00434 if (msg->isUnread() || msg->isNew() ||
00435 ( folder() == kmkernel->outboxFolder() )) {
00436 --mUnreadMsgs;
00437 if ( !mQuiet ) {
00438 emit numUnreadMsgsChanged( folder() );
00439 }else{
00440 if ( !mEmitChangedTimer->isActive() ) {
00441 mEmitChangedTimer->start( 3000 );
00442 }
00443 mChanged = true;
00444 }
00445 }
00446 --mTotalMsgs;
00447 msg->setParent(0);
00448 setDirty( true );
00449 needsCompact=true;
00450 QString msgIdMD5 = msg->msgIdMD5();
00451 emit msgRemoved( idx, msgIdMD5 );
00452 emit msgRemoved( folder() );
00453
00454 return msg;
00455 }
00456
00457 void FolderStorage::take(QPtrList<KMMessage> msgList)
00458 {
00459 for ( KMMessage* msg = msgList.first(); msg; msg = msgList.next() )
00460 {
00461 if (msg->parent())
00462 {
00463 int idx = msg->parent()->find(msg);
00464 take(idx);
00465 }
00466 }
00467 }
00468
00469
00470
00471 KMMessage* FolderStorage::getMsg(int idx)
00472 {
00473 if ( idx < 0 || idx >= count() )
00474 return 0;
00475
00476 KMMsgBase* mb = getMsgBase(idx);
00477 if (!mb) return 0;
00478
00479 KMMessage *msg = 0;
00480 bool undo = mb->enableUndo();
00481 if (mb->isMessage()) {
00482 msg = ((KMMessage*)mb);
00483 } else {
00484 QString mbSubject = mb->subject();
00485 msg = readMsg(idx);
00486
00487 if (mCompactable && (!msg || (msg->subject().isEmpty() != mbSubject.isEmpty()))) {
00488 kdDebug(5006) << "Error: " << location() <<
00489 " Index file is inconsistent with folder file. This should never happen." << endl;
00490 mCompactable = false;
00491 writeConfig();
00492 }
00493
00494 }
00495
00496
00497
00498 if ( msg->getMsgSerNum() == 0 )
00499 return 0;
00500 msg->setEnableUndo(undo);
00501 msg->setComplete( true );
00502 return msg;
00503 }
00504
00505
00506 KMMessage* FolderStorage::readTemporaryMsg(int idx)
00507 {
00508 if(!(idx >= 0 && idx <= count()))
00509 return 0;
00510
00511 KMMsgBase* mb = getMsgBase(idx);
00512 if (!mb) return 0;
00513
00514 unsigned long sernum = mb->getMsgSerNum();
00515
00516 KMMessage *msg = 0;
00517 bool undo = mb->enableUndo();
00518 if (mb->isMessage()) {
00519
00520 msg = new KMMessage(*(KMMessage*)mb);
00521 msg->setMsgSerNum(sernum);
00522 msg->setComplete( true );
00523 } else {
00524
00525 msg = new KMMessage(*(KMMsgInfo*)mb);
00526 msg->setMsgSerNum(sernum);
00527 msg->setComplete( true );
00528 msg->fromDwString(getDwString(idx));
00529 }
00530 msg->setEnableUndo(undo);
00531 return msg;
00532 }
00533
00534
00535
00536 KMMsgInfo* FolderStorage::unGetMsg(int idx)
00537 {
00538 KMMsgBase* mb;
00539
00540 if(!(idx >= 0 && idx <= count()))
00541 return 0;
00542
00543 mb = getMsgBase(idx);
00544 if (!mb) return 0;
00545
00546
00547 if (mb->isMessage()) {
00548
00549
00550 KMMessage *msg = static_cast<KMMessage*>(mb);
00551 if ( msg->transferInProgress() ) return 0;
00552 ignoreJobsForMessage( msg );
00553 return setIndexEntry( idx, msg );
00554 }
00555
00556 return 0;
00557 }
00558
00559
00560
00561 bool FolderStorage::isMessage(int idx)
00562 {
00563 KMMsgBase* mb;
00564 if (!(idx >= 0 && idx <= count())) return false;
00565 mb = getMsgBase(idx);
00566 return (mb && mb->isMessage());
00567 }
00568
00569
00570 FolderJob* FolderStorage::createJob( KMMessage *msg, FolderJob::JobType jt,
00571 KMFolder *folder, QString partSpecifier,
00572 const AttachmentStrategy *as ) const
00573 {
00574 FolderJob * job = doCreateJob( msg, jt, folder, partSpecifier, as );
00575 if ( job )
00576 addJob( job );
00577 return job;
00578 }
00579
00580
00581 FolderJob* FolderStorage::createJob( QPtrList<KMMessage>& msgList, const QString& sets,
00582 FolderJob::JobType jt, KMFolder *folder ) const
00583 {
00584 FolderJob * job = doCreateJob( msgList, sets, jt, folder );
00585 if ( job )
00586 addJob( job );
00587 return job;
00588 }
00589
00590
00591 int FolderStorage::moveMsg(KMMessage* aMsg, int* aIndex_ret)
00592 {
00593 assert(aMsg != 0);
00594 KMFolder* msgParent = aMsg->parent();
00595
00596 if (msgParent)
00597 msgParent->open("moveMsgSrc");
00598
00599 open("moveMsgDest");
00600 int rc = addMsg(aMsg, aIndex_ret);
00601 close("moveMsgDest");
00602
00603 if (msgParent)
00604 msgParent->close("moveMsgSrc");
00605
00606 return rc;
00607 }
00608
00609
00610 int FolderStorage::moveMsg(QPtrList<KMMessage> msglist, int* aIndex_ret)
00611 {
00612 KMMessage* aMsg = msglist.first();
00613 assert(aMsg != 0);
00614 KMFolder* msgParent = aMsg->parent();
00615
00616 if (msgParent)
00617 msgParent->open("foldermovemsg");
00618
00619 QValueList<int> index;
00620 open("moveMsg");
00621 int rc = addMsg(msglist, index);
00622 close("moveMsg");
00623
00624 if ( !index.isEmpty() )
00625 aIndex_ret = &index.first();
00626
00627 if (msgParent)
00628 msgParent->close("foldermovemsg");
00629
00630 return rc;
00631 }
00632
00633
00634
00635 int FolderStorage::rename(const QString& newName, KMFolderDir *newParent)
00636 {
00637 QString oldLoc, oldIndexLoc, oldIdsLoc, newLoc, newIndexLoc, newIdsLoc;
00638 QString oldSubDirLoc, newSubDirLoc;
00639 QString oldName;
00640 int rc=0;
00641 KMFolderDir *oldParent;
00642
00643 assert(!newName.isEmpty());
00644
00645 oldLoc = location();
00646 oldIndexLoc = indexLocation();
00647 oldSubDirLoc = folder()->subdirLocation();
00648 oldIdsLoc = KMMsgDict::instance()->getFolderIdsLocation( *this );
00649 QString oldConfigString = "Folder-" + folder()->idString();
00650
00651 close("rename", true);
00652
00653 oldName = folder()->fileName();
00654 oldParent = folder()->parent();
00655 if (newParent)
00656 folder()->setParent( newParent );
00657
00658 folder()->setName(newName);
00659 newLoc = location();
00660 newIndexLoc = indexLocation();
00661 newSubDirLoc = folder()->subdirLocation();
00662 newIdsLoc = KMMsgDict::instance()->getFolderIdsLocation( *this );
00663
00664 if (::rename(QFile::encodeName(oldLoc), QFile::encodeName(newLoc))) {
00665 folder()->setName(oldName);
00666 folder()->setParent(oldParent);
00667 rc = errno;
00668 }
00669 else {
00670
00671 if (!oldIndexLoc.isEmpty()) {
00672 ::rename(QFile::encodeName(oldIndexLoc), QFile::encodeName(newIndexLoc));
00673 ::rename(QFile::encodeName(oldIndexLoc) + ".sorted",
00674 QFile::encodeName(newIndexLoc) + ".sorted");
00675 }
00676
00677
00678 if (!oldIdsLoc.isEmpty())
00679 ::rename(QFile::encodeName(oldIdsLoc), QFile::encodeName(newIdsLoc));
00680
00681
00682 KMFolderDir* child = 0;
00683 if( folder() )
00684 child = folder()->child();
00685
00686 if (!::rename(QFile::encodeName(oldSubDirLoc), QFile::encodeName(newSubDirLoc) )) {
00687
00688
00689
00690 if( child && ( oldName != newName ) ) {
00691 child->setName( "." + QFile::encodeName(newName) + ".directory" );
00692 }
00693 }
00694
00695
00696
00697 if (newParent) {
00698 if (oldParent->findRef( folder() ) != -1)
00699 oldParent->take();
00700 newParent->inSort( folder() );
00701 if ( child ) {
00702 if ( child->parent()->findRef( child ) != -1 )
00703 child->parent()->take();
00704 newParent->inSort( child );
00705 child->setParent( newParent );
00706 }
00707 }
00708 }
00709
00710 writeConfig();
00711
00712
00713 if ( oldConfigString != "Folder-" + folder()->idString() )
00714 KMKernel::config()->deleteGroup( oldConfigString );
00715
00716 emit locationChanged( oldLoc, newLoc );
00717 emit nameChanged();
00718 kmkernel->folderMgr()->contentsChanged();
00719 emit closed(folder());
00720 return rc;
00721 }
00722
00723
00724
00725 void FolderStorage::remove()
00726 {
00727 assert(!folder()->name().isEmpty());
00728
00729 clearIndex( true, mExportsSernums );
00730 close("remove", true);
00731
00732 if ( mExportsSernums ) {
00733 KMMsgDict::mutableInstance()->removeFolderIds( *this );
00734 mExportsSernums = false;
00735 }
00736 unlink(QFile::encodeName(indexLocation()) + ".sorted");
00737 unlink(QFile::encodeName(indexLocation()));
00738
00739 int rc = removeContents();
00740
00741 needsCompact = false;
00742
00743
00744 KConfig* config = KMKernel::config();
00745 config->deleteGroup( "Folder-" + folder()->idString() );
00746
00747 emit closed(folder());
00748 emit removed(folder(), (rc ? false : true));
00749 }
00750
00751
00752
00753 int FolderStorage::expunge()
00754 {
00755 assert(!folder()->name().isEmpty());
00756
00757 clearIndex( true, mExportsSernums );
00758 close( "expunge", true );
00759
00760 if ( mExportsSernums )
00761 KMMsgDict::mutableInstance()->removeFolderIds( *this );
00762 if ( mAutoCreateIndex )
00763 truncateIndex();
00764 else unlink(QFile::encodeName(indexLocation()));
00765
00766 int rc = expungeContents();
00767 if (rc) return rc;
00768
00769 mDirty = false;
00770 needsCompact = false;
00771
00772 mUnreadMsgs = 0;
00773 mTotalMsgs = 0;
00774 emit numUnreadMsgsChanged( folder() );
00775 if ( mAutoCreateIndex )
00776 writeConfig();
00777 emit changed();
00778 emit expunged( folder() );
00779
00780 return 0;
00781 }
00782
00783
00784 QString FolderStorage::label() const
00785 {
00786 return folder()->label();
00787 }
00788
00789 int FolderStorage::count(bool cache) const
00790 {
00791 if (cache && mTotalMsgs != -1)
00792 return mTotalMsgs;
00793 else
00794 return -1;
00795 }
00796
00797
00798 int FolderStorage::countUnread()
00799 {
00800 if (mGuessedUnreadMsgs > -1)
00801 return mGuessedUnreadMsgs;
00802 if (mUnreadMsgs > -1)
00803 return mUnreadMsgs;
00804
00805 readConfig();
00806
00807 if (mUnreadMsgs > -1)
00808 return mUnreadMsgs;
00809
00810 open("countunread");
00811 int unread = mUnreadMsgs;
00812 close("countunread");
00813 return (unread > 0) ? unread : 0;
00814 }
00815
00816
00817 void FolderStorage::msgStatusChanged(const KMMsgStatus oldStatus,
00818 const KMMsgStatus newStatus, int idx)
00819 {
00820 int oldUnread = 0;
00821 int newUnread = 0;
00822
00823 if (((oldStatus & KMMsgStatusUnread || oldStatus & KMMsgStatusNew) &&
00824 !(oldStatus & KMMsgStatusIgnored)) ||
00825 (folder() == kmkernel->outboxFolder()))
00826 oldUnread = 1;
00827 if (((newStatus & KMMsgStatusUnread || newStatus & KMMsgStatusNew) &&
00828 !(newStatus & KMMsgStatusIgnored)) ||
00829 (folder() == kmkernel->outboxFolder()))
00830 newUnread = 1;
00831 int deltaUnread = newUnread - oldUnread;
00832
00833 mDirtyTimer->changeInterval(mDirtyTimerInterval);
00834 if (deltaUnread != 0) {
00835 if (mUnreadMsgs < 0) mUnreadMsgs = 0;
00836 mUnreadMsgs += deltaUnread;
00837 if ( !mQuiet ) {
00838 emit numUnreadMsgsChanged( folder() );
00839 }else{
00840 if ( !mEmitChangedTimer->isActive() ) {
00841 mEmitChangedTimer->start( 3000 );
00842 }
00843 mChanged = true;
00844 }
00845 Q_UINT32 serNum = KMMsgDict::instance()->getMsgSerNum(folder(), idx);
00846 emit msgChanged( folder(), serNum, deltaUnread );
00847 }
00848 }
00849
00850
00851 void FolderStorage::headerOfMsgChanged(const KMMsgBase* aMsg, int idx)
00852 {
00853 if (idx < 0)
00854 idx = aMsg->parent()->find( aMsg );
00855
00856 if (idx >= 0 )
00857 {
00858 if ( !mQuiet )
00859 emit msgHeaderChanged(folder(), idx);
00860 else{
00861 if ( !mEmitChangedTimer->isActive() ) {
00862 mEmitChangedTimer->start( 3000 );
00863 }
00864 mChanged = true;
00865 }
00866 } else
00867 mChanged = true;
00868 }
00869
00870
00871 void FolderStorage::readConfig()
00872 {
00873
00874 KConfig* config = KMKernel::config();
00875 KConfigGroupSaver saver(config, "Folder-" + folder()->idString());
00876 if (mUnreadMsgs == -1)
00877 mUnreadMsgs = config->readNumEntry("UnreadMsgs", -1);
00878 if (mTotalMsgs == -1)
00879 mTotalMsgs = config->readNumEntry("TotalMsgs", -1);
00880 mCompactable = config->readBoolEntry("Compactable", true);
00881
00882 int type = config->readNumEntry( "ContentsType", 0 );
00883 if ( type < 0 || type > KMail::ContentsTypeLast ) type = 0;
00884 setContentsType( static_cast<KMail::FolderContentsType>( type ) );
00885
00886 if( folder() ) folder()->readConfig( config );
00887 }
00888
00889
00890 void FolderStorage::writeConfig()
00891 {
00892 KConfig* config = KMKernel::config();
00893 KConfigGroupSaver saver(config, "Folder-" + folder()->idString());
00894 config->writeEntry("UnreadMsgs",
00895 mGuessedUnreadMsgs == -1 ? mUnreadMsgs : mGuessedUnreadMsgs);
00896 config->writeEntry("TotalMsgs", mTotalMsgs);
00897 config->writeEntry("Compactable", mCompactable);
00898 config->writeEntry("ContentsType", mContentsType);
00899
00900
00901 if( folder() ) folder()->writeConfig( config );
00902
00903 GlobalSettings::self()->requestSync();
00904 }
00905
00906
00907 void FolderStorage::correctUnreadMsgsCount()
00908 {
00909 open("countunreadmsg");
00910 close("countunreadmsg");
00911 emit numUnreadMsgsChanged( folder() );
00912 }
00913
00914 void FolderStorage::registerWithMessageDict()
00915 {
00916 mExportsSernums = true;
00917 readFolderIdsFile();
00918 }
00919
00920 void FolderStorage::deregisterFromMessageDict()
00921 {
00922 writeFolderIdsFile();
00923 mExportsSernums = false;
00924 }
00925
00926 void FolderStorage::readFolderIdsFile()
00927 {
00928 if ( !mExportsSernums ) return;
00929 if ( KMMsgDict::mutableInstance()->readFolderIds( *this ) == -1 ) {
00930 invalidateFolder();
00931 }
00932 if ( !KMMsgDict::mutableInstance()->hasFolderIds( *this ) ) {
00933 invalidateFolder();
00934 }
00935 }
00936
00937 void FolderStorage::invalidateFolder()
00938 {
00939 if ( !mExportsSernums ) return;
00940 unlink(QFile::encodeName( indexLocation()) + ".sorted");
00941 unlink(QFile::encodeName( indexLocation()) + ".ids");
00942 fillMessageDict();
00943 KMMsgDict::mutableInstance()->writeFolderIds( *this );
00944 emit invalidated( folder() );
00945 }
00946
00947
00948
00949 int FolderStorage::writeFolderIdsFile() const
00950 {
00951 if ( !mExportsSernums ) return -1;
00952 return KMMsgDict::mutableInstance()->writeFolderIds( *this );
00953 }
00954
00955
00956 int FolderStorage::touchFolderIdsFile()
00957 {
00958 if ( !mExportsSernums ) return -1;
00959 return KMMsgDict::mutableInstance()->touchFolderIds( *this );
00960 }
00961
00962
00963 int FolderStorage::appendToFolderIdsFile( int idx )
00964 {
00965 if ( !mExportsSernums ) return -1;
00966 int ret = 0;
00967 if ( count() == 1 ) {
00968 ret = KMMsgDict::mutableInstance()->writeFolderIds( *this );
00969 } else {
00970 ret = KMMsgDict::mutableInstance()->appendToFolderIds( *this, idx );
00971 }
00972 return ret;
00973 }
00974
00975 void FolderStorage::replaceMsgSerNum( unsigned long sernum, KMMsgBase* msg, int idx )
00976 {
00977 if ( !mExportsSernums ) return;
00978 KMMsgDict::mutableInstance()->replace( sernum, msg, idx );
00979 }
00980
00981 void FolderStorage::setRDict( KMMsgDictREntry *rentry ) const
00982 {
00983 if ( ! mExportsSernums )
00984 kdDebug(5006) << "WTF, this FolderStorage should be invisible to the msgdict, who is calling us?" << kdBacktrace() << endl;
00985 assert( mExportsSernums );
00986 if ( rentry == mRDict )
00987 return;
00988 KMMsgDict::deleteRentry( mRDict );
00989 mRDict = rentry;
00990 }
00991
00992
00993 void FolderStorage::setStatus(int idx, KMMsgStatus status, bool toggle)
00994 {
00995 KMMsgBase *msg = getMsgBase(idx);
00996 if ( msg ) {
00997 if (toggle)
00998 msg->toggleStatus(status, idx);
00999 else
01000 msg->setStatus(status, idx);
01001 }
01002 }
01003
01004
01005
01006 void FolderStorage::setStatus(QValueList<int>& ids, KMMsgStatus status, bool toggle)
01007 {
01008 for ( QValueList<int>::Iterator it = ids.begin(); it != ids.end(); ++it )
01009 {
01010 FolderStorage::setStatus(*it, status, toggle);
01011 }
01012 }
01013
01014 void FolderStorage::ignoreJobsForMessage( KMMessage *msg )
01015 {
01016 if ( !msg || msg->transferInProgress() )
01017 return;
01018
01019 QPtrListIterator<FolderJob> it( mJobList );
01020 while ( it.current() )
01021 {
01022
01023
01024
01025 if ( it.current()->msgList().first() == msg )
01026 {
01027 FolderJob* job = it.current();
01028 mJobList.remove( job );
01029 delete job;
01030 } else
01031 ++it;
01032 }
01033 }
01034
01035
01036 void FolderStorage::removeJobs()
01037 {
01038 mJobList.setAutoDelete( true );
01039 mJobList.clear();
01040 mJobList.setAutoDelete( false );
01041 }
01042
01043
01044
01045
01046 void FolderStorage::updateChildrenState()
01047 {
01048 if ( folder() && folder()->child() )
01049 {
01050 if ( kmkernel->folderMgr()->folderCount( folder()->child() ) > 0 )
01051 setHasChildren( HasChildren );
01052 else
01053 setHasChildren( HasNoChildren );
01054 }
01055 }
01056
01057
01058 void FolderStorage::setNoChildren( bool aNoChildren )
01059 {
01060 mNoChildren = aNoChildren;
01061 if ( aNoChildren )
01062 setHasChildren( HasNoChildren );
01063 }
01064
01065
01066 void FolderStorage::setContentsType( KMail::FolderContentsType type, bool quiet )
01067 {
01068 if ( type != mContentsType ) {
01069 mContentsType = type;
01070 if ( !quiet )
01071 emit contentsTypeChanged( type );
01072 }
01073 }
01074
01075
01076 void FolderStorage::search( const KMSearchPattern* pattern )
01077 {
01078 mSearchPattern = pattern;
01079 mCurrentSearchedMsg = 0;
01080 if ( pattern )
01081 slotProcessNextSearchBatch();
01082 }
01083
01084 void FolderStorage::slotProcessNextSearchBatch()
01085 {
01086 if ( !mSearchPattern ) return;
01087 QValueList<Q_UINT32> matchingSerNums;
01088 int end = ( count() - mCurrentSearchedMsg > 100 ) ? 100+mCurrentSearchedMsg : count();
01089 for ( int i = mCurrentSearchedMsg; i < end; ++i )
01090 {
01091 Q_UINT32 serNum = KMMsgDict::instance()->getMsgSerNum( folder(), i );
01092 if ( mSearchPattern->matches( serNum ) )
01093 matchingSerNums.append( serNum );
01094 }
01095 mCurrentSearchedMsg = end;
01096 bool complete = ( end == count() ) ? true : false;
01097 emit searchResult( folder(), matchingSerNums, mSearchPattern, complete );
01098 if ( !complete )
01099 QTimer::singleShot( 0, this, SLOT(slotProcessNextSearchBatch()) );
01100 }
01101
01102
01103 void FolderStorage::search( const KMSearchPattern* pattern, Q_UINT32 serNum )
01104 {
01105 bool matches = pattern && pattern->matches( serNum );
01106
01107 emit searchDone( folder(), serNum, pattern, matches );
01108 }
01109
01110
01111 int FolderStorage::addMsg( QPtrList<KMMessage>& msgList, QValueList<int>& index_ret )
01112 {
01113 int ret = 0;
01114 int index;
01115 for ( QPtrListIterator<KMMessage> it( msgList ); *it; ++it )
01116 {
01117 int aret = addMsg( *it, &index );
01118 index_ret << index;
01119 if ( aret != 0 )
01120 ret = aret;
01121 }
01122 return ret;
01123 }
01124
01125
01126 bool FolderStorage::isMoveable() const
01127 {
01128 return ( folder()->isSystemFolder() ) ? false : true;
01129 }
01130
01131 #include "folderstorage.moc"