kmail Library API Documentation

folderstorage.cpp

00001 /* 00002 Virtual base class for mail storage. 00003 00004 This file is part of KMail. 00005 00006 Copyright (c) 2004 Bo Thorsen <bo@klaralvdalens-datakonsult.se> 00007 00008 This library is free software; you can redistribute it and/or 00009 modify it under the terms of the GNU Library General Public 00010 License as published by the Free Software Foundation; either 00011 version 2 of the License, or (at your option) any later version. 00012 00013 This library is distributed in the hope that it will be useful, 00014 but WITHOUT ANY WARRANTY; without even the implied warranty of 00015 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 00016 Library General Public License for more details. 00017 00018 You should have received a copy of the GNU Library General Public License 00019 along with this library; see the file COPYING.LIB. If not, write to 00020 the Free Software Foundation, Inc., 59 Temple Place - Suite 330, 00021 Boston, MA 02111-1307, USA. 00022 00023 In addition, as a special exception, the copyright holders give 00024 permission to link the code of this program with any edition of 00025 the Qt library by Trolltech AS, Norway (or with modified versions 00026 of Qt that use the same license as Qt), and distribute linked 00027 combinations including the two. You must obey the GNU General 00028 Public License in all respects for all of the code used other than 00029 Qt. If you modify this file, you may extend this exception to 00030 your version of the file, but you are not obligated to do so. If 00031 you do not wish to do so, delete this exception statement from 00032 your version. 00033 */ 00034 00035 #include <config.h> 00036 00037 #include "folderstorage.h" 00038 #include "kmfolder.h" 00039 00040 #include "kmfolderimap.h" //for the nasty imap hacks, FIXME 00041 #include "undostack.h" 00042 #include "kmmsgdict.h" 00043 #include "kmfoldermgr.h" 00044 #include "kmkernel.h" 00045 #include "kmcommands.h" 00046 #include "listjob.h" 00047 using KMail::ListJob; 00048 #include "kmailicalifaceimpl.h" 00049 00050 #include <klocale.h> 00051 #include <kconfig.h> 00052 #include <kdebug.h> 00053 00054 #include <qfile.h> 00055 #include <qregexp.h> 00056 00057 #include <mimelib/mimepp.h> 00058 #include <errno.h> 00059 00060 //----------------------------------------------------------------------------- 00061 00062 FolderStorage::FolderStorage( KMFolder* folder, const char* aName ) 00063 : QObject( folder, aName ), mFolder( folder ) 00064 { 00065 mOpenCount = 0; 00066 mQuiet = 0; 00067 mChanged = FALSE; 00068 mAutoCreateIndex= TRUE; 00069 folder->setType( "plain" ); 00070 mAcctList = 0; 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 mHasChildren = HasNoChildren; 00085 mContentsType = KMail::ContentsTypeMail; 00086 } 00087 00088 //----------------------------------------------------------------------------- 00089 FolderStorage::~FolderStorage() 00090 { 00091 delete mAcctList; 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 if (beQuiet) 00195 mQuiet++; 00196 else { 00197 mQuiet--; 00198 if (mQuiet <= 0) 00199 { 00200 mQuiet = 0; 00201 if (mChanged) 00202 emit changed(); 00203 mChanged = FALSE; 00204 } 00205 } 00206 } 00207 00208 //----------------------------------------------------------------------------- 00209 00210 // Needed to use QSortedList in reduceSize() 00211 00213 int operator<( KMMsgBase & m1, KMMsgBase & m2 ) 00214 { 00215 return (m1.date() < m2.date()); 00216 } 00217 00219 int operator==( KMMsgBase & m1, KMMsgBase & m2 ) 00220 { 00221 return (m1.date() == m2.date()); 00222 } 00223 00224 00225 //----------------------------------------------------------------------------- 00226 int FolderStorage::expungeOldMsg(int days) 00227 { 00228 int i, msgnb=0; 00229 time_t msgTime, maxTime; 00230 const KMMsgBase* mb; 00231 QValueList<int> rmvMsgList; 00232 00233 maxTime = time(0) - days * 3600 * 24; 00234 00235 for (i=count()-1; i>=0; i--) { 00236 mb = getMsgBase(i); 00237 assert(mb); 00238 msgTime = mb->date(); 00239 00240 if (msgTime < maxTime) { 00241 //kdDebug(5006) << "deleting msg " << i << " : " << mb->subject() << " - " << mb->dateStr(); // << endl; 00242 removeMsg( i ); 00243 msgnb++; 00244 } 00245 } 00246 return msgnb; 00247 } 00248 00249 //----------------------------------------------------------------------------- 00250 void FolderStorage::emitMsgAddedSignals(int idx) 00251 { 00252 Q_UINT32 serNum = kmkernel->msgDict()->getMsgSerNum( folder() , idx ); 00253 if (!mQuiet) { 00254 emit msgAdded(idx); 00255 } else { 00256 mChanged=true; 00257 } 00258 emit msgAdded( folder(), serNum ); 00259 } 00260 00261 //----------------------------------------------------------------------------- 00262 bool FolderStorage::canAddMsgNow(KMMessage* aMsg, int* aIndex_ret) 00263 { 00264 if (aIndex_ret) *aIndex_ret = -1; 00265 KMFolder *msgParent = aMsg->parent(); 00266 // If the message has a parent and is in transfer, bail out. If it does not 00267 // have a parent we want to be able to add it even if it is in transfer. 00268 if (aMsg->transferInProgress() && msgParent) 00269 return false; 00270 if (!aMsg->isComplete() && msgParent && msgParent->folderType() == KMFolderTypeImap) 00271 { 00272 FolderJob *job = msgParent->createJob(aMsg); 00273 connect(job, SIGNAL(messageRetrieved(KMMessage*)), 00274 SLOT(reallyAddMsg(KMMessage*))); 00275 job->start(); 00276 aMsg->setTransferInProgress(TRUE); 00277 return FALSE; 00278 } 00279 return TRUE; 00280 } 00281 00282 00283 //----------------------------------------------------------------------------- 00284 void FolderStorage::reallyAddMsg(KMMessage* aMsg) 00285 { 00286 if (!aMsg) // the signal that is connected can call with aMsg=0 00287 return; 00288 aMsg->setTransferInProgress(FALSE); 00289 KMFolder *aFolder = aMsg->parent(); 00290 int index; 00291 ulong serNum = aMsg->getMsgSerNum(); 00292 bool undo = aMsg->enableUndo(); 00293 addMsg(aMsg, &index); 00294 if (index < 0) return; 00295 unGetMsg(index); 00296 if (undo) 00297 { 00298 kmkernel->undoStack()->pushSingleAction( serNum, aFolder, folder() ); 00299 } 00300 } 00301 00302 00303 //----------------------------------------------------------------------------- 00304 void FolderStorage::reallyAddCopyOfMsg(KMMessage* aMsg) 00305 { 00306 aMsg->setParent( 0 ); 00307 aMsg->setTransferInProgress( false ); 00308 addMsg( aMsg ); 00309 unGetMsg( count() - 1 ); 00310 } 00311 00312 int FolderStorage::find( const KMMessage * msg ) const { 00313 return find( &msg->toMsgBase() ); 00314 } 00315 00316 //----------------------------------------------------------------------------- 00317 void FolderStorage::removeMsg(const QPtrList<KMMsgBase>& msgList, bool imapQuiet) 00318 { 00319 for( QPtrListIterator<KMMsgBase> it( msgList ); *it; ++it ) 00320 { 00321 int idx = find(it.current()); 00322 assert( idx != -1); 00323 removeMsg(idx, imapQuiet); 00324 } 00325 } 00326 00327 //----------------------------------------------------------------------------- 00328 void FolderStorage::removeMsg(const QPtrList<KMMessage>& msgList, bool imapQuiet) 00329 { 00330 for( QPtrListIterator<KMMessage> it( msgList ); *it; ++it ) 00331 { 00332 int idx = find(it.current()); 00333 assert( idx != -1); 00334 removeMsg(idx, imapQuiet); 00335 } 00336 } 00337 00338 //----------------------------------------------------------------------------- 00339 void FolderStorage::removeMsg(int idx, bool) 00340 { 00341 //assert(idx>=0); 00342 if(idx < 0) 00343 { 00344 kdDebug(5006) << "FolderStorage::removeMsg() : idx < 0\n" << endl; 00345 return; 00346 } 00347 00348 KMMsgBase* mb = getMsgBase(idx); 00349 00350 Q_UINT32 serNum = kmkernel->msgDict()->getMsgSerNum( folder(), idx ); 00351 if (serNum != 0) 00352 emit msgRemoved( folder(), serNum ); 00353 mb = takeIndexEntry( idx ); 00354 00355 setDirty( true ); 00356 needsCompact=true; // message is taken from here - needs to be compacted 00357 00358 if (mb->isUnread() || mb->isNew() || 00359 (folder() == kmkernel->outboxFolder())) { 00360 --mUnreadMsgs; 00361 emit numUnreadMsgsChanged( folder() ); 00362 } 00363 --mTotalMsgs; 00364 00365 QString msgIdMD5 = mb->msgIdMD5(); 00366 QString strippedSubjMD5 = mb->strippedSubjectMD5(); 00367 if (strippedSubjMD5.isEmpty()) { 00368 mb->initStrippedSubjectMD5(); 00369 strippedSubjMD5 = mb->strippedSubjectMD5(); 00370 } 00371 emit msgRemoved(idx, msgIdMD5, strippedSubjMD5); 00372 emit msgRemoved( folder() ); 00373 } 00374 00375 00376 //----------------------------------------------------------------------------- 00377 KMMessage* FolderStorage::take(int idx) 00378 { 00379 KMMsgBase* mb; 00380 KMMessage* msg; 00381 00382 assert(idx>=0 && idx<=count()); 00383 00384 mb = getMsgBase(idx); 00385 if (!mb) return 0; 00386 if (!mb->isMessage()) readMsg(idx); 00387 Q_UINT32 serNum = kmkernel->msgDict()->getMsgSerNum( folder(), idx ); 00388 emit msgRemoved( folder(), serNum ); 00389 00390 msg = (KMMessage*)takeIndexEntry(idx); 00391 00392 if (msg->isUnread() || msg->isNew() || 00393 ( folder() == kmkernel->outboxFolder() )) { 00394 --mUnreadMsgs; 00395 emit numUnreadMsgsChanged( folder() ); 00396 } 00397 --mTotalMsgs; 00398 msg->setParent(0); 00399 setDirty( true ); 00400 needsCompact=true; // message is taken from here - needs to be compacted 00401 QString msgIdMD5 = msg->msgIdMD5(); 00402 QString strippedSubjMD5 = msg->strippedSubjectMD5(); 00403 if (strippedSubjMD5.isEmpty()) { 00404 msg->initStrippedSubjectMD5(); 00405 strippedSubjMD5 = msg->strippedSubjectMD5(); 00406 } 00407 emit msgRemoved(idx, msgIdMD5, strippedSubjMD5); 00408 emit msgRemoved( folder() ); 00409 00410 return msg; 00411 } 00412 00413 void FolderStorage::take(QPtrList<KMMessage> msgList) 00414 { 00415 for ( KMMessage* msg = msgList.first(); msg; msg = msgList.next() ) 00416 { 00417 if (msg->parent()) 00418 { 00419 int idx = msg->parent()->find(msg); 00420 assert( idx != -1); 00421 FolderStorage::take(idx); 00422 } 00423 } 00424 } 00425 00426 00427 //----------------------------------------------------------------------------- 00428 KMMessage* FolderStorage::getMsg(int idx) 00429 { 00430 KMMsgBase* mb; 00431 00432 if(!(idx >= 0 && idx <= count())) 00433 return 0; 00434 00435 mb = getMsgBase(idx); 00436 if (!mb) return 0; 00437 00438 #if 0 00439 if (mb->isMessage()) return ((KMMessage*)mb); 00440 return readMsg(idx); 00441 #else 00442 KMMessage *msg = 0; 00443 bool undo = mb->enableUndo(); 00444 if (mb->isMessage()) { 00445 msg = ((KMMessage*)mb); 00446 } else { 00447 QString mbSubject = mb->subject(); 00448 msg = readMsg(idx); 00449 // sanity check 00450 if (mCompactable && (!msg || (msg->subject().isEmpty() != mbSubject.isEmpty()))) { 00451 kdDebug(5006) << "Error: " << location() << 00452 " Index file is inconsistent with folder file. This should never happen." << endl; 00453 mCompactable = FALSE; // Don't compact 00454 writeConfig(); 00455 } 00456 } 00457 msg->setEnableUndo(undo); 00458 00459 if (msg->getMsgSerNum() == 0) { 00460 msg->setMsgSerNum(kmkernel->msgDict()->insert(0, msg, idx)); 00461 kdDebug(5006) << "Serial number generated for message in folder " 00462 << label() << endl; 00463 } 00464 msg->setComplete( true ); 00465 return msg; 00466 #endif 00467 00468 00469 } 00470 00471 00472 //----------------------------------------------------------------------------- 00473 KMMsgInfo* FolderStorage::unGetMsg(int idx) 00474 { 00475 KMMsgBase* mb; 00476 00477 if(!(idx >= 0 && idx <= count())) 00478 return 0; 00479 00480 mb = getMsgBase(idx); 00481 if (!mb) return 0; 00482 00483 00484 if (mb->isMessage()) { 00485 // Remove this message from all jobs' list it might still be on. 00486 // setIndexEntry deletes the message. 00487 KMMessage *msg = static_cast<KMMessage*>(mb); 00488 if ( msg->transferInProgress() ) return 0; 00489 ignoreJobsForMessage( msg ); 00490 return setIndexEntry( idx, msg ); 00491 } 00492 00493 return 0; 00494 } 00495 00496 00497 //----------------------------------------------------------------------------- 00498 bool FolderStorage::isMessage(int idx) 00499 { 00500 KMMsgBase* mb; 00501 if (!(idx >= 0 && idx <= count())) return FALSE; 00502 mb = getMsgBase(idx); 00503 return (mb && mb->isMessage()); 00504 } 00505 00506 //----------------------------------------------------------------------------- 00507 FolderJob* FolderStorage::createJob( KMMessage *msg, FolderJob::JobType jt, 00508 KMFolder *folder, QString partSpecifier, 00509 const AttachmentStrategy *as ) const 00510 { 00511 FolderJob * job = doCreateJob( msg, jt, folder, partSpecifier, as ); 00512 if ( job ) 00513 addJob( job ); 00514 return job; 00515 } 00516 00517 //----------------------------------------------------------------------------- 00518 FolderJob* FolderStorage::createJob( QPtrList<KMMessage>& msgList, const QString& sets, 00519 FolderJob::JobType jt, KMFolder *folder ) const 00520 { 00521 FolderJob * job = doCreateJob( msgList, sets, jt, folder ); 00522 if ( job ) 00523 addJob( job ); 00524 return job; 00525 } 00526 00527 //----------------------------------------------------------------------------- 00528 int FolderStorage::moveMsg(KMMessage* aMsg, int* aIndex_ret) 00529 { 00530 assert(aMsg != 0); 00531 KMFolder* msgParent = aMsg->parent(); 00532 00533 if (msgParent) 00534 msgParent->open(); 00535 00536 open(); 00537 int rc = addMsg(aMsg, aIndex_ret); 00538 close(); 00539 00540 if (msgParent) 00541 msgParent->close(); 00542 00543 return rc; 00544 } 00545 00546 //----------------------------------------------------------------------------- 00547 int FolderStorage::moveMsg(QPtrList<KMMessage> msglist, int* aIndex_ret) 00548 { 00549 KMMessage* aMsg = msglist.first(); 00550 assert(aMsg != 0); 00551 KMFolder* msgParent = aMsg->parent(); 00552 00553 if (msgParent) 00554 msgParent->open(); 00555 00556 open(); 00557 //FIXME : is it always imap ? 00558 int rc = static_cast<KMFolderImap*>(this)->addMsg(msglist, aIndex_ret); //yuck: Don 00559 close(); 00560 00561 if (msgParent) 00562 msgParent->close(); 00563 00564 return rc; 00565 } 00566 00567 00568 //----------------------------------------------------------------------------- 00569 int FolderStorage::rename(const QString& newName, KMFolderDir *newParent) 00570 { 00571 QString oldLoc, oldIndexLoc, oldIdsLoc, newLoc, newIndexLoc, newIdsLoc; 00572 QString oldSubDirLoc, newSubDirLoc; 00573 QString oldName; 00574 int rc=0, openCount=mOpenCount; 00575 KMFolderDir *oldParent; 00576 00577 assert(!newName.isEmpty()); 00578 00579 oldLoc = location(); 00580 oldIndexLoc = indexLocation(); 00581 oldSubDirLoc = folder()->subdirLocation(); 00582 if (kmkernel->msgDict()) 00583 oldIdsLoc = kmkernel->msgDict()->getFolderIdsLocation( folder() ); 00584 QString oldConfigString = "Folder-" + folder()->idString(); 00585 00586 close(TRUE); 00587 00588 oldName = folder()->fileName(); 00589 oldParent = folder()->parent(); 00590 if (newParent) 00591 folder()->setParent( newParent ); 00592 00593 folder()->setName(newName); 00594 newLoc = location(); 00595 newIndexLoc = indexLocation(); 00596 newSubDirLoc = folder()->subdirLocation(); 00597 if (kmkernel->msgDict()) 00598 newIdsLoc = kmkernel->msgDict()->getFolderIdsLocation( folder() ); 00599 00600 if (::rename(QFile::encodeName(oldLoc), QFile::encodeName(newLoc))) { 00601 folder()->setName(oldName); 00602 folder()->setParent(oldParent); 00603 rc = errno; 00604 } 00605 else { 00606 // rename/move index file and index.sorted file 00607 if (!oldIndexLoc.isEmpty()) { 00608 ::rename(QFile::encodeName(oldIndexLoc), QFile::encodeName(newIndexLoc)); 00609 ::rename(QFile::encodeName(oldIndexLoc) + ".sorted", 00610 QFile::encodeName(newIndexLoc) + ".sorted"); 00611 } 00612 00613 // rename/move serial number file 00614 if (!oldIdsLoc.isEmpty()) 00615 ::rename(QFile::encodeName(oldIdsLoc), QFile::encodeName(newIdsLoc)); 00616 00617 // rename/move the subfolder directory 00618 KMFolderDir* child = 0; 00619 if( folder() ) 00620 child = folder()->child(); 00621 00622 if (!::rename(QFile::encodeName(oldSubDirLoc), QFile::encodeName(newSubDirLoc) )) { 00623 // now that the subfolder directory has been renamed and/or moved also 00624 // change the name that is stored in the corresponding KMFolderNode 00625 // (provide that the name actually changed) 00626 if( child && ( oldName != newName ) ) { 00627 child->setName( "." + QFile::encodeName(newName) + ".directory" ); 00628 } 00629 } 00630 00631 // if the folder is being moved then move its node and, if necessary, also 00632 // the associated subfolder directory node to the new parent 00633 if (newParent) { 00634 if (oldParent->findRef( folder() ) != -1) 00635 oldParent->take(); 00636 newParent->inSort( folder() ); 00637 if ( child ) { 00638 if ( child->parent()->findRef( child ) != -1 ) 00639 child->parent()->take(); 00640 newParent->inSort( child ); 00641 child->setParent( newParent ); 00642 } 00643 } 00644 } 00645 00646 if (openCount > 0) 00647 { 00648 open(); 00649 mOpenCount = openCount; 00650 } 00651 writeConfig(); 00652 00653 // delete the old entry as we get two entries with the same ID otherwise 00654 KMKernel::config()->deleteGroup( oldConfigString ); 00655 00656 emit nameChanged(); 00657 return rc; 00658 } 00659 00660 00661 //----------------------------------------------------------------------------- 00662 void FolderStorage::remove() 00663 { 00664 assert(!folder()->name().isEmpty()); 00665 00666 clearIndex(true, true); // delete and remove from dict 00667 close(TRUE); 00668 00669 if (kmkernel->msgDict()) kmkernel->msgDict()->removeFolderIds( folder() ); 00670 unlink(QFile::encodeName(indexLocation()) + ".sorted"); 00671 unlink(QFile::encodeName(indexLocation())); 00672 00673 int rc = removeContents(); 00674 00675 needsCompact = false; //we are dead - no need to compact us 00676 00677 // Erase settings, otherwise they might interfer when recreating the folder 00678 KConfig* config = KMKernel::config(); 00679 config->deleteGroup( "Folder-" + folder()->idString() ); 00680 00681 emit removed(folder(), (rc ? false : true)); 00682 } 00683 00684 00685 //----------------------------------------------------------------------------- 00686 int FolderStorage::expunge() 00687 { 00688 int openCount = mOpenCount; 00689 00690 assert(!folder()->name().isEmpty()); 00691 00692 clearIndex(true, true); // delete and remove from dict 00693 close(TRUE); 00694 00695 kmkernel->msgDict()->removeFolderIds( folder() ); 00696 if (mAutoCreateIndex) 00697 truncateIndex(); 00698 else unlink(QFile::encodeName(indexLocation())); 00699 00700 int rc = expungeContents(); 00701 if (rc) return rc; 00702 00703 mDirty = FALSE; 00704 needsCompact = false; //we're cleared and truncated no need to compact 00705 00706 if (openCount > 0) 00707 { 00708 open(); 00709 mOpenCount = openCount; 00710 } 00711 00712 mUnreadMsgs = 0; 00713 mTotalMsgs = 0; 00714 emit numUnreadMsgsChanged( folder() ); 00715 if (mAutoCreateIndex) 00716 writeConfig(); 00717 emit changed(); 00718 emit expunged(); 00719 00720 return 0; 00721 } 00722 00723 00724 //----------------------------------------------------------------------------- 00725 const char* FolderStorage::type() const 00726 { 00727 if (mAcctList) return "In"; 00728 return folder()->KMFolderNode::type(); 00729 } 00730 00731 00732 //----------------------------------------------------------------------------- 00733 QString FolderStorage::label() const 00734 { 00735 return folder()->label(); 00736 } 00737 00738 int FolderStorage::count(bool cache) const 00739 { 00740 if (cache && mTotalMsgs != -1) 00741 return mTotalMsgs; 00742 else 00743 return -1; 00744 } 00745 00746 //----------------------------------------------------------------------------- 00747 int FolderStorage::countUnread() 00748 { 00749 if (mGuessedUnreadMsgs > -1) 00750 return mGuessedUnreadMsgs; 00751 if (mUnreadMsgs > -1) 00752 return mUnreadMsgs; 00753 00754 readConfig(); 00755 00756 if (mUnreadMsgs > -1) 00757 return mUnreadMsgs; 00758 00759 open(); // will update unreadMsgs 00760 int unread = mUnreadMsgs; 00761 close(); 00762 return (unread > 0) ? unread : 0; 00763 } 00764 00765 //----------------------------------------------------------------------------- 00766 void FolderStorage::msgStatusChanged(const KMMsgStatus oldStatus, 00767 const KMMsgStatus newStatus, int idx) 00768 { 00769 int oldUnread = 0; 00770 int newUnread = 0; 00771 00772 if (oldStatus & KMMsgStatusUnread || oldStatus & KMMsgStatusNew || 00773 (folder() == kmkernel->outboxFolder())) 00774 oldUnread = 1; 00775 if (newStatus & KMMsgStatusUnread || newStatus & KMMsgStatusNew || 00776 (folder() == kmkernel->outboxFolder())) 00777 newUnread = 1; 00778 int deltaUnread = newUnread - oldUnread; 00779 00780 mDirtyTimer->changeInterval(mDirtyTimerInterval); 00781 if (deltaUnread != 0) { 00782 if (mUnreadMsgs < 0) mUnreadMsgs = 0; 00783 mUnreadMsgs += deltaUnread; 00784 if ( !mQuiet ) 00785 emit numUnreadMsgsChanged( folder() ); 00786 else 00787 mChanged = true; 00788 Q_UINT32 serNum = kmkernel->msgDict()->getMsgSerNum(folder(), idx); 00789 emit msgChanged( folder(), serNum, deltaUnread ); 00790 } 00791 } 00792 00793 //----------------------------------------------------------------------------- 00794 void FolderStorage::headerOfMsgChanged(const KMMsgBase* aMsg, int idx) 00795 { 00796 if (idx < 0) 00797 idx = aMsg->parent()->find( aMsg ); 00798 if (idx >= 0 && !mQuiet) 00799 emit msgHeaderChanged(folder(), idx); 00800 else 00801 mChanged = true; 00802 } 00803 00804 //----------------------------------------------------------------------------- 00805 void FolderStorage::readConfig() 00806 { 00807 //kdDebug(5006)<<"#### READING CONFIG = "<< name() <<endl; 00808 KConfig* config = KMKernel::config(); 00809 KConfigGroupSaver saver(config, "Folder-" + folder()->idString()); 00810 if (mUnreadMsgs == -1) 00811 mUnreadMsgs = config->readNumEntry("UnreadMsgs", -1); 00812 if (mTotalMsgs == -1) 00813 mTotalMsgs = config->readNumEntry("TotalMsgs", -1); 00814 mCompactable = config->readBoolEntry("Compactable", TRUE); 00815 00816 int type = config->readNumEntry( "ContentsType", 0 ); 00817 if ( type < 0 || type > KMail::ContentsTypeLast ) type = 0; 00818 setContentsType( static_cast<KMail::FolderContentsType>( type ) ); 00819 00820 if( folder() ) folder()->readConfig( config ); 00821 } 00822 00823 //----------------------------------------------------------------------------- 00824 void FolderStorage::writeConfig() 00825 { 00826 KConfig* config = KMKernel::config(); 00827 KConfigGroupSaver saver(config, "Folder-" + folder()->idString()); 00828 config->writeEntry("UnreadMsgs", mGuessedUnreadMsgs == -1 ? mUnreadMsgs : -1); 00829 config->writeEntry("TotalMsgs", mTotalMsgs); 00830 config->writeEntry("Compactable", mCompactable); 00831 config->writeEntry("ContentsType", mContentsType); 00832 00833 // Write the KMFolder parts 00834 if( folder() ) folder()->writeConfig( config ); 00835 } 00836 00837 //----------------------------------------------------------------------------- 00838 void FolderStorage::correctUnreadMsgsCount() 00839 { 00840 open(); 00841 close(); 00842 emit numUnreadMsgsChanged( folder() ); 00843 } 00844 00845 //----------------------------------------------------------------------------- 00846 void FolderStorage::fillMsgDict(KMMsgDict *dict) 00847 { 00848 fillDictFromIndex(dict); 00849 } 00850 00851 //----------------------------------------------------------------------------- 00852 int FolderStorage::writeMsgDict(KMMsgDict *dict) 00853 { 00854 int ret = 0; 00855 if (!dict) 00856 dict = kmkernel->msgDict(); 00857 if (dict) 00858 ret = dict->writeFolderIds(folder()); 00859 return ret; 00860 } 00861 00862 //----------------------------------------------------------------------------- 00863 int FolderStorage::touchMsgDict() 00864 { 00865 int ret = 0; 00866 KMMsgDict *dict = kmkernel->msgDict(); 00867 if (dict) 00868 ret = dict->touchFolderIds(folder()); 00869 return ret; 00870 } 00871 00872 //----------------------------------------------------------------------------- 00873 int FolderStorage::appendtoMsgDict(int idx) 00874 { 00875 int ret = 0; 00876 KMMsgDict *dict = kmkernel->msgDict(); 00877 if (dict) { 00878 if (count() == 1) { 00879 ret = dict->writeFolderIds(folder()); 00880 } else { 00881 ret = dict->appendtoFolderIds(folder(), idx); 00882 } 00883 } 00884 return ret; 00885 } 00886 00887 //----------------------------------------------------------------------------- 00888 void FolderStorage::setStatus(int idx, KMMsgStatus status, bool toggle) 00889 { 00890 KMMsgBase *msg = getMsgBase(idx); 00891 if ( msg ) { 00892 if (toggle) 00893 msg->toggleStatus(status, idx); 00894 else 00895 msg->setStatus(status, idx); 00896 } 00897 } 00898 00899 void FolderStorage::setRDict(KMMsgDictREntry *rentry) { 00900 if (rentry == mRDict) 00901 return; 00902 KMMsgDict::deleteRentry(mRDict); 00903 mRDict = rentry; 00904 } 00905 00906 //----------------------------------------------------------------------------- 00907 void FolderStorage::setStatus(QValueList<int>& ids, KMMsgStatus status, bool toggle) 00908 { 00909 for ( QValueList<int>::Iterator it = ids.begin(); it != ids.end(); ++it ) 00910 { 00911 FolderStorage::setStatus(*it, status, toggle); 00912 } 00913 } 00914 00915 void FolderStorage::ignoreJobsForMessage( KMMessage *msg ) 00916 { 00917 if ( !msg || msg->transferInProgress() ) 00918 return; 00919 00920 QPtrListIterator<FolderJob> it( mJobList ); 00921 while ( it.current() ) 00922 { 00923 //FIXME: the questions is : should we iterate through all 00924 //messages in jobs? I don't think so, because it would 00925 //mean canceling the jobs that work with other messages 00926 if ( it.current()->msgList().first() == msg ) 00927 { 00928 FolderJob* job = it.current(); 00929 mJobList.remove( job ); 00930 delete job; 00931 } else 00932 ++it; 00933 } 00934 } 00935 00936 //----------------------------------------------------------------------------- 00937 void FolderStorage::removeJobs() 00938 { 00939 mJobList.setAutoDelete( true ); 00940 mJobList.clear(); 00941 mJobList.setAutoDelete( false ); 00942 } 00943 00944 //----------------------------------------------------------------------------- 00945 size_t FolderStorage::crlf2lf( char* str, const size_t strLen ) 00946 { 00947 if ( !str || strLen == 0 ) return 0; 00948 00949 const char* source = str; 00950 const char* sourceEnd = source + strLen; 00951 00952 // search the first occurrence of "\r\n" 00953 for ( ; source < sourceEnd - 1; ++source ) { 00954 if ( *source == '\r' && *( source + 1 ) == '\n' ) 00955 break; 00956 } 00957 00958 if ( source == sourceEnd - 1 ) { 00959 // no "\r\n" found 00960 return strLen; 00961 } 00962 00963 // replace all occurrences of "\r\n" with "\n" (in place) 00964 char* target = const_cast<char*>( source ); // target points to '\r' 00965 ++source; // source points to '\n' 00966 for ( ; source < sourceEnd; ++source ) { 00967 if ( *source != '\r' || *( source + 1 ) != '\n' ) 00968 *target++ = *source; 00969 } 00970 *target = '\0'; // terminate result 00971 return target - str; 00972 } 00973 00974 //----------------------------------------------------------------------------- 00975 void FolderStorage::updateChildrenState() 00976 { 00977 if ( folder() && folder()->child() ) 00978 { 00979 if ( kmkernel->folderMgr()->folderCount( folder()->child() ) > 0 ) 00980 setHasChildren( HasChildren ); 00981 else 00982 setHasChildren( HasNoChildren ); 00983 } 00984 } 00985 00986 //----------------------------------------------------------------------------- 00987 void FolderStorage::setNoChildren( bool aNoChildren ) 00988 { 00989 mNoChildren = aNoChildren; 00990 if ( aNoChildren ) 00991 setHasChildren( HasNoChildren ); 00992 } 00993 00994 //----------------------------------------------------------------------------- 00995 void FolderStorage::setContentsType( KMail::FolderContentsType type ) 00996 { 00997 if ( type != mContentsType ) { 00998 mContentsType = type; 00999 kmkernel->iCalIface().folderContentsTypeChanged( folder(), type ); 01000 } 01001 } 01002 01003 #include "folderstorage.moc"
KDE Logo
This file is part of the documentation for kmail Library Version 3.3.0.
Documentation copyright © 1996-2004 the KDE developers.
Generated on Thu Oct 21 19:46:45 2004 by doxygen 1.3.7 written by Dimitri van Heesch, © 1997-2003