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 <tqfile.h>
00056 #include <tqregexp.h>
00057
00058 #include <mimelib/mimepp.h>
00059 #include <errno.h>
00060
00061
00062
00063 FolderStorage::FolderStorage( KMFolder* folder, const char* aName )
00064 : TQObject( 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 TQTimer(this, "mDirtyTimer");
00083 connect(mDirtyTimer, TQT_SIGNAL(timeout()),
00084 this, TQT_SLOT(updateIndex()));
00085
00086 mHasChildren = HasNoChildren;
00087 mContentsType = KMail::ContentsTypeMail;
00088
00089 connect(this, TQT_SIGNAL(closed(KMFolder*)), mFolder, TQT_SIGNAL(closed()));
00090 }
00091
00092
00093 FolderStorage::~FolderStorage()
00094 {
00095 mJobList.setAutoDelete( true );
00096 TQObject::disconnect( TQT_SIGNAL(destroyed(TQObject*)), 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 TQString FolderStorage::dotEscape(const TQString& aStr)
00114 {
00115 if (aStr[0] != '.') return aStr;
00116 return aStr.left(aStr.find(TQRegExp("[^\\.]"))) + aStr;
00117 }
00118
00119 void FolderStorage::addJob( FolderJob* job ) const
00120 {
00121 TQObject::connect( job, TQT_SIGNAL(destroyed(TQObject*)),
00122 TQT_SLOT(removeJob(TQObject*)) );
00123 mJobList.append( job );
00124 }
00125
00126 void FolderStorage::removeJob( TQObject* job )
00127 {
00128 mJobList.remove( static_cast<FolderJob*>( job ) );
00129 }
00130
00131
00132
00133 TQString FolderStorage::location() const
00134 {
00135 TQString sLocation(const_cast<FolderStorage*>(this)->folder()->path());
00136
00137 if (!sLocation.isEmpty()) sLocation += '/';
00138 sLocation += dotEscape(fileName());
00139
00140 return sLocation;
00141 }
00142
00143 TQString 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 KMSeStatusCommand( 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 TQTimer( this, "mEmitChangedTimer" );
00215 connect( mEmitChangedTimer, TQT_SIGNAL( timeout() ),
00216 this, TQT_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 TQValueList<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 TQ_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, TQT_SIGNAL(messageRetrieved(KMMessage*)),
00313 TQT_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 TQPtrList<KMMsgBase>& msgList, bool imapQuiet)
00359 {
00360 for( TQPtrListIterator<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 TQPtrList<KMMessage>& msgList, bool imapQuiet)
00370 {
00371 for( TQPtrListIterator<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 TQ_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 TQString 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 TQ_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 TQString msgIdMD5 = msg->msgIdMD5();
00456 emit msgRemoved( idx, msgIdMD5 );
00457 emit msgRemoved( folder() );
00458
00459 return msg;
00460 }
00461
00462 void FolderStorage::take(TQPtrList<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 TQString 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
00506
00507
00508
00509 mCompactable = false;
00510 writeConfig();
00511 }
00512
00513 }
00514
00515
00516
00517 if ( msg->getMsgSerNum() == 0 ) {
00518 kdWarning(5006) << "FolderStorage::getMsg, message has no sernum, index: " << idx << endl;
00519 return 0;
00520 }
00521 msg->setEnableUndo(undo);
00522 msg->setComplete( true );
00523 return msg;
00524 }
00525
00526
00527 KMMessage* FolderStorage::readTemporaryMsg(int idx)
00528 {
00529 if(!(idx >= 0 && idx <= count())) {
00530 kdDebug(5006) << k_funcinfo << "Invalid index " << idx << "!" << endl;
00531 return 0;
00532 }
00533
00534 KMMsgBase* mb = getMsgBase(idx);
00535 if (!mb) {
00536 kdDebug(5006) << k_funcinfo << "getMsgBase() for " << idx << " failed!" << endl;
00537 return 0;
00538 }
00539
00540 unsigned long sernum = mb->getMsgSerNum();
00541
00542 KMMessage *msg = 0;
00543 bool undo = mb->enableUndo();
00544 if (mb->isMessage()) {
00545
00546 msg = new KMMessage(*(KMMessage*)mb);
00547 msg->setMsgSerNum(sernum);
00548 msg->setComplete( true );
00549 } else {
00550
00551 msg = new KMMessage(*(KMMsgInfo*)mb);
00552 msg->setMsgSerNum(sernum);
00553 msg->setComplete( true );
00554 const DwString msgString = getDwString( idx );
00555 if ( msgString.size() <= 0 ) {
00556 kdDebug(5006) << k_funcinfo << " Calling getDwString() failed!" << endl;
00557 }
00558 msg->fromDwString( msgString );
00559 }
00560 msg->setEnableUndo(undo);
00561 return msg;
00562 }
00563
00564
00565
00566 KMMsgInfo* FolderStorage::unGetMsg(int idx)
00567 {
00568 KMMsgBase* mb;
00569
00570 if(!(idx >= 0 && idx <= count()))
00571 return 0;
00572
00573 mb = getMsgBase(idx);
00574 if (!mb) return 0;
00575
00576
00577 if (mb->isMessage()) {
00578
00579
00580 KMMessage *msg = static_cast<KMMessage*>(mb);
00581 if ( msg->transferInProgress() ) return 0;
00582 ignoreJobsForMessage( msg );
00583 return setIndexEntry( idx, msg );
00584 }
00585
00586 return 0;
00587 }
00588
00589
00590
00591 bool FolderStorage::isMessage(int idx)
00592 {
00593 KMMsgBase* mb;
00594 if (!(idx >= 0 && idx <= count())) return false;
00595 mb = getMsgBase(idx);
00596 return (mb && mb->isMessage());
00597 }
00598
00599
00600 FolderJob* FolderStorage::createJob( KMMessage *msg, FolderJob::JobType jt,
00601 KMFolder *folder, TQString partSpecifier,
00602 const AttachmentStrategy *as ) const
00603 {
00604 FolderJob * job = doCreateJob( msg, jt, folder, partSpecifier, as );
00605 if ( job )
00606 addJob( job );
00607 return job;
00608 }
00609
00610
00611 FolderJob* FolderStorage::createJob( TQPtrList<KMMessage>& msgList, const TQString& sets,
00612 FolderJob::JobType jt, KMFolder *folder ) const
00613 {
00614 FolderJob * job = doCreateJob( msgList, sets, jt, folder );
00615 if ( job )
00616 addJob( job );
00617 return job;
00618 }
00619
00620
00621 int FolderStorage::moveMsg(KMMessage* aMsg, int* aIndex_ret)
00622 {
00623 assert(aMsg != 0);
00624 KMFolder* msgParent = aMsg->parent();
00625
00626 if (msgParent)
00627 msgParent->open("moveMsgSrc");
00628
00629 open("moveMsgDest");
00630 int rc = addMsg(aMsg, aIndex_ret);
00631 close("moveMsgDest");
00632
00633 if (msgParent)
00634 msgParent->close("moveMsgSrc");
00635
00636 return rc;
00637 }
00638
00639
00640 int FolderStorage::moveMsg(TQPtrList<KMMessage> msglist, int* aIndex_ret)
00641 {
00642 KMMessage* aMsg = msglist.first();
00643 assert(aMsg != 0);
00644 KMFolder* msgParent = aMsg->parent();
00645
00646 if (msgParent)
00647 msgParent->open("foldermovemsg");
00648
00649 TQValueList<int> index;
00650 open("moveMsg");
00651 int rc = addMsg(msglist, index);
00652 close("moveMsg");
00653
00654 if ( !index.isEmpty() )
00655 aIndex_ret = &index.first();
00656
00657 if (msgParent)
00658 msgParent->close("foldermovemsg");
00659
00660 return rc;
00661 }
00662
00663
00664
00665 int FolderStorage::rename(const TQString& newName, KMFolderDir *newParent)
00666 {
00667 TQString oldLoc, oldIndexLoc, oldIdsLoc, newLoc, newIndexLoc, newIdsLoc;
00668 TQString oldSubDirLoc, newSubDirLoc;
00669 TQString oldName;
00670 int rc=0;
00671 KMFolderDir *oldParent;
00672
00673 assert(!newName.isEmpty());
00674
00675 oldLoc = location();
00676 oldIndexLoc = indexLocation();
00677 oldSubDirLoc = folder()->subdirLocation();
00678 oldIdsLoc = KMMsgDict::instance()->getFolderIdsLocation( *this );
00679 TQString oldConfigString = "Folder-" + folder()->idString();
00680
00681 close("rename", true);
00682
00683 oldName = folder()->fileName();
00684 oldParent = folder()->parent();
00685 if (newParent)
00686 folder()->setParent( newParent );
00687
00688 folder()->setName(newName);
00689 newLoc = location();
00690 newIndexLoc = indexLocation();
00691 newSubDirLoc = folder()->subdirLocation();
00692 newIdsLoc = KMMsgDict::instance()->getFolderIdsLocation( *this );
00693
00694 if (::rename(TQFile::encodeName(oldLoc), TQFile::encodeName(newLoc))) {
00695 folder()->setName(oldName);
00696 folder()->setParent(oldParent);
00697 rc = errno;
00698 }
00699 else {
00700
00701 if (!oldIndexLoc.isEmpty()) {
00702 ::rename(TQFile::encodeName(oldIndexLoc), TQFile::encodeName(newIndexLoc));
00703 ::rename(TQFile::encodeName(oldIndexLoc) + ".sorted",
00704 TQFile::encodeName(newIndexLoc) + ".sorted");
00705 }
00706
00707
00708 if (!oldIdsLoc.isEmpty())
00709 ::rename(TQFile::encodeName(oldIdsLoc), TQFile::encodeName(newIdsLoc));
00710
00711
00712 KMFolderDir* child = 0;
00713 if( folder() )
00714 child = folder()->child();
00715
00716 if (!::rename(TQFile::encodeName(oldSubDirLoc), TQFile::encodeName(newSubDirLoc) )) {
00717
00718
00719
00720 if( child && ( oldName != newName ) ) {
00721 child->setName( "." + TQFile::encodeName(newName) + ".directory" );
00722 }
00723 }
00724
00725
00726
00727 if (newParent) {
00728 if (oldParent->findRef( folder() ) != -1)
00729 oldParent->take();
00730 newParent->inSort( folder() );
00731 if ( child ) {
00732 if ( child->parent()->findRef( child ) != -1 )
00733 child->parent()->take();
00734 newParent->inSort( child );
00735 child->setParent( newParent );
00736 }
00737 }
00738 }
00739
00740 writeConfig();
00741
00742
00743 if ( oldConfigString != "Folder-" + folder()->idString() )
00744 KMKernel::config()->deleteGroup( oldConfigString );
00745
00746 emit locationChanged( oldLoc, newLoc );
00747 emit nameChanged();
00748 kmkernel->folderMgr()->contentsChanged();
00749 emit closed(folder());
00750 return rc;
00751 }
00752
00753
00754
00755 void FolderStorage::remove()
00756 {
00757 assert(!folder()->name().isEmpty());
00758
00759 clearIndex( true, mExportsSernums );
00760 close("remove", true);
00761
00762 if ( mExportsSernums ) {
00763 KMMsgDict::mutableInstance()->removeFolderIds( *this );
00764 mExportsSernums = false;
00765 }
00766 unlink(TQFile::encodeName(indexLocation()) + ".sorted");
00767 unlink(TQFile::encodeName(indexLocation()));
00768
00769 int rc = removeContents();
00770
00771 needsCompact = false;
00772
00773
00774 KConfig* config = KMKernel::config();
00775 config->deleteGroup( "Folder-" + folder()->idString() );
00776
00777 emit closed(folder());
00778 emit removed(folder(), (rc ? false : true));
00779 }
00780
00781
00782
00783 int FolderStorage::expunge()
00784 {
00785 assert(!folder()->name().isEmpty());
00786
00787 clearIndex( true, mExportsSernums );
00788 close( "expunge", true );
00789
00790 if ( mExportsSernums )
00791 KMMsgDict::mutableInstance()->removeFolderIds( *this );
00792 if ( mAutoCreateIndex )
00793 truncateIndex();
00794 else unlink(TQFile::encodeName(indexLocation()));
00795
00796 int rc = expungeContents();
00797 if (rc) return rc;
00798
00799 mDirty = false;
00800 needsCompact = false;
00801
00802 mUnreadMsgs = 0;
00803 mTotalMsgs = 0;
00804 mSize = 0;
00805 emit numUnreadMsgsChanged( folder() );
00806 if ( mAutoCreateIndex )
00807 writeConfig();
00808 emit changed();
00809 emit expunged( folder() );
00810
00811 return 0;
00812 }
00813
00814
00815 TQString FolderStorage::label() const
00816 {
00817 return folder()->label();
00818 }
00819
00820 int FolderStorage::count(bool cache) const
00821 {
00822 if (cache && mTotalMsgs != -1)
00823 return mTotalMsgs;
00824 else
00825 return -1;
00826 }
00827
00828
00829 int FolderStorage::countUnread()
00830 {
00831 if (mGuessedUnreadMsgs > -1)
00832 return mGuessedUnreadMsgs;
00833 if (mUnreadMsgs > -1)
00834 return mUnreadMsgs;
00835
00836 readConfig();
00837
00838 if (mUnreadMsgs > -1)
00839 return mUnreadMsgs;
00840
00841 open("countunread");
00842 int unread = mUnreadMsgs;
00843 close("countunread");
00844 return (unread > 0) ? unread : 0;
00845 }
00846
00847 TQ_INT64 FolderStorage::folderSize() const
00848 {
00849 if ( mSize != -1 ) {
00850 return mSize;
00851 } else {
00852 return doFolderSize();
00853 }
00854 }
00855
00856
00857
00858 bool FolderStorage::isCloseToQuota() const
00859 {
00860 return false;
00861 }
00862
00863
00864 void FolderStorage::msgStatusChanged(const KMMsgStatus oldStatus,
00865 const KMMsgStatus newStatus, int idx)
00866 {
00867 int oldUnread = 0;
00868 int newUnread = 0;
00869
00870 if (((oldStatus & KMMsgStatusUnread || oldStatus & KMMsgStatusNew) &&
00871 !(oldStatus & KMMsgStatusIgnored)) ||
00872 (folder() == kmkernel->outboxFolder()))
00873 oldUnread = 1;
00874 if (((newStatus & KMMsgStatusUnread || newStatus & KMMsgStatusNew) &&
00875 !(newStatus & KMMsgStatusIgnored)) ||
00876 (folder() == kmkernel->outboxFolder()))
00877 newUnread = 1;
00878 int deltaUnread = newUnread - oldUnread;
00879
00880 mDirtyTimer->changeInterval(mDirtyTimerInterval);
00881 if (deltaUnread != 0) {
00882 if (mUnreadMsgs < 0) mUnreadMsgs = 0;
00883 mUnreadMsgs += deltaUnread;
00884 if ( !mQuiet ) {
00885 emit numUnreadMsgsChanged( folder() );
00886 }else{
00887 if ( !mEmitChangedTimer->isActive() ) {
00888 mEmitChangedTimer->start( 3000 );
00889 }
00890 mChanged = true;
00891 }
00892 TQ_UINT32 serNum = KMMsgDict::instance()->getMsgSerNum(folder(), idx);
00893 emit msgChanged( folder(), serNum, deltaUnread );
00894 }
00895 }
00896
00897
00898 void FolderStorage::headerOfMsgChanged(const KMMsgBase* aMsg, int idx)
00899 {
00900 if (idx < 0)
00901 idx = aMsg->parent()->find( aMsg );
00902
00903 if (idx >= 0 )
00904 {
00905 if ( !mQuiet )
00906 emit msgHeaderChanged(folder(), idx);
00907 else{
00908 if ( !mEmitChangedTimer->isActive() ) {
00909 mEmitChangedTimer->start( 3000 );
00910 }
00911 mChanged = true;
00912 }
00913 } else
00914 mChanged = true;
00915 }
00916
00917
00918 void FolderStorage::readConfig()
00919 {
00920
00921 KConfig* config = KMKernel::config();
00922 KConfigGroupSaver saver(config, "Folder-" + folder()->idString());
00923 if (mUnreadMsgs == -1)
00924 mUnreadMsgs = config->readNumEntry("UnreadMsgs", -1);
00925 if (mTotalMsgs == -1)
00926 mTotalMsgs = config->readNumEntry("TotalMsgs", -1);
00927 mCompactable = config->readBoolEntry("Compactable", true);
00928 if ( mSize == -1 )
00929 mSize = config->readNum64Entry("FolderSize", -1);
00930
00931 int type = config->readNumEntry( "ContentsType", 0 );
00932 if ( type < 0 || type > KMail::ContentsTypeLast ) type = 0;
00933 setContentsType( static_cast<KMail::FolderContentsType>( type ) );
00934
00935 if( folder() ) folder()->readConfig( config );
00936 }
00937
00938
00939 void FolderStorage::writeConfig()
00940 {
00941 KConfig* config = KMKernel::config();
00942 KConfigGroupSaver saver(config, "Folder-" + folder()->idString());
00943 config->writeEntry("UnreadMsgs",
00944 mGuessedUnreadMsgs == -1 ? mUnreadMsgs : mGuessedUnreadMsgs);
00945 config->writeEntry("TotalMsgs", mTotalMsgs);
00946 config->writeEntry("Compactable", mCompactable);
00947 config->writeEntry("ContentsType", mContentsType);
00948 config->writeEntry("FolderSize", mSize);
00949
00950
00951 if( folder() ) folder()->writeConfig( config );
00952
00953 GlobalSettings::self()->requestSync();
00954 }
00955
00956
00957 void FolderStorage::correctUnreadMsgsCount()
00958 {
00959 open("countunreadmsg");
00960 close("countunreadmsg");
00961 emit numUnreadMsgsChanged( folder() );
00962 }
00963
00964 void FolderStorage::registerWithMessageDict()
00965 {
00966 mExportsSernums = true;
00967 readFolderIdsFile();
00968 }
00969
00970 void FolderStorage::deregisterFromMessageDict()
00971 {
00972 writeFolderIdsFile();
00973 mExportsSernums = false;
00974 }
00975
00976 void FolderStorage::readFolderIdsFile()
00977 {
00978 if ( !mExportsSernums ) return;
00979 if ( KMMsgDict::mutableInstance()->readFolderIds( *this ) == -1 ) {
00980 invalidateFolder();
00981 }
00982 if ( !KMMsgDict::mutableInstance()->hasFolderIds( *this ) ) {
00983 invalidateFolder();
00984 }
00985 }
00986
00987 void FolderStorage::invalidateFolder()
00988 {
00989 if ( !mExportsSernums ) return;
00990 unlink(TQFile::encodeName( indexLocation()) + ".sorted");
00991 unlink(TQFile::encodeName( indexLocation()) + ".ids");
00992 fillMessageDict();
00993 KMMsgDict::mutableInstance()->writeFolderIds( *this );
00994 emit invalidated( folder() );
00995 }
00996
00997
00998
00999 int FolderStorage::writeFolderIdsFile() const
01000 {
01001 if ( !mExportsSernums ) return -1;
01002 return KMMsgDict::mutableInstance()->writeFolderIds( *this );
01003 }
01004
01005
01006 int FolderStorage::touchFolderIdsFile()
01007 {
01008 if ( !mExportsSernums ) return -1;
01009 return KMMsgDict::mutableInstance()->touchFolderIds( *this );
01010 }
01011
01012
01013 int FolderStorage::appendToFolderIdsFile( int idx )
01014 {
01015 if ( !mExportsSernums ) return -1;
01016 int ret = 0;
01017 if ( count() == 1 ) {
01018 ret = KMMsgDict::mutableInstance()->writeFolderIds( *this );
01019 } else {
01020 ret = KMMsgDict::mutableInstance()->appendToFolderIds( *this, idx );
01021 }
01022 return ret;
01023 }
01024
01025 void FolderStorage::replaceMsgSerNum( unsigned long sernum, KMMsgBase* msg, int idx )
01026 {
01027 if ( !mExportsSernums ) return;
01028 KMMsgDict::mutableInstance()->replace( sernum, msg, idx );
01029 }
01030
01031 void FolderStorage::setRDict( KMMsgDictREntry *rentry ) const
01032 {
01033 if ( ! mExportsSernums )
01034 kdDebug(5006) << "WTF, this FolderStorage should be invisible to the msgdict, who is calling us?" << kdBacktrace() << endl;
01035 assert( mExportsSernums );
01036 if ( rentry == mRDict )
01037 return;
01038 KMMsgDict::deleteRentry( mRDict );
01039 mRDict = rentry;
01040 }
01041
01042
01043 void FolderStorage::setStatus(int idx, KMMsgStatus status, bool toggle)
01044 {
01045 KMMsgBase *msg = getMsgBase(idx);
01046 if ( msg ) {
01047 if (toggle)
01048 msg->toggleStatus(status, idx);
01049 else
01050 msg->setStatus(status, idx);
01051 }
01052 }
01053
01054
01055
01056 void FolderStorage::setStatus(TQValueList<int>& ids, KMMsgStatus status, bool toggle)
01057 {
01058 for ( TQValueList<int>::Iterator it = ids.begin(); it != ids.end(); ++it )
01059 {
01060 FolderStorage::setStatus(*it, status, toggle);
01061 }
01062 }
01063
01064 void FolderStorage::ignoreJobsForMessage( KMMessage *msg )
01065 {
01066 if ( !msg || msg->transferInProgress() )
01067 return;
01068
01069 TQPtrListIterator<FolderJob> it( mJobList );
01070 while ( it.current() )
01071 {
01072
01073
01074
01075 if ( it.current()->msgList().first() == msg )
01076 {
01077 FolderJob* job = it.current();
01078 mJobList.remove( job );
01079 delete job;
01080 } else
01081 ++it;
01082 }
01083 }
01084
01085
01086 void FolderStorage::removeJobs()
01087 {
01088 mJobList.setAutoDelete( true );
01089 mJobList.clear();
01090 mJobList.setAutoDelete( false );
01091 }
01092
01093
01094
01095
01096 void FolderStorage::updateChildrenState()
01097 {
01098 if ( folder() && folder()->child() )
01099 {
01100 if ( kmkernel->folderMgr()->folderCount( folder()->child() ) > 0 )
01101 setHasChildren( HasChildren );
01102 else
01103 setHasChildren( HasNoChildren );
01104 }
01105 }
01106
01107
01108 void FolderStorage::setNoChildren( bool aNoChildren )
01109 {
01110 mNoChildren = aNoChildren;
01111 if ( aNoChildren )
01112 setHasChildren( HasNoChildren );
01113 }
01114
01115
01116 void FolderStorage::setContentsType( KMail::FolderContentsType type, bool quiet )
01117 {
01118 if ( type != mContentsType ) {
01119 mContentsType = type;
01120 if ( !quiet )
01121 emit contentsTypeChanged( type );
01122 }
01123 }
01124
01125
01126 void FolderStorage::search( const KMSearchPattern* pattern )
01127 {
01128 mSearchPattern = pattern;
01129 mCurrentSearchedMsg = 0;
01130 if ( pattern )
01131 slotProcessNextSearchBatch();
01132 }
01133
01134 void FolderStorage::slotProcessNextSearchBatch()
01135 {
01136 if ( !mSearchPattern )
01137 return;
01138 TQValueList<TQ_UINT32> matchingSerNums;
01139 const int end = TQMIN( mCurrentSearchedMsg + 15, count() );
01140 for ( int i = mCurrentSearchedMsg; i < end; ++i )
01141 {
01142 TQ_UINT32 serNum = KMMsgDict::instance()->getMsgSerNum( folder(), i );
01143 if ( mSearchPattern->matches( serNum ) )
01144 matchingSerNums.append( serNum );
01145 }
01146 mCurrentSearchedMsg = end;
01147 bool complete = ( end >= count() );
01148 emit searchResult( folder(), matchingSerNums, mSearchPattern, complete );
01149 if ( !complete )
01150 TQTimer::singleShot( 0, this, TQT_SLOT(slotProcessNextSearchBatch()) );
01151 }
01152
01153
01154 void FolderStorage::search( const KMSearchPattern* pattern, TQ_UINT32 serNum )
01155 {
01156 bool matches = pattern && pattern->matches( serNum );
01157
01158 emit searchDone( folder(), serNum, pattern, matches );
01159 }
01160
01161
01162 int FolderStorage::addMsg( TQPtrList<KMMessage>& msgList, TQValueList<int>& index_ret )
01163 {
01164 int ret = 0;
01165 int index;
01166 for ( TQPtrListIterator<KMMessage> it( msgList ); *it; ++it )
01167 {
01168 int aret = addMsg( *it, &index );
01169 index_ret << index;
01170 if ( aret != 0 )
01171 ret = aret;
01172 }
01173 return ret;
01174 }
01175
01176
01177 bool FolderStorage::isMoveable() const
01178 {
01179 return ( folder()->isSystemFolder() ) ? false : true;
01180 }
01181
01182
01183
01184 KMAccount* FolderStorage::account() const
01185 {
01186 return 0;
01187 }
01188
01189 bool FolderStorage::mailCheckInProgress() const
01190 {
01191 return false;
01192 }
01193
01194 bool FolderStorage::canDeleteMessages() const
01195 {
01196 return !isReadOnly();
01197 }
01198
01199 void FolderStorage::setNoContent(bool aNoContent)
01200 {
01201 const bool changed = aNoContent != mNoContent;
01202 mNoContent = aNoContent;
01203 if ( changed )
01204 emit noContentChanged();
01205 }
01206
01207 #include "folderstorage.moc"