38 #include <tqvaluevector.h>
41 #include "kmfoldercachedimap.h"
42 #include "undostack.h"
43 #include "kmfoldermgr.h"
44 #include "kmacctcachedimap.h"
45 #include "accountmanager.h"
47 #include "kmailicalifaceimpl.h"
51 #include "broadcaststatus.h"
52 using KPIM::BroadcastStatus;
53 #include "progressmanager.h"
55 using KMail::CachedImapJob;
56 #include "imapaccountbase.h"
57 using KMail::ImapAccountBase;
61 #include "kmfolderseldlg.h"
62 #include "kmcommands.h"
63 #include "kmmainwidget.h"
65 #include <tdeapplication.h>
66 #include <tdemessagebox.h>
67 #include <tdelocale.h>
69 #include <tdeconfig.h>
70 #include <tdeio/global.h>
71 #include <tdeio/scheduler.h>
73 #include <tqbuttongroup.h>
74 #include <tqcombobox.h>
79 #include <tqradiobutton.h>
80 #include <tqvaluelist.h>
81 #include "annotationjobs.h"
82 #include "quotajobs.h"
83 using namespace KMail;
84 #include <globalsettings.h>
86 #define UIDCACHE_VERSION 1
87 #define MAIL_LOSS_DEBUGGING 0
89 static TQString incidencesForToString( KMFolderCachedImap::IncidencesFor r ) {
91 case KMFolderCachedImap::IncForNobody:
return "nobody";
92 case KMFolderCachedImap::IncForAdmins:
return "admins";
93 case KMFolderCachedImap::IncForReaders:
return "readers";
98 static KMFolderCachedImap::IncidencesFor incidencesForFromString(
const TQString& str ) {
99 if ( str ==
"nobody" )
return KMFolderCachedImap::IncForNobody;
100 if ( str ==
"admins" )
return KMFolderCachedImap::IncForAdmins;
101 if ( str ==
"readers" )
return KMFolderCachedImap::IncForReaders;
102 return KMFolderCachedImap::IncForAdmins;
105 DImapTroubleShootDialog::DImapTroubleShootDialog( TQWidget* parent,
107 : KDialogBase( Plain, i18n(
"Troubleshooting IMAP Cache" ),
108 Ok | Cancel, Cancel, parent, name, true ),
111 TQFrame* page = plainPage();
112 TQVBoxLayout *topLayout =
new TQVBoxLayout( page, 0 );
114 TQString txt = i18n(
"<p><b>Troubleshooting the IMAP cache.</b></p>"
115 "<p>If you have problems with synchronizing an IMAP "
116 "folder, you should first try rebuilding the index "
117 "file. This will take some time to rebuild, but will "
118 "not cause any problems.</p><p>If that is not enough, "
119 "you can try refreshing the IMAP cache. If you do this, "
120 "you will loose all your local changes for this folder "
121 "and all its subfolders.</p>",
122 "<p><b>Troubleshooting the IMAP cache.</b></p>"
123 "<p>If you have problems with synchronizing an IMAP "
124 "folder, you should first try rebuilding the index "
125 "file. This will take some time to rebuild, but will "
126 "not cause any problems.</p><p>If that is not enough, "
127 "you can try refreshing the IMAP cache. If you do this, "
128 "you will lose all your local changes for this folder "
129 "and all its subfolders.</p>" );
130 topLayout->addWidget(
new TQLabel( txt, page ) );
132 mButtonGroup =
new TQButtonGroup( 0 );
134 mIndexButton =
new TQRadioButton( page );
135 mIndexButton->setText( i18n(
"Rebuild &Index" ) );
136 mButtonGroup->insert( mIndexButton );
137 topLayout->addWidget( mIndexButton );
139 TQHBox *hbox =
new TQHBox( page );
140 TQLabel *scopeLabel =
new TQLabel( i18n(
"Scope:" ), hbox );
141 scopeLabel->setEnabled(
false );
142 mIndexScope =
new TQComboBox( hbox );
143 mIndexScope->insertItem( i18n(
"Only current folder" ) );
144 mIndexScope->insertItem( i18n(
"Current folder and all subfolders" ) );
145 mIndexScope->insertItem( i18n(
"All folders of this account" ) );
146 mIndexScope->setEnabled(
false );
147 topLayout->addWidget( hbox );
149 mCacheButton =
new TQRadioButton( page );
150 mCacheButton->setText( i18n(
"Refresh &Cache" ) );
151 mButtonGroup->insert( mCacheButton );
152 topLayout->addWidget( mCacheButton );
154 enableButtonSeparator(
true );
156 connect ( mIndexButton, TQ_SIGNAL(toggled(
bool)), mIndexScope, TQ_SLOT(setEnabled(
bool)) );
157 connect ( mIndexButton, TQ_SIGNAL(toggled(
bool)), scopeLabel, TQ_SLOT(setEnabled(
bool)) );
158 connect( mButtonGroup, TQ_SIGNAL( clicked(
int ) ), TQ_SLOT( slotChanged() ) );
159 connect(
this, TQ_SIGNAL( okClicked () ),
this, TQ_SLOT( slotDone() ) );
160 enableButtonOK(
false );
163 int DImapTroubleShootDialog::run()
165 DImapTroubleShootDialog d;
170 void DImapTroubleShootDialog::slotChanged()
172 enableButtonOK( mButtonGroup->selected() != 0 );
175 void DImapTroubleShootDialog::slotDone()
178 if ( mIndexButton->isOn() )
179 rc = mIndexScope->currentItem();
180 else if ( mCacheButton->isOn() )
185 KMFolderCachedImap::KMFolderCachedImap(
KMFolder* folder,
const char* aName )
186 : KMFolderMaildir( folder, aName ),
187 mSyncState( SYNC_STATE_INITIAL ), mContentState( imapNoInformation ),
188 mSubfolderState( imapNoInformation ),
189 mIncidencesFor( IncForAdmins ),
190 mSharedSeenFlags( false ),
191 mIsSelected( false ),
192 mCheckFlags( true ), mReadOnly( false ), mAccount( NULL ), uidMapDirty( true ),
193 uidWriteTimer( -1 ), mLastUid( 0 ), mTentativeHighestUid( 0 ),
194 mFoundAnIMAPDigest( false ),
195 mUserRights( 0 ), mOldUserRights( 0 ), mUserRightsState(
KMail::ACLJobs::
NotFetchedYet ),
197 mSilentUpload( false ),
199 mFolderRemoved( false ),
202 mAnnotationFolderTypeChanged( false ),
203 mIncidencesForChanged( false ),
204 mSharedSeenFlagsChanged( false ),
205 mStatusChangedLocally( false ),
206 mPersonalNamespacesCheckDone( true ),
207 mQuotaInfo(), mSomeSubFolderCloseToQuotaChanged( false ), mAlarmsBlocked( false ),
208 mRescueCommandCount( 0 ),
209 mPermanentFlags( 31 )
213 if ( readUidCache() == -1 ) {
214 if ( TQFile::exists( uidCacheLocation() ) ) {
215 KMessageBox::error( 0,
216 i18n(
"The UID cache file for folder %1 could not be read. There "
217 "could be a problem with file system permission, or it is corrupted."
221 unlink( TQFile::encodeName( uidCacheLocation() ) );
228 KMFolderCachedImap::~KMFolderCachedImap()
230 if (kmkernel->undoStack()) kmkernel->undoStack()->folderDestroyed( folder() );
234 void KMFolderCachedImap::reallyDoClose(
const char* owner )
236 if( !mFolderRemoved ) {
239 KMFolderMaildir::reallyDoClose( owner );
242 void KMFolderCachedImap::initializeFrom( KMFolderCachedImap* parent )
244 setAccount( parent->account() );
247 mAccount->removeDeletedFolder( imapPath() );
248 setUserRights( parent->userRights(), parent->userRightsState() );
251 void KMFolderCachedImap::readConfig()
253 TDEConfig* config = KMKernel::config();
254 TDEConfigGroupSaver saver( config,
"Folder-" + folder()->idString() );
255 if( mImapPath.isEmpty() ) mImapPath = config->readEntry(
"ImapPath" );
256 if( TQString( name() ).upper() ==
"INBOX" && mImapPath ==
"/INBOX/" )
258 folder()->setLabel( i18n(
"inbox" ) );
260 folder()->setSystemFolder(
true );
262 mNoContent = config->readBoolEntry(
"NoContent",
false );
263 mReadOnly = config->readBoolEntry(
"ReadOnly",
false );
264 if ( !config->readEntry(
"FolderAttributes" ).isEmpty() )
265 mFolderAttributes = config->readEntry(
"FolderAttributes" );
267 if ( mAnnotationFolderType !=
"FROMSERVER" ) {
268 mAnnotationFolderType = config->readEntry(
"Annotation-FolderType" );
270 if ( !mAnnotationFolderType.isEmpty() && !mAnnotationFolderType.startsWith(
"mail" ) )
271 kmkernel->iCalIface().setStorageFormat( folder(), KMailICalIfaceImpl::StorageXML );
275 mIncidencesFor = incidencesForFromString( config->readEntry(
"IncidencesFor" ) );
276 mAlarmsBlocked = config->readBoolEntry(
"AlarmsBlocked",
false );
279 mSharedSeenFlags = config->readBoolEntry(
"SharedSeenFlags",
false );
281 mUserRights = config->readNumEntry(
"UserRights", 0 );
284 mOldUserRights = mUserRights;
286 int storageQuotaUsage = config->readNumEntry(
"StorageQuotaUsage", -1 );
287 int storageQuotaLimit = config->readNumEntry(
"StorageQuotaLimit", -1 );
288 TQString storageQuotaRoot = config->readEntry(
"StorageQuotaRoot", TQString() );
289 if ( !storageQuotaRoot.isNull() ) {
290 mQuotaInfo.setName(
"STORAGE" );
291 mQuotaInfo.setRoot( storageQuotaRoot );
293 if ( storageQuotaUsage > -1 )
294 mQuotaInfo.setCurrent( storageQuotaUsage );
295 if ( storageQuotaLimit > -1 )
296 mQuotaInfo.setMax( storageQuotaLimit );
301 mStatusChangedLocally =
302 config->readBoolEntry(
"StatusChangedLocally",
false );
303 TQStringList uidsChanged = config->readListEntry(
"UIDStatusChangedLocally" );
304 for ( TQStringList::iterator it = uidsChanged.begin(); it != uidsChanged.end(); it++ ) {
305 mUIDsOfLocallyChangedStatuses.insert( ( *it ).toUInt() );
308 mAnnotationFolderTypeChanged = config->readBoolEntry(
"AnnotationFolderTypeChanged",
false );
309 mIncidencesForChanged = config->readBoolEntry(
"IncidencesForChanged",
false );
310 mSharedSeenFlagsChanged = config->readBoolEntry(
"SharedSeenFlagsChanged",
false );
312 if ( mImapPath.isEmpty() ) {
313 mImapPathCreation = config->readEntry(
"ImapPathCreation");
316 TQStringList delUids = config->readListEntry(
"UIDSDeletedSinceLastSync" );
317 #if MAIL_LOSS_DEBUGGING
318 kdDebug( 5006 ) <<
"READING IN UIDSDeletedSinceLastSync: " << folder()->
prettyURL() << endl << uids << endl;
320 for ( TQStringList::iterator it = delUids.begin(); it != delUids.end(); it++ ) {
321 mDeletedUIDsSinceLastSync.insert( (*it).toULong(), 0);
325 void KMFolderCachedImap::writeConfig()
329 if ( mFolderRemoved )
332 TDEConfigGroup configGroup( KMKernel::config(),
"Folder-" + folder()->idString() );
333 configGroup.writeEntry(
"ImapPath", mImapPath );
334 configGroup.writeEntry(
"NoContent", mNoContent );
335 configGroup.writeEntry(
"ReadOnly", mReadOnly );
336 configGroup.writeEntry(
"FolderAttributes", mFolderAttributes );
339 configGroup.writeEntry(
"StatusChangedLocally",
false );
340 TQStringList uidsToWrite;
341 for( std::set<ulong>::iterator it = mUIDsOfLocallyChangedStatuses.begin();
342 it != mUIDsOfLocallyChangedStatuses.end(); it++ ) {
343 uidsToWrite.append( TQString::number( (*it) ) );
345 configGroup.writeEntry(
"UIDStatusChangedLocally", uidsToWrite );
346 if ( !mImapPathCreation.isEmpty() ) {
347 if ( mImapPath.isEmpty() ) {
348 configGroup.writeEntry(
"ImapPathCreation", mImapPathCreation );
350 configGroup.deleteEntry(
"ImapPathCreation" );
353 if ( !mDeletedUIDsSinceLastSync.isEmpty() ) {
354 TQValueList<ulong> uids = mDeletedUIDsSinceLastSync.keys();
355 TQStringList uidstrings;
356 for( TQValueList<ulong>::iterator it = uids.begin(); it != uids.end(); it++ ) {
357 uidstrings.append( TQString::number( (*it) ) );
359 configGroup.writeEntry(
"UIDSDeletedSinceLastSync", uidstrings );
360 #if MAIL_LOSS_DEBUGGING
361 kdDebug( 5006 ) <<
"WRITING OUT UIDSDeletedSinceLastSync in: " << folder( )->
prettyURL( ) << endl << uidstrings << endl;
364 configGroup.deleteEntry(
"UIDSDeletedSinceLastSync" );
366 writeConfigKeysWhichShouldNotGetOverwrittenByReadConfig();
370 void KMFolderCachedImap::writeConfigKeysWhichShouldNotGetOverwrittenByReadConfig()
372 TDEConfigGroup configGroup( KMKernel::config(),
"Folder-" + folder()->idString() );
373 if ( !folder()->noContent() )
375 configGroup.writeEntry(
"AnnotationFolderTypeChanged", mAnnotationFolderTypeChanged );
376 configGroup.writeEntry(
"Annotation-FolderType", mAnnotationFolderType );
377 configGroup.writeEntry(
"IncidencesForChanged", mIncidencesForChanged );
378 configGroup.writeEntry(
"IncidencesFor", incidencesForToString( mIncidencesFor ) );
379 configGroup.writeEntry(
"AlarmsBlocked", mAlarmsBlocked );
380 configGroup.writeEntry(
"SharedSeenFlags", mSharedSeenFlags );
381 configGroup.writeEntry(
"SharedSeenFlagsChanged", mSharedSeenFlagsChanged );
383 configGroup.writeEntry(
"UserRights", mUserRights );
384 configGroup.writeEntry(
"UserRightsState", mUserRightsState );
387 configGroup.deleteEntry(
"StorageQuotaUsage");
388 configGroup.deleteEntry(
"StorageQuotaRoot");
389 configGroup.deleteEntry(
"StorageQuotaLimit");
391 if ( mQuotaInfo.isValid() ) {
392 if ( mQuotaInfo.current().isValid() ) {
393 configGroup.writeEntry(
"StorageQuotaUsage", mQuotaInfo.current().toInt() );
395 if ( mQuotaInfo.max().isValid() ) {
396 configGroup.writeEntry(
"StorageQuotaLimit", mQuotaInfo.max().toInt() );
398 configGroup.writeEntry(
"StorageQuotaRoot", mQuotaInfo.root() );
403 int KMFolderCachedImap::create()
405 int rc = KMFolderMaildir::create();
412 void KMFolderCachedImap::remove()
414 mFolderRemoved =
true;
416 TQString part1 = folder()->path() +
"/." + dotEscape(name());
417 TQString uidCacheFile = part1 +
".uidcache";
420 if( TQFile::exists(uidCacheFile) )
421 unlink( TQFile::encodeName( uidCacheFile ) );
426 TQString KMFolderCachedImap::uidCacheLocation()
const
428 TQString sLocation(folder()->path());
429 if (!sLocation.isEmpty()) sLocation +=
'/';
430 return sLocation +
'.' + dotEscape(fileName()) +
".uidcache";
433 int KMFolderCachedImap::readUidCache()
435 TQFile uidcache( uidCacheLocation() );
436 if( uidcache.open( IO_ReadOnly ) ) {
438 int len = uidcache.readLine( buf,
sizeof(buf) );
441 sscanf( buf,
"# KMail-UidCache V%d\n", &cacheVersion );
442 if( cacheVersion == UIDCACHE_VERSION ) {
443 len = uidcache.readLine( buf,
sizeof(buf) );
445 setUidValidity( TQString(TQString::fromLocal8Bit(buf)).stripWhiteSpace() );
446 len = uidcache.readLine( buf,
sizeof(buf) );
448 #if MAIL_LOSS_DEBUGGING
449 kdDebug(5006) <<
"Reading in last uid from cache: " << TQString::fromLocal8Bit(buf).stripWhiteSpace() <<
" in " << folder()->
prettyURL() << endl;
452 setLastUid( TQString(TQString::fromLocal8Bit(buf)).stripWhiteSpace().toULong() );
462 int KMFolderCachedImap::writeUidCache()
464 if( uidValidity().isEmpty() || uidValidity() ==
"INVALID" ) {
466 if( TQFile::exists( uidCacheLocation() ) )
467 return unlink( TQFile::encodeName( uidCacheLocation() ) );
470 #if MAIL_LOSS_DEBUGGING
471 kdDebug(5006) <<
"Writing out UID cache lastuid: " << lastUid() <<
" in: " << folder()->
prettyURL() << endl;
473 TQFile uidcache( uidCacheLocation() );
474 if( uidcache.open( IO_WriteOnly ) ) {
475 TQTextStream str( &uidcache );
476 str <<
"# KMail-UidCache V" << UIDCACHE_VERSION << endl;
477 str << uidValidity() << endl;
478 str << lastUid() << endl;
480 if ( uidcache.status() == IO_Ok ) {
483 if ( uidcache.status() == IO_Ok )
487 KMessageBox::error( 0,
488 i18n(
"The UID cache file for folder %1 could not be written. There "
489 "could be a problem with file system permission." ).arg( folder()->prettyURL() ) );
494 void KMFolderCachedImap::reloadUidMap()
499 for(
int i = 0; i < count(); ++i ) {
500 KMMsgBase *msg = getMsgBase( i );
502 ulong uid = msg->UID();
504 uidMap.insert( uid, i );
510 KMMessage* KMFolderCachedImap::take(
int idx)
513 rememberDeletion( idx );
514 return KMFolderMaildir::take(idx);
517 void KMFolderCachedImap::takeTemporarily(
int idx )
519 KMFolderMaildir::take( idx );
523 int KMFolderCachedImap::addMsgInternal(
KMMessage* msg,
bool newMail,
527 ulong uid = msg->
UID();
532 KMFolderOpener openThis(folder(),
"KMFolderCachedImap::addMsgInternal");
533 int rc = openThis.openResult();
535 kdDebug(5006) << k_funcinfo <<
"open: " << rc <<
" of folder: " << label() << endl;
542 if( newMail && ( imapPath() ==
"/INBOX/" ||
543 ( ( mUserRights != ACLJobs::Ok || userRights() & ACLJobs::Administer)
544 && (contentsType() == ContentsTypeMail || GlobalSettings::self()->filterGroupwareFolders()) ) ) )
548 if ( GlobalSettings::filterSourceFolders().isEmpty() ) {
549 if ( imapPath() ==
"/INBOX/" )
552 if ( GlobalSettings::filterSourceFolders().contains( folder()->
id() ) )
556 mAccount->processNewMsg( msg );
565 if ( !canAddMsgNow( msg, index_return ) )
return 0;
567 int rc = KMFolderMaildir::addMsgInternal(msg, index_return,
true );
571 void KMFolderCachedImap::rememberDeletion(
int idx )
573 KMMsgBase *msg = getMsgBase( idx );
575 long uid = msg->UID();
577 mDeletedUIDsSinceLastSync.insert(uid, 0);
578 kdDebug(5006) <<
"Explicit delete of UID " << uid <<
" at index: " << idx <<
" in " << folder()->
prettyURL() << endl;
582 void KMFolderCachedImap::removeMsg(
int idx,
bool imapQuiet)
584 if ( contentsType() != ContentsTypeMail ) {
585 kdDebug(5006) << k_funcinfo <<
"Deleting message with idx " << idx <<
" in folder " << label() << endl;
588 rememberDeletion( idx );
590 KMFolderMaildir::removeMsg(idx,imapQuiet);
593 bool KMFolderCachedImap::canRemoveFolder()
const {
595 if( folder() && folder()->child() && folder()->child()->count() > 0 )
600 return KMFolderMaildir::canRemoveFolder();
606 int KMFolderCachedImap::rename(
const TQString& aName,
609 if ( account() == 0 || imapPath().isEmpty() ) {
612 TQString err = i18n(
"You must synchronize with the server before renaming IMAP folders.");
613 KMessageBox::error( 0, err );
617 TQString oldName = mAccount->renamedFolder( imapPath() );
618 if ( oldName.isEmpty() ) oldName = name();
619 if ( aName == oldName )
628 if ( name() != aName )
629 mAccount->addRenamedFolder( imapPath(), folder()->label(), aName );
631 mAccount->removeRenamedFolder( imapPath() );
633 folder()->setLabel( aName );
639 KMFolder* KMFolderCachedImap::trashFolder()
const
641 TQString trashStr = account()->trash();
642 return kmkernel->dimapFolderMgr()->findIdString( trashStr );
645 void KMFolderCachedImap::setLastUid( ulong uid )
647 #if MAIL_LOSS_DEBUGGING
648 kdDebug(5006) <<
"Setting mLastUid to: " << uid <<
" in " << folder()->
prettyURL() << endl;
651 if( uidWriteTimer == -1 )
653 uidWriteTimer = startTimer( 60000 );
656 void KMFolderCachedImap::timerEvent( TQTimerEvent* )
658 killTimer( uidWriteTimer );
660 if ( writeUidCache() == -1 )
661 unlink( TQFile::encodeName( uidCacheLocation() ) );
664 ulong KMFolderCachedImap::lastUid()
669 KMMsgBase* KMFolderCachedImap::findByUID( ulong uid )
671 bool mapReloaded =
false;
677 TQMap<ulong,int>::Iterator it = uidMap.find( uid );
678 if( it != uidMap.end() ) {
679 KMMsgBase *msg = getMsgBase( *it );
680 #if MAIL_LOSS_DEBUGGING
681 kdDebug(5006) <<
"Folder: " << folder()->
prettyURL() << endl;
682 kdDebug(5006) <<
"UID " << uid <<
" is supposed to be in the map" << endl;
683 kdDebug(5006) <<
"UID's index is to be " << *it << endl;
684 kdDebug(5006) <<
"There is a message there? " << (msg != 0) << endl;
686 kdDebug(5006) <<
"Its UID is: " << msg->UID() << endl;
690 if( msg && msg->UID() == uid )
692 kdDebug(5006) <<
"########## Didn't find uid: " << uid <<
"in cache athough it's supposed to be there!" << endl;
694 #if MAIL_LOSS_DEBUGGING
695 kdDebug(5006) <<
"Didn't find uid: " << uid <<
"in cache!" << endl;
704 it = uidMap.find( uid );
705 if( it != uidMap.end() )
707 return getMsgBase( *it );
708 #if MAIL_LOSS_DEBUGGING
710 kdDebug(5006) <<
"Reloaded, but stil didn't find uid: " << uid << endl;
718 KMAcctCachedImap *KMFolderCachedImap::account()
const
720 if( (KMAcctCachedImap *)mAccount == 0 && kmkernel && kmkernel->acctMgr() ) {
722 mAccount =
static_cast<KMAcctCachedImap *
>( kmkernel->acctMgr()->findByName( name() ) );
728 void KMFolderCachedImap::slotTroubleshoot()
730 const int rc = DImapTroubleShootDialog::run();
732 if( rc == DImapTroubleShootDialog::RefreshCache ) {
735 KMessageBox::sorry( 0, i18n(
"No account setup for this folder.\n"
736 "Please try running a sync before this.") );
739 TQString str = i18n(
"Are you sure you want to refresh the IMAP cache of "
740 "the folder %1 and all its subfolders?\nThis will "
741 "remove all changes you have done locally to your "
742 "folders.").arg( label() );
743 TQString s1 = i18n(
"Refresh IMAP Cache");
744 TQString s2 = i18n(
"&Refresh");
745 if( KMessageBox::warningContinueCancel( 0, str, s1, s2 ) ==
746 KMessageBox::Continue )
747 account()->invalidateIMAPFolders(
this );
751 case DImapTroubleShootDialog::ReindexAll:
753 KMFolderCachedImap *rootStorage =
dynamic_cast<KMFolderCachedImap*
>( account()->rootFolder() );
755 rootStorage->createIndexFromContentsRecursive();
758 case DImapTroubleShootDialog::ReindexCurrent:
759 createIndexFromContents();
761 case DImapTroubleShootDialog::ReindexRecursive:
762 createIndexFromContentsRecursive();
767 KMessageBox::information( 0, i18n(
"The index of this folder has been "
770 kmkernel->getKMMainWidget()->folderSelected();
774 void KMFolderCachedImap::serverSync(
bool recurse,
bool quotaOnly )
776 if( mSyncState != SYNC_STATE_INITIAL ) {
777 if( KMessageBox::warningYesNo( 0, i18n(
"Folder %1 is not in initial sync state (state was %2). Do you want to reset it to initial sync state and sync anyway?" ).arg( imapPath() ).arg( mSyncState ), TQString(), i18n(
"Reset && Sync"), KStdGuiItem::cancel() ) == KMessageBox::Yes ) {
778 mSyncState = SYNC_STATE_INITIAL;
783 mQuotaOnly = quotaOnly;
786 ProgressItem *progressItem = mAccount->mailCheckProgressItem();
787 if ( progressItem ) {
788 progressItem->reset();
789 progressItem->setTotalItems( 100 );
796 account()->mailCheckProgressItem()->setProgress( 100 );
798 newState( mProgress, i18n(
"Synchronization skipped"));
799 mSyncState = SYNC_STATE_INITIAL;
800 emit folderComplete(
this,
true );
804 mTentativeHighestUid = 0;
806 serverSyncInternal();
809 TQString KMFolderCachedImap::state2String(
int state )
const
812 case SYNC_STATE_INITIAL:
return "SYNC_STATE_INITIAL";
813 case SYNC_STATE_GET_USERRIGHTS:
return "SYNC_STATE_GET_USERRIGHTS";
814 case SYNC_STATE_PUT_MESSAGES:
return "SYNC_STATE_PUT_MESSAGES";
815 case SYNC_STATE_UPLOAD_FLAGS:
return "SYNC_STATE_UPLOAD_FLAGS";
816 case SYNC_STATE_CREATE_SUBFOLDERS:
return "SYNC_STATE_CREATE_SUBFOLDERS";
817 case SYNC_STATE_LIST_SUBFOLDERS:
return "SYNC_STATE_LIST_SUBFOLDERS";
818 case SYNC_STATE_LIST_NAMESPACES:
return "SYNC_STATE_LIST_NAMESPACES";
819 case SYNC_STATE_LIST_SUBFOLDERS2:
return "SYNC_STATE_LIST_SUBFOLDERS2";
820 case SYNC_STATE_DELETE_SUBFOLDERS:
return "SYNC_STATE_DELETE_SUBFOLDERS";
821 case SYNC_STATE_LIST_MESSAGES:
return "SYNC_STATE_LIST_MESSAGES";
822 case SYNC_STATE_DELETE_MESSAGES:
return "SYNC_STATE_DELETE_MESSAGES";
823 case SYNC_STATE_GET_MESSAGES:
return "SYNC_STATE_GET_MESSAGES";
824 case SYNC_STATE_EXPUNGE_MESSAGES:
return "SYNC_STATE_EXPUNGE_MESSAGES";
825 case SYNC_STATE_HANDLE_INBOX:
return "SYNC_STATE_HANDLE_INBOX";
826 case SYNC_STATE_TEST_ANNOTATIONS:
return "SYNC_STATE_TEST_ANNOTATIONS";
827 case SYNC_STATE_GET_ANNOTATIONS:
return "SYNC_STATE_GET_ANNOTATIONS";
828 case SYNC_STATE_SET_ANNOTATIONS:
return "SYNC_STATE_SET_ANNOTATIONS";
829 case SYNC_STATE_GET_ACLS:
return "SYNC_STATE_GET_ACLS";
830 case SYNC_STATE_SET_ACLS:
return "SYNC_STATE_SET_ACLS";
831 case SYNC_STATE_GET_QUOTA:
return "SYNC_STATE_GET_QUOTA";
832 case SYNC_STATE_FIND_SUBFOLDERS:
return "SYNC_STATE_FIND_SUBFOLDERS";
833 case SYNC_STATE_SYNC_SUBFOLDERS:
return "SYNC_STATE_SYNC_SUBFOLDERS";
834 case SYNC_STATE_RENAME_FOLDER:
return "SYNC_STATE_RENAME_FOLDER";
835 case SYNC_STATE_CHECK_UIDVALIDITY:
return "SYNC_STATE_CHECK_UIDVALIDITY";
836 case SYNC_STATE_CLOSE:
return "SYNC_STATE_CLOSE";
837 case SYNC_STATE_GET_SUBFOLDER_QUOTA:
return "SYNC_STATE_GET_SUBFOLDER_QUOTA";
838 default:
return "Unknown state";
873 void KMFolderCachedImap::serverSyncInternal()
878 if( kmkernel->mailCheckAborted() ) {
880 emit folderComplete(
this,
false );
885 switch( mSyncState ) {
886 case SYNC_STATE_INITIAL:
889 foldersForDeletionOnServer.clear();
890 newState( mProgress, i18n(
"Synchronizing"));
894 mAccount->addLastUnreadMsgCount(
this, countUnread() );
897 ImapAccountBase::ConnectionState cs = mAccount->makeConnection();
898 if ( cs == ImapAccountBase::Error ) {
902 newState( mProgress, i18n(
"Error connecting to server %1" ).arg( mAccount->host() ) );
904 emit folderComplete(
this,
false);
906 }
else if ( cs == ImapAccountBase::Connecting ) {
907 mAccount->setAnnotationCheckPassed(
false );
909 newState( mProgress, i18n(
"Connecting to %1").arg( mAccount->host() ) );
911 connect( mAccount, TQ_SIGNAL( connectionResult(
int,
const TQString&) ),
912 this, TQ_SLOT( slotConnectionResult(
int,
const TQString&) ) );
917 mSyncState = SYNC_STATE_GET_USERRIGHTS;
923 case SYNC_STATE_GET_USERRIGHTS:
926 emit syncStateChanged();
929 mSyncState = SYNC_STATE_RENAME_FOLDER;
931 if( !mQuotaOnly && !noContent() && mAccount->hasACLSupport() ) {
933 mOldUserRights = mUserRights;
934 newState( mProgress, i18n(
"Checking permissions"));
935 connect( mAccount, TQ_SIGNAL( receivedUserRights(
KMFolder* ) ),
936 this, TQ_SLOT( slotReceivedUserRights(
KMFolder* ) ) );
937 mAccount->getUserRights( folder(), imapPath() );
941 else if ( !mQuotaOnly && noContent() && mAccount->hasACLSupport() ) {
946 writeConfigKeysWhichShouldNotGetOverwrittenByReadConfig();
949 case SYNC_STATE_RENAME_FOLDER:
951 mSyncState = SYNC_STATE_CHECK_UIDVALIDITY;
953 bool isResourceFolder = kmkernel->iCalIface().isStandardResourceFolder( folder() );
954 TQString newName = mAccount->renamedFolder( imapPath() );
955 if ( !newName.isEmpty() && !folder()->isSystemFolder() && !isResourceFolder ) {
956 newState( mProgress, i18n(
"Renaming folder") );
957 CachedImapJob *job =
new CachedImapJob( newName, CachedImapJob::tRenameFolder,
this );
958 connect( job, TQ_SIGNAL( result(KMail::FolderJob *) ),
this, TQ_SLOT( slotIncreaseProgress() ) );
959 connect( job, TQ_SIGNAL( finished() ),
this, TQ_SLOT( slotRenameFolderFinished() ) );
965 case SYNC_STATE_CHECK_UIDVALIDITY:
966 mSyncState = SYNC_STATE_CREATE_SUBFOLDERS;
967 if( !mQuotaOnly && !noContent() ) {
973 case SYNC_STATE_CREATE_SUBFOLDERS:
974 mSyncState = SYNC_STATE_PUT_MESSAGES;
980 case SYNC_STATE_PUT_MESSAGES:
981 mSyncState = SYNC_STATE_UPLOAD_FLAGS;
982 if( !mQuotaOnly && !noContent() ) {
987 case SYNC_STATE_UPLOAD_FLAGS:
988 mSyncState = SYNC_STATE_LIST_NAMESPACES;
989 if( !mQuotaOnly && !noContent() ) {
996 ( mUserRights & (KMail::ACLJobs::WriteFlags ) ) ) {
997 if ( !mUIDsOfLocallyChangedStatuses.empty() || mStatusChangedLocally ) {
1003 }
else if ( mUserRights & KMail::ACLJobs::WriteSeenFlag ) {
1004 if ( !mUIDsOfLocallyChangedStatuses.empty() || mStatusChangedLocally ) {
1012 case SYNC_STATE_LIST_NAMESPACES:
1013 if ( !mQuotaOnly &&
this == mAccount->rootFolder() ) {
1017 mSyncState = SYNC_STATE_LIST_SUBFOLDERS;
1020 case SYNC_STATE_LIST_SUBFOLDERS:
1021 newState( mProgress, i18n(
"Retrieving folderlist"));
1022 mSyncState = SYNC_STATE_LIST_SUBFOLDERS2;
1023 if ( !mQuotaOnly ) {
1024 if( !listDirectory() ) {
1025 mSyncState = SYNC_STATE_INITIAL;
1026 KMessageBox::error(0, i18n(
"Error while retrieving the folderlist"));
1031 case SYNC_STATE_LIST_SUBFOLDERS2:
1032 mSyncState = SYNC_STATE_DELETE_SUBFOLDERS;
1034 if ( !mQuotaOnly ) {
1035 newState( mProgress, i18n(
"Retrieving subfolders"));
1040 case SYNC_STATE_DELETE_SUBFOLDERS:
1041 mSyncState = SYNC_STATE_LIST_MESSAGES;
1042 if( !mQuotaOnly && !foldersForDeletionOnServer.isEmpty() ) {
1043 newState( mProgress, i18n(
"Deleting folders from server"));
1044 CachedImapJob* job =
new CachedImapJob( foldersForDeletionOnServer,
1045 CachedImapJob::tDeleteFolders,
this );
1046 connect( job, TQ_SIGNAL( result(KMail::FolderJob *) ),
this, TQ_SLOT( slotIncreaseProgress() ) );
1047 connect( job, TQ_SIGNAL( finished() ),
this, TQ_SLOT( slotFolderDeletionOnServerFinished() ) );
1055 case SYNC_STATE_LIST_MESSAGES:
1056 mSyncState = SYNC_STATE_DELETE_MESSAGES;
1057 if( !mQuotaOnly && !noContent() ) {
1058 newState( mProgress, i18n(
"Retrieving message list"));
1064 case SYNC_STATE_DELETE_MESSAGES:
1065 mSyncState = SYNC_STATE_EXPUNGE_MESSAGES;
1066 if( !mQuotaOnly && !noContent() ) {
1067 if( deleteMessages() ) {
1071 newState( mProgress, i18n(
"No messages to delete..."));
1072 mSyncState = SYNC_STATE_GET_MESSAGES;
1073 serverSyncInternal();
1079 case SYNC_STATE_EXPUNGE_MESSAGES:
1080 mSyncState = SYNC_STATE_GET_MESSAGES;
1081 if( !mQuotaOnly && !noContent() ) {
1082 newState( mProgress, i18n(
"Expunging deleted messages"));
1083 CachedImapJob *job =
new CachedImapJob( TQString(),
1084 CachedImapJob::tExpungeFolder,
this );
1085 connect( job, TQ_SIGNAL( result(KMail::FolderJob *) ),
this, TQ_SLOT( slotIncreaseProgress() ) );
1086 connect( job, TQ_SIGNAL( finished() ),
this, TQ_SLOT( serverSyncInternal() ) );
1092 case SYNC_STATE_GET_MESSAGES:
1093 mSyncState = SYNC_STATE_HANDLE_INBOX;
1094 if( !mQuotaOnly && !noContent() ) {
1095 if( !mMsgsForDownload.isEmpty() ) {
1096 newState( mProgress, i18n(
"Retrieving one new message",
"Retrieving %n new messages",mMsgsForDownload.size()));
1097 CachedImapJob *job =
new CachedImapJob( mMsgsForDownload,
1098 CachedImapJob::tGetMessage,
1100 connect( job, TQ_SIGNAL( progress(
unsigned long,
unsigned long) ),
1101 this, TQ_SLOT( slotProgress(
unsigned long,
unsigned long) ) );
1102 connect( job, TQ_SIGNAL( finished() ),
this, TQ_SLOT( slotUpdateLastUid() ) );
1103 connect( job, TQ_SIGNAL( finished() ),
this, TQ_SLOT( serverSyncInternal() ) );
1105 mMsgsForDownload.clear();
1108 newState( mProgress, i18n(
"No new messages from server"));
1114 slotUpdateLastUid();
1115 if( mLastUid == 0 && uidWriteTimer == -1 ) {
1117 if ( writeUidCache() == -1 ) {
1119 emit folderComplete(
this,
false );
1128 case SYNC_STATE_HANDLE_INBOX:
1131 mSyncState = SYNC_STATE_TEST_ANNOTATIONS;
1133 #define KOLAB_FOLDERTEST "/vendor/kolab/folder-test"
1134 case SYNC_STATE_TEST_ANNOTATIONS:
1135 mSyncState = SYNC_STATE_GET_ANNOTATIONS;
1137 if( !mQuotaOnly && !mAccount->annotationCheckPassed() &&
1139 && !imapPath().isEmpty() && imapPath() !=
"/" ) {
1140 kdDebug(5006) <<
"Setting test attribute on folder: "<< folder()->
prettyURL() << endl;
1141 newState( mProgress, i18n(
"Checking annotation support"));
1143 KURL url = mAccount->getUrl();
1144 url.setPath( imapPath() );
1145 KMail::AnnotationList annotations;
1148 annotations.append( attr );
1150 kdDebug(5006) <<
"Setting test attribute to "<< url << endl;
1151 TDEIO::Job* job = AnnotationJobs::multiSetAnnotation( mAccount->slave(),
1154 jd.cancellable =
true;
1155 mAccount->insertJob(job, jd);
1156 connect(job, TQ_SIGNAL(result(TDEIO::Job *)),
1157 TQ_SLOT(slotTestAnnotationResult(TDEIO::Job *)));
1161 case SYNC_STATE_GET_ANNOTATIONS: {
1162 #define KOLAB_FOLDERTYPE "/vendor/kolab/folder-type"
1163 #define KOLAB_INCIDENCESFOR "/vendor/kolab/incidences-for"
1164 #define KOLAB_SHAREDSEEN "/vendor/cmu/cyrus-imapd/sharedseen"
1166 mSyncState = SYNC_STATE_SET_ANNOTATIONS;
1168 bool needToGetInitialAnnotations =
false;
1169 if ( !mQuotaOnly && !noContent() ) {
1171 if ( mAnnotationFolderType ==
"FROMSERVER" ) {
1172 needToGetInitialAnnotations =
true;
1173 mAnnotationFolderType = TQString();
1175 updateAnnotationFolderType();
1181 if ( !mQuotaOnly && !noContent() && mAccount->hasAnnotationSupport() &&
1182 ( kmkernel->iCalIface().isEnabled() || needToGetInitialAnnotations ) ) {
1183 TQStringList annotations;
1184 if ( !mAnnotationFolderTypeChanged || mAnnotationFolderType.isEmpty() )
1185 annotations << KOLAB_FOLDERTYPE;
1186 if ( !mIncidencesForChanged )
1187 annotations << KOLAB_INCIDENCESFOR;
1188 if ( !mSharedSeenFlagsChanged )
1189 annotations << KOLAB_SHAREDSEEN;
1190 if ( !annotations.isEmpty() ) {
1191 newState( mProgress, i18n(
"Retrieving annotations"));
1192 KURL url = mAccount->getUrl();
1193 url.setPath( imapPath() );
1195 AnnotationJobs::multiGetAnnotation( mAccount->slave(), url, annotations );
1197 jd.cancellable =
true;
1198 mAccount->insertJob(job, jd);
1200 connect( job, TQ_SIGNAL(annotationResult(
const TQString&,
const TQString&,
bool)),
1201 TQ_SLOT(slotAnnotationResult(
const TQString&,
const TQString&,
bool)) );
1202 connect( job, TQ_SIGNAL(result(TDEIO::Job *)),
1203 TQ_SLOT(slotGetAnnotationResult(TDEIO::Job *)) );
1208 case SYNC_STATE_SET_ANNOTATIONS:
1210 mSyncState = SYNC_STATE_SET_ACLS;
1211 if ( !mQuotaOnly && !noContent() && mAccount->hasAnnotationSupport() &&
1212 ( mUserRightsState !=
KMail::ACLJobs::Ok || ( mUserRights & ACLJobs::Administer ) ) ) {
1213 newState( mProgress, i18n(
"Setting annotations"));
1214 KURL url = mAccount->getUrl();
1215 url.setPath( imapPath() );
1216 KMail::AnnotationList annotations;
1217 if ( mAnnotationFolderTypeChanged && !mAnnotationFolderType.isEmpty() ) {
1219 annotations.append( attr );
1220 kdDebug(5006) <<
"Setting folder-type annotation for " << label() <<
" to " << mAnnotationFolderType << endl;
1222 if ( mIncidencesForChanged ) {
1223 const TQString val = incidencesForToString( mIncidencesFor );
1225 annotations.append( attr );
1226 kdDebug(5006) <<
"Setting incidences-for annotation for " << label() <<
" to " << val << endl;
1228 if ( mSharedSeenFlagsChanged ) {
1229 const TQString val = mSharedSeenFlags ?
"true" :
"false";
1231 annotations.append( attr );
1232 kdDebug(5006) << k_funcinfo <<
"Setting sharedseen annotation for " << label() <<
" to " << val << endl;
1234 if ( !annotations.isEmpty() ) {
1236 AnnotationJobs::multiSetAnnotation( mAccount->slave(), url, annotations );
1238 jd.cancellable =
true;
1239 mAccount->insertJob(job, jd);
1241 connect(job, TQ_SIGNAL(annotationChanged(
const TQString&,
const TQString&,
const TQString& ) ),
1242 TQ_SLOT( slotAnnotationChanged(
const TQString&,
const TQString&,
const TQString& ) ));
1243 connect(job, TQ_SIGNAL(result(TDEIO::Job *)),
1244 TQ_SLOT(slotSetAnnotationResult(TDEIO::Job *)));
1249 case SYNC_STATE_SET_ACLS:
1250 mSyncState = SYNC_STATE_GET_ACLS;
1252 if( !mQuotaOnly && !noContent() && mAccount->hasACLSupport() &&
1253 ( mUserRightsState !=
KMail::ACLJobs::Ok || ( mUserRights & ACLJobs::Administer ) ) ) {
1254 bool hasChangedACLs =
false;
1255 ACLList::ConstIterator it = mACLList.begin();
1256 for ( ; it != mACLList.end() && !hasChangedACLs; ++it ) {
1257 hasChangedACLs = (*it).changed;
1259 if ( hasChangedACLs ) {
1260 newState( mProgress, i18n(
"Setting permissions"));
1261 KURL url = mAccount->getUrl();
1262 url.setPath( imapPath() );
1265 mAccount->insertJob(job, jd);
1267 connect(job, TQ_SIGNAL(result(TDEIO::Job *)),
1268 TQ_SLOT(slotMultiSetACLResult(TDEIO::Job *)));
1269 connect(job, TQ_SIGNAL(aclChanged(
const TQString&,
int )),
1270 TQ_SLOT(slotACLChanged(
const TQString&,
int )) );
1275 case SYNC_STATE_GET_ACLS:
1276 mSyncState = SYNC_STATE_FIND_SUBFOLDERS;
1278 if( !mQuotaOnly && !noContent() && mAccount->hasACLSupport() ) {
1279 newState( mProgress, i18n(
"Retrieving permissions" ) );
1280 mAccount->getACL( folder(), mImapPath );
1281 connect( mAccount, TQ_SIGNAL(receivedACL(
KMFolder*, TDEIO::Job*,
const KMail::ACLList& )),
1282 this, TQ_SLOT(slotReceivedACL(
KMFolder*, TDEIO::Job*,
const KMail::ACLList& )) );
1285 case SYNC_STATE_FIND_SUBFOLDERS:
1287 mSyncState = SYNC_STATE_SYNC_SUBFOLDERS;
1288 mSomeSubFolderCloseToQuotaChanged =
false;
1289 buildSubFolderList();
1293 case SYNC_STATE_SYNC_SUBFOLDERS:
1294 syncNextSubFolder(
false );
1296 case SYNC_STATE_GET_SUBFOLDER_QUOTA:
1300 syncNextSubFolder(
true );
1302 case SYNC_STATE_GET_QUOTA:
1303 mSyncState = SYNC_STATE_CLOSE;
1304 if( !noContent() && mAccount->hasQuotaSupport() ) {
1306 newState( mProgress, i18n(
"Getting quota information"));
1307 KURL url = mAccount->getUrl();
1308 url.setPath( imapPath() );
1311 mAccount->insertJob(job, jd);
1312 connect( job, TQ_SIGNAL( storageQuotaResult(
const QuotaInfo& ) ),
1313 TQ_SLOT( slotStorageQuotaResult(
const QuotaInfo& ) ) );
1314 connect( job, TQ_SIGNAL(result(TDEIO::Job *)),
1315 TQ_SLOT(slotQuotaResult(TDEIO::Job *)) );
1318 case SYNC_STATE_CLOSE:
1321 newState( mProgress, i18n(
"Synchronization done"));
1322 KURL url = mAccount->getUrl();
1323 url.setPath( imapPath() );
1324 kmkernel->iCalIface().folderSynced( folder(), url );
1326 mSyncState = SYNC_STATE_INITIAL;
1327 mAccount->addUnreadMsgCount(
this, countUnread() );
1328 close(
"cachedimap" );
1329 emit syncStateChanged();
1330 emit folderComplete(
this,
true );
1335 kdDebug(5006) <<
"KMFolderCachedImap::serverSyncInternal() WARNING: no such state "
1336 << mSyncState << endl;
1340 void KMFolderCachedImap::syncNextSubFolder(
bool secondSync )
1342 if( mCurrentSubfolder ) {
1343 disconnectSubFolderSignals();
1346 if( mSubfoldersForSync.isEmpty() ) {
1350 if ( mSomeSubFolderCloseToQuotaChanged && mRecurse && !secondSync ) {
1351 buildSubFolderList();
1352 mSyncState = SYNC_STATE_GET_SUBFOLDER_QUOTA;
1353 serverSyncInternal();
1361 mSyncState = SYNC_STATE_GET_QUOTA;
1362 serverSyncInternal();
1365 mCurrentSubfolder = mSubfoldersForSync.front();
1366 mSubfoldersForSync.pop_front();
1367 if ( mCurrentSubfolder ) {
1368 connect( mCurrentSubfolder, TQ_SIGNAL( folderComplete(KMFolderCachedImap*,
bool) ),
1369 this, TQ_SLOT( slotSubFolderComplete(KMFolderCachedImap*,
bool) ) );
1370 connect( mCurrentSubfolder, TQ_SIGNAL( closeToQuotaChanged() ),
1371 this, TQ_SLOT( slotSubFolderCloseToQuotaChanged() ) );
1374 assert( !mCurrentSubfolder->imapPath().isEmpty() );
1375 mCurrentSubfolder->setAccount( account() );
1376 const bool recurse = mCurrentSubfolder->noChildren() ? false :
true;
1377 const bool quotaOnly = secondSync || mQuotaOnly;
1378 mCurrentSubfolder->serverSync( recurse, quotaOnly );
1383 syncNextSubFolder( secondSync );
1388 void KMFolderCachedImap::buildSubFolderList()
1390 mSubfoldersForSync.clear();
1391 mCurrentSubfolder = 0;
1392 if( folder() && folder()->child() ) {
1393 KMFolderNode *node = folder()->
child()->first();
1395 if( !node->isDir() ) {
1396 KMFolderCachedImap* storage =
static_cast<KMFolderCachedImap*
>(
static_cast<KMFolder*
>(node)->storage());
1397 const bool folderIsNew = mNewlyCreatedSubfolders.contains( TQGuardedPtr<KMFolderCachedImap>( storage ) );
1399 if ( !storage->imapPath().isEmpty()
1401 && !foldersForDeletionOnServer.contains( storage->imapPath() ) ) {
1402 if ( mRecurse || folderIsNew ) {
1403 mSubfoldersForSync << storage;
1406 kdDebug(5006) <<
"Do not add " << storage->
label()
1407 <<
" to synclist" << endl;
1410 node = folder()->
child()->next();
1414 mNewlyCreatedSubfolders.clear();
1417 void KMFolderCachedImap::disconnectSubFolderSignals()
1419 disconnect( mCurrentSubfolder, TQ_SIGNAL( folderComplete(KMFolderCachedImap*,
bool) ),
1420 this, TQ_SLOT( slotSubFolderComplete(KMFolderCachedImap*,
bool) ) );
1421 disconnect( mCurrentSubfolder, TQ_SIGNAL( closeToQuotaChanged() ),
1422 this, TQ_SLOT( slotSubFolderCloseToQuotaChanged() ) );
1423 mCurrentSubfolder = 0;
1429 void KMFolderCachedImap::slotConnectionResult(
int errorCode,
const TQString& errorMsg )
1431 disconnect( mAccount, TQ_SIGNAL( connectionResult(
int,
const TQString&) ),
1432 this, TQ_SLOT( slotConnectionResult(
int,
const TQString&) ) );
1435 mSyncState = SYNC_STATE_GET_USERRIGHTS;
1437 serverSyncInternal();
1440 newState( mProgress, TDEIO::buildErrorString( errorCode, errorMsg ));
1441 emit folderComplete(
this,
false);
1446 TQValueList<unsigned long> KMFolderCachedImap::findNewMessages()
1448 TQValueList<unsigned long> result;
1449 for(
int i = 0; i < count(); ++i ) {
1450 KMMsgBase *msg = getMsgBase( i );
1451 if( !msg )
continue;
1452 if ( msg->UID() == 0 )
1453 result.append( msg->getMsgSerNum() );
1459 void KMFolderCachedImap::uploadNewMessages()
1461 TQValueList<unsigned long> newMsgs = findNewMessages();
1462 if( !newMsgs.isEmpty() ) {
1463 if ( mUserRightsState !=
KMail::ACLJobs::Ok || ( mUserRights & ( KMail::ACLJobs::Insert ) ) ) {
1464 newState( mProgress, i18n(
"Uploading messages to server"));
1465 CachedImapJob *job =
new CachedImapJob( newMsgs, CachedImapJob::tPutMessage,
this );
1466 connect( job, TQ_SIGNAL( progress(
unsigned long,
unsigned long) ),
1467 this, TQ_SLOT( slotPutProgress(
unsigned long,
unsigned long) ) );
1468 connect( job, TQ_SIGNAL( finished() ),
this, TQ_SLOT( serverSyncInternal() ) );
1472 KMCommand *command = rescueUnsyncedMessages();
1473 connect( command, TQ_SIGNAL( completed( KMCommand * ) ),
1474 this, TQ_SLOT( serverSyncInternal() ) );
1477 if ( mUserRights != mOldUserRights && (mOldUserRights & KMail::ACLJobs::Insert)
1478 && !(mUserRights & KMail::ACLJobs::Insert) ) {
1480 KMessageBox::information( 0, i18n(
"<p>Your access rights to folder <b>%1</b> have been restricted, "
1481 "it will no longer be possible to add messages to this folder.</p>").arg( folder()->prettyURL() ),
1482 i18n(
"Acces rights revoked"),
"KMailACLRevocationNotification" );
1485 newState( mProgress, i18n(
"No messages to upload to server"));
1486 serverSyncInternal();
1490 void KMFolderCachedImap::slotPutProgress(
unsigned long done,
unsigned long total )
1493 int progressSpan = 10;
1494 newState( mProgress + (progressSpan * done) / total, TQString() );
1495 if ( done == total )
1496 mProgress += progressSpan;
1500 void KMFolderCachedImap::uploadFlags()
1502 if ( !uidMap.isEmpty() ) {
1503 mStatusFlagsJobs = 0;
1504 newState( mProgress, i18n(
"Uploading status of messages to server"));
1507 TQMap< TQString, TQStringList > groups;
1509 for(
int i = 0; i < count(); ++i ) {
1510 KMMsgBase* msg = getMsgBase( i );
1511 if( !msg || msg->UID() == 0 )
1514 if ( mUIDsOfLocallyChangedStatuses.find( msg->UID() ) == mUIDsOfLocallyChangedStatuses.end()
1515 && !mStatusChangedLocally ) {
1520 TQString flags = KMFolderImap::statusToFlags(msg->status(), mPermanentFlags);
1523 uid.setNum( msg->UID() );
1524 groups[flags].append(uid);
1526 TQMapIterator< TQString, TQStringList > dit;
1527 for( dit = groups.begin(); dit != groups.end(); ++dit ) {
1528 TQCString flags = dit.key().latin1();
1529 TQStringList sets = KMFolderImap::makeSets( (*dit),
true );
1530 mStatusFlagsJobs += sets.count();
1532 for( TQStringList::Iterator slit = sets.begin(); slit != sets.end(); ++slit ) {
1533 TQString imappath = imapPath() +
";UID=" + ( *slit );
1534 mAccount->setImapStatus(folder(), imappath, flags);
1539 if ( mStatusFlagsJobs ) {
1540 connect( mAccount, TQ_SIGNAL( imapStatusChanged(
KMFolder*,
const TQString&,
bool) ),
1541 this, TQ_SLOT( slotImapStatusChanged(
KMFolder*,
const TQString&,
bool) ) );
1545 newState( mProgress, i18n(
"No messages to upload to server"));
1546 serverSyncInternal();
1549 void KMFolderCachedImap::uploadSeenFlags()
1551 if ( !uidMap.isEmpty() ) {
1552 mStatusFlagsJobs = 0;
1553 newState( mProgress, i18n(
"Uploading status of messages to server"));
1555 TQValueList<ulong> seenUids, unseenUids;
1556 for(
int i = 0; i < count(); ++i ) {
1557 KMMsgBase* msg = getMsgBase( i );
1558 if( !msg || msg->UID() == 0 )
1562 if ( mUIDsOfLocallyChangedStatuses.find( msg->UID() ) == mUIDsOfLocallyChangedStatuses.end()
1563 && !mStatusChangedLocally ) {
1568 if ( msg->status() & KMMsgStatusOld || msg->status() & KMMsgStatusRead )
1569 seenUids.append( msg->UID() );
1571 unseenUids.append( msg->UID() );
1573 if ( !seenUids.isEmpty() ) {
1574 TQStringList sets = KMFolderImap::makeSets( seenUids,
true );
1575 mStatusFlagsJobs += sets.count();
1576 for( TQStringList::Iterator it = sets.begin(); it != sets.end(); ++it ) {
1577 TQString imappath = imapPath() +
";UID=" + ( *it );
1578 mAccount->setImapSeenStatus( folder(), imappath,
true );
1581 if ( !unseenUids.isEmpty() ) {
1582 TQStringList sets = KMFolderImap::makeSets( unseenUids,
true );
1583 mStatusFlagsJobs += sets.count();
1584 for( TQStringList::Iterator it = sets.begin(); it != sets.end(); ++it ) {
1585 TQString imappath = imapPath() +
";UID=" + ( *it );
1586 mAccount->setImapSeenStatus( folder(), imappath,
false );
1590 if ( mStatusFlagsJobs ) {
1591 connect( mAccount, TQ_SIGNAL( imapStatusChanged(
KMFolder*,
const TQString&,
bool) ),
1592 this, TQ_SLOT( slotImapStatusChanged(
KMFolder*,
const TQString&,
bool) ) );
1596 newState( mProgress, i18n(
"No messages to upload to server"));
1597 serverSyncInternal();
1600 void KMFolderCachedImap::slotImapStatusChanged(
KMFolder* folder,
const TQString&,
bool cont)
1602 if ( mSyncState == SYNC_STATE_INITIAL ){
1607 if ( folder->storage() ==
this ) {
1609 if ( mStatusFlagsJobs == 0 || !cont )
1610 disconnect( mAccount, TQ_SIGNAL( imapStatusChanged(
KMFolder*,
const TQString&,
bool) ),
1611 this, TQ_SLOT( slotImapStatusChanged(
KMFolder*,
const TQString&,
bool) ) );
1612 if ( mStatusFlagsJobs == 0 && cont ) {
1614 serverSyncInternal();
1621 void KMFolderCachedImap::setStatus(
int idx, KMMsgStatus status,
bool toggle)
1624 const KMMsgBase *msg = getMsgBase( idx );
1627 mUIDsOfLocallyChangedStatuses.insert( msg->UID() );
1630 void KMFolderCachedImap::setStatus(TQValueList<int>& ids, KMMsgStatus status,
bool toggle)
1633 for (TQValueList<int>::iterator it = ids.begin(); it != ids.end(); it++ ) {
1634 const KMMsgBase *msg = getMsgBase( *it );
1637 mUIDsOfLocallyChangedStatuses.insert( msg->UID() );
1642 void KMFolderCachedImap::createNewFolders()
1644 TQValueList<KMFolderCachedImap*> newFolders = findNewFolders();
1646 if( !newFolders.isEmpty() ) {
1647 newState( mProgress, i18n(
"Creating subfolders on server"));
1648 CachedImapJob *job =
new CachedImapJob( newFolders, CachedImapJob::tAddSubfolders,
this );
1649 connect( job, TQ_SIGNAL( result(KMail::FolderJob *) ),
this, TQ_SLOT( slotIncreaseProgress() ) );
1650 connect( job, TQ_SIGNAL( finished() ),
this, TQ_SLOT( serverSyncInternal() ) );
1653 serverSyncInternal();
1657 TQValueList<KMFolderCachedImap*> KMFolderCachedImap::findNewFolders()
1659 TQValueList<KMFolderCachedImap*> newFolders;
1660 if( folder() && folder()->child() ) {
1661 KMFolderNode *node = folder()->
child()->first();
1663 if( !node->isDir() ) {
1664 if(
static_cast<KMFolder*
>(node)->folderType() != KMFolderTypeCachedImap ) {
1665 kdError(5006) <<
"KMFolderCachedImap::findNewFolders(): ARGH!!! "
1666 << node->name() <<
" is not an IMAP folder\n";
1667 node = folder()->
child()->next();
1670 KMFolderCachedImap* folder =
static_cast<KMFolderCachedImap*
>(
static_cast<KMFolder*
>(node)->storage());
1671 if( folder->imapPath().isEmpty() ) {
1672 newFolders << folder;
1675 node = folder()->
child()->next();
1681 bool KMFolderCachedImap::deleteMessages()
1684 TQPtrList<KMMsgBase> msgsForDeletion;
1691 TQMap<ulong,int>::const_iterator it = uidMap.constBegin();
1692 for( ; it != uidMap.end(); it++ ) {
1693 ulong uid ( it.key() );
1694 if( uid!=0 && !uidsOnServer.find( uid ) ) {
1695 uids << TQString::number( uid );
1696 msgsForDeletion.append( getMsgBase( *it ) );
1700 if( !msgsForDeletion.isEmpty() ) {
1701 if ( contentsType() != ContentsTypeMail ) {
1702 kdDebug(5006) << k_funcinfo << label() <<
" Going to locally delete " << msgsForDeletion.count()
1703 <<
" messages, with the uids " << uids.join(
"," ) << endl;
1705 #if MAIL_LOSS_DEBUGGING
1706 if ( KMessageBox::warningYesNo(
1707 0, i18n(
"<qt><p>Mails on the server in folder <b>%1</b> were deleted. "
1708 "Do you want to delete them locally?<br>UIDs: %2</p></qt>" )
1709 .arg( folder()->prettyURL() ).arg( uids.join(
",") ) ) == KMessageBox::Yes )
1711 removeMsg( msgsForDeletion );
1714 if ( mUserRightsState ==
KMail::ACLJobs::Ok && !( mUserRights & KMail::ACLJobs::Delete ) )
1718 if( !uidsForDeletionOnServer.isEmpty() ) {
1719 newState( mProgress, i18n(
"Deleting removed messages from server"));
1720 TQStringList sets = KMFolderImap::makeSets( uidsForDeletionOnServer,
true );
1721 uidsForDeletionOnServer.clear();
1722 kdDebug(5006) <<
"Deleting " << sets.count() <<
" sets of messages from server folder " << imapPath() << endl;
1723 CachedImapJob *job =
new CachedImapJob( sets, CachedImapJob::tDeleteMessage,
this );
1724 connect( job, TQ_SIGNAL( result(KMail::FolderJob *) ),
1725 this, TQ_SLOT( slotDeleteMessagesResult(KMail::FolderJob *) ) );
1733 mDeletedUIDsSinceLastSync.clear();
1738 void KMFolderCachedImap::slotDeleteMessagesResult( KMail::FolderJob* job )
1740 if ( job->error() ) {
1742 mSyncState = SYNC_STATE_GET_MESSAGES;
1745 mDeletedUIDsSinceLastSync.clear();
1748 serverSyncInternal();
1751 void KMFolderCachedImap::checkUidValidity() {
1754 if( imapPath().isEmpty() || imapPath() ==
"/" )
1756 serverSyncInternal();
1758 newState( mProgress, i18n(
"Checking folder validity"));
1759 CachedImapJob *job =
new CachedImapJob( FolderJob::tCheckUidValidity,
this );
1760 connect( job, TQ_SIGNAL(permanentFlags(
int)), TQ_SLOT(slotPermanentFlags(
int)) );
1761 connect( job, TQ_SIGNAL( result( KMail::FolderJob* ) ),
1762 this, TQ_SLOT( slotCheckUidValidityResult( KMail::FolderJob* ) ) );
1767 void KMFolderCachedImap::slotCheckUidValidityResult( KMail::FolderJob* job )
1769 if ( job->error() ) {
1772 mSyncState = SYNC_STATE_HANDLE_INBOX;
1775 serverSyncInternal();
1778 void KMFolderCachedImap::slotPermanentFlags(
int flags)
1780 mPermanentFlags = flags;
1785 void KMFolderCachedImap::listMessages() {
1786 bool groupwareOnly = GlobalSettings::self()->showOnlyGroupwareFoldersForGroupwareAccount()
1787 && GlobalSettings::self()->theIMAPResourceAccount() == (int)mAccount->id()
1788 && folder()->isSystemFolder()
1789 && mImapPath ==
"/INBOX/";
1792 if( imapPath() ==
"/" || groupwareOnly ) {
1793 serverSyncInternal();
1797 if( !mAccount->slave() ) {
1799 emit folderComplete(
this,
false );
1802 uidsOnServer.clear();
1803 uidsOnServer.resize( count() * 2 );
1804 uidsForDeletionOnServer.clear();
1805 mMsgsForDownload.clear();
1806 mUidsForDownload.clear();
1808 mFoundAnIMAPDigest =
false;
1810 CachedImapJob* job =
new CachedImapJob( FolderJob::tListMessages,
this );
1811 connect( job, TQ_SIGNAL( result(KMail::FolderJob *) ),
1812 this, TQ_SLOT( slotGetLastMessagesResult(KMail::FolderJob *) ) );
1816 void KMFolderCachedImap::slotGetLastMessagesResult(KMail::FolderJob *job)
1818 getMessagesResult(job,
true);
1822 void KMFolderCachedImap::slotGetMessagesData(TDEIO::Job * job,
const TQByteArray & data)
1824 KMAcctCachedImap::JobIterator it = mAccount->findJob(job);
1825 if ( it == mAccount->jobsEnd() ) {
1826 kdDebug(5006) <<
"could not find job!?!?!" << endl;
1830 mSyncState = SYNC_STATE_HANDLE_INBOX;
1831 serverSyncInternal();
1834 (*it).cdata += TQCString(data, data.size() + 1);
1835 int pos = (*it).cdata.find(
"\r\n--IMAPDIGEST");
1837 int a = (*it).cdata.find(
"\r\nX-uidValidity:");
1839 int b = (*it).cdata.find(
"\r\n", a + 17);
1840 setUidValidity((*it).cdata.mid(a + 17, b - a - 17));
1842 a = (*it).cdata.find(
"\r\nX-Access:");
1849 int b = (*it).cdata.find(
"\r\n", a + 12);
1850 const TQString access = (*it).cdata.mid(a + 12, b - a - 12);
1851 setReadOnly( access ==
"Read only" );
1853 (*it).cdata.remove(0, pos);
1854 mFoundAnIMAPDigest =
true;
1856 pos = (*it).cdata.find(
"\r\n--IMAPDIGEST", 1);
1858 if ( uidsOnServer.size() == 0 )
1859 uidsOnServer.resize( KMail::nextPrime( 2000 ) );
1871 const TQCString& entry( (*it).cdata );
1872 const int indexOfUID = entry.find(
"X-UID", 16);
1873 const int startOfUIDValue = indexOfUID + 7;
1874 const int indexOfLength = entry.find(
"X-Length", startOfUIDValue );
1875 const int startOfLengthValue = indexOfLength + 10;
1876 const int indexOfFlags = entry.find(
"X-Flags", startOfLengthValue );
1877 const int startOfFlagsValue = indexOfFlags + 9;
1879 const int flags = entry.mid( startOfFlagsValue, entry.find(
'\r', startOfFlagsValue ) - startOfFlagsValue ).toInt();
1880 const ulong size = entry.mid( startOfLengthValue, entry.find(
'\r', startOfLengthValue ) - startOfLengthValue ).toULong();
1881 const ulong uid = entry.mid( startOfUIDValue, entry.find(
'\r', startOfUIDValue ) - startOfUIDValue ).toULong();
1883 const bool deleted = ( flags & 8 );
1886 if ( uidsOnServer.count() == uidsOnServer.size() ) {
1887 uidsOnServer.resize( KMail::nextPrime( uidsOnServer.size() * 2 ) );
1890 uidsOnServer.insert( uid, &v );
1892 bool redownload =
false;
1893 if ( uid <= lastUid() ) {
1904 KMMsgBase *existingMessage = findByUID(uid);
1905 if( !existingMessage ) {
1906 #if MAIL_LOSS_DEBUGGING
1907 kdDebug(5006) <<
"Looking at uid " << uid <<
" high water is: " << lastUid() <<
" we should delete it" << endl;
1910 if ( mDeletedUIDsSinceLastSync.contains(uid) ) {
1911 if ( mUserRightsState !=
KMail::ACLJobs::Ok || ( mUserRights & KMail::ACLJobs::Delete ) ) {
1912 #if MAIL_LOSS_DEBUGGING
1913 kdDebug(5006) <<
"message with uid " << uid <<
" is gone from local cache. Must be deleted on server!!!" << endl;
1915 uidsForDeletionOnServer << uid;
1920 kdDebug(5006) <<
"WARNING: ####### " << endl;
1921 kdDebug(5006) <<
"Message locally missing but not deleted in folder: " << folder()->prettyURL() << endl;
1922 kdDebug(5006) <<
"The missing UID: " << uid <<
". It will be redownloaded " << endl;
1930 if ( !mReadOnly || !GlobalSettings::allowLocalFlags() ) {
1932 KMFolderImap::flagsToStatus( existingMessage, flags,
false, mReadOnly ? INT_MAX : mPermanentFlags );
1933 }
else if ( mUserRights & KMail::ACLJobs::WriteSeenFlag ) {
1934 KMFolderImap::seenFlagToStatus( existingMessage, flags );
1939 if ( uid > lastUid() || redownload ) {
1940 #if MAIL_LOSS_DEBUGGING
1941 kdDebug(5006) <<
"Looking at uid " << uid <<
" high water is: " << lastUid() <<
" we should download it" << endl;
1945 if ( !uidMap.contains( uid ) ) {
1947 if( imapPath() ==
"/INBOX/" )
1948 mUidsForDownload << uid;
1951 if ( uid > mTentativeHighestUid ) {
1952 #if MAIL_LOSS_DEBUGGING
1953 kdDebug(5006) <<
"Setting the tentative highest UID to: " << uid << endl;
1955 mTentativeHighestUid = uid;
1959 (*it).cdata.remove(0, pos);
1961 pos = (*it).cdata.find(
"\r\n--IMAPDIGEST", 1);
1965 void KMFolderCachedImap::getMessagesResult( KMail::FolderJob *job,
bool lastSet )
1968 if ( !job->error() && !mFoundAnIMAPDigest ) {
1969 kdWarning(5006) <<
"######## Folderlisting did not complete, but there was no error! "
1970 "Aborting sync of folder: " << folder()->prettyURL() << endl;
1971 #if MAIL_LOSS_DEBUGGING
1972 kmkernel->emergencyExit( i18n(
"Folder listing failed in interesting ways." ) );
1975 if( job->error() ) {
1976 mContentState = imapNoInformation;
1977 mSyncState = SYNC_STATE_HANDLE_INBOX;
1980 mContentState = imapFinished;
1981 mUIDsOfLocallyChangedStatuses.clear();
1982 mStatusChangedLocally =
false;
1985 serverSyncInternal();
1988 void KMFolderCachedImap::slotProgress(
unsigned long done,
unsigned long total)
1990 int progressSpan = 100 - 5 - mProgress;
1991 int additionalProgress = ( total == 0 ) ?
1993 ( progressSpan * done ) / total;
1997 newState( mProgress + additionalProgress, TQString() );
2000 void KMFolderCachedImap::setAccount(KMAcctCachedImap *aAccount)
2002 assert( aAccount->isA(
"KMAcctCachedImap") );
2003 mAccount = aAccount;
2004 if( imapPath()==
"/" ) aAccount->setFolder( folder() );
2007 TQString newName = mAccount->renamedFolder( imapPath() );
2008 if ( !newName.isEmpty() )
2009 folder()->setLabel( newName );
2011 if( !folder() || !folder()->child() || !folder()->child()->count() )
return;
2012 for( KMFolderNode* node = folder()->child()->first(); node;
2013 node = folder()->child()->next() )
2015 static_cast<KMFolderCachedImap*
>(
static_cast<KMFolder*
>(node)->storage())->setAccount(aAccount);
2018 void KMFolderCachedImap::listNamespaces()
2020 ImapAccountBase::ListType type = ImapAccountBase::List;
2021 if ( mAccount->onlySubscribedFolders() )
2022 type = ImapAccountBase::ListSubscribed;
2024 kdDebug(5006) <<
"listNamespaces " << mNamespacesToList << endl;
2025 if ( mNamespacesToList.isEmpty() ) {
2026 mSyncState = SYNC_STATE_DELETE_SUBFOLDERS;
2027 mPersonalNamespacesCheckDone =
true;
2029 TQStringList ns = mAccount->namespaces()[ImapAccountBase::OtherUsersNS];
2030 ns += mAccount->namespaces()[ImapAccountBase::SharedNS];
2031 mNamespacesToCheck = ns.count();
2032 for ( TQStringList::Iterator it = ns.begin(); it != ns.end(); ++it )
2034 if ( (*it).isEmpty() ) {
2036 --mNamespacesToCheck;
2041 connect( job, TQ_SIGNAL(receivedFolders(
const TQStringList&,
const TQStringList&,
2043 this, TQ_SLOT(slotCheckNamespace(
const TQStringList&,
const TQStringList&,
2047 if ( mNamespacesToCheck == 0 ) {
2048 serverSyncInternal();
2052 mPersonalNamespacesCheckDone =
false;
2054 TQString ns = mNamespacesToList.front();
2055 mNamespacesToList.pop_front();
2057 mSyncState = SYNC_STATE_LIST_SUBFOLDERS2;
2058 newState( mProgress, i18n(
"Retrieving folders for namespace %1").arg(ns));
2060 mAccount->addPathToNamespace( ns ) );
2063 connect( job, TQ_SIGNAL(receivedFolders(
const TQStringList&,
const TQStringList&,
2065 this, TQ_SLOT(slotListResult(
const TQStringList&,
const TQStringList&,
2070 void KMFolderCachedImap::slotCheckNamespace(
const TQStringList& subfolderNames,
2071 const TQStringList& subfolderPaths,
2072 const TQStringList& subfolderMimeTypes,
2073 const TQStringList& subfolderAttributes,
2076 Q_UNUSED( subfolderPaths );
2077 Q_UNUSED( subfolderMimeTypes );
2078 Q_UNUSED( subfolderAttributes );
2079 --mNamespacesToCheck;
2080 kdDebug(5006) <<
"slotCheckNamespace " << subfolderNames <<
",remain=" <<
2081 mNamespacesToCheck << endl;
2085 TQString name = jobData.path.mid( 1, jobData.path.length()-2 );
2086 name.remove( mAccount->delimiterForNamespace( name ) );
2087 if ( name.isEmpty() ) {
2089 kdWarning(5006) <<
"slotCheckNamespace: ignoring empty folder!" << endl;
2093 folder()->createChildFolder();
2094 KMFolderNode *node = 0;
2095 for ( node = folder()->child()->first(); node;
2096 node = folder()->child()->next())
2098 if ( !node->isDir() && node->name() == name )
2101 if ( !subfolderNames.isEmpty() ) {
2104 kdDebug(5006) <<
"found namespace folder " << name << endl;
2108 kdDebug(5006) <<
"create namespace folder " << name << endl;
2110 KMFolderTypeCachedImap );
2112 KMFolderCachedImap *f =
static_cast<KMFolderCachedImap*
>( newFolder->storage() );
2113 f->setImapPath( mAccount->addPathToNamespace( name ) );
2115 f->setAccount( mAccount );
2116 f->close(
"cachedimap");
2117 kmkernel->dimapFolderMgr()->contentsChanged();
2122 kdDebug(5006) <<
"delete namespace folder " << name << endl;
2124 kmkernel->dimapFolderMgr()->remove( fld );
2128 if ( mNamespacesToCheck == 0 ) {
2130 serverSyncInternal();
2136 bool KMFolderCachedImap::listDirectory()
2138 if( !mAccount->slave() ) {
2140 emit folderComplete(
this,
false );
2143 mSubfolderState = imapInProgress;
2146 ImapAccountBase::ListType type = ImapAccountBase::List;
2147 if ( mAccount->onlySubscribedFolders() )
2148 type = ImapAccountBase::ListSubscribed;
2151 connect( job, TQ_SIGNAL(receivedFolders(
const TQStringList&,
const TQStringList&,
2153 this, TQ_SLOT(slotListResult(
const TQStringList&,
const TQStringList&,
2160 void KMFolderCachedImap::slotListResult(
const TQStringList& folderNames,
2161 const TQStringList& folderPaths,
2162 const TQStringList& folderMimeTypes,
2163 const TQStringList& folderAttributes,
2166 Q_UNUSED( jobData );
2169 mSubfolderNames = folderNames;
2170 mSubfolderPaths = folderPaths;
2171 mSubfolderMimeTypes = folderMimeTypes;
2172 mSubfolderState = imapFinished;
2173 mSubfolderAttributes = folderAttributes;
2176 folder()->createChildFolder();
2177 KMFolderNode *node = folder()->child()->first();
2178 bool root = (
this == mAccount->rootFolder() );
2180 TQPtrList<KMFolder> toRemove;
2181 bool emptyList = ( root && mSubfolderNames.empty() );
2184 if (!node->isDir() ) {
2185 KMFolderCachedImap *f =
static_cast<KMFolderCachedImap*
>(
static_cast<KMFolder*
>(node)->storage());
2187 if ( mSubfolderNames.findIndex(node->name()) == -1 ) {
2188 TQString name = node->name();
2191 bool isInNamespace = ( jobData.curNamespace.isEmpty() ||
2192 jobData.curNamespace == mAccount->namespaceForFolder( f ) );
2194 bool ignore = root && ( f->imapPath() ==
"/INBOX/" ||
2195 mAccount->isNamespaceFolder( name ) || !isInNamespace );
2198 if( !f->imapPath().isEmpty() && !ignore ) {
2201 toRemove.append( f->folder() );
2202 kdDebug(5006) << node->name() <<
" isn't on the server. It has an imapPath -> delete it locally" << endl;
2210 int index = mSubfolderNames.findIndex( node->name() );
2211 f->mFolderAttributes = folderAttributes[ index ];
2216 node = folder()->child()->next();
2220 for (
KMFolder* doomed=toRemove.first(); doomed; doomed = toRemove.next() ) {
2221 rescueUnsyncedMessagesAndDeleteFolder( doomed );
2227 slotRescueDone( 0 );
2231 void KMFolderCachedImap::listDirectory2()
2233 TQString path = folder()->path();
2234 kmkernel->dimapFolderMgr()->quiet(
true);
2236 bool root = (
this == mAccount->rootFolder() );
2237 if ( root && !mAccount->hasInbox() )
2239 KMFolderCachedImap *f = 0;
2242 for (node = folder()->child()->first(); node; node = folder()->child()->next())
2243 if (!node->isDir() && node->name() ==
"INBOX")
break;
2245 f =
static_cast<KMFolderCachedImap*
>(
static_cast<KMFolder*
>(node)->storage());
2249 f =
static_cast<KMFolderCachedImap*
>(newFolder->storage());
2253 f->setAccount( mAccount );
2254 f->setImapPath(
"/INBOX/" );
2255 f->folder()->setLabel( i18n(
"inbox") );
2259 f->close(
"cachedimap");
2260 kmkernel->dimapFolderMgr()->contentsChanged();
2263 mAccount->setHasInbox(
true );
2266 if ( root && !mSubfolderNames.isEmpty() ) {
2267 KMFolderCachedImap* parent =
2268 findParent( mSubfolderPaths.first(), mSubfolderNames.first() );
2270 kdDebug(5006) <<
"KMFolderCachedImap::listDirectory2 - pass listing to "
2271 << parent->label() << endl;
2272 mSubfolderNames.clear();
2277 TQValueVector<int> foldersNewOnServer;
2278 for (uint i = 0; i < mSubfolderNames.count(); i++) {
2281 KMFolderCachedImap *f = 0;
2282 KMFolderNode *node = 0;
2283 for (node = folder()->child()->first(); node;
2284 node = folder()->child()->next())
2285 if (!node->isDir() && node->name() == mSubfolderNames[i])
break;
2290 TQString subfolderPath = mSubfolderPaths[i];
2294 bool locallyDeleted = mAccount->isDeletedFolder( subfolderPath );
2298 if ( !locallyDeleted && mAccount->isPreviouslyDeletedFolder( subfolderPath ) ) {
2299 locallyDeleted = KMessageBox::warningYesNo(
2300 0, i18n(
"<qt><p>It seems that the folder <b>%1</b> was deleted. Do you want to delete it from the server?</p></qt>" ).arg( mSubfolderNames[i] ), TQString(), KStdGuiItem::del(), KStdGuiItem::cancel() ) == KMessageBox::Yes;
2303 if ( locallyDeleted ) {
2304 kdDebug(5006) << subfolderPath <<
" was deleted locally => delete on server." << endl;
2305 foldersForDeletionOnServer += mAccount->deletedFolderPaths( subfolderPath );
2307 kdDebug(5006) << subfolderPath <<
" is a new folder on the server => create local cache" << endl;
2308 foldersNewOnServer.append( i );
2311 if(
static_cast<KMFolder*
>(node)->folderType() == KMFolderTypeCachedImap )
2312 f =
dynamic_cast<KMFolderCachedImap*
>(
static_cast<KMFolder*
>(node)->storage());
2317 f->setAccount(mAccount);
2318 f->setNoContent(mSubfolderMimeTypes[i] ==
"inode/directory");
2319 f->setNoChildren(mSubfolderMimeTypes[i] ==
"message/digest");
2320 f->setImapPath(mSubfolderPaths[i]);
2335 if ( GlobalSettings::self()->showOnlyGroupwareFoldersForGroupwareAccount()
2336 && GlobalSettings::self()->theIMAPResourceAccount() == (int)mAccount->id()
2337 && mAccount->hasAnnotationSupport()
2338 && GlobalSettings::self()->theIMAPResourceEnabled()
2339 && !foldersNewOnServer.isEmpty() ) {
2342 for ( uint i = 0; i < foldersNewOnServer.count(); ++i )
2343 paths << mSubfolderPaths[ foldersNewOnServer[i] ];
2346 AnnotationJobs::multiUrlGetAnnotation( mAccount->slave(), mAccount->getUrl(), paths, KOLAB_FOLDERTYPE );
2348 jd.cancellable =
true;
2349 mAccount->insertJob(job, jd);
2350 connect( job, TQ_SIGNAL(result(TDEIO::Job *)),
2351 TQ_SLOT(slotMultiUrlGetAnnotationResult(TDEIO::Job *)) );
2354 createFoldersNewOnServerAndFinishListing( foldersNewOnServer );
2358 void KMFolderCachedImap::createFoldersNewOnServerAndFinishListing(
const TQValueVector<int> foldersNewOnServer )
2360 for ( uint i = 0; i < foldersNewOnServer.count(); ++i ) {
2361 int idx = foldersNewOnServer[i];
2364 KMFolderCachedImap *f =
dynamic_cast<KMFolderCachedImap*
>(newFolder->storage());
2365 kdDebug(5006) <<
" ####### Locally creating folder " << mSubfolderNames[idx] <<endl;
2366 f->
close(
"cachedimap");
2367 f->setAccount(mAccount);
2368 f->mAnnotationFolderType =
"FROMSERVER";
2369 f->setNoContent(mSubfolderMimeTypes[idx] ==
"inode/directory");
2370 f->setNoChildren(mSubfolderMimeTypes[idx] ==
"message/digest");
2371 f->setImapPath(mSubfolderPaths[idx]);
2372 f->mFolderAttributes = mSubfolderAttributes[idx];
2373 mNewlyCreatedSubfolders.append( TQGuardedPtr<KMFolderCachedImap>( f ) );
2374 kdDebug(5006) <<
" ####### Attributes: " << f->mFolderAttributes <<endl;
2376 kmkernel->dimapFolderMgr()->contentsChanged();
2378 kdDebug(5006) <<
"can't create folder " << mSubfolderNames[idx] <<endl;
2382 kmkernel->dimapFolderMgr()->quiet(
false);
2383 emit listComplete(
this);
2384 if ( !mPersonalNamespacesCheckDone ) {
2386 mSyncState = SYNC_STATE_LIST_NAMESPACES;
2388 serverSyncInternal();
2392 KMFolderCachedImap* KMFolderCachedImap::findParent(
const TQString& path,
2393 const TQString& name )
2395 TQString parent = path.left( path.length() - name.length() - 2 );
2396 if ( parent.length() > 1 )
2399 parent = parent.right( parent.length() - 1 );
2400 if ( parent != label() )
2402 KMFolderNode *node = folder()->child()->first();
2406 if ( node->name() == parent )
2409 KMFolderCachedImap* imapFld =
2410 static_cast<KMFolderCachedImap*
>( fld->storage() );
2413 node = folder()->
child()->next();
2420 void KMFolderCachedImap::slotSubFolderComplete(KMFolderCachedImap* sub,
bool success)
2425 serverSyncInternal();
2430 if ( mCurrentSubfolder ) {
2431 Q_ASSERT( sub == mCurrentSubfolder );
2432 disconnectSubFolderSignals();
2437 mSubfoldersForSync.clear();
2438 mSyncState = SYNC_STATE_INITIAL;
2439 close(
"cachedimap");
2440 emit syncStateChanged();
2441 emit folderComplete(
this,
false );
2445 void KMFolderCachedImap::slotSubFolderCloseToQuotaChanged()
2447 if ( !mQuotaOnly ) {
2448 mSomeSubFolderCloseToQuotaChanged =
true;
2452 void KMFolderCachedImap::slotSimpleData(TDEIO::Job * job,
const TQByteArray & data)
2454 KMAcctCachedImap::JobIterator it = mAccount->findJob(job);
2455 if (it == mAccount->jobsEnd())
return;
2456 TQBuffer buff((*it).data);
2457 buff.open(IO_WriteOnly | IO_Append);
2458 buff.writeBlock(data.data(), data.size());
2463 KMFolderCachedImap::doCreateJob(
KMMessage *msg, FolderJob::JobType jt,
KMFolder *folder,
2464 TQString,
const AttachmentStrategy* )
const
2466 TQPtrList<KMMessage> msgList;
2467 msgList.append( msg );
2468 CachedImapJob *job =
new CachedImapJob( msgList, jt, folder?
static_cast<KMFolderCachedImap*
>( folder->storage() ):0 );
2469 job->setParentFolder(
this );
2474 KMFolderCachedImap::doCreateJob( TQPtrList<KMMessage>& msgList,
const TQString& sets,
2475 FolderJob::JobType jt,
KMFolder *folder )
const
2479 CachedImapJob *job =
new CachedImapJob( msgList, jt, folder?
static_cast<KMFolderCachedImap*
>( folder->storage() ):0 );
2480 job->setParentFolder(
this );
2487 mUserRights = userRights;
2488 mUserRightsState = state;
2489 writeConfigKeysWhichShouldNotGetOverwrittenByReadConfig();
2493 KMFolderCachedImap::slotReceivedUserRights(
KMFolder* folder )
2495 if ( folder->storage() ==
this ) {
2496 disconnect( mAccount, TQ_SIGNAL( receivedUserRights(
KMFolder* ) ),
2497 this, TQ_SLOT( slotReceivedUserRights(
KMFolder* ) ) );
2499 setReadOnly( ( mUserRights & KMail::ACLJobs::Insert ) == 0 );
2502 serverSyncInternal();
2507 KMFolderCachedImap::setReadOnly(
bool readOnly )
2509 if ( readOnly != mReadOnly ) {
2510 mReadOnly = readOnly;
2511 emit readOnlyChanged( folder() );
2516 KMFolderCachedImap::slotReceivedACL(
KMFolder* folder, TDEIO::Job* job,
const KMail::ACLList& aclList )
2518 if ( folder->storage() ==
this ) {
2519 disconnect( mAccount, TQ_SIGNAL(receivedACL(
KMFolder*, TDEIO::Job*,
const KMail::ACLList& )),
2520 this, TQ_SLOT(slotReceivedACL(
KMFolder*, TDEIO::Job*,
const KMail::ACLList& )) );
2523 serverSyncInternal();
2528 KMFolderCachedImap::slotStorageQuotaResult(
const QuotaInfo& info )
2530 setQuotaInfo( info );
2533 void KMFolderCachedImap::setQuotaInfo(
const QuotaInfo & info )
2535 if ( info != mQuotaInfo ) {
2536 const bool wasCloseToQuota = isCloseToQuota();
2538 writeConfigKeysWhichShouldNotGetOverwrittenByReadConfig();
2539 if ( wasCloseToQuota != isCloseToQuota() ) {
2540 emit closeToQuotaChanged();
2542 emit folderSizeChanged();
2547 KMFolderCachedImap::setACLList(
const ACLList& arr )
2554 KMFolderCachedImap::slotMultiSetACLResult(TDEIO::Job *job)
2556 KMAcctCachedImap::JobIterator it = mAccount->findJob(job);
2557 if ( it == mAccount->jobsEnd() )
return;
2558 if ( (*it).parent != folder() )
return;
2563 job->showErrorDialog();
2565 kmkernel->iCalIface().addFolderChange( folder(), KMailICalIfaceImpl::ACL );
2567 if (mAccount->slave()) mAccount->removeJob(job);
2568 serverSyncInternal();
2572 KMFolderCachedImap::slotACLChanged(
const TQString& userId,
int permissions )
2576 for( ACLList::Iterator it = mACLList.begin(); it != mACLList.end(); ++it ) {
2577 if ( (*it).userId == userId && (*it).permissions == permissions ) {
2578 if ( permissions == -1 )
2579 mACLList.erase( it );
2581 (*it).changed =
false;
2588 void KMFolderCachedImap::resetSyncState()
2590 if ( mSyncState == SYNC_STATE_INITIAL )
return;
2591 mSubfoldersForSync.clear();
2592 mNewlyCreatedSubfolders.clear();
2593 mSyncState = SYNC_STATE_INITIAL;
2594 close(
"cachedimap");
2596 KPIM::ProgressItem *progressItem = mAccount->mailCheckProgressItem();
2597 TQString str = i18n(
"Aborted");
2599 progressItem->setStatus( str );
2600 emit statusMsg( str );
2601 emit syncStateChanged();
2604 void KMFolderCachedImap::slotIncreaseProgress()
2609 void KMFolderCachedImap::newState(
int progress,
const TQString& syncStatus )
2612 KPIM::ProgressItem *progressItem = mAccount->mailCheckProgressItem();
2614 progressItem->setCompletedItems( progress );
2615 if ( !syncStatus.isEmpty() ) {
2618 if ( mAccount->imapFolder() ==
this )
2621 str = TQString(
"%1: %2" ).arg( label() ).arg( syncStatus );
2623 progressItem->setStatus( str );
2624 emit statusMsg( str );
2627 progressItem->updateProgress();
2630 void KMFolderCachedImap::setSubfolderState( imapState state )
2632 mSubfolderState = state;
2633 if ( state == imapNoInformation && folder()->child() )
2637 TQPtrListIterator<KMFolderNode> it( *folder()->child() );
2638 for ( ; (node = it.current()); )
2641 if (node->isDir())
continue;
2643 static_cast<KMFolderCachedImap*
>(folder->storage())->setSubfolderState( state );
2648 void KMFolderCachedImap::setImapPath(
const TQString &path)
2653 static bool isFolderTypeKnownToUs(
const TQString &type )
2655 for ( uint i = 0 ; i <= ContentsTypeLast; ++i ) {
2656 FolderContentsType contentsType =
static_cast<KMail::FolderContentsType
>( i );
2657 if ( type == KMailICalIfaceImpl::annotationForContentsType( contentsType ) )
2668 void KMFolderCachedImap::updateAnnotationFolderType()
2670 TQString oldType = mAnnotationFolderType;
2671 TQString oldSubType;
2672 int dot = oldType.find(
'.' );
2674 oldType.truncate( dot );
2675 oldSubType = mAnnotationFolderType.mid( dot + 1 );
2678 TQString newType, newSubType;
2680 if ( kmkernel->iCalIface().storageFormat( folder() ) == KMailICalIfaceImpl::StorageXML ) {
2681 newType = KMailICalIfaceImpl::annotationForContentsType( mContentsType );
2682 if ( kmkernel->iCalIface().isStandardResourceFolder( folder() ) )
2683 newSubType =
"default";
2684 else if ( oldSubType !=
"default" )
2685 newSubType = oldSubType;
2691 const bool changingTypeAllowed = isFolderTypeKnownToUs( oldType ) ||
2692 ( mContentsType != ContentsTypeMail );
2695 if ( ( newType != oldType || newSubType != oldSubType ) && changingTypeAllowed ) {
2696 mAnnotationFolderType = newType + ( newSubType.isEmpty() ? TQString() :
"."+newSubType );
2697 mAnnotationFolderTypeChanged =
true;
2698 kdDebug(5006) << mImapPath <<
": updateAnnotationFolderType: '" << mAnnotationFolderType <<
"', was (" << oldType <<
" " << oldSubType <<
") => mAnnotationFolderTypeChanged set to TRUE" << endl;
2701 writeConfigKeysWhichShouldNotGetOverwrittenByReadConfig();
2704 void KMFolderCachedImap::setIncidencesFor( IncidencesFor incfor )
2706 if ( mIncidencesFor != incfor ) {
2707 mIncidencesFor = incfor;
2708 mIncidencesForChanged =
true;
2712 void KMFolderCachedImap::setSharedSeenFlags(
bool b)
2714 if ( mSharedSeenFlags != b ) {
2715 mSharedSeenFlags = b;
2716 mSharedSeenFlagsChanged =
true;
2720 void KMFolderCachedImap::slotAnnotationResult(
const TQString& entry,
const TQString& value,
bool found)
2722 if ( entry == KOLAB_FOLDERTYPE ) {
2729 TQString type = value;
2731 int dot = value.find(
'.' );
2733 type.truncate( dot );
2734 subtype = value.mid( dot + 1 );
2736 bool foundKnownType =
false;
2737 for ( uint i = 0 ; i <= ContentsTypeLast; ++i ) {
2738 FolderContentsType contentsType =
static_cast<KMail::FolderContentsType
>( i );
2739 if ( type == KMailICalIfaceImpl::annotationForContentsType( contentsType ) ) {
2742 if ( contentsType != ContentsTypeMail )
2743 kmkernel->iCalIface().setStorageFormat( folder(), KMailICalIfaceImpl::StorageXML );
2744 mAnnotationFolderType = value;
2745 if ( folder()->parent()->owner()->
idString() != GlobalSettings::self()->theIMAPResourceFolderParent()
2746 && GlobalSettings::self()->theIMAPResourceEnabled()
2747 && subtype ==
"default" ) {
2750 mAnnotationFolderType = type;
2751 kdDebug(5006) << mImapPath <<
": slotGetAnnotationResult: parent folder is " << folder()->parent()->owner()->
idString() <<
" => truncating annotation to " << value << endl;
2753 setContentsType( contentsType );
2754 mAnnotationFolderTypeChanged =
false;
2755 foundKnownType =
true;
2761 if ( contentsType != ContentsTypeMail )
2767 if ( !foundKnownType ) {
2772 mAnnotationFolderTypeChanged =
false;
2773 mAnnotationFolderType = value;
2774 setContentsType( ContentsTypeMail );
2778 writeConfigKeysWhichShouldNotGetOverwrittenByReadConfig();
2781 else if ( !mReadOnly ) {
2784 mAnnotationFolderTypeChanged =
true;
2786 }
else if ( entry == KOLAB_INCIDENCESFOR ) {
2788 mIncidencesFor = incidencesForFromString( value );
2789 Q_ASSERT( mIncidencesForChanged ==
false );
2791 }
else if ( entry == KOLAB_SHAREDSEEN ) {
2793 mSharedSeenFlags = value ==
"true";
2798 void KMFolderCachedImap::slotGetAnnotationResult( TDEIO::Job* job )
2800 KMAcctCachedImap::JobIterator it = mAccount->findJob(job);
2801 Q_ASSERT( it != mAccount->jobsEnd() );
2802 if ( it == mAccount->jobsEnd() )
return;
2803 Q_ASSERT( (*it).parent == folder() );
2804 if ( (*it).parent != folder() )
return;
2807 if ( annjob->error() ) {
2808 if ( job->error() == TDEIO::ERR_UNSUPPORTED_ACTION ) {
2810 if ( GlobalSettings::self()->theIMAPResourceStorageFormat() == GlobalSettings::EnumTheIMAPResourceStorageFormat::XML
2811 && (uint)GlobalSettings::self()->theIMAPResourceAccount() == mAccount->id() )
2812 KMessageBox::error( 0, i18n(
"The IMAP server %1 does not have support for IMAP annotations. The XML storage cannot be used on this server; please re-configure KMail differently." ).arg( mAccount->host() ) );
2813 mAccount->setHasNoAnnotationSupport();
2816 kdWarning(5006) <<
"slotGetAnnotationResult: " << job->errorString() << endl;
2819 if (mAccount->slave()) mAccount->removeJob(job);
2821 serverSyncInternal();
2824 void KMFolderCachedImap::slotMultiUrlGetAnnotationResult( TDEIO::Job* job )
2826 KMAcctCachedImap::JobIterator it = mAccount->findJob(job);
2827 Q_ASSERT( it != mAccount->jobsEnd() );
2828 if ( it == mAccount->jobsEnd() )
return;
2829 Q_ASSERT( (*it).parent == folder() );
2830 if ( (*it).parent != folder() )
return;
2832 TQValueVector<int> folders;
2835 if ( annjob->error() ) {
2836 if ( job->error() == TDEIO::ERR_UNSUPPORTED_ACTION ) {
2838 if ( GlobalSettings::self()->theIMAPResourceStorageFormat() == GlobalSettings::EnumTheIMAPResourceStorageFormat::XML
2839 && (uint)GlobalSettings::self()->theIMAPResourceAccount() == mAccount->id() )
2840 KMessageBox::error( 0, i18n(
"The IMAP server %1 doesn't have support for imap annotations. The XML storage cannot be used on this server, please re-configure KMail differently" ).arg( mAccount->host() ) );
2841 mAccount->setHasNoAnnotationSupport();
2844 kdWarning(5006) <<
"slotGetMultiUrlAnnotationResult: " << job->errorString() << endl;
2847 TQMap<TQString, TQString> annotations = annjob->annotations();
2848 TQMap<TQString, TQString>::Iterator it = annotations.begin();
2849 for ( ; it != annotations.end(); ++it ) {
2850 const TQString folderPath = it.key();
2851 const TQString annotation = it.data();
2852 kdDebug(5006) << k_funcinfo <<
"Folder: " << folderPath <<
" has type: " << annotation << endl;
2854 TQString type(annotation);
2855 int dot = annotation.find(
'.' );
2856 if ( dot != -1 ) type.truncate( dot );
2857 type = type.simplifyWhiteSpace();
2859 const int idx = mSubfolderPaths.findIndex( folderPath );
2860 const bool isNoContent = mSubfolderMimeTypes[idx] ==
"inode/directory";
2861 if ( ( isNoContent && type.isEmpty() )
2862 || ( !type.isEmpty() && type != KMailICalIfaceImpl::annotationForContentsType( ContentsTypeMail ) ) ) {
2863 folders.append( idx );
2864 kdDebug(5006) << k_funcinfo <<
" subscribing to: " << folderPath << endl;
2866 kdDebug(5006) << k_funcinfo <<
" automatically unsubscribing from: " << folderPath << endl;
2867 mAccount->changeLocalSubscription( folderPath,
false );
2872 if (mAccount->slave()) mAccount->removeJob(job);
2873 createFoldersNewOnServerAndFinishListing( folders );
2876 void KMFolderCachedImap::slotQuotaResult( TDEIO::Job* job )
2878 KMAcctCachedImap::JobIterator it = mAccount->findJob(job);
2879 Q_ASSERT( it != mAccount->jobsEnd() );
2880 if ( it == mAccount->jobsEnd() )
return;
2881 Q_ASSERT( (*it).parent == folder() );
2882 if ( (*it).parent != folder() )
return;
2886 if ( quotajob->error() ) {
2887 if ( job->error() == TDEIO::ERR_UNSUPPORTED_ACTION ) {
2889 mAccount->setHasNoQuotaSupport();
2890 setQuotaInfo( empty );
2893 kdWarning(5006) <<
"slotGetQuotaResult: " << job->errorString() << endl;
2896 if (mAccount->slave()) mAccount->removeJob(job);
2898 serverSyncInternal();
2902 KMFolderCachedImap::slotAnnotationChanged(
const TQString& entry,
const TQString& attribute,
const TQString& value )
2904 Q_UNUSED( attribute );
2907 if ( entry == KOLAB_FOLDERTYPE )
2908 mAnnotationFolderTypeChanged =
false;
2909 else if ( entry == KOLAB_INCIDENCESFOR ) {
2910 mIncidencesForChanged =
false;
2913 kmkernel->iCalIface().addFolderChange( folder(), KMailICalIfaceImpl::ACL );
2914 }
else if ( entry == KOLAB_SHAREDSEEN ) {
2915 mSharedSeenFlagsChanged =
false;
2919 void KMFolderCachedImap::slotTestAnnotationResult(TDEIO::Job *job)
2921 KMAcctCachedImap::JobIterator it = mAccount->findJob(job);
2922 Q_ASSERT( it != mAccount->jobsEnd() );
2923 if ( it == mAccount->jobsEnd() )
return;
2924 Q_ASSERT( (*it).parent == folder() );
2925 if ( (*it).parent != folder() )
return;
2927 mAccount->setAnnotationCheckPassed(
true );
2928 if ( job->error() ) {
2929 kdDebug(5006) <<
"Test Annotation was not passed, disabling annotation support" << endl;
2930 mAccount->setHasNoAnnotationSupport( );
2932 kdDebug(5006) <<
"Test Annotation was passed OK" << endl;
2934 if (mAccount->slave()) mAccount->removeJob(job);
2935 serverSyncInternal();
2939 KMFolderCachedImap::slotSetAnnotationResult(TDEIO::Job *job)
2941 KMAcctCachedImap::JobIterator it = mAccount->findJob(job);
2942 if ( it == mAccount->jobsEnd() )
return;
2943 if ( (*it).parent != folder() )
return;
2946 if ( job->error() ) {
2948 if ( job->error() == TDEIO::ERR_UNSUPPORTED_ACTION && contentsType() == ContentsTypeMail ) {
2949 if (mAccount->slave()) mAccount->removeJob(job);
2951 cont = mAccount->handleJobError( job, i18n(
"Error while setting annotation: " ) +
'\n' );
2954 if (mAccount->slave()) mAccount->removeJob(job);
2957 serverSyncInternal();
2960 void KMFolderCachedImap::slotUpdateLastUid()
2962 if( mTentativeHighestUid != 0 ) {
2974 bool sane = count() == 0;
2976 for (
int i=0;i<count(); i++ ) {
2977 ulong uid = getMsgBase(i)->UID();
2978 if ( uid > mTentativeHighestUid && uid > lastUid() ) {
2979 kdWarning(5006) <<
"DANGER: Either the server listed a wrong highest uid, "
2980 "or we parsed it wrong. Send email to adam@kde.org, please, and include this log." << endl;
2981 kdWarning(5006) <<
"uid: " << uid <<
" mTentativeHighestUid: " << mTentativeHighestUid << endl;
2989 #if MAIL_LOSS_DEBUGGING
2990 kdDebug(5006) <<
"Tentative highest UID test was sane, writing out: " << mTentativeHighestUid << endl;
2992 setLastUid( mTentativeHighestUid );
2995 mTentativeHighestUid = 0;
2998 bool KMFolderCachedImap::isMoveable()
const
3000 return ( hasChildren() == HasNoChildren &&
3001 !folder()->isSystemFolder() ) ? true :
false;
3004 void KMFolderCachedImap::slotFolderDeletionOnServerFinished()
3006 for ( TQStringList::const_iterator it = foldersForDeletionOnServer.constBegin();
3007 it != foldersForDeletionOnServer.constEnd(); ++it ) {
3008 KURL url( mAccount->getUrl() );
3010 kmkernel->iCalIface().folderDeletedOnServer( url );
3012 serverSyncInternal();
3015 int KMFolderCachedImap::createIndexFromContentsRecursive()
3017 if ( !folder() || !folder()->child() )
3020 KMFolderNode *node = 0;
3021 for( TQPtrListIterator<KMFolderNode> it( *folder()->child() ); (node = it.current()); ++it ) {
3022 if( !node->isDir() ) {
3023 KMFolderCachedImap* storage =
static_cast<KMFolderCachedImap*
>(
static_cast<KMFolder*
>(node)->storage());
3024 kdDebug() << k_funcinfo <<
"Re-indexing: " << storage->folder()->label() << endl;
3025 int rv = storage->createIndexFromContentsRecursive();
3031 return createIndexFromContents();
3034 void KMFolderCachedImap::setAlarmsBlocked(
bool blocked )
3036 mAlarmsBlocked = blocked;
3039 bool KMFolderCachedImap::alarmsBlocked()
const
3041 return mAlarmsBlocked;
3044 bool KMFolderCachedImap::isCloseToQuota()
const
3046 bool closeToQuota =
false;
3047 if ( mQuotaInfo.isValid() && mQuotaInfo.max().toInt() > 0 ) {
3048 const int ratio = mQuotaInfo.current().toInt() * 100 / mQuotaInfo.max().toInt();
3050 closeToQuota = ( ratio > 0 && ratio >= GlobalSettings::closeToQuotaThreshold() );
3053 return closeToQuota;
3056 KMCommand* KMFolderCachedImap::rescueUnsyncedMessages()
3058 TQValueList<unsigned long> newMsgs = findNewMessages();
3059 kdDebug() << k_funcinfo << newMsgs <<
" of " << count() << endl;
3060 if ( newMsgs.isEmpty() )
3063 bool manualMove =
true;
3064 while ( GlobalSettings::autoLostFoundMove() ) {
3066 KMFolder *inboxFolder = kmkernel->findFolderById( TQString(
".%1.directory/INBOX").arg( account()->
id() ) );
3067 if ( !inboxFolder ) {
3068 kdWarning(5006) << k_funcinfo <<
"inbox not found!" << endl;
3072 if ( !inboxDir && !inboxFolder->storage() )
3074 assert( inboxFolder->storage()->
folderType() == KMFolderTypeCachedImap );
3079 if ( !(node = inboxDir->
hasNamedFolder( i18n(
"lost+found") )) ) {
3080 kdDebug(5006) << k_funcinfo <<
"creating lost+found folder" << endl;
3081 KMFolder* folder = kmkernel->dimapFolderMgr()->createFolder(
3082 i18n(
"lost+found"),
false, KMFolderTypeCachedImap, inboxDir );
3083 if ( !folder || !folder->storage() )
3085 static_cast<KMFolderCachedImap*
>( folder->storage() )->initializeFrom(
3086 static_cast<KMFolderCachedImap*
>( inboxFolder->storage() ) );
3091 kdDebug(5006) << k_funcinfo <<
"found lost+found folder" << endl;
3092 lfFolder =
dynamic_cast<KMFolder*
>( node );
3098 TQDate today = TQDate::currentDate();
3099 TQString baseName = folder()->
label() +
"-" + TQString::number( today.year() )
3100 + (today.month() < 10 ?
"0" :
"" ) + TQString::number( today.month() )
3101 + (today.day() < 10 ?
"0" :
"" ) + TQString::number( today.day() );
3102 TQString name = baseName;
3106 name = baseName +
'-' + TQString::number( suffix );
3108 kdDebug(5006) << k_funcinfo <<
"creating lost+found folder " << name << endl;
3109 dest = kmkernel->dimapFolderMgr()->createFolder( name,
false, KMFolderTypeCachedImap, lfFolder->
child() );
3110 if ( !dest || !dest->storage() )
3112 static_cast<KMFolderCachedImap*
>( dest->storage() )->initializeFrom(
3113 static_cast<KMFolderCachedImap*
>( lfFolder->storage() ) );
3117 KMessageBox::sorry( 0, i18n(
"<p>There are new messages in folder <b>%1</b>, which "
3118 "have not been uploaded to the server yet, but the folder has been deleted "
3119 "on the server or you do not "
3120 "have sufficient access rights on the folder to upload them.</p>"
3121 "<p>All affected messages will therefore be moved to <b>%2</b> "
3122 "to avoid data loss.</p>").arg( folder()->prettyURL() ).arg( dest->
prettyURL() ),
3123 i18n(
"Insufficient access rights") );
3129 const TQString msg ( i18n(
"<p>There are new messages in this folder (%1), which "
3130 "have not been uploaded to the server yet, but the folder has been deleted "
3131 "on the server or you do not "
3132 "have sufficient access rights on the folder now to upload them. "
3133 "Please contact your administrator to allow upload of new messages "
3134 "to you, or move them out of this folder.</p> "
3135 "<p>Do you want to move these messages to another folder now?</p>").arg( folder()->prettyURL() ) );
3136 if ( KMessageBox::warningYesNo( 0, msg, TQString(), i18n(
"Move"), i18n(
"Do Not Move") ) == KMessageBox::Yes ) {
3137 KMail::KMFolderSelDlg dlg( kmkernel->getKMMainWidget(),
3138 i18n(
"Move Messages to Folder"),
true );
3140 dest = dlg.folder();
3145 TQPtrList<KMMsgBase> msgs;
3146 for(
int i = 0; i < count(); ++i ) {
3147 KMMsgBase *msg = getMsgBase( i );
3148 if( !msg )
continue;
3149 if ( msg->UID() == 0 )
3152 KMCommand *command =
new KMMoveCommand( dest, msgs );
3159 void KMFolderCachedImap::rescueUnsyncedMessagesAndDeleteFolder(
KMFolder *folder,
bool root )
3161 kdDebug() << k_funcinfo << folder <<
" " << root << endl;
3163 mToBeDeletedAfterRescue.append( folder );
3164 folder->
open(
"cachedimap");
3165 KMFolderCachedImap* storage =
dynamic_cast<KMFolderCachedImap*
>( folder->storage() );
3167 KMCommand *command = storage->rescueUnsyncedMessages();
3169 connect( command, TQ_SIGNAL(completed(KMCommand*)),
3170 TQ_SLOT(slotRescueDone(KMCommand*)) );
3171 ++mRescueCommandCount;
3175 folder->
close(
"cachedimap");
3178 if ( folder->
child() ) {
3179 KMFolderNode *node = folder->
child()->first();
3181 if (!node->isDir() ) {
3183 rescueUnsyncedMessagesAndDeleteFolder( subFolder,
false );
3185 node = folder->
child()->next();
3190 void KMFolderCachedImap::slotRescueDone(KMCommand * command)
3194 --mRescueCommandCount;
3195 if ( mRescueCommandCount > 0 )
3197 for ( TQValueList<KMFolder*>::ConstIterator it = mToBeDeletedAfterRescue.constBegin();
3198 it != mToBeDeletedAfterRescue.constEnd(); ++it ) {
3199 kmkernel->dimapFolderMgr()->remove( *it );
3201 mToBeDeletedAfterRescue.clear();
3202 serverSyncInternal();
3205 void KMFolderCachedImap::slotRenameFolderFinished()
3210 open(
"cachedimap" );
3211 serverSyncInternal();
3214 bool KMFolderCachedImap::canDeleteMessages()
const
3223 bool KMFolderCachedImap::mailCheckInProgress()
const
3225 return mSyncState != SYNC_STATE_INITIAL;
3228 #include "kmfoldercachedimap.moc"
virtual void setContentsType(KMail::FolderContentsType type, bool quiet=false)
Set the type of contents held in this folder (mail, calendar, etc.)
virtual void readConfig()
Read the config file.
virtual void setStatus(int idx, KMMsgStatus status, bool toggle=false)
Set the status of the message at index idx to status.
virtual KMFolderType folderType() const
Returns the type of this folder.
virtual void remove()
Removes the folder physically from disk and empties the contents of the folder in memory.
virtual void writeConfig()
Write the config file.
virtual int addMsg(TQPtrList< KMMessage > &, TQValueList< int > &index_return)
Adds the given messages to the folder.
KMail list that manages the contents of one directory that may contain folders and/or other directori...
virtual KMFolder * createFolder(const TQString &folderName, bool sysFldr=false, KMFolderType folderType=KMFolderTypeMbox)
Create a mail folder in this directory with given name.
virtual KMFolderNode * hasNamedFolder(const TQString &name)
Returns folder with given name or zero if it does not exist.
TQString label() const
Returns the label of the folder for visualization.
RAII for KMFolder::open() / close().
TQString idString() const
Returns a string that can be used to identify this folder.
virtual TQString prettyURL() const
URL of the node for visualization purposes.
virtual TQString label() const
Returns the label of the folder for visualization.
KMFolderDir * child() const
Returns the folder directory associated with this node or 0 if no such directory exists.
void close(const char *owner, bool force=false)
Close folder.
KMFolderDir * createChildFolder()
Create a child folder directory and associates it with this folder.
void setNoContent(bool aNoContent)
Specify, that the folder can't contain mails.
int open(const char *owner)
Open folder for access.
ulong UID() const
Get/set UID.
The account manager is responsible for creating accounts of various types via the factory method crea...
for multiUrlGetAnnotation
Generic folder list job for (d)imap accounts.
void setHonorLocalSubscription(bool value)
Set whether the listing should include only folders that the account is subscribed to locally.
void setNamespace(const TQString &ns)
Set the namespace for this listing.
@ NotFetchedYet
The user rights/ACL have not been fetched from the server yet, we don't know them.
@ Ok
The user rights/ACL have been fetched from the server sucessfully.
@ FetchFailed
The attempt to fetch the user rights/ACL from the server failed.
MultiSetACLJob * multiSetACL(TDEIO::Slave *slave, const KURL &url, const ACLList &acl)
Set and delete a list of permissions for different users on a given url.
GetStorageQuotaJob * getStorageQuota(TDEIO::Slave *slave, const KURL &url)
Get the storage quota for a mailbox, if there is one.
One entry in the annotation list: attribute name and attribute value.
Information about a message to be downloaded (from the 'IMAP envelope')