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