00001
00002
00003
00004
00005
#include <config.h>
00006
00007
#include "kmfolder.h"
00008
00009
#include "kmfolderimap.h"
00010
#include "undostack.h"
00011
#include "kmmsgdict.h"
00012
#include "identitymanager.h"
00013
#include "kmidentity.h"
00014
#include "kmfoldermgr.h"
00015
#include "kmkernel.h"
00016
#include "kmcommands.h"
00017
00018
#include <kmessagebox.h>
00019
#include <klocale.h>
00020
#include <kconfig.h>
00021
#include <kdebug.h>
00022
00023
#include <qfile.h>
00024
#include <qregexp.h>
00025
00026
#include <mimelib/mimepp.h>
00027
#include <errno.h>
00028
00029
00030
00031 KMFolder :: KMFolder(
KMFolderDir* aParent,
const QString& aName) :
00032 KMFolderNode(aParent, aName)
00033 {
00034 mOpenCount = 0;
00035 mQuiet = 0;
00036 mChanged = FALSE;
00037
mAutoCreateIndex= TRUE;
00038 mIsSystemFolder = FALSE;
00039 mType =
"plain";
00040 mAcctList = 0;
00041
mDirty = FALSE;
00042
mUnreadMsgs = -1;
00043
mGuessedUnreadMsgs = -1;
00044 mTotalMsgs = -1;
00045
needsCompact = FALSE;
00046 mChild = 0;
00047 mConvertToUtf8 = FALSE;
00048 mMailingListEnabled = FALSE;
00049
mCompactable = TRUE;
00050 mNoContent = FALSE;
00051
expireMessages = FALSE;
00052 unreadExpireAge = 28;
00053 unreadExpireUnits = expireNever;
00054 readExpireAge = 14;
00055 readExpireUnits = expireNever;
00056
mRDict = 0;
00057
mUseCustomIcons =
false;
00058 mDirtyTimer =
new QTimer(
this);
00059 connect(mDirtyTimer, SIGNAL(timeout()),
00060
this, SLOT(
updateIndex()));
00061
00062
if ( aParent ) {
00063 connect(
this, SIGNAL(
msgAdded(
KMFolder*, Q_UINT32)),
00064 parent()->manager(), SIGNAL(
msgAdded(
KMFolder*, Q_UINT32)));
00065 connect(
this, SIGNAL(
msgRemoved(
KMFolder*, Q_UINT32)),
00066 parent()->manager(), SIGNAL(
msgRemoved(
KMFolder*, Q_UINT32)));
00067 connect(
this, SIGNAL(
msgChanged(
KMFolder*, Q_UINT32,
int)),
00068 parent()->manager(), SIGNAL(
msgChanged(
KMFolder*, Q_UINT32,
int)));
00069 connect(
this, SIGNAL(
msgHeaderChanged(
KMFolder*,
int)),
00070 parent()->manager(), SIGNAL(
msgHeaderChanged(
KMFolder*,
int)));
00071 }
00072
00073
readConfig();
00074 }
00075
00076
00077
00078 KMFolder :: ~KMFolder()
00079 {
00080
delete mAcctList;
00081 mJobList.setAutoDelete(
true );
00082 QObject::disconnect( SIGNAL(destroyed(QObject*)),
this, 0 );
00083 mJobList.clear();
00084 KMMsgDict::deleteRentry(mRDict);
00085 }
00086
00087
00088
00089 QString
KMFolder::dotEscape(
const QString& aStr)
const
00090
{
00091
if (aStr[0] !=
'.')
return aStr;
00092
return aStr.left(aStr.find(QRegExp(
"[^\\.]"))) + aStr;
00093 }
00094
00095
void KMFolder::addJob( FolderJob* job )
const
00096
{
00097 QObject::connect( job, SIGNAL(destroyed(QObject*)),
00098 SLOT(removeJob(QObject*)) );
00099 mJobList.append( job );
00100 }
00101
00102
void KMFolder::removeJob( QObject* job )
00103 {
00104
mJobList.remove( static_cast<FolderJob*>( job ) );
00105 }
00106
00107
00108
00109 QString
KMFolder::location()
const
00110
{
00111 QString sLocation(path());
00112
00113
if (!sLocation.isEmpty()) sLocation +=
'/';
00114 sLocation +=
dotEscape(
fileName());
00115
00116
return sLocation;
00117 }
00118
00119
00120
00121
00122 QString
KMFolder::subdirLocation()
const
00123
{
00124 QString sLocation(path());
00125
00126
if (!sLocation.isEmpty()) sLocation +=
'/';
00127 sLocation +=
'.';
00128 sLocation +=
dotEscape(
fileName());
00129 sLocation +=
".directory";
00130
00131
return sLocation;
00132 }
00133
00134
00135 KMFolderDir*
KMFolder::createChildFolder()
00136 {
00137 QString childName =
"." +
fileName() +
".directory";
00138 QString childDir = path() +
"/" + childName;
00139
bool ok =
true;
00140
00141
if (mChild)
00142
return mChild;
00143
00144
if (access(QFile::encodeName(childDir), W_OK) != 0)
00145 {
00146
if (mkdir(QFile::encodeName(childDir), S_IRWXU) != 0
00147 && chmod(QFile::encodeName(childDir), S_IRWXU) != 0)
00148 ok=
false;
00149 }
00150
00151
if (!ok) {
00152 QString wmsg = QString(
" '%1': %2").arg(childDir).arg(strerror(errno));
00153 KMessageBox::information(0,i18n(
"Failed to create folder") + wmsg);
00154
return 0;
00155 }
00156
00157
KMFolderDir* folderDir =
new KMFolderDir(parent(), childName,
00158 (
folderType() == KMFolderTypeImap) ? KMImapDir : KMStandardDir);
00159
if (!folderDir)
00160
return 0;
00161 folderDir->
reload();
00162 parent()->append(folderDir);
00163 mChild = folderDir;
00164
return folderDir;
00165 }
00166
00167
00168 void KMFolder::setAutoCreateIndex(
bool autoIndex)
00169 {
00170
mAutoCreateIndex = autoIndex;
00171 }
00172
00173
00174 void KMFolder::setDirty(
bool f)
00175 {
00176
mDirty = f;
00177
if (
mDirty &&
mAutoCreateIndex)
00178 mDirtyTimer->changeInterval( mDirtyTimerInterval );
00179
else
00180 mDirtyTimer->stop();
00181 }
00182
00183
00184
void KMFolder::setIdentity( uint identity ) {
00185 mIdentity = identity;
00186 kmkernel->slotRequestConfigSync();
00187 }
00188
00189
00190 void KMFolder::markNewAsUnread()
00191 {
00192 KMMsgBase* msgBase;
00193
int i;
00194
00195
for (i=0; i<
count(); ++i)
00196 {
00197
if (!(msgBase =
getMsgBase(i)))
continue;
00198
if (msgBase->isNew())
00199 {
00200 msgBase->setStatus(KMMsgStatusUnread);
00201 msgBase->setDirty(TRUE);
00202 }
00203 }
00204 }
00205
00206 void KMFolder::markUnreadAsRead()
00207 {
00208 KMMsgBase* msgBase;
00209 SerNumList serNums;
00210
00211
for (
int i=
count()-1; i>=0; --i)
00212 {
00213 msgBase =
getMsgBase(i);
00214 assert(msgBase);
00215
if (msgBase->isNew() || msgBase->isUnread())
00216 {
00217 serNums.append( msgBase->getMsgSerNum() );
00218 }
00219 }
00220
if (serNums.empty())
00221
return;
00222
00223 KMCommand *command =
new KMSetStatusCommand( KMMsgStatusRead, serNums );
00224 command->start();
00225 }
00226
00227
00228 void KMFolder::quiet(
bool beQuiet)
00229 {
00230
if (beQuiet)
00231 mQuiet++;
00232
else {
00233 mQuiet--;
00234
if (mQuiet <= 0)
00235 {
00236 mQuiet = 0;
00237
if (mChanged)
00238 emit
changed();
00239 mChanged = FALSE;
00240 }
00241 }
00242 }
00243
00244
00245
00246
00247
00249
int operator<( KMMsgBase & m1, KMMsgBase & m2 )
00250 {
00251
return (m1.date() < m2.date());
00252 }
00253
00255
int operator==( KMMsgBase & m1, KMMsgBase & m2 )
00256 {
00257
return (m1.date() == m2.date());
00258 }
00259
00260
00261
00262 int KMFolder::expungeOldMsg(
int days)
00263 {
00264
int i, msgnb=0;
00265 time_t msgTime, maxTime;
00266
const KMMsgBase* mb;
00267 QValueList<int> rmvMsgList;
00268
00269 maxTime = time(0) - days * 3600 * 24;
00270
00271
for (i=
count()-1; i>=0; i--) {
00272 mb =
getMsgBase(i);
00273 assert(mb);
00274 msgTime = mb->date();
00275
00276
if (msgTime < maxTime) {
00277
00278
removeMsg( i );
00279 msgnb++;
00280 }
00281 }
00282
return msgnb;
00283 }
00284
00285
00286
00291
int
00292 KMFolder::daysToExpire(
int number, ExpireUnits units) {
00293
switch (units) {
00294
case expireDays:
00295
return number;
00296
case expireWeeks:
00297
return number * 7;
00298
case expireMonths:
00299
return number * 31;
00300
default:
00301 ;
00302 }
00303
00304
return -1;
00305
00306 }
00307
00308
00314 void KMFolder::expireOldMessages() {
00315 FolderJob *job =
createJob( 0, FolderJob::tExpireMessages );
00316 job->start();
00317 }
00318
00319
00320
00321 void KMFolder::emitMsgAddedSignals(
int idx)
00322 {
00323 Q_UINT32 serNum = kmkernel->msgDict()->getMsgSerNum(
this, idx);
00324
if (!mQuiet) {
00325 emit
msgAdded(idx);
00326 }
else {
00327 mChanged=
true;
00328 }
00329 emit
msgAdded(
this, serNum);
00330 }
00331
00332
00333 bool KMFolder::canAddMsgNow(KMMessage* aMsg,
int* aIndex_ret)
00334 {
00335
if (aIndex_ret) *aIndex_ret = -1;
00336
KMFolder *msgParent = aMsg->parent();
00337
00338
00339
if (aMsg->transferInProgress() && msgParent)
00340
return false;
00341
if (!aMsg->isComplete() && msgParent && msgParent->
folderType() == KMFolderTypeImap)
00342 {
00343 FolderJob *job = msgParent->
createJob(aMsg);
00344 connect(job, SIGNAL(messageRetrieved(KMMessage*)),
00345 SLOT(
reallyAddMsg(KMMessage*)));
00346 job->start();
00347 aMsg->setTransferInProgress(TRUE);
00348
return FALSE;
00349 }
00350
return TRUE;
00351 }
00352
00353
00354
00355 void KMFolder::reallyAddMsg(KMMessage* aMsg)
00356 {
00357
if (!aMsg)
00358
return;
00359 aMsg->setTransferInProgress(FALSE);
00360
KMFolder *folder = aMsg->parent();
00361
int index;
00362 ulong serNum = aMsg->getMsgSerNum();
00363
bool undo = aMsg->enableUndo();
00364
addMsg(aMsg, &index);
00365
if (index < 0)
return;
00366
unGetMsg(index);
00367
if (undo)
00368 {
00369 kmkernel->undoStack()->pushSingleAction( serNum, folder,
this );
00370 }
00371 }
00372
00373
00374
00375 void KMFolder::reallyAddCopyOfMsg(KMMessage* aMsg)
00376 {
00377 aMsg->setParent( 0 );
00378 aMsg->setTransferInProgress(
false );
00379
addMsg( aMsg );
00380
unGetMsg(
count() - 1 );
00381 }
00382
00383
int KMFolder::find(
const KMMessage * msg )
const {
00384
return find( &msg->toMsgBase() );
00385 }
00386
00387
00388
void KMFolder::removeMsg(QPtrList<KMMessage> msgList,
bool imapQuiet)
00389 {
00390
for ( KMMessage* msg = msgList.first(); msg; msg = msgList.next() )
00391 {
00392
int idx =
find(msg);
00393 assert( idx != -1);
00394
removeMsg(idx, imapQuiet);
00395 }
00396 }
00397
00398
00399 void KMFolder::removeMsg(
int idx,
bool)
00400 {
00401
00402
if(idx < 0)
00403 {
00404 kdDebug(5006) <<
"KMFolder::removeMsg() : idx < 0\n" << endl;
00405
return;
00406 }
00407
00408 KMMsgBase* mb =
getMsgBase(idx);
00409
00410 Q_UINT32 serNum = kmkernel->msgDict()->getMsgSerNum(
this, idx);
00411
if (serNum != 0)
00412 emit
msgRemoved(
this, serNum);
00413 mb = takeIndexEntry( idx );
00414
00415
setDirty(
true );
00416
needsCompact=
true;
00417
00418
if (mb->isUnread() || mb->isNew() ||
00419 (
this == kmkernel->outboxFolder())) {
00420 --
mUnreadMsgs;
00421 emit
numUnreadMsgsChanged(
this );
00422 }
00423 --mTotalMsgs;
00424
00425 QString msgIdMD5 = mb->msgIdMD5();
00426 QString strippedSubjMD5 = mb->strippedSubjectMD5();
00427
if (strippedSubjMD5.isEmpty()) {
00428 mb->initStrippedSubjectMD5();
00429 strippedSubjMD5 = mb->strippedSubjectMD5();
00430 }
00431 emit msgRemoved(idx, msgIdMD5, strippedSubjMD5);
00432 emit msgRemoved(
this);
00433 }
00434
00435
00436
00437 KMMessage*
KMFolder::take(
int idx)
00438 {
00439 KMMsgBase* mb;
00440 KMMessage* msg;
00441
00442 assert(idx>=0 && idx<=
count());
00443
00444 mb =
getMsgBase(idx);
00445
if (!mb)
return 0;
00446
if (!mb->isMessage())
readMsg(idx);
00447 Q_UINT32 serNum = kmkernel->msgDict()->getMsgSerNum(
this, idx);
00448 emit
msgRemoved(
this,serNum);
00449
00450 msg = (KMMessage*)takeIndexEntry(idx);
00451
00452
if (msg->isUnread() || msg->isNew() ||
00453 (
this == kmkernel->outboxFolder())) {
00454 --
mUnreadMsgs;
00455 emit
numUnreadMsgsChanged(
this );
00456 }
00457 --mTotalMsgs;
00458 msg->setParent(0);
00459
setDirty(
true );
00460
needsCompact=
true;
00461 QString msgIdMD5 = msg->msgIdMD5();
00462 QString strippedSubjMD5 = msg->strippedSubjectMD5();
00463
if (strippedSubjMD5.isEmpty()) {
00464 msg->initStrippedSubjectMD5();
00465 strippedSubjMD5 = msg->strippedSubjectMD5();
00466 }
00467 emit msgRemoved(idx, msgIdMD5, strippedSubjMD5);
00468 emit msgRemoved(
this);
00469
00470
return msg;
00471 }
00472
00473
void KMFolder::take(QPtrList<KMMessage> msgList)
00474 {
00475
for ( KMMessage* msg = msgList.first(); msg; msg = msgList.next() )
00476 {
00477
if (msg->parent())
00478 {
00479
int idx = msg->parent()->find(msg);
00480 assert( idx != -1);
00481 KMFolder::take(idx);
00482 }
00483 }
00484 }
00485
00486
00487
00488 KMMessage*
KMFolder::getMsg(
int idx)
00489 {
00490 KMMsgBase* mb;
00491
00492
if(!(idx >= 0 && idx <=
count()))
00493
return 0;
00494
00495 mb =
getMsgBase(idx);
00496
if (!mb)
return 0;
00497
00498
#if 0
00499
if (mb->isMessage())
return ((KMMessage*)mb);
00500
return readMsg(idx);
00501
#else
00502
KMMessage *msg = 0;
00503
bool undo = mb->enableUndo();
00504
if (mb->isMessage()) {
00505 msg = ((KMMessage*)mb);
00506 }
else {
00507 QString mbSubject = mb->subject();
00508 msg =
readMsg(idx);
00509
00510
if (
mCompactable && (!msg || (msg->subject().isEmpty() != mbSubject.isEmpty()))) {
00511 kdDebug(5006) <<
"Error: " <<
location() <<
00512
" Index file is inconsistent with folder file. This should never happen." << endl;
00513
mCompactable = FALSE;
00514
writeConfig();
00515 }
00516 }
00517 msg->setEnableUndo(undo);
00518
00519
if (msg->getMsgSerNum() == 0) {
00520 msg->setMsgSerNum(kmkernel->msgDict()->insert(0, msg, idx));
00521 kdDebug(5006) <<
"Serial number generated for message in folder " <<
label() << endl;
00522 }
00523 msg->setComplete(
true );
00524
return msg;
00525
#endif
00526
00527
00528 }
00529
00530
00531
00532 KMMsgInfo*
KMFolder::unGetMsg(
int idx)
00533 {
00534 KMMsgBase* mb;
00535
00536
if(!(idx >= 0 && idx <=
count()))
00537
return 0;
00538
00539 mb =
getMsgBase(idx);
00540
if (!mb)
return 0;
00541
00542
00543
if (mb->isMessage()) {
00544
00545
00546 KMMessage *msg = static_cast<KMMessage*>(mb);
00547
if ( msg->transferInProgress() )
return 0;
00548
ignoreJobsForMessage( msg );
00549
return setIndexEntry( idx, msg );
00550 }
00551
00552
return 0;
00553 }
00554
00555
00556
00557 bool KMFolder::isMessage(
int idx)
00558 {
00559 KMMsgBase* mb;
00560
if (!(idx >= 0 && idx <=
count()))
return FALSE;
00561 mb =
getMsgBase(idx);
00562
return (mb && mb->isMessage());
00563 }
00564
00565
00566 FolderJob*
KMFolder::createJob( KMMessage *msg, FolderJob::JobType jt,
00567
KMFolder *folder, QString partSpecifier,
00568
const AttachmentStrategy *as )
const
00569
{
00570 FolderJob * job =
doCreateJob( msg, jt, folder, partSpecifier, as );
00571
if ( job )
00572 addJob( job );
00573
return job;
00574 }
00575
00576
00577 FolderJob* KMFolder::createJob( QPtrList<KMMessage>& msgList,
const QString& sets,
00578 FolderJob::JobType jt,
KMFolder *folder )
const
00579
{
00580 FolderJob * job = doCreateJob( msgList, sets, jt, folder );
00581
if ( job )
00582 addJob( job );
00583
return job;
00584 }
00585
00586
00587 int KMFolder::moveMsg(KMMessage* aMsg,
int* aIndex_ret)
00588 {
00589
KMFolder* msgParent;
00590
int rc;
00591
00592 assert(aMsg != 0);
00593 msgParent = aMsg->parent();
00594
00595
if (msgParent)
00596 msgParent->
open();
00597
00598
open();
00599 rc =
addMsg(aMsg, aIndex_ret);
00600
close();
00601
00602
if (msgParent)
00603 msgParent->
close();
00604
00605
return rc;
00606 }
00607
00608
00609
int KMFolder::moveMsg(QPtrList<KMMessage> msglist,
int* aIndex_ret)
00610 {
00611
KMFolder* msgParent;
00612
int rc;
00613
00614 KMMessage* aMsg = msglist.first();
00615 assert(aMsg != 0);
00616 msgParent = aMsg->parent();
00617
00618
if (msgParent)
00619 msgParent->
open();
00620
00621
open();
00622
00623 rc = static_cast<KMFolderImap*>(
this)->addMsg(msglist, aIndex_ret);
00624 close();
00625
00626
if (msgParent)
00627 msgParent->
close();
00628
00629
return rc;
00630 }
00631
00632
00633
00634 int KMFolder::rename(
const QString& newName,
KMFolderDir *newParent)
00635 {
00636 QString oldLoc, oldIndexLoc, oldIdsLoc, newLoc, newIndexLoc, newIdsLoc;
00637 QString oldSubDirLoc, newSubDirLoc;
00638 QString oldName;
00639
int rc=0, openCount=mOpenCount;
00640
KMFolderDir *oldParent;
00641
00642 assert(!newName.isEmpty());
00643
00644 oldLoc =
location();
00645 oldIndexLoc =
indexLocation();
00646 oldSubDirLoc =
subdirLocation();
00647
if (kmkernel->msgDict())
00648 oldIdsLoc = kmkernel->msgDict()->getFolderIdsLocation(
this);
00649
00650
close(TRUE);
00651
00652 oldName =
fileName();
00653 oldParent = parent();
00654
if (newParent)
00655 setParent( newParent );
00656
00657 setName(newName);
00658 newLoc =
location();
00659 newIndexLoc =
indexLocation();
00660 newSubDirLoc =
subdirLocation();
00661
if (kmkernel->msgDict())
00662 newIdsLoc = kmkernel->msgDict()->getFolderIdsLocation(
this);
00663
00664
if (::rename(QFile::encodeName(oldLoc), QFile::encodeName(newLoc))) {
00665 setName(oldName);
00666 setParent(oldParent);
00667 rc = errno;
00668 }
00669
else {
00670
00671
if (!oldIndexLoc.isEmpty()) {
00672 ::rename(QFile::encodeName(oldIndexLoc), QFile::encodeName(newIndexLoc));
00673 ::rename(QFile::encodeName(oldIndexLoc) +
".sorted",
00674 QFile::encodeName(newIndexLoc) +
".sorted");
00675 }
00676
00677
00678
if (!oldIdsLoc.isEmpty())
00679 ::rename(QFile::encodeName(oldIdsLoc), QFile::encodeName(newIdsLoc));
00680
00681
00682
if (!::rename(QFile::encodeName(oldSubDirLoc), QFile::encodeName(newSubDirLoc) )) {
00683
00684
00685
00686
if( mChild && ( oldName != newName ) ) {
00687 mChild->setName(
"." + QFile::encodeName(newName) +
".directory" );
00688 }
00689 }
00690
00691
00692
00693
if (newParent) {
00694
if (oldParent->findRef(
this ) != -1)
00695 oldParent->take();
00696 newParent->inSort(
this );
00697
if (mChild) {
00698
if (mChild->parent()->findRef( mChild ) != -1)
00699 mChild->parent()->take();
00700 newParent->inSort( mChild );
00701 mChild->setParent( newParent );
00702 }
00703 }
00704 }
00705
00706
if (openCount > 0)
00707 {
00708
open();
00709 mOpenCount = openCount;
00710 }
00711
00712 emit
nameChanged();
00713
return rc;
00714 }
00715
00716
00717
00718 int KMFolder::remove()
00719 {
00720 assert(!name().isEmpty());
00721
00722 mChild = 0;
00723 clearIndex(
true,
true);
00724
close(TRUE);
00725
00726
if (kmkernel->msgDict()) kmkernel->msgDict()->removeFolderIds(
this);
00727 unlink(QFile::encodeName(
indexLocation()) +
".sorted");
00728 unlink(QFile::encodeName(
indexLocation()));
00729
00730
int rc =
removeContents();
00731
if (rc)
return rc;
00732
00733
needsCompact =
false;
00734
return 0;
00735 }
00736
00737
00738
00739 int KMFolder::expunge()
00740 {
00741
int openCount = mOpenCount;
00742
00743 assert(!name().isEmpty());
00744
00745 clearIndex(
true,
true);
00746
close(TRUE);
00747
00748 kmkernel->msgDict()->removeFolderIds(
this);
00749
if (
mAutoCreateIndex)
00750 truncateIndex();
00751
else unlink(QFile::encodeName(
indexLocation()));
00752
00753
int rc =
expungeContents();
00754
if (rc)
return rc;
00755
00756
mDirty = FALSE;
00757
needsCompact =
false;
00758
00759
if (openCount > 0)
00760 {
00761
open();
00762 mOpenCount = openCount;
00763 }
00764
00765
mUnreadMsgs = 0;
00766 mTotalMsgs = 0;
00767 emit
numUnreadMsgsChanged(
this );
00768
if (
mAutoCreateIndex)
00769
writeConfig();
00770 emit
changed();
00771 emit
expunged();
00772
00773
return 0;
00774 }
00775
00776
00777
00778 const char*
KMFolder::type()
const
00779
{
00780
if (mAcctList)
return "In";
00781
return KMFolderNode::type();
00782 }
00783
00784
00785
00786 QString
KMFolder::label()
const
00787
{
00788
if (mIsSystemFolder && !
mLabel.isEmpty())
return mLabel;
00789
if (mIsSystemFolder)
return i18n(name().latin1());
00790
return name();
00791 }
00792
00793 int KMFolder::count(
bool cache)
const
00794
{
00795
if (cache && mTotalMsgs != -1)
00796
return mTotalMsgs;
00797
else
00798
return -1;
00799 }
00800
00801
00802 int KMFolder::countUnread()
00803 {
00804
if (
mGuessedUnreadMsgs > -1)
00805
return mGuessedUnreadMsgs;
00806
if (
mUnreadMsgs > -1)
00807
return mUnreadMsgs;
00808
00809
readConfig();
00810
00811
if (
mUnreadMsgs > -1)
00812
return mUnreadMsgs;
00813
00814
open();
00815
int unread =
mUnreadMsgs;
00816
close();
00817
return (unread > 0) ? unread : 0;
00818 }
00819
00820
00821 int KMFolder::countUnreadRecursive()
00822 {
00823
KMFolder *folder;
00824
int count =
countUnread();
00825
KMFolderDir *dir =
child();
00826
if (!dir)
00827
return count;
00828
00829 QPtrListIterator<KMFolderNode> it(*dir);
00830
for ( ; it.current(); ++it )
00831
if (!it.current()->isDir()) {
00832 folder = static_cast<KMFolder*>(it.current());
00833 count += folder->
countUnreadRecursive();
00834 }
00835
00836
return count;
00837 }
00838
00839
00840 void KMFolder::msgStatusChanged(
const KMMsgStatus oldStatus,
00841
const KMMsgStatus newStatus,
int idx)
00842 {
00843
int oldUnread = 0;
00844
int newUnread = 0;
00845
00846
if (oldStatus & KMMsgStatusUnread || oldStatus & KMMsgStatusNew ||
00847 (
this == kmkernel->outboxFolder()))
00848 oldUnread = 1;
00849
if (newStatus & KMMsgStatusUnread || newStatus & KMMsgStatusNew ||
00850 (
this == kmkernel->outboxFolder()))
00851 newUnread = 1;
00852
int deltaUnread = newUnread - oldUnread;
00853
00854 mDirtyTimer->changeInterval(mDirtyTimerInterval);
00855
if (deltaUnread != 0) {
00856
if (
mUnreadMsgs < 0)
mUnreadMsgs = 0;
00857
mUnreadMsgs += deltaUnread;
00858 emit
numUnreadMsgsChanged(
this );
00859
00860 Q_UINT32 serNum = kmkernel->msgDict()->getMsgSerNum(
this, idx);
00861 emit
msgChanged(
this, serNum, deltaUnread );
00862 }
00863 }
00864
00865
00866 void KMFolder::headerOfMsgChanged(
const KMMsgBase* aMsg,
int idx)
00867 {
00868
if (idx < 0)
00869 idx = aMsg->parent()->find( aMsg );
00870
if (idx >= 0 && !mQuiet)
00871 emit
msgHeaderChanged(
this, idx);
00872
else
00873 mChanged = TRUE;
00874 }
00875
00876
00877 QString
KMFolder::idString()
const
00878
{
00879 KMFolderNode* folderNode = parent();
00880
if (!folderNode)
00881
return "";
00882
while (folderNode->parent())
00883 folderNode = folderNode->parent();
00884
int pathLen = path().length() - folderNode->path().length();
00885 QString relativePath = path().right( pathLen );
00886
if (!relativePath.isEmpty())
00887 relativePath = relativePath.right( relativePath.length() - 1 ) +
"/";
00888 QString escapedName = QString( name() );
00889
00890
00891 escapedName.replace(
"[",
"%(" );
00892 escapedName.replace(
"]",
"%)" );
00893
return relativePath + escapedName;
00894 }
00895
00896
00897 void KMFolder::readConfig()
00898 {
00899
00900 KConfig* config = KMKernel::config();
00901 KConfigGroupSaver saver(config,
"Folder-" +
idString());
00902
if (
mUnreadMsgs == -1)
00903
mUnreadMsgs = config->readNumEntry(
"UnreadMsgs", -1);
00904
if (mTotalMsgs == -1)
00905 mTotalMsgs = config->readNumEntry(
"TotalMsgs", -1);
00906 mMailingListEnabled = config->readBoolEntry(
"MailingListEnabled");
00907 mMailingListPostingAddress = config->readEntry(
"MailingListPostingAddress");
00908 mMailingListAdminAddress = config->readEntry(
"MailingListAdminAddress");
00909 mIdentity = config->readUnsignedNumEntry(
"Identity",0);
00910
mCompactable = config->readBoolEntry(
"Compactable", TRUE);
00911
00912
expireMessages = config->readBoolEntry(
"ExpireMessages", FALSE);
00913 readExpireAge = config->readNumEntry(
"ReadExpireAge", 3);
00914 readExpireUnits = (ExpireUnits)config->readNumEntry(
"ReadExpireUnits", expireMonths);
00915 unreadExpireAge = config->readNumEntry(
"UnreadExpireAge", 12);
00916 unreadExpireUnits = (ExpireUnits)config->readNumEntry(
"UnreadExpireUnits", expireNever);
00917 setUserWhoField( config->readEntry(
"WhoField"),
false );
00918
mUseCustomIcons = config->readBoolEntry(
"UseCustomIcons",
false );
00919 mNormalIconPath = config->readEntry(
"NormalIconPath" );
00920 mUnreadIconPath = config->readEntry(
"UnreadIconPath" );
00921
if (
mUseCustomIcons )
00922 emit
iconsChanged();
00923 }
00924
00925
00926 void KMFolder::writeConfig()
00927 {
00928 KConfig* config = KMKernel::config();
00929 KConfigGroupSaver saver(config,
"Folder-" +
idString());
00930 config->writeEntry(
"UnreadMsgs",
countUnread());
00931 config->writeEntry(
"TotalMsgs", mTotalMsgs);
00932 config->writeEntry(
"MailingListEnabled", mMailingListEnabled);
00933 config->writeEntry(
"MailingListPostingAddress", mMailingListPostingAddress);
00934 config->writeEntry(
"MailingListAdminAddress", mMailingListAdminAddress);
00935 config->writeEntry(
"Identity", mIdentity);
00936 config->writeEntry(
"Compactable",
mCompactable);
00937 config->writeEntry(
"ExpireMessages",
expireMessages);
00938 config->writeEntry(
"ReadExpireAge", readExpireAge);
00939 config->writeEntry(
"ReadExpireUnits", readExpireUnits);
00940 config->writeEntry(
"UnreadExpireAge", unreadExpireAge);
00941 config->writeEntry(
"UnreadExpireUnits", unreadExpireUnits);
00942 config->writeEntry(
"WhoField",
mUserWhoField);
00943
00944 config->writeEntry(
"UseCustomIcons",
mUseCustomIcons);
00945 config->writeEntry(
"NormalIconPath", mNormalIconPath);
00946 config->writeEntry(
"UnreadIconPath", mUnreadIconPath);
00947 }
00948
00949
00950 void KMFolder::correctUnreadMsgsCount()
00951 {
00952
open();
00953
close();
00954 emit
numUnreadMsgsChanged(
this );
00955 }
00956
00957
00958 void KMFolder::fillMsgDict(KMMsgDict *dict)
00959 {
00960 fillDictFromIndex(dict);
00961 }
00962
00963
00964 int KMFolder::writeMsgDict(KMMsgDict *dict)
00965 {
00966
int ret = 0;
00967
if (!dict)
00968 dict = kmkernel->msgDict();
00969
if (dict)
00970 ret = dict->writeFolderIds(
this);
00971
return ret;
00972 }
00973
00974
00975 int KMFolder::touchMsgDict()
00976 {
00977
int ret = 0;
00978 KMMsgDict *dict = kmkernel->msgDict();
00979
if (dict)
00980 ret = dict->touchFolderIds(
this);
00981
return ret;
00982 }
00983
00984
00985 int KMFolder::appendtoMsgDict(
int idx)
00986 {
00987
int ret = 0;
00988 KMMsgDict *dict = kmkernel->msgDict();
00989
if (dict) {
00990
if (
count() == 1) {
00991 ret = dict->writeFolderIds(
this);
00992 }
else {
00993 ret = dict->appendtoFolderIds(
this, idx);
00994 }
00995 }
00996
return ret;
00997 }
00998
00999
01000 void KMFolder::setStatus(
int idx, KMMsgStatus status,
bool toggle)
01001 {
01002 KMMsgBase *msg =
getMsgBase(idx);
01003
if ( msg ) {
01004
if (toggle)
01005 msg->toggleStatus(status, idx);
01006
else
01007 msg->setStatus(status, idx);
01008 }
01009 }
01010
01011 void KMFolder::setRDict(KMMsgDictREntry *rentry) {
01012
if (rentry ==
mRDict)
01013
return;
01014 KMMsgDict::deleteRentry(
mRDict);
01015
mRDict = rentry;
01016 }
01017
01018
01019 void KMFolder::setStatus(QValueList<int>& ids, KMMsgStatus status,
bool toggle)
01020 {
01021
for ( QValueList<int>::Iterator it = ids.begin(); it != ids.end(); ++it )
01022 {
01023
KMFolder::setStatus(*it, status, toggle);
01024 }
01025 }
01026
01027
01028
void KMFolder::setUserWhoField(
const QString &whoField,
bool aWriteConfig)
01029 {
01030 mUserWhoField = whoField;
01031
if ( whoField.isEmpty() )
01032 {
01033
01034
const KMIdentity & identity =
01035 kmkernel->identityManager()->identityForUoidOrDefault( mIdentity );
01036
01037
if ( mIsSystemFolder &&
folderType() != KMFolderTypeImap )
01038 {
01039
01040
if (
this == kmkernel->inboxFolder() ||
this == kmkernel->trashFolder() ) mWhoField =
"From";
01041
if (
this == kmkernel->outboxFolder() ||
this == kmkernel->sentFolder() ||
this == kmkernel->draftsFolder() ) mWhoField =
"To";
01042
01043 }
else if ( identity.
drafts() ==
idString() || identity.
fcc() ==
idString() ) {
01044
01045
mWhoField =
"To";
01046 }
else {
01047
mWhoField =
"From";
01048 }
01049
01050 }
else if ( whoField ==
"From" || whoField ==
"To" ) {
01051
01052
01053
mWhoField = whoField;
01054
01055 }
else {
01056
01057 kdDebug(5006) <<
"Illegal setting " << whoField <<
" for userWhoField!" << endl;
01058 }
01059
01060
if (aWriteConfig)
01061
writeConfig();
01062 }
01063
01064 void KMFolder::ignoreJobsForMessage( KMMessage *msg )
01065 {
01066
if ( !msg || msg->transferInProgress() )
01067
return;
01068
01069 QPtrListIterator<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
void KMFolder::setIconPaths(
const QString &normalPath,
const QString &unreadPath)
01086 {
01087 mNormalIconPath = normalPath;
01088 mUnreadIconPath = unreadPath;
01089
writeConfig();
01090 emit
iconsChanged();
01091 }
01092
01093
01094
void KMFolder::removeJobs()
01095 {
01096
mJobList.setAutoDelete(
true );
01097
mJobList.clear();
01098
mJobList.setAutoDelete(
false );
01099 }
01100
01101
01102 size_t
KMFolder::crlf2lf(
char* str,
const size_t strLen )
01103 {
01104
if ( !str || strLen == 0 )
return 0;
01105
01106
const char* source = str;
01107
const char* sourceEnd = source + strLen;
01108
01109
01110
for ( ; source < sourceEnd - 1; ++source ) {
01111
if ( *source ==
'\r' && *( source + 1 ) ==
'\n' )
01112
break;
01113 }
01114
01115
if ( source == sourceEnd - 1 ) {
01116
01117
return strLen;
01118 }
01119
01120
01121
char* target = const_cast<char*>( source );
01122 ++source;
01123
for ( ; source < sourceEnd; ++source ) {
01124
if ( *source !=
'\r' || *( source + 1 ) !=
'\n' )
01125 *target++ = *source;
01126 }
01127 *target =
'\0';
01128
return target - str;
01129 }
01130
01131
#include "kmfolder.moc"