// -*- mode: C++; c-file-style: "gnu" -*- // kmfiltermgr.cpp // my header #ifdef HAVE_CONFIG_H #include #endif #include "kmfiltermgr.h" // other kmail headers #include "filterlog.h" using KMail::FilterLog; #include "kmfilterdlg.h" #include "kmfolderindex.h" #include "filterimporterexporter.h" using KMail::FilterImporterExporter; #include "kmfoldermgr.h" #include "kmmsgdict.h" #include "messageproperty.h" using KMail::MessageProperty; // other KDE headers #include #include #include // other TQt headers #include #include // other headers #include //----------------------------------------------------------------------------- KMFilterMgr::KMFilterMgr( bool popFilter ) : mEditDialog( 0 ), bPopFilter( popFilter ), mShowLater( false ), mDirtyBufferedFolderTarget( true ), mBufferedFolderTarget( true ), mRefCount( 0 ) { connect( kmkernel, TQT_SIGNAL( folderRemoved( KMFolder* ) ), this, TQT_SLOT( slotFolderRemoved( KMFolder* ) ) ); } //----------------------------------------------------------------------------- KMFilterMgr::~KMFilterMgr() { deref( true ); writeConfig( false ); clear(); } void KMFilterMgr::clear() { mDirtyBufferedFolderTarget = true; for ( TQValueListIterator it = mFilters.begin() ; it != mFilters.end() ; ++it ) { delete *it; } } //----------------------------------------------------------------------------- void KMFilterMgr::readConfig(void) { TDEConfig* config = KMKernel::config(); clear(); if (bPopFilter) { TDEConfigGroupSaver saver(config, "General"); mShowLater = config->readNumEntry("popshowDLmsgs",0); } mFilters = FilterImporterExporter::readFiltersFromConfig( config, bPopFilter ); } //----------------------------------------------------------------------------- void KMFilterMgr::writeConfig(bool withSync) { TDEConfig* config = KMKernel::config(); // Now, write out the new stuff: FilterImporterExporter::writeFiltersToConfig( mFilters, config, bPopFilter ); TDEConfigGroupSaver saver(config, "General"); if (bPopFilter) config->writeEntry("popshowDLmsgs", mShowLater); if (withSync) config->sync(); } int KMFilterMgr::processPop( KMMessage * msg ) const { for ( TQValueListConstIterator it = mFilters.constBegin(); it != mFilters.constEnd() ; ++it ) if ( (*it)->pattern()->matches( msg ) ) return (*it)->action(); return NoAction; } bool KMFilterMgr::beginFiltering(KMMsgBase *msgBase) const { if (MessageProperty::filtering( msgBase )) return false; MessageProperty::setFiltering( msgBase, true ); MessageProperty::setFilterFolder( msgBase, 0 ); if ( FilterLog::instance()->isLogging() ) { FilterLog::instance()->addSeparator(); } return true; } int KMFilterMgr::moveMessage(KMMessage *msg) const { if (MessageProperty::filterFolder(msg)->moveMsg( msg ) == 0) { if ( kmkernel->folderIsTrash( MessageProperty::filterFolder( msg ))) KMFilterAction::sendMDN( msg, KMime::MDN::Deleted ); } else { kdDebug(5006) << "KMfilterAction - couldn't move msg" << endl; return 2; } return 0; } void KMFilterMgr::endFiltering(KMMsgBase *msgBase) const { KMFolder *parent = msgBase->parent(); if ( parent ) { if ( parent == MessageProperty::filterFolder( msgBase ) ) { parent->take( parent->find( msgBase ) ); } else if ( ! MessageProperty::filterFolder( msgBase ) ) { int index = parent->find( msgBase ); KMMessage *msg = parent->getMsg( index ); parent->take( index ); parent->addMsgKeepUID( msg ); } } MessageProperty::setFiltering( msgBase, false ); } int KMFilterMgr::process( KMMessage * msg, const KMFilter * filter ) { if ( !msg || !filter || !beginFiltering( msg )) return 1; bool stopIt = false; int result = 1; if ( FilterLog::instance()->isLogging() ) { TQString logText( i18n( "Evaluating filter rules: " ) ); logText.append( filter->pattern()->asString() ); FilterLog::instance()->add( logText, FilterLog::patternDesc ); } if (filter->pattern()->matches( msg )) { if ( FilterLog::instance()->isLogging() ) { FilterLog::instance()->add( i18n( "Filter rules have matched." ), FilterLog::patternResult ); } if (filter->execActions( msg, stopIt ) == KMFilter::CriticalError) return 2; KMFolder *folder = MessageProperty::filterFolder( msg ); endFiltering( msg ); if (folder) { tempOpenFolder( folder ); result = folder->moveMsg( msg ); } } else { endFiltering( msg ); result = 1; } return result; } int KMFilterMgr::process( TQ_UINT32 serNum, const KMFilter *filter ) { bool stopIt = false; int result = 1; if ( !filter ) return 1; if ( isMatching( serNum, filter ) ) { KMFolder *folder = 0; int idx = -1; // get the message with the serNum KMMsgDict::instance()->getLocation( serNum, &folder, &idx ); if ( !folder || ( idx == -1 ) || ( idx >= folder->count() ) ) { return 1; } KMFolderOpener openFolder(folder, "filtermgr"); KMMsgBase *msgBase = folder->getMsgBase( idx ); bool unGet = !msgBase->isMessage(); KMMessage *msg = folder->getMsg( idx ); // do the actual filtering stuff if ( !msg || !beginFiltering( msg ) ) { if ( unGet ) folder->unGetMsg( idx ); return 1; } if ( filter->execActions( msg, stopIt ) == KMFilter::CriticalError ) { if ( unGet ) folder->unGetMsg( idx ); return 2; } KMFolder *targetFolder = MessageProperty::filterFolder( msg ); endFiltering( msg ); if ( targetFolder ) { tempOpenFolder( targetFolder ); msg->setTransferInProgress( false ); result = targetFolder->moveMsg( msg ); msg->setTransferInProgress( true ); } if ( unGet ) folder->unGetMsg( idx ); } else { result = 1; } return result; } int KMFilterMgr::process( KMMessage * msg, FilterSet set, bool account, uint accountId ) { if ( bPopFilter ) return processPop( msg ); if ( set == NoSet ) { kdDebug(5006) << "KMFilterMgr: process() called with not filter set selected" << endl; return 1; } bool stopIt = false; bool atLeastOneRuleMatched = false; if (!beginFiltering( msg )) return 1; for ( TQValueListConstIterator it = mFilters.constBegin(); !stopIt && it != mFilters.constEnd() ; ++it ) { if ( ( ( (set&Inbound) && (*it)->applyOnInbound() ) && ( !account || ( account && (*it)->applyOnAccount( accountId ) ) ) ) || ( (set&Outbound) && (*it)->applyOnOutbound() ) || ( (set&Explicit) && (*it)->applyOnExplicit() ) ) { // filter is applicable if ( FilterLog::instance()->isLogging() ) { TQString logText( i18n( "Evaluating filter rules: " ) ); logText.append( (*it)->pattern()->asString() ); FilterLog::instance()->add( logText, FilterLog::patternDesc ); } if ( (*it)->pattern()->matches( msg ) ) { // filter matches if ( FilterLog::instance()->isLogging() ) { FilterLog::instance()->add( i18n( "Filter rules have matched." ), FilterLog::patternResult ); } atLeastOneRuleMatched = true; // execute actions: if ( (*it)->execActions(msg, stopIt) == KMFilter::CriticalError ) return 2; } } } KMFolder *folder = MessageProperty::filterFolder( msg ); /* endFilter does a take() and addButKeepUID() to ensure the changed * message is on disk. This is unnessecary if nothing matched, so just * reset state and don't update the listview at all. */ if ( atLeastOneRuleMatched ) endFiltering( msg ); else MessageProperty::setFiltering( msg, false ); if (folder) { tempOpenFolder( folder ); folder->moveMsg(msg); return 0; } return 1; } bool KMFilterMgr::isMatching( TQ_UINT32 serNum, const KMFilter *filter ) { bool result = false; if ( FilterLog::instance()->isLogging() ) { TQString logText( i18n( "Evaluating filter rules: " ) ); logText.append( filter->pattern()->asString() ); FilterLog::instance()->add( logText, FilterLog::patternDesc ); } if ( filter->pattern()->matches( serNum ) ) { if ( FilterLog::instance()->isLogging() ) { FilterLog::instance()->add( i18n( "Filter rules have matched." ), FilterLog::patternResult ); } result = true; } return result; } bool KMFilterMgr::atLeastOneFilterAppliesTo( unsigned int accountID ) const { TQValueListConstIterator it = mFilters.constBegin(); for ( ; it != mFilters.constEnd() ; ++it ) { if ( (*it)->applyOnAccount( accountID ) ) { return true; } } return false; } bool KMFilterMgr::atLeastOneIncomingFilterAppliesTo( unsigned int accountID ) const { TQValueListConstIterator it = mFilters.constBegin(); for ( ; it != mFilters.constEnd() ; ++it ) { if ( (*it)->applyOnInbound() && (*it)->applyOnAccount( accountID ) ) { return true; } } return false; } bool KMFilterMgr::atLeastOneOnlineImapFolderTarget() { if (!mDirtyBufferedFolderTarget) return mBufferedFolderTarget; mDirtyBufferedFolderTarget = false; TQValueListConstIterator it = mFilters.constBegin(); for ( ; it != mFilters.constEnd() ; ++it ) { KMFilter *filter = *it; TQPtrListIterator jt( *filter->actions() ); for ( jt.toFirst() ; jt.current() ; ++jt ) { KMFilterActionWithFolder *f = dynamic_cast(*jt); if (!f) continue; TQString name = f->argsAsString(); KMFolder *folder = kmkernel->imapFolderMgr()->findIdString( name ); if (folder) { mBufferedFolderTarget = true; return true; } } } mBufferedFolderTarget = false; return false; } //----------------------------------------------------------------------------- void KMFilterMgr::ref(void) { mRefCount++; } //----------------------------------------------------------------------------- void KMFilterMgr::deref(bool force) { if (!force) mRefCount--; if (mRefCount < 0) mRefCount = 0; if (mRefCount && !force) return; TQValueVector< KMFolder *>::const_iterator it; for ( it = mOpenFolders.constBegin(); it != mOpenFolders.constEnd(); ++it ) (*it)->close("filtermgr"); mOpenFolders.clear(); } //----------------------------------------------------------------------------- int KMFilterMgr::tempOpenFolder(KMFolder* aFolder) { assert( aFolder ); int rc = aFolder->open("filermgr"); if (rc) return rc; mOpenFolders.append( aFolder ); return 0; } //----------------------------------------------------------------------------- void KMFilterMgr::openDialog( TQWidget *, bool checkForEmptyFilterList ) { if( !mEditDialog ) { // // We can't use the parent as long as the dialog is modeless // and there is one shared dialog for all top level windows. // mEditDialog = new KMFilterDlg( 0, "filterdialog", bPopFilter, checkForEmptyFilterList ); } mEditDialog->show(); } //----------------------------------------------------------------------------- void KMFilterMgr::createFilter( const TQCString & field, const TQString & value ) { openDialog( 0, false ); mEditDialog->createFilter( field, value ); } //----------------------------------------------------------------------------- const TQString KMFilterMgr::createUniqueName( const TQString & name ) { TQString uniqueName = name; int counter = 0; bool found = true; while ( found ) { found = false; for ( TQValueListConstIterator it = mFilters.constBegin(); it != mFilters.constEnd(); ++it ) { if ( !( (*it)->name().compare( uniqueName ) ) ) { found = true; ++counter; uniqueName = name; uniqueName += TQString( " (" ) + TQString::number( counter ) + TQString( ")" ); break; } } } return uniqueName; } //----------------------------------------------------------------------------- void KMFilterMgr::appendFilters( const TQValueList &filters, bool replaceIfNameExists ) { mDirtyBufferedFolderTarget = true; beginUpdate(); if ( replaceIfNameExists ) { TQValueListConstIterator it1 = filters.constBegin(); for ( ; it1 != filters.constEnd() ; ++it1 ) { TQValueListConstIterator it2 = mFilters.constBegin(); for ( ; it2 != mFilters.constEnd() ; ++it2 ) { if ( (*it1)->name() == (*it2)->name() ) { mFilters.remove( (*it2) ); it2 = mFilters.constBegin(); } } } } mFilters += filters; writeConfig( true ); endUpdate(); } void KMFilterMgr::setFilters( const TQValueList &filters ) { beginUpdate(); clear(); mFilters = filters; writeConfig( true ); endUpdate(); } void KMFilterMgr::slotFolderRemoved( KMFolder * aFolder ) { folderRemoved( aFolder, 0 ); } //----------------------------------------------------------------------------- bool KMFilterMgr::folderRemoved(KMFolder* aFolder, KMFolder* aNewFolder) { mDirtyBufferedFolderTarget = true; bool rem = false; TQValueListConstIterator it = mFilters.constBegin(); for ( ; it != mFilters.constEnd() ; ++it ) if ( (*it)->folderRemoved(aFolder, aNewFolder) ) rem = true; return rem; } //----------------------------------------------------------------------------- #ifndef NDEBUG void KMFilterMgr::dump(void) const { TQValueListConstIterator it = mFilters.constBegin(); for ( ; it != mFilters.constEnd() ; ++it ) { kdDebug(5006) << (*it)->asString() << endl; } } #endif //----------------------------------------------------------------------------- void KMFilterMgr::endUpdate(void) { emit filterListUpdated(); } #include "kmfiltermgr.moc"