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