Logo Search packages:      
Sourcecode: kdepim version File versions

folderstorage.cpp

/*
    Virtual base class for mail storage.

    This file is part of KMail.

    Copyright (c) 2004 Bo Thorsen <bo@sonofthor.dk>

    This library is free software; you can redistribute it and/or
    modify it under the terms of the GNU Library General Public
    License as published by the Free Software Foundation; either
    version 2 of the License, or (at your option) any later version.

    This library is distributed in the hope that it will be useful,
    but WITHOUT ANY WARRANTY; without even the implied warranty of
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
    Library General Public License for more details.

    You should have received a copy of the GNU Library General Public License
    along with this library; see the file COPYING.LIB.  If not, write to
    the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
    Boston, MA 02111-1307, USA.

    In addition, as a special exception, the copyright holders give
    permission to link the code of this program with any edition of
    the Qt library by Trolltech AS, Norway (or with modified versions
    of Qt that use the same license as Qt), and distribute linked
    combinations including the two.  You must obey the GNU General
    Public License in all respects for all of the code used other than
    Qt.  If you modify this file, you may extend this exception to
    your version of the file, but you are not obligated to do so.  If
    you do not wish to do so, delete this exception statement from
    your version.
*/

#include <config.h>

#include "folderstorage.h"
#include "kmfolder.h"

#include "kmfolderimap.h" //for the nasty imap hacks, FIXME
#include "undostack.h"
#include "kmmsgdict.h"
#include "kmfoldermgr.h"
#include "kmkernel.h"
#include "kmcommands.h"
#include "listjob.h"
using KMail::ListJob;
#include "kmailicalifaceimpl.h"

#include <klocale.h>
#include <kconfig.h>
#include <kdebug.h>

#include <qfile.h>
#include <qregexp.h>

#include <mimelib/mimepp.h>
#include <errno.h>

//-----------------------------------------------------------------------------

00062 FolderStorage::FolderStorage( KMFolder* folder, const char* aName )
  : QObject( folder, aName ), mFolder( folder )
{
  mOpenCount      = 0;
  mQuiet      = 0;
  mChanged        = FALSE;
  mAutoCreateIndex= TRUE;
  folder->setType( "plain" );
  mAcctList       = 0;
  mDirty          = FALSE;
  mUnreadMsgs      = -1;
  mGuessedUnreadMsgs = -1;
  mTotalMsgs      = -1;
  needsCompact    = FALSE;
  mConvertToUtf8  = FALSE;
  mCompactable     = TRUE;
  mNoContent      = FALSE;
  mNoChildren     = FALSE;
  mRDict = 0;
  mDirtyTimer = new QTimer(this);
  connect(mDirtyTimer, SIGNAL(timeout()),
        this, SLOT(updateIndex()));
  mHasChildren = HasNoChildren;
  mContentsType = KMail::ContentsTypeMail;
}

//-----------------------------------------------------------------------------
FolderStorage::~FolderStorage()
{
  delete mAcctList;
  mJobList.setAutoDelete( true );
  QObject::disconnect( SIGNAL(destroyed(QObject*)), this, 0 );
  mJobList.clear();
  KMMsgDict::deleteRentry(mRDict);
}


//-----------------------------------------------------------------------------
00100 QString FolderStorage::dotEscape(const QString& aStr)
{
  if (aStr[0] != '.') return aStr;
  return aStr.left(aStr.find(QRegExp("[^\\.]"))) + aStr;
}

void FolderStorage::addJob( FolderJob* job ) const
{
  QObject::connect( job, SIGNAL(destroyed(QObject*)),
                    SLOT(removeJob(QObject*)) );
  mJobList.append( job );
}

void FolderStorage::removeJob( QObject* job )
{
  mJobList.remove( static_cast<FolderJob*>( job ) );
}


//-----------------------------------------------------------------------------
00120 QString FolderStorage::location() const
{
  QString sLocation(const_cast<FolderStorage*>(this)->folder()->path());

  if (!sLocation.isEmpty()) sLocation += '/';
  sLocation += dotEscape(fileName());

  return sLocation;
}

00130 QString FolderStorage::fileName() const
{
  return mFolder->name();
}



//-----------------------------------------------------------------------------
00138 void FolderStorage::setAutoCreateIndex(bool autoIndex)
{
  mAutoCreateIndex = autoIndex;
}

//-----------------------------------------------------------------------------
00144 void FolderStorage::setDirty(bool f)
{
  mDirty = f;
  if (mDirty  && mAutoCreateIndex)
    mDirtyTimer->changeInterval( mDirtyTimerInterval );
  else
    mDirtyTimer->stop();
}

//-----------------------------------------------------------------------------
00154 void FolderStorage::markNewAsUnread()
{
  KMMsgBase* msgBase;
  int i;

  for (i=0; i< count(); ++i)
  {
    if (!(msgBase = getMsgBase(i))) continue;
    if (msgBase->isNew())
    {
      msgBase->setStatus(KMMsgStatusUnread);
      msgBase->setDirty(TRUE);
    }
  }
}

00170 void FolderStorage::markUnreadAsRead()
{
  KMMsgBase* msgBase;
  SerNumList serNums;

  for (int i=count()-1; i>=0; --i)
  {
    msgBase = getMsgBase(i);
    assert(msgBase);
    if (msgBase->isNew() || msgBase->isUnread())
    {
      serNums.append( msgBase->getMsgSerNum() );
    }
  }
  if (serNums.empty())
    return;

  KMCommand *command = new KMSetStatusCommand( KMMsgStatusRead, serNums );
  command->start();
}

//-----------------------------------------------------------------------------
00192 void FolderStorage::quiet(bool beQuiet)
{
  if (beQuiet)
    mQuiet++;
  else {
    mQuiet--;
    if (mQuiet <= 0)
    {
      mQuiet = 0;
      if (mChanged)
       emit changed();
      mChanged = FALSE;
    }
  }
}

//-----------------------------------------------------------------------------

// Needed to use QSortedList in reduceSize()

/** Compare message's date. This is useful for message sorting */
int operator<( KMMsgBase & m1, KMMsgBase & m2 )
{
  return (m1.date() < m2.date());
}

/** Compare message's date. This is useful for message sorting */
int operator==( KMMsgBase & m1, KMMsgBase & m2 )
{
  return (m1.date() == m2.date());
}


//-----------------------------------------------------------------------------
00226 int FolderStorage::expungeOldMsg(int days)
{
  int i, msgnb=0;
  time_t msgTime, maxTime;
  const KMMsgBase* mb;
  QValueList<int> rmvMsgList;

  maxTime = time(0) - days * 3600 * 24;

  for (i=count()-1; i>=0; i--) {
    mb = getMsgBase(i);
    assert(mb);
    msgTime = mb->date();

    if (msgTime < maxTime) {
      //kdDebug(5006) << "deleting msg " << i << " : " << mb->subject() << " - " << mb->dateStr(); // << endl;
      removeMsg( i );
      msgnb++;
    }
  }
  return msgnb;
}

//-----------------------------------------------------------------------------
00250 void FolderStorage::emitMsgAddedSignals(int idx)
{
  Q_UINT32 serNum = kmkernel->msgDict()->getMsgSerNum( folder() , idx );
  if (!mQuiet) {
    emit msgAdded(idx);
  } else {
    mChanged=true;
  }
  emit msgAdded( folder(), serNum );
}

//-----------------------------------------------------------------------------
00262 bool FolderStorage::canAddMsgNow(KMMessage* aMsg, int* aIndex_ret)
{
  if (aIndex_ret) *aIndex_ret = -1;
  KMFolder *msgParent = aMsg->parent();
  // If the message has a parent and is in transfer, bail out. If it does not
  // have a parent we want to be able to add it even if it is in transfer.
  if (aMsg->transferInProgress() && msgParent)
      return false;
  if (!aMsg->isComplete() && msgParent && msgParent->folderType() == KMFolderTypeImap)
  {
    FolderJob *job = msgParent->createJob(aMsg);
    connect(job, SIGNAL(messageRetrieved(KMMessage*)),
            SLOT(reallyAddMsg(KMMessage*)));
    job->start();
    aMsg->setTransferInProgress(TRUE);
    return FALSE;
  }
  return TRUE;
}


//-----------------------------------------------------------------------------
00284 void FolderStorage::reallyAddMsg(KMMessage* aMsg)
{
  if (!aMsg) // the signal that is connected can call with aMsg=0
    return;
  aMsg->setTransferInProgress(FALSE);
  KMFolder *aFolder = aMsg->parent();
  int index;
  ulong serNum = aMsg->getMsgSerNum();
  bool undo = aMsg->enableUndo();
  addMsg(aMsg, &index);
  if (index < 0) return;
  unGetMsg(index);
  if (undo)
  {
    kmkernel->undoStack()->pushSingleAction( serNum, aFolder, folder() );
  }
}


//-----------------------------------------------------------------------------
00304 void FolderStorage::reallyAddCopyOfMsg(KMMessage* aMsg)
{
  aMsg->setParent( 0 );
  aMsg->setTransferInProgress( false );
  addMsg( aMsg );
  unGetMsg( count() - 1 );
}

int FolderStorage::find( const KMMessage * msg ) const {
  return find( &msg->toMsgBase() );
}

//-----------------------------------------------------------------------------
void FolderStorage::removeMsg(const QPtrList<KMMsgBase>& msgList, bool imapQuiet)
{
  for( QPtrListIterator<KMMsgBase> it( msgList ); *it; ++it )
  {
    int idx = find(it.current());
    assert( idx != -1);
    removeMsg(idx, imapQuiet);
  }
}

//-----------------------------------------------------------------------------
void FolderStorage::removeMsg(const QPtrList<KMMessage>& msgList, bool imapQuiet)
{
  for( QPtrListIterator<KMMessage> it( msgList ); *it; ++it )
  {
    int idx = find(it.current());
    assert( idx != -1);
    removeMsg(idx, imapQuiet);
  }
}

//-----------------------------------------------------------------------------
00339 void FolderStorage::removeMsg(int idx, bool)
{
  //assert(idx>=0);
  if(idx < 0)
  {
    kdDebug(5006) << "FolderStorage::removeMsg() : idx < 0\n" << endl;
    return;
  }

  KMMsgBase* mb = getMsgBase(idx);

  Q_UINT32 serNum = kmkernel->msgDict()->getMsgSerNum( folder(), idx );
  if (serNum != 0)
    emit msgRemoved( folder(), serNum );
  mb = takeIndexEntry( idx );

  setDirty( true );
  needsCompact=true; // message is taken from here - needs to be compacted

  if (mb->isUnread() || mb->isNew() ||
      (folder() == kmkernel->outboxFolder())) {
    --mUnreadMsgs;
    emit numUnreadMsgsChanged( folder() );
  }
  --mTotalMsgs;

  QString msgIdMD5 = mb->msgIdMD5();
  QString strippedSubjMD5 = mb->strippedSubjectMD5();
  if (strippedSubjMD5.isEmpty()) {
     mb->initStrippedSubjectMD5();
     strippedSubjMD5 = mb->strippedSubjectMD5();
  }
  emit msgRemoved(idx, msgIdMD5, strippedSubjMD5);
  emit msgRemoved( folder() );
}


//-----------------------------------------------------------------------------
00377 KMMessage* FolderStorage::take(int idx)
{
  KMMsgBase* mb;
  KMMessage* msg;

  assert(idx>=0 && idx<=count());

  mb = getMsgBase(idx);
  if (!mb) return 0;
  if (!mb->isMessage()) readMsg(idx);
  Q_UINT32 serNum = kmkernel->msgDict()->getMsgSerNum( folder(), idx );
  emit msgRemoved( folder(), serNum );

  msg = (KMMessage*)takeIndexEntry(idx);

  if (msg->isUnread() || msg->isNew() ||
      ( folder() == kmkernel->outboxFolder() )) {
    --mUnreadMsgs;
    emit numUnreadMsgsChanged( folder() );
  }
  --mTotalMsgs;
  msg->setParent(0);
  setDirty( true );
  needsCompact=true; // message is taken from here - needs to be compacted
  QString msgIdMD5 = msg->msgIdMD5();
  QString strippedSubjMD5 = msg->strippedSubjectMD5();
  if (strippedSubjMD5.isEmpty()) {
     msg->initStrippedSubjectMD5();
     strippedSubjMD5 = msg->strippedSubjectMD5();
  }
  emit msgRemoved(idx, msgIdMD5, strippedSubjMD5);
  emit msgRemoved( folder() );

  return msg;
}

void FolderStorage::take(QPtrList<KMMessage> msgList)
{
  for ( KMMessage* msg = msgList.first(); msg; msg = msgList.next() )
  {
    if (msg->parent())
    {
      int idx = msg->parent()->find(msg);
      assert( idx != -1);
      FolderStorage::take(idx);
    }
  }
}


//-----------------------------------------------------------------------------
00428 KMMessage* FolderStorage::getMsg(int idx)
{
  if(!(idx >= 0 && idx <= count()))
    return 0;

  KMMsgBase* mb = getMsgBase(idx);
  if (!mb) return 0;

  KMMessage *msg = 0;
  bool undo = mb->enableUndo();
  if (mb->isMessage()) {
      msg = ((KMMessage*)mb);
  } else {
      QString mbSubject = mb->subject();
      msg = readMsg(idx);
      // sanity check
      if (mCompactable && (!msg || (msg->subject().isEmpty() != mbSubject.isEmpty()))) {
        kdDebug(5006) << "Error: " << location() <<
        " Index file is inconsistent with folder file. This should never happen." << endl;
        mCompactable = FALSE; // Don't compact
        writeConfig();
      }

  }
  msg->setEnableUndo(undo);

  // Can't happen. Either isMessage and we had a sernum, or readMsg gives us one
  // (via insertion into mMsgList).
  if (msg->getMsgSerNum() == 0) {
    msg->setMsgSerNum(kmkernel->msgDict()->insert(0, msg, idx));
    kdDebug(5006) << "Serial number generated for message in folder "
                  << label() << endl;
  }
  msg->setComplete( true );
  return msg;
}

//-----------------------------------------------------------------------------
00466 KMMessage* FolderStorage::readTemporaryMsg(int idx)
{
  if(!(idx >= 0 && idx <= count()))
    return 0;

  KMMsgBase* mb = getMsgBase(idx);
  if (!mb) return 0;

  unsigned long sernum = mb->getMsgSerNum();

  KMMessage *msg = 0;
  bool undo = mb->enableUndo();
  if (mb->isMessage()) {
    // the caller will delete it, so we must make a copy it
    msg = new KMMessage(*(KMMessage*)mb);
    msg->setMsgSerNum(sernum);
  } else {
    // ## Those three lines need to be moved to a virtual method for KMFolderSearch, like readMsg
    msg = new KMMessage(*(KMMsgInfo*)mb);
    msg->setMsgSerNum(sernum); // before fromDwString so that readyToShow uses the right sernum
    msg->fromDwString(getDwString(idx));
  }
  msg->setEnableUndo(undo);
  msg->setComplete( true );
  return msg;
}


//-----------------------------------------------------------------------------
00495 KMMsgInfo* FolderStorage::unGetMsg(int idx)
{
  KMMsgBase* mb;

  if(!(idx >= 0 && idx <= count()))
    return 0;

  mb = getMsgBase(idx);
  if (!mb) return 0;


  if (mb->isMessage()) {
    // Remove this message from all jobs' list it might still be on.
    // setIndexEntry deletes the message.
    KMMessage *msg = static_cast<KMMessage*>(mb);
    if ( msg->transferInProgress() ) return 0;
    ignoreJobsForMessage( msg );
    return setIndexEntry( idx, msg );
  }

  return 0;
}


//-----------------------------------------------------------------------------
00520 bool FolderStorage::isMessage(int idx)
{
  KMMsgBase* mb;
  if (!(idx >= 0 && idx <= count())) return FALSE;
  mb = getMsgBase(idx);
  return (mb && mb->isMessage());
}

//-----------------------------------------------------------------------------
FolderJob* FolderStorage::createJob( KMMessage *msg, FolderJob::JobType jt,
                                KMFolder *folder, QString partSpecifier,
                                const AttachmentStrategy *as ) const
{
  FolderJob * job = doCreateJob( msg, jt, folder, partSpecifier, as );
  if ( job )
    addJob( job );
  return job;
}

//-----------------------------------------------------------------------------
FolderJob* FolderStorage::createJob( QPtrList<KMMessage>& msgList, const QString& sets,
                                FolderJob::JobType jt, KMFolder *folder ) const
{
  FolderJob * job = doCreateJob( msgList, sets, jt, folder );
  if ( job )
    addJob( job );
  return job;
}

//-----------------------------------------------------------------------------
00550 int FolderStorage::moveMsg(KMMessage* aMsg, int* aIndex_ret)
{
  assert(aMsg != 0);
  KMFolder* msgParent = aMsg->parent();

  if (msgParent)
    msgParent->open();

  open();
  int rc = addMsg(aMsg, aIndex_ret);
  close();

  if (msgParent)
    msgParent->close();

  return rc;
}

//-----------------------------------------------------------------------------
int FolderStorage::moveMsg(QPtrList<KMMessage> msglist, int* aIndex_ret)
{
  KMMessage* aMsg = msglist.first();
  assert(aMsg != 0);
  KMFolder* msgParent = aMsg->parent();

  if (msgParent)
    msgParent->open();

  open();
  //FIXME : is it always imap ?
  int rc = static_cast<KMFolderImap*>(this)->addMsg(msglist, aIndex_ret); //yuck: Don
  close();

  if (msgParent)
    msgParent->close();

  return rc;
}


//-----------------------------------------------------------------------------
00591 int FolderStorage::rename(const QString& newName, KMFolderDir *newParent)
{
  QString oldLoc, oldIndexLoc, oldIdsLoc, newLoc, newIndexLoc, newIdsLoc;
  QString oldSubDirLoc, newSubDirLoc;
  QString oldName;
  int rc=0, openCount=mOpenCount;
  KMFolderDir *oldParent;

  assert(!newName.isEmpty());

  oldLoc = location();
  oldIndexLoc = indexLocation();
  oldSubDirLoc = folder()->subdirLocation();
  if (kmkernel->msgDict())
    oldIdsLoc = kmkernel->msgDict()->getFolderIdsLocation( folder() );
  QString oldConfigString = "Folder-" + folder()->idString();

  close(TRUE);

  oldName = folder()->fileName();
  oldParent = folder()->parent();
  if (newParent)
    folder()->setParent( newParent );

  folder()->setName(newName);
  newLoc = location();
  newIndexLoc = indexLocation();
  newSubDirLoc = folder()->subdirLocation();
  if (kmkernel->msgDict())
    newIdsLoc = kmkernel->msgDict()->getFolderIdsLocation( folder() );

  if (::rename(QFile::encodeName(oldLoc), QFile::encodeName(newLoc))) {
    folder()->setName(oldName);
    folder()->setParent(oldParent);
    rc = errno;
  }
  else {
    // rename/move index file and index.sorted file
    if (!oldIndexLoc.isEmpty()) {
      ::rename(QFile::encodeName(oldIndexLoc), QFile::encodeName(newIndexLoc));
      ::rename(QFile::encodeName(oldIndexLoc) + ".sorted",
               QFile::encodeName(newIndexLoc) + ".sorted");
    }

    // rename/move serial number file
    if (!oldIdsLoc.isEmpty())
      ::rename(QFile::encodeName(oldIdsLoc), QFile::encodeName(newIdsLoc));

    // rename/move the subfolder directory
    KMFolderDir* child = 0;
    if( folder() )
      child = folder()->child();

    if (!::rename(QFile::encodeName(oldSubDirLoc), QFile::encodeName(newSubDirLoc) )) {
      // now that the subfolder directory has been renamed and/or moved also
      // change the name that is stored in the corresponding KMFolderNode
      // (provide that the name actually changed)
      if( child && ( oldName != newName ) ) {
        child->setName( "." + QFile::encodeName(newName) + ".directory" );
      }
    }

    // if the folder is being moved then move its node and, if necessary, also
    // the associated subfolder directory node to the new parent
    if (newParent) {
      if (oldParent->findRef( folder() ) != -1)
        oldParent->take();
      newParent->inSort( folder() );
      if ( child ) {
        if ( child->parent()->findRef( child ) != -1 )
          child->parent()->take();
        newParent->inSort( child );
        child->setParent( newParent );
      }
    }
  }

  if (openCount > 0)
  {
    open();
    mOpenCount = openCount;
  }
  writeConfig();

  // delete the old entry as we get two entries with the same ID otherwise
  KMKernel::config()->deleteGroup( oldConfigString );

  emit nameChanged();
  return rc;
}


//-----------------------------------------------------------------------------
00684 void FolderStorage::remove()
{
  assert(!folder()->name().isEmpty());

  clearIndex(true, true); // delete and remove from dict
  close(TRUE);

  if (kmkernel->msgDict()) kmkernel->msgDict()->removeFolderIds( folder() );
  unlink(QFile::encodeName(indexLocation()) + ".sorted");
  unlink(QFile::encodeName(indexLocation()));

  int rc = removeContents();

  needsCompact = false; //we are dead - no need to compact us

  // Erase settings, otherwise they might interfer when recreating the folder
  KConfig* config = KMKernel::config();
  config->deleteGroup( "Folder-" + folder()->idString() );

  emit removed(folder(), (rc ? false : true));
}


//-----------------------------------------------------------------------------
00708 int FolderStorage::expunge()
{
  int openCount = mOpenCount;

  assert(!folder()->name().isEmpty());

  clearIndex(true, true);   // delete and remove from dict
  close(TRUE);

  kmkernel->msgDict()->removeFolderIds( folder() );
  if (mAutoCreateIndex)
    truncateIndex();
  else unlink(QFile::encodeName(indexLocation()));

  int rc = expungeContents();
  if (rc) return rc;

  mDirty = FALSE;
  needsCompact = false; //we're cleared and truncated no need to compact

  if (openCount > 0)
  {
    open();
    mOpenCount = openCount;
  }

  mUnreadMsgs = 0;
  mTotalMsgs = 0;
  emit numUnreadMsgsChanged( folder() );
  if (mAutoCreateIndex)
    writeConfig();
  emit changed();
  emit expunged( folder() );

  return 0;
}


//-----------------------------------------------------------------------------
00747 const char* FolderStorage::type() const
{
  if (mAcctList) return "In";
  return folder()->KMFolderNode::type();
}


//-----------------------------------------------------------------------------
00755 QString FolderStorage::label() const
{
  return folder()->label();
}

00760 int FolderStorage::count(bool cache) const
{
  if (cache && mTotalMsgs != -1)
    return mTotalMsgs;
  else
    return -1;
}

//-----------------------------------------------------------------------------
00769 int FolderStorage::countUnread()
{
  if (mGuessedUnreadMsgs > -1)
    return mGuessedUnreadMsgs;
  if (mUnreadMsgs > -1)
    return mUnreadMsgs;

  readConfig();

  if (mUnreadMsgs > -1)
    return mUnreadMsgs;

  open(); // will update unreadMsgs
  int unread = mUnreadMsgs;
  close();
  return (unread > 0) ? unread : 0;
}

//-----------------------------------------------------------------------------
00788 void FolderStorage::msgStatusChanged(const KMMsgStatus oldStatus,
  const KMMsgStatus newStatus, int idx)
{
  int oldUnread = 0;
  int newUnread = 0;

  if (oldStatus & KMMsgStatusUnread || oldStatus & KMMsgStatusNew ||
      (folder() == kmkernel->outboxFolder()))
    oldUnread = 1;
  if (newStatus & KMMsgStatusUnread || newStatus & KMMsgStatusNew ||
      (folder() == kmkernel->outboxFolder()))
    newUnread = 1;
  int deltaUnread = newUnread - oldUnread;

  mDirtyTimer->changeInterval(mDirtyTimerInterval);
  if (deltaUnread != 0) {
    if (mUnreadMsgs < 0) mUnreadMsgs = 0;
    mUnreadMsgs += deltaUnread;
    if ( !mQuiet )
      emit numUnreadMsgsChanged( folder() );
    else
      mChanged = true;
    Q_UINT32 serNum = kmkernel->msgDict()->getMsgSerNum(folder(), idx);
    emit msgChanged( folder(), serNum, deltaUnread );
  }
}

//-----------------------------------------------------------------------------
00816 void FolderStorage::headerOfMsgChanged(const KMMsgBase* aMsg, int idx)
{
  if (idx < 0)
    idx = aMsg->parent()->find( aMsg );
  if (idx >= 0 && !mQuiet)
    emit msgHeaderChanged(folder(), idx);
  else
    mChanged = true;
}

//-----------------------------------------------------------------------------
00827 void FolderStorage::readConfig()
{
  //kdDebug(5006)<<"#### READING CONFIG  = "<< name() <<endl;
  KConfig* config = KMKernel::config();
  KConfigGroupSaver saver(config, "Folder-" + folder()->idString());
  if (mUnreadMsgs == -1)
    mUnreadMsgs = config->readNumEntry("UnreadMsgs", -1);
  if (mTotalMsgs == -1)
    mTotalMsgs = config->readNumEntry("TotalMsgs", -1);
  mCompactable = config->readBoolEntry("Compactable", TRUE);

  int type = config->readNumEntry( "ContentsType", 0 );
  if ( type < 0 || type > KMail::ContentsTypeLast ) type = 0;
  setContentsType( static_cast<KMail::FolderContentsType>( type ) );

  if( folder() ) folder()->readConfig( config );
}

//-----------------------------------------------------------------------------
00846 void FolderStorage::writeConfig()
{
  KConfig* config = KMKernel::config();
  KConfigGroupSaver saver(config, "Folder-" + folder()->idString());
  config->writeEntry("UnreadMsgs", mGuessedUnreadMsgs == -1 ? mUnreadMsgs : -1);
  config->writeEntry("TotalMsgs", mTotalMsgs);
  config->writeEntry("Compactable", mCompactable);
  config->writeEntry("ContentsType", mContentsType);

  // Write the KMFolder parts
  if( folder() ) folder()->writeConfig( config );
}

//-----------------------------------------------------------------------------
00860 void FolderStorage::correctUnreadMsgsCount()
{
  open();
  close();
  emit numUnreadMsgsChanged( folder() );
}

//-----------------------------------------------------------------------------
00868 void FolderStorage::fillMsgDict(KMMsgDict *dict)
{
  fillDictFromIndex(dict);
}

//-----------------------------------------------------------------------------
00874 int FolderStorage::writeMsgDict(KMMsgDict *dict)
{
  int ret = 0;
  if (!dict)
    dict = kmkernel->msgDict();
  if (dict)
    ret = dict->writeFolderIds(folder());
  return ret;
}

//-----------------------------------------------------------------------------
00885 int FolderStorage::touchMsgDict()
{
  int ret = 0;
  KMMsgDict *dict = kmkernel->msgDict();
  if (dict)
    ret = dict->touchFolderIds(folder());
  return ret;
}

//-----------------------------------------------------------------------------
00895 int FolderStorage::appendtoMsgDict(int idx)
{
  int ret = 0;
  KMMsgDict *dict = kmkernel->msgDict();
  if (dict) {
    if (count() == 1) {
      ret = dict->writeFolderIds(folder());
    } else {
      ret = dict->appendtoFolderIds(folder(), idx);
    }
  }
  return ret;
}

//-----------------------------------------------------------------------------
00910 void FolderStorage::setStatus(int idx, KMMsgStatus status, bool toggle)
{
  KMMsgBase *msg = getMsgBase(idx);
  if ( msg ) {
    if (toggle)
      msg->toggleStatus(status, idx);
    else
      msg->setStatus(status, idx);
  }
}

00921 void FolderStorage::setRDict(KMMsgDictREntry *rentry) {
  if (rentry == mRDict)
      return;
  KMMsgDict::deleteRentry(mRDict);
  mRDict = rentry;
}

//-----------------------------------------------------------------------------
00929 void FolderStorage::setStatus(QValueList<int>& ids, KMMsgStatus status, bool toggle)
{
  for ( QValueList<int>::Iterator it = ids.begin(); it != ids.end(); ++it )
  {
    FolderStorage::setStatus(*it, status, toggle);
  }
}

00937 void FolderStorage::ignoreJobsForMessage( KMMessage *msg )
{
  if ( !msg || msg->transferInProgress() )
    return;

  QPtrListIterator<FolderJob> it( mJobList );
  while ( it.current() )
  {
    //FIXME: the questions is : should we iterate through all
    //messages in jobs? I don't think so, because it would
    //mean canceling the jobs that work with other messages
    if ( it.current()->msgList().first() == msg )
    {
      FolderJob* job = it.current();
      mJobList.remove( job );
      delete job;
    } else
      ++it;
  }
}

//-----------------------------------------------------------------------------
void FolderStorage::removeJobs()
{
  mJobList.setAutoDelete( true );
  mJobList.clear();
  mJobList.setAutoDelete( false );
}

//-----------------------------------------------------------------------------
00967 size_t FolderStorage::crlf2lf( char* str, const size_t strLen )
{
  if ( !str || strLen == 0 ) return 0;

  const char* source = str;
  const char* sourceEnd = source + strLen;

  // search the first occurrence of "\r\n"
  for ( ; source < sourceEnd - 1; ++source ) {
    if ( *source == '\r' && *( source + 1 ) == '\n' )
      break;
  }

  if ( source == sourceEnd - 1 ) {
    // no "\r\n" found
    return strLen;
  }

  // replace all occurrences of "\r\n" with "\n" (in place)
  char* target = const_cast<char*>( source ); // target points to '\r'
  ++source; // source points to '\n'
  for ( ; source < sourceEnd; ++source ) {
    if ( *source != '\r' || *( source + 1 ) != '\n' )
      *target++ = *source;
  }
  *target = '\0'; // terminate result
  return target - str;
}

//-----------------------------------------------------------------------------
00997 void FolderStorage::updateChildrenState()
{
  if ( folder() && folder()->child() )
  {
    if ( kmkernel->folderMgr()->folderCount( folder()->child() ) > 0 )
      setHasChildren( HasChildren );
    else
      setHasChildren( HasNoChildren );
  }
}

//-----------------------------------------------------------------------------
01009 void FolderStorage::setNoChildren( bool aNoChildren )
{
  mNoChildren = aNoChildren;
  if ( aNoChildren )
    setHasChildren( HasNoChildren );
}

//-----------------------------------------------------------------------------
01017 void FolderStorage::setContentsType( KMail::FolderContentsType type )
{
  if ( type != mContentsType ) {
    mContentsType = type;
    kmkernel->iCalIface().folderContentsTypeChanged( folder(), type );
  }
}

#include "folderstorage.moc"

Generated by  Doxygen 1.6.0   Back to index