37 #include "folderstorage.h"
41 #include "kmfolderimap.h"
42 #include "undostack.h"
43 #include "kmmsgdict.h"
44 #include "kmfoldermgr.h"
45 #include "kmcommands.h"
48 #include "kmsearchpattern.h"
49 #include "globalsettings.h"
51 #include <tdelocale.h>
52 #include <tdeconfig.h>
58 #include <mimelib/mimepp.h>
64 : TQObject( folder, aName ), mFolder( folder ), mEmitChangedTimer( 0L )
73 mGuessedUnreadMsgs = -1;
77 mConvertToUtf8 =
false;
82 mDirtyTimer =
new TQTimer(
this,
"mDirtyTimer");
83 connect(mDirtyTimer, TQT_SIGNAL(timeout()),
86 mHasChildren = HasNoChildren;
93 FolderStorage::~FolderStorage()
96 TQObject::disconnect( TQT_SIGNAL(destroyed(TQObject*)),
this, 0 );
98 KMMsgDict::deleteRentry(
mRDict);
104 if (mOpenCount <= 0)
return;
105 if (mOpenCount > 0) mOpenCount--;
106 if (mOpenCount > 0 && !aForced)
return;
109 reallyDoClose(owner);
115 if (aStr[0] !=
'.')
return aStr;
116 return aStr.left(aStr.find(TQRegExp(
"[^\\.]"))) + aStr;
121 TQObject::connect( job, TQT_SIGNAL(destroyed(TQObject*)),
122 TQT_SLOT(removeJob(TQObject*)) );
126 void FolderStorage::removeJob( TQObject* job )
128 mJobList.remove( static_cast<FolderJob*>( job ) );
135 TQString sLocation(const_cast<FolderStorage*>(
this)->folder()->path());
137 if (!sLocation.isEmpty()) sLocation +=
'/';
145 return mFolder->name();
161 mDirtyTimer->changeInterval( mDirtyTimerInterval );
172 for (i=0; i<
count(); ++i)
175 if (msgBase->isNew())
177 msgBase->setStatus(KMMsgStatusUnread);
178 msgBase->setDirty(
true);
188 for (
int i=
count()-1; i>=0; --i)
192 if (msgBase->isNew() || msgBase->isUnread())
194 serNums.append( msgBase->getMsgSerNum() );
200 KMCommand *command =
new KMSeStatusCommand( KMMsgStatusRead, serNums );
213 if ( !mEmitChangedTimer) {
214 mEmitChangedTimer=
new TQTimer(
this,
"mEmitChangedTimer" );
215 connect( mEmitChangedTimer, TQT_SIGNAL( timeout() ),
223 delete mEmitChangedTimer;
224 mEmitChangedTimer=0L;
241 int operator<( KMMsgBase & m1, KMMsgBase & m2 )
243 return (m1.date() < m2.date());
247 int operator==( KMMsgBase & m1, KMMsgBase & m2 )
249 return (m1.date() == m2.date());
257 time_t msgTime, maxTime;
259 TQValueList<int> rmvMsgList;
261 maxTime = time(0) - days * 3600 * 24;
263 for (i=
count()-1; i>=0; i--) {
266 msgTime = mb->date();
268 if (msgTime < maxTime) {
292 if ( !mEmitChangedTimer->isActive() ) {
293 mEmitChangedTimer->start( 3000 );
303 if (aIndex_ret) *aIndex_ret = -1;
304 KMFolder *msgParent = aMsg->parent();
311 FolderJob *job = msgParent->
createJob(aMsg);
312 connect(job, TQT_SIGNAL(messageRetrieved(
KMMessage*)),
331 ulong serNum = aMsg->getMsgSerNum();
332 bool undo = aMsg->enableUndo();
334 if (index < 0)
return;
338 kmkernel->undoStack()->pushSingleAction( serNum, aFolder, folder() );
347 aMsg->setParent( 0 );
360 for( TQPtrListIterator<KMMsgBase> it( msgList ); *it; ++it )
362 int idx =
find(it.current());
371 for( TQPtrListIterator<KMMessage> it( msgList ); *it; ++it )
373 int idx =
find(it.current());
385 kdDebug(5006) <<
"FolderStorage::removeMsg() : idx < 0\n" << endl;
394 mb = takeIndexEntry( idx );
399 if (mb->isUnread() || mb->isNew() ||
400 (folder() == kmkernel->outboxFolder())) {
406 if ( !mEmitChangedTimer->isActive() ) {
408 mEmitChangedTimer->start( 3000 );
416 TQString msgIdMD5 = mb->msgIdMD5();
428 assert(idx>=0 && idx<=
count());
432 if (!mb->isMessage())
readMsg(idx);
438 if (msg->isUnread() || msg->isNew() ||
439 ( folder() == kmkernel->outboxFolder() )) {
444 if ( !mEmitChangedTimer->isActive() ) {
445 mEmitChangedTimer->start( 3000 );
455 TQString msgIdMD5 = msg->msgIdMD5();
464 for (
KMMessage* msg = msgList.first(); msg; msg = msgList.next() )
468 int idx = msg->parent()->find(msg);
479 if ( mOpenCount <= 0 ) {
480 kdWarning(5006) <<
"FolderStorage::getMsg was called on a closed folder: " << folder()->
prettyURL() << endl;
483 if ( idx < 0 || idx >=
count() ) {
484 kdWarning(5006) <<
"FolderStorage::getMsg was asked for an invalid index. idx =" << idx <<
" count()=" <<
count() << endl;
490 kdWarning(5006) <<
"FolderStorage::getMsg, getMsgBase failed for index: " << idx << endl;
495 bool undo = mb->enableUndo();
496 if (mb->isMessage()) {
499 TQString mbSubject = mb->
subject();
503 kdDebug(5006) <<
"Error: " <<
location() <<
504 " Index file is inconsistent with folder file. This should never happen." << endl;
517 if ( msg->getMsgSerNum() == 0 ) {
518 kdWarning(5006) <<
"FolderStorage::getMsg, message has no sernum, index: " << idx << endl;
521 msg->setEnableUndo(undo);
529 if(!(idx >= 0 && idx <=
count())) {
530 kdDebug(5006) << k_funcinfo <<
"Invalid index " << idx <<
"!" << endl;
536 kdDebug(5006) << k_funcinfo <<
"getMsgBase() for " << idx <<
" failed!" << endl;
540 unsigned long sernum = mb->getMsgSerNum();
543 bool undo = mb->enableUndo();
544 if (mb->isMessage()) {
555 if ( msgString.size() <= 0 ) {
556 kdDebug(5006) << k_funcinfo <<
" Calling getDwString() failed!" << endl;
560 msg->setEnableUndo(undo);
570 if(!(idx >= 0 && idx <=
count()))
577 if (mb->isMessage()) {
583 return setIndexEntry( idx, msg );
594 if (!(idx >= 0 && idx <=
count()))
return false;
596 return (mb && mb->isMessage());
601 KMFolder *folder, TQString partSpecifier,
602 const AttachmentStrategy *as )
const
604 FolderJob * job =
doCreateJob( msg, jt, folder, partSpecifier, as );
612 FolderJob::JobType jt,
KMFolder *folder )
const
614 FolderJob * job =
doCreateJob( msgList, sets, jt, folder );
624 KMFolder* msgParent = aMsg->parent();
627 msgParent->
open(
"moveMsgSrc");
630 int rc =
addMsg(aMsg, aIndex_ret);
631 close(
"moveMsgDest");
634 msgParent->
close(
"moveMsgSrc");
644 KMFolder* msgParent = aMsg->parent();
647 msgParent->
open(
"foldermovemsg");
649 TQValueList<int> index;
651 int rc =
addMsg(msglist, index);
654 if ( !index.isEmpty() )
655 aIndex_ret = &index.first();
658 msgParent->
close(
"foldermovemsg");
667 TQString oldLoc, oldIndexLoc, oldIdsLoc, newLoc, newIndexLoc, newIdsLoc;
668 TQString oldSubDirLoc, newSubDirLoc;
673 assert(!newName.isEmpty());
679 TQString oldConfigString =
"Folder-" + folder()->
idString();
681 close(
"rename",
true);
684 oldParent = folder()->parent();
686 folder()->setParent( newParent );
688 folder()->setName(newName);
694 if (::
rename(TQFile::encodeName(oldLoc), TQFile::encodeName(newLoc))) {
695 folder()->setName(oldName);
696 folder()->setParent(oldParent);
701 if (!oldIndexLoc.isEmpty()) {
702 ::rename(TQFile::encodeName(oldIndexLoc), TQFile::encodeName(newIndexLoc));
703 ::rename(TQFile::encodeName(oldIndexLoc) +
".sorted",
704 TQFile::encodeName(newIndexLoc) +
".sorted");
708 if (!oldIdsLoc.isEmpty())
709 ::
rename(TQFile::encodeName(oldIdsLoc), TQFile::encodeName(newIdsLoc));
714 child = folder()->
child();
716 if (!::
rename(TQFile::encodeName(oldSubDirLoc), TQFile::encodeName(newSubDirLoc) )) {
720 if( child && ( oldName != newName ) ) {
721 child->setName(
"." + TQFile::encodeName(newName) +
".directory" );
728 if (oldParent->findRef( folder() ) != -1)
730 newParent->inSort( folder() );
732 if ( child->parent()->findRef( child ) != -1 )
733 child->parent()->take();
734 newParent->inSort( child );
735 child->setParent( newParent );
743 if ( oldConfigString !=
"Folder-" + folder()->idString() )
744 KMKernel::config()->deleteGroup( oldConfigString );
748 kmkernel->folderMgr()->contentsChanged();
757 assert(!folder()->name().isEmpty());
760 close(
"remove",
true);
763 KMMsgDict::mutableInstance()->removeFolderIds( *
this );
774 TDEConfig* config = KMKernel::config();
775 config->deleteGroup(
"Folder-" + folder()->idString() );
778 emit
removed(folder(), (rc ?
false :
true));
785 assert(!folder()->name().isEmpty());
788 close(
"expunge",
true );
791 KMMsgDict::mutableInstance()->removeFolderIds( *
this );
817 return folder()->
label();
822 if (cache && mTotalMsgs != -1)
831 if (mGuessedUnreadMsgs > -1)
832 return mGuessedUnreadMsgs;
843 close(
"countunread");
844 return (unread > 0) ? unread : 0;
852 return doFolderSize();
865 const KMMsgStatus newStatus,
int idx)
870 if (((oldStatus & KMMsgStatusUnread || oldStatus & KMMsgStatusNew) &&
871 !(oldStatus & KMMsgStatusIgnored)) ||
872 (folder() == kmkernel->outboxFolder()))
874 if (((newStatus & KMMsgStatusUnread || newStatus & KMMsgStatusNew) &&
875 !(newStatus & KMMsgStatusIgnored)) ||
876 (folder() == kmkernel->outboxFolder()))
878 int deltaUnread = newUnread - oldUnread;
880 mDirtyTimer->changeInterval(mDirtyTimerInterval);
881 if (deltaUnread != 0) {
887 if ( !mEmitChangedTimer->isActive() ) {
888 mEmitChangedTimer->start( 3000 );
893 emit
msgChanged( folder(), serNum, deltaUnread );
901 idx = aMsg->parent()->find( aMsg );
908 if ( !mEmitChangedTimer->isActive() ) {
909 mEmitChangedTimer->start( 3000 );
921 TDEConfig* config = KMKernel::config();
922 TDEConfigGroupSaver saver(config,
"Folder-" + folder()->idString());
924 mUnreadMsgs = config->readNumEntry(
"UnreadMsgs", -1);
925 if (mTotalMsgs == -1)
926 mTotalMsgs = config->readNumEntry(
"TotalMsgs", -1);
927 mCompactable = config->readBoolEntry(
"Compactable",
true);
929 mSize = config->readNum64Entry(
"FolderSize", -1);
931 int type = config->readNumEntry(
"ContentsType", 0 );
932 if ( type < 0 || type > KMail::ContentsTypeLast ) type = 0;
935 if( folder() ) folder()->
readConfig( config );
941 TDEConfig* config = KMKernel::config();
942 TDEConfigGroupSaver saver(config,
"Folder-" + folder()->idString());
943 config->writeEntry(
"UnreadMsgs",
944 mGuessedUnreadMsgs == -1 ?
mUnreadMsgs : mGuessedUnreadMsgs);
945 config->writeEntry(
"TotalMsgs", mTotalMsgs);
948 config->writeEntry(
"FolderSize", mSize);
953 GlobalSettings::self()->requestSync();
959 open(
"countunreadmsg");
960 close(
"countunreadmsg");
979 if ( KMMsgDict::mutableInstance()->readFolderIds( *
this ) == -1 ) {
982 if ( !KMMsgDict::mutableInstance()->hasFolderIds( *
this ) ) {
993 KMMsgDict::mutableInstance()->writeFolderIds( *
this );
1002 return KMMsgDict::mutableInstance()->writeFolderIds( *
this );
1009 return KMMsgDict::mutableInstance()->touchFolderIds( *
this );
1017 if (
count() == 1 ) {
1018 ret = KMMsgDict::mutableInstance()->writeFolderIds( *
this );
1020 ret = KMMsgDict::mutableInstance()->appendToFolderIds( *
this, idx );
1028 KMMsgDict::mutableInstance()->replace( sernum, msg, idx );
1034 kdDebug(5006) <<
"WTF, this FolderStorage should be invisible to the msgdict, who is calling us?" << kdBacktrace() << endl;
1038 KMMsgDict::deleteRentry(
mRDict );
1048 msg->toggleStatus(status, idx);
1050 msg->setStatus(status, idx);
1058 for ( TQValueList<int>::Iterator it = ids.begin(); it != ids.end(); ++it )
1069 TQPtrListIterator<FolderJob> it(
mJobList );
1070 while ( it.current() )
1075 if ( it.current()->msgList().first() == msg )
1077 FolderJob* job = it.current();
1086 void FolderStorage::removeJobs()
1098 if ( folder() && folder()->child() )
1100 if ( kmkernel->folderMgr()->folderCount( folder()->child() ) > 0 )
1110 mNoChildren = aNoChildren;
1128 mSearchPattern = pattern;
1129 mCurrentSearchedMsg = 0;
1136 if ( !mSearchPattern )
1138 TQValueList<TQ_UINT32> matchingSerNums;
1139 const int end = TQMIN( mCurrentSearchedMsg + 15,
count() );
1140 for (
int i = mCurrentSearchedMsg; i < end; ++i )
1143 if ( mSearchPattern->
matches( serNum ) )
1144 matchingSerNums.append( serNum );
1146 mCurrentSearchedMsg = end;
1147 bool complete = ( end >=
count() );
1148 emit
searchResult( folder(), matchingSerNums, mSearchPattern, complete );
1156 bool matches = pattern && pattern->
matches( serNum );
1158 emit
searchDone( folder(), serNum, pattern, matches );
1166 for ( TQPtrListIterator<KMMessage> it( msgList ); *it; ++it )
1168 int aret =
addMsg( *it, &index );
1179 return ( folder()->isSystemFolder() ) ?
false :
true;
1184 KMAccount* FolderStorage::account()
const
1189 bool FolderStorage::mailCheckInProgress()
const
1201 const bool changed = aNoContent != mNoContent;
1202 mNoContent = aNoContent;
1207 #include "folderstorage.moc"