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 if ( idx >= 0 )
00455 take(idx);
00456 }
00457 }
00458 }
00459
00460
00461
00462 KMMessage* FolderStorage::getMsg(int idx)
00463 {
00464 if ( idx < 0 || idx >= count() )
00465 return 0;
00466
00467 KMMsgBase* mb = getMsgBase(idx);
00468 if (!mb) return 0;
00469
00470 KMMessage *msg = 0;
00471 bool undo = mb->enableUndo();
00472 if (mb->isMessage()) {
00473 msg = ((KMMessage*)mb);
00474 } else {
00475 QString mbSubject = mb->subject();
00476 msg = readMsg(idx);
00477
00478 if (mCompactable && (!msg || (msg->subject().isEmpty() != mbSubject.isEmpty()))) {
00479 kdDebug(5006) << "Error: " << location() <<
00480 " Index file is inconsistent with folder file. This should never happen." << endl;
00481 mCompactable = false;
00482 writeConfig();
00483 }
00484
00485 }
00486
00487
00488
00489 if ( msg->getMsgSerNum() == 0 )
00490 return 0;
00491 msg->setEnableUndo(undo);
00492 msg->setComplete( true );
00493 return msg;
00494 }
00495
00496
00497 KMMessage* FolderStorage::readTemporaryMsg(int idx)
00498 {
00499 if(!(idx >= 0 && idx <= count()))
00500 return 0;
00501
00502 KMMsgBase* mb = getMsgBase(idx);
00503 if (!mb) return 0;
00504
00505 unsigned long sernum = mb->getMsgSerNum();
00506
00507 KMMessage *msg = 0;
00508 bool undo = mb->enableUndo();
00509 if (mb->isMessage()) {
00510
00511 msg = new KMMessage(*(KMMessage*)mb);
00512 msg->setMsgSerNum(sernum);
00513 msg->setComplete( true );
00514 } else {
00515
00516 msg = new KMMessage(*(KMMsgInfo*)mb);
00517 msg->setMsgSerNum(sernum);
00518 msg->setComplete( true );
00519 msg->fromDwString(getDwString(idx));
00520 }
00521 msg->setEnableUndo(undo);
00522 return msg;
00523 }
00524
00525
00526
00527 KMMsgInfo* FolderStorage::unGetMsg(int idx)
00528 {
00529 KMMsgBase* mb;
00530
00531 if(!(idx >= 0 && idx <= count()))
00532 return 0;
00533
00534 mb = getMsgBase(idx);
00535 if (!mb) return 0;
00536
00537
00538 if (mb->isMessage()) {
00539
00540
00541 KMMessage *msg = static_cast<KMMessage*>(mb);
00542 if ( msg->transferInProgress() ) return 0;
00543 ignoreJobsForMessage( msg );
00544 return setIndexEntry( idx, msg );
00545 }
00546
00547 return 0;
00548 }
00549
00550
00551
00552 bool FolderStorage::isMessage(int idx)
00553 {
00554 KMMsgBase* mb;
00555 if (!(idx >= 0 && idx <= count())) return false;
00556 mb = getMsgBase(idx);
00557 return (mb && mb->isMessage());
00558 }
00559
00560
00561 FolderJob* FolderStorage::createJob( KMMessage *msg, FolderJob::JobType jt,
00562 KMFolder *folder, QString partSpecifier,
00563 const AttachmentStrategy *as ) const
00564 {
00565 FolderJob * job = doCreateJob( msg, jt, folder, partSpecifier, as );
00566 if ( job )
00567 addJob( job );
00568 return job;
00569 }
00570
00571
00572 FolderJob* FolderStorage::createJob( QPtrList<KMMessage>& msgList, const QString& sets,
00573 FolderJob::JobType jt, KMFolder *folder ) const
00574 {
00575 FolderJob * job = doCreateJob( msgList, sets, jt, folder );
00576 if ( job )
00577 addJob( job );
00578 return job;
00579 }
00580
00581
00582 int FolderStorage::moveMsg(KMMessage* aMsg, int* aIndex_ret)
00583 {
00584 assert(aMsg != 0);
00585 KMFolder* msgParent = aMsg->parent();
00586
00587 if (msgParent)
00588 msgParent->open();
00589
00590 open();
00591 int rc = addMsg(aMsg, aIndex_ret);
00592 close();
00593
00594 if (msgParent)
00595 msgParent->close();
00596
00597 return rc;
00598 }
00599
00600
00601 int FolderStorage::moveMsg(QPtrList<KMMessage> msglist, int* aIndex_ret)
00602 {
00603 KMMessage* aMsg = msglist.first();
00604 assert(aMsg != 0);
00605 KMFolder* msgParent = aMsg->parent();
00606
00607 if (msgParent)
00608 msgParent->open();
00609
00610 QValueList<int> index;
00611 open();
00612 int rc = addMsg(msglist, index);
00613 close();
00614
00615 if ( !index.isEmpty() )
00616 aIndex_ret = &index.first();
00617
00618 if (msgParent)
00619 msgParent->close();
00620
00621 return rc;
00622 }
00623
00624
00625
00626 int FolderStorage::rename(const QString& newName, KMFolderDir *newParent)
00627 {
00628 QString oldLoc, oldIndexLoc, oldIdsLoc, newLoc, newIndexLoc, newIdsLoc;
00629 QString oldSubDirLoc, newSubDirLoc;
00630 QString oldName;
00631 int rc=0, openCount=mOpenCount;
00632 KMFolderDir *oldParent;
00633
00634 assert(!newName.isEmpty());
00635
00636 oldLoc = location();
00637 oldIndexLoc = indexLocation();
00638 oldSubDirLoc = folder()->subdirLocation();
00639 oldIdsLoc = KMMsgDict::instance()->getFolderIdsLocation( *this );
00640 QString oldConfigString = "Folder-" + folder()->idString();
00641
00642 close(true);
00643
00644 oldName = folder()->fileName();
00645 oldParent = folder()->parent();
00646 if (newParent)
00647 folder()->setParent( newParent );
00648
00649 folder()->setName(newName);
00650 newLoc = location();
00651 newIndexLoc = indexLocation();
00652 newSubDirLoc = folder()->subdirLocation();
00653 newIdsLoc = KMMsgDict::instance()->getFolderIdsLocation( *this );
00654
00655 if (::rename(QFile::encodeName(oldLoc), QFile::encodeName(newLoc))) {
00656 folder()->setName(oldName);
00657 folder()->setParent(oldParent);
00658 rc = errno;
00659 }
00660 else {
00661
00662 if (!oldIndexLoc.isEmpty()) {
00663 ::rename(QFile::encodeName(oldIndexLoc), QFile::encodeName(newIndexLoc));
00664 ::rename(QFile::encodeName(oldIndexLoc) + ".sorted",
00665 QFile::encodeName(newIndexLoc) + ".sorted");
00666 }
00667
00668
00669 if (!oldIdsLoc.isEmpty())
00670 ::rename(QFile::encodeName(oldIdsLoc), QFile::encodeName(newIdsLoc));
00671
00672
00673 KMFolderDir* child = 0;
00674 if( folder() )
00675 child = folder()->child();
00676
00677 if (!::rename(QFile::encodeName(oldSubDirLoc), QFile::encodeName(newSubDirLoc) )) {
00678
00679
00680
00681 if( child && ( oldName != newName ) ) {
00682 child->setName( "." + QFile::encodeName(newName) + ".directory" );
00683 }
00684 }
00685
00686
00687
00688 if (newParent) {
00689 if (oldParent->findRef( folder() ) != -1)
00690 oldParent->take();
00691 newParent->inSort( folder() );
00692 if ( child ) {
00693 if ( child->parent()->findRef( child ) != -1 )
00694 child->parent()->take();
00695 newParent->inSort( child );
00696 child->setParent( newParent );
00697 }
00698 }
00699 }
00700
00701 if (openCount > 0)
00702 {
00703 open();
00704 mOpenCount = openCount;
00705 }
00706 writeConfig();
00707
00708
00709 if ( oldConfigString != "Folder-" + folder()->idString() )
00710 KMKernel::config()->deleteGroup( oldConfigString );
00711
00712 emit locationChanged( oldLoc, newLoc );
00713 emit nameChanged();
00714 kmkernel->folderMgr()->contentsChanged();
00715 return rc;
00716 }
00717
00718
00719
00720 void FolderStorage::remove()
00721 {
00722 assert(!folder()->name().isEmpty());
00723
00724 clearIndex( true, mExportsSernums );
00725 close(true);
00726
00727 if ( mExportsSernums )
00728 KMMsgDict::mutableInstance()->removeFolderIds( *this );
00729 unlink(QFile::encodeName(indexLocation()) + ".sorted");
00730 unlink(QFile::encodeName(indexLocation()));
00731
00732 int rc = removeContents();
00733
00734 needsCompact = false;
00735
00736
00737 KConfig* config = KMKernel::config();
00738 config->deleteGroup( "Folder-" + folder()->idString() );
00739
00740 emit removed(folder(), (rc ? false : true));
00741 }
00742
00743
00744
00745 int FolderStorage::expunge()
00746 {
00747 int openCount = mOpenCount;
00748
00749 assert(!folder()->name().isEmpty());
00750
00751 clearIndex( true, mExportsSernums );
00752 close( true );
00753
00754 if ( mExportsSernums )
00755 KMMsgDict::mutableInstance()->removeFolderIds( *this );
00756 if ( mAutoCreateIndex )
00757 truncateIndex();
00758 else unlink(QFile::encodeName(indexLocation()));
00759
00760 int rc = expungeContents();
00761 if (rc) return rc;
00762
00763 mDirty = false;
00764 needsCompact = false;
00765
00766 if (openCount > 0)
00767 {
00768 open();
00769 mOpenCount = openCount;
00770 }
00771
00772 mUnreadMsgs = 0;
00773 mTotalMsgs = 0;
00774 emit numUnreadMsgsChanged( folder() );
00775 if ( mAutoCreateIndex )
00776 writeConfig();
00777 emit changed();
00778 emit expunged( folder() );
00779
00780 return 0;
00781 }
00782
00783
00784 QString FolderStorage::label() const
00785 {
00786 return folder()->label();
00787 }
00788
00789 int FolderStorage::count(bool cache) const
00790 {
00791 if (cache && mTotalMsgs != -1)
00792 return mTotalMsgs;
00793 else
00794 return -1;
00795 }
00796
00797
00798 int FolderStorage::countUnread()
00799 {
00800 if (mGuessedUnreadMsgs > -1)
00801 return mGuessedUnreadMsgs;
00802 if (mUnreadMsgs > -1)
00803 return mUnreadMsgs;
00804
00805 readConfig();
00806
00807 if (mUnreadMsgs > -1)
00808 return mUnreadMsgs;
00809
00810 open();
00811 int unread = mUnreadMsgs;
00812 close();
00813 return (unread > 0) ? unread : 0;
00814 }
00815
00816
00817 void FolderStorage::msgStatusChanged(const KMMsgStatus oldStatus,
00818 const KMMsgStatus newStatus, int idx)
00819 {
00820 int oldUnread = 0;
00821 int newUnread = 0;
00822
00823 if (((oldStatus & KMMsgStatusUnread || oldStatus & KMMsgStatusNew) &&
00824 !(oldStatus & KMMsgStatusIgnored)) ||
00825 (folder() == kmkernel->outboxFolder()))
00826 oldUnread = 1;
00827 if (((newStatus & KMMsgStatusUnread || newStatus & KMMsgStatusNew) &&
00828 !(newStatus & KMMsgStatusIgnored)) ||
00829 (folder() == kmkernel->outboxFolder()))
00830 newUnread = 1;
00831 int deltaUnread = newUnread - oldUnread;
00832
00833 mDirtyTimer->changeInterval(mDirtyTimerInterval);
00834 if (deltaUnread != 0) {
00835 if (mUnreadMsgs < 0) mUnreadMsgs = 0;
00836 mUnreadMsgs += deltaUnread;
00837 if ( !mQuiet ) {
00838 emit numUnreadMsgsChanged( folder() );
00839 }else{
00840 if ( !mEmitChangedTimer->isActive() ) {
00841 mEmitChangedTimer->start( 3000 );
00842 }
00843 mChanged = true;
00844 }
00845 Q_UINT32 serNum = KMMsgDict::instance()->getMsgSerNum(folder(), idx);
00846 emit msgChanged( folder(), serNum, deltaUnread );
00847 }
00848 }
00849
00850
00851 void FolderStorage::headerOfMsgChanged(const KMMsgBase* aMsg, int idx)
00852 {
00853 if (idx < 0)
00854 idx = aMsg->parent()->find( aMsg );
00855
00856 if (idx >= 0 )
00857 {
00858 if ( !mQuiet )
00859 emit msgHeaderChanged(folder(), idx);
00860 else{
00861 if ( !mEmitChangedTimer->isActive() ) {
00862 mEmitChangedTimer->start( 3000 );
00863 }
00864 mChanged = true;
00865 }
00866 } else
00867 mChanged = true;
00868 }
00869
00870
00871 void FolderStorage::readConfig()
00872 {
00873
00874 KConfig* config = KMKernel::config();
00875 KConfigGroupSaver saver(config, "Folder-" + folder()->idString());
00876 if (mUnreadMsgs == -1)
00877 mUnreadMsgs = config->readNumEntry("UnreadMsgs", -1);
00878 if (mTotalMsgs == -1)
00879 mTotalMsgs = config->readNumEntry("TotalMsgs", -1);
00880 mCompactable = config->readBoolEntry("Compactable", true);
00881
00882 int type = config->readNumEntry( "ContentsType", 0 );
00883 if ( type < 0 || type > KMail::ContentsTypeLast ) type = 0;
00884 setContentsType( static_cast<KMail::FolderContentsType>( type ) );
00885
00886 if( folder() ) folder()->readConfig( config );
00887 }
00888
00889
00890 void FolderStorage::writeConfig()
00891 {
00892 KConfig* config = KMKernel::config();
00893 KConfigGroupSaver saver(config, "Folder-" + folder()->idString());
00894 config->writeEntry("UnreadMsgs",
00895 mGuessedUnreadMsgs == -1 ? mUnreadMsgs : mGuessedUnreadMsgs);
00896 config->writeEntry("TotalMsgs", mTotalMsgs);
00897 config->writeEntry("Compactable", mCompactable);
00898 config->writeEntry("ContentsType", mContentsType);
00899
00900
00901 if( folder() ) folder()->writeConfig( config );
00902
00903 GlobalSettings::self()->requestSync();
00904 }
00905
00906
00907 void FolderStorage::correctUnreadMsgsCount()
00908 {
00909 open();
00910 close();
00911 emit numUnreadMsgsChanged( folder() );
00912 }
00913
00914 void FolderStorage::registerWithMessageDict()
00915 {
00916 mExportsSernums = true;
00917 readFolderIdsFile();
00918 }
00919
00920 void FolderStorage::deregisterFromMessageDict()
00921 {
00922 writeFolderIdsFile();
00923 mExportsSernums = false;
00924 }
00925
00926 void FolderStorage::readFolderIdsFile()
00927 {
00928 if ( !mExportsSernums ) return;
00929 if ( KMMsgDict::mutableInstance()->readFolderIds( *this ) == -1 ) {
00930 invalidateFolder();
00931 }
00932 if ( !KMMsgDict::mutableInstance()->hasFolderIds( *this ) ) {
00933 invalidateFolder();
00934 }
00935 }
00936
00937 void FolderStorage::invalidateFolder()
00938 {
00939 if ( !mExportsSernums ) return;
00940 unlink(QFile::encodeName( indexLocation()) + ".sorted");
00941 unlink(QFile::encodeName( indexLocation()) + ".ids");
00942 fillMessageDict();
00943 KMMsgDict::mutableInstance()->writeFolderIds( *this );
00944 emit invalidated( folder() );
00945 }
00946
00947
00948
00949 int FolderStorage::writeFolderIdsFile() const
00950 {
00951 if ( !mExportsSernums ) return -1;
00952 return KMMsgDict::mutableInstance()->writeFolderIds( *this );
00953 }
00954
00955
00956 int FolderStorage::touchFolderIdsFile()
00957 {
00958 if ( !mExportsSernums ) return -1;
00959 return KMMsgDict::mutableInstance()->touchFolderIds( *this );
00960 }
00961
00962
00963 int FolderStorage::appendToFolderIdsFile( int idx )
00964 {
00965 if ( !mExportsSernums ) return -1;
00966 int ret = 0;
00967 if ( count() == 1 ) {
00968 ret = KMMsgDict::mutableInstance()->writeFolderIds( *this );
00969 } else {
00970 ret = KMMsgDict::mutableInstance()->appendToFolderIds( *this, idx );
00971 }
00972 return ret;
00973 }
00974
00975 void FolderStorage::replaceMsgSerNum( unsigned long sernum, KMMsgBase* msg, int idx )
00976 {
00977 if ( !mExportsSernums ) return;
00978 KMMsgDict::mutableInstance()->replace( sernum, msg, idx );
00979 }
00980
00981 void FolderStorage::setRDict( KMMsgDictREntry *rentry ) const
00982 {
00983 if ( ! mExportsSernums )
00984 kdDebug(5006) << "WTF, this FolderStorage should be invisible to the msgdict, who is calling us?" << kdBacktrace() << endl;
00985 assert( mExportsSernums );
00986 if ( rentry == mRDict )
00987 return;
00988 KMMsgDict::deleteRentry( mRDict );
00989 mRDict = rentry;
00990 }
00991
00992
00993 void FolderStorage::setStatus(int idx, KMMsgStatus status, bool toggle)
00994 {
00995 KMMsgBase *msg = getMsgBase(idx);
00996 if ( msg ) {
00997 if (toggle)
00998 msg->toggleStatus(status, idx);
00999 else
01000 msg->setStatus(status, idx);
01001 }
01002 }
01003
01004
01005
01006 void FolderStorage::setStatus(QValueList<int>& ids, KMMsgStatus status, bool toggle)
01007 {
01008 for ( QValueList<int>::Iterator it = ids.begin(); it != ids.end(); ++it )
01009 {
01010 FolderStorage::setStatus(*it, status, toggle);
01011 }
01012 }
01013
01014 void FolderStorage::ignoreJobsForMessage( KMMessage *msg )
01015 {
01016 if ( !msg || msg->transferInProgress() )
01017 return;
01018
01019 QPtrListIterator<FolderJob> it( mJobList );
01020 while ( it.current() )
01021 {
01022
01023
01024
01025 if ( it.current()->msgList().first() == msg )
01026 {
01027 FolderJob* job = it.current();
01028 mJobList.remove( job );
01029 delete job;
01030 } else
01031 ++it;
01032 }
01033 }
01034
01035
01036 void FolderStorage::removeJobs()
01037 {
01038 mJobList.setAutoDelete( true );
01039 mJobList.clear();
01040 mJobList.setAutoDelete( false );
01041 }
01042
01043
01044
01045
01046 void FolderStorage::updateChildrenState()
01047 {
01048 if ( folder() && folder()->child() )
01049 {
01050 if ( kmkernel->folderMgr()->folderCount( folder()->child() ) > 0 )
01051 setHasChildren( HasChildren );
01052 else
01053 setHasChildren( HasNoChildren );
01054 }
01055 }
01056
01057
01058 void FolderStorage::setNoChildren( bool aNoChildren )
01059 {
01060 mNoChildren = aNoChildren;
01061 if ( aNoChildren )
01062 setHasChildren( HasNoChildren );
01063 }
01064
01065
01066 void FolderStorage::setContentsType( KMail::FolderContentsType type )
01067 {
01068 if ( type != mContentsType ) {
01069 mContentsType = type;
01070 emit contentsTypeChanged( type );
01071 }
01072 }
01073
01074
01075 void FolderStorage::search( const KMSearchPattern* pattern )
01076 {
01077 mSearchPattern = pattern;
01078 mCurrentSearchedMsg = 0;
01079 if ( pattern )
01080 slotProcessNextSearchBatch();
01081 }
01082
01083 void FolderStorage::slotProcessNextSearchBatch()
01084 {
01085 if ( !mSearchPattern ) return;
01086 QValueList<Q_UINT32> matchingSerNums;
01087 int end = ( count() - mCurrentSearchedMsg > 100 ) ? 100+mCurrentSearchedMsg : count();
01088 for ( int i = mCurrentSearchedMsg; i < end; ++i )
01089 {
01090 Q_UINT32 serNum = KMMsgDict::instance()->getMsgSerNum( folder(), i );
01091 if ( mSearchPattern->matches( serNum ) )
01092 matchingSerNums.append( serNum );
01093 }
01094 mCurrentSearchedMsg = end;
01095 bool complete = ( end == count() ) ? true : false;
01096 emit searchResult( folder(), matchingSerNums, mSearchPattern, complete );
01097 if ( !complete )
01098 QTimer::singleShot( 0, this, SLOT(slotProcessNextSearchBatch()) );
01099 }
01100
01101
01102 void FolderStorage::search( const KMSearchPattern* pattern, Q_UINT32 serNum )
01103 {
01104 bool matches = pattern && pattern->matches( serNum );
01105
01106 emit searchDone( folder(), serNum, pattern, matches );
01107 }
01108
01109
01110 int FolderStorage::addMsg( QPtrList<KMMessage>& msgList, QValueList<int>& index_ret )
01111 {
01112 int ret = 0;
01113 int index;
01114 for ( QPtrListIterator<KMMessage> it( msgList ); *it; ++it )
01115 {
01116 int aret = addMsg( *it, &index );
01117 index_ret << index;
01118 if ( aret != 0 )
01119 ret = aret;
01120 }
01121 return ret;
01122 }
01123
01124
01125 bool FolderStorage::isMoveable() const
01126 {
01127 return ( folder()->isSystemFolder() ) ? false : true;
01128 }
01129
01130 #include "folderstorage.moc"