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