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