Fix multiple retrieval race.
[kdepim.git] / mailcommon / filteraction.cpp
blob18a7d6b6d54142a04345e58daa6a8996971d6ab7
1 // kmfilteraction.cpp
2 #include "filteractionwidget.h"
3 #include "filteraction.h"
5 #include "filtermanager.h"
6 #include "folderrequester.h"
7 #include "mailutil.h"
8 #include "mailkernel.h"
9 #include "mdnadvicedialog.h"
10 #include "messageproperty.h"
11 #include "minimumcombobox.h"
12 #include "regexplineedit.h"
14 #ifndef _WIN32_WCE
15 #include "soundtestwidget.h"
16 #endif
18 #include <akonadi/collectioncombobox.h>
19 #include <akonadi/itemcopyjob.h>
20 #include <akonadi/itemmodifyjob.h>
21 #include <akonadi/kmime/messagestatus.h>
22 #include <kabc/addressee.h>
23 #include <kdebug.h>
24 #include <klocale.h>
25 #include <kmime/kmime_message.h>
26 #include <kpimidentities/identity.h>
27 #include <kpimidentities/identitycombo.h>
28 #include <kpimidentities/identitymanager.h>
29 #include <kpimutils/kfileio.h>
30 #include <kpimutils/email.h>
31 #include <kprocess.h>
32 #include <kshell.h>
33 #include <ktemporaryfile.h>
34 #include <kurlrequester.h>
35 #include <libkdepim/addcontactjob.h>
36 #include <messagecore/emailaddressrequester.h>
37 #include <messagecore/mdnstateattribute.h>
38 #include <messagecore/messagehelpers.h>
39 #include <messagecore/stringutil.h>
40 #include <messagecomposer/messagefactory.h>
41 #include <messagecomposer/messagesender.h>
42 #include <messageviewer/globalsettings.h>
44 #ifndef KDEPIM_NO_NEPOMUK
45 #include <nepomuk/tag.h>
46 #endif
47 #include <phonon/mediaobject.h>
48 #include <templateparser/customtemplates_kfg.h>
49 #include <templateparser/customtemplates.h>
51 #include <QtGui/QHBoxLayout>
52 #include <QtGui/QLabel>
53 #include <QtGui/QTextDocument>
55 #include <assert.h>
56 #include <string.h>
58 using MailCommon::MessageProperty;
59 using MailCommon::RegExpLineEdit;
60 using MessageComposer::MessageFactory;
62 using namespace MailCommon;
64 FilterAction::FilterAction( const char *name, const QString &label, QObject *parent )
65 : QObject( parent ), mName( name ), mLabel( label )
69 FilterAction::~FilterAction()
73 QString FilterAction::label() const
75 return mLabel;
78 QString FilterAction::name() const
80 return mName;
83 bool FilterAction::requiresBody() const
85 return true;
88 bool FilterAction::isEmpty() const
90 return false;
93 FilterAction* FilterAction::newAction()
95 return 0;
98 QWidget* FilterAction::createParamWidget( QWidget *parent ) const
100 return new QWidget( parent );
103 void FilterAction::applyParamWidgetValue( QWidget* )
107 void FilterAction::setParamWidgetValue( QWidget* ) const
111 void FilterAction::clearParamWidget( QWidget* ) const
115 bool FilterAction::folderRemoved( const Akonadi::Collection&, const Akonadi::Collection& )
117 return false;
120 void FilterAction::sendMDN( const Akonadi::Item &item, KMime::MDN::DispositionType type,
121 const QList<KMime::MDN::DispositionModifier> &modifiers )
123 const KMime::Message::Ptr msg = MessageCore::Util::message( item );
124 if ( !msg )
125 return;
127 const QPair<bool, KMime::MDN::SendingMode> mdnSend = MDNAdviceHelper::instance()->checkAndSetMDNInfo( item, type, true );
128 if ( mdnSend.first ) {
129 const int quote = MessageViewer::GlobalSettings::self()->quoteMessage();
130 MessageFactory factory( msg, Akonadi::Item().id() );
131 factory.setIdentityManager( KernelIf->identityManager() );
133 const KMime::Message::Ptr mdn = factory.createMDN( KMime::MDN::AutomaticAction, type, mdnSend.second, quote, modifiers );
134 if ( mdn ) {
135 if ( !KernelIf->msgSender()->send( mdn, MessageSender::SendLater ) ) {
136 kDebug() << "Sending failed.";
142 //=============================================================================
144 // FilterActionWithNone
146 //=============================================================================
148 FilterActionWithNone::FilterActionWithNone( const char *name, const QString &label, QObject *parent )
149 : FilterAction( name, label, parent )
153 QString FilterActionWithNone::displayString() const
155 return label();
158 void FilterActionWithNone::argsFromString( const QString& )
162 QString FilterActionWithNone::argsAsString() const
164 return QString();
167 //=============================================================================
169 // FilterActionWithUOID
171 //=============================================================================
173 FilterActionWithUOID::FilterActionWithUOID( const char *name, const QString &label, QObject *parent )
174 : FilterAction( name, label, parent ), mParameter( 0 )
178 bool FilterActionWithUOID::isEmpty() const
180 return (mParameter == 0);
183 void FilterActionWithUOID::argsFromString( const QString &argsStr )
185 mParameter = argsStr.trimmed().toUInt();
188 QString FilterActionWithUOID::argsAsString() const
190 return QString::number( mParameter );
193 QString FilterActionWithUOID::displayString() const
195 return label() + QLatin1String( " \"" ) + Qt::escape( argsAsString() ) + QLatin1String( "\"" );
199 //=============================================================================
201 // FilterActionWithString
203 //=============================================================================
205 FilterActionWithString::FilterActionWithString( const char *name, const QString &label, QObject *parent )
206 : FilterAction( name, label, parent )
210 bool FilterActionWithString::isEmpty() const
212 return mParameter.trimmed().isEmpty();
215 QWidget* FilterActionWithString::createParamWidget( QWidget *parent ) const
217 KLineEdit *lineEdit = new KLineEdit( parent );
218 lineEdit->setClearButtonShown( true );
219 lineEdit->setText( mParameter );
221 connect( lineEdit, SIGNAL(textChanged(QString)), this, SIGNAL(filterActionModified()) );
223 return lineEdit;
226 void FilterActionWithString::applyParamWidgetValue( QWidget *paramWidget )
228 mParameter = static_cast<KLineEdit*>( paramWidget )->text();
231 void FilterActionWithString::setParamWidgetValue( QWidget *paramWidget ) const
233 static_cast<KLineEdit*>( paramWidget )->setText( mParameter );
236 void FilterActionWithString::clearParamWidget( QWidget *paramWidget ) const
238 static_cast<KLineEdit*>( paramWidget )->clear();
241 void FilterActionWithString::argsFromString( const QString &argsStr )
243 mParameter = argsStr;
246 QString FilterActionWithString::argsAsString() const
248 return mParameter;
251 QString FilterActionWithString::displayString() const
253 return label() + QLatin1String( " \"" ) + Qt::escape( argsAsString() ) + QLatin1String( "\"" );
256 //=============================================================================
258 // class FilterActionWithStringList
260 //=============================================================================
262 FilterActionWithStringList::FilterActionWithStringList( const char *name, const QString &label, QObject *parent )
263 : FilterActionWithString( name, label, parent )
267 QWidget* FilterActionWithStringList::createParamWidget( QWidget *parent ) const
269 MinimumComboBox *comboBox = new MinimumComboBox( parent );
270 comboBox->setEditable( false );
271 comboBox->addItems( mParameterList );
272 setParamWidgetValue( comboBox );
274 connect( comboBox, SIGNAL(currentIndexChanged(int)),
275 this, SIGNAL(filterActionModified()) );
277 return comboBox;
280 void FilterActionWithStringList::applyParamWidgetValue( QWidget *paramWidget )
282 mParameter = static_cast<MinimumComboBox*>( paramWidget )->currentText();
285 void FilterActionWithStringList::setParamWidgetValue( QWidget *paramWidget ) const
287 const int index = mParameterList.indexOf( mParameter );
288 static_cast<MinimumComboBox*>( paramWidget )->setCurrentIndex( index >= 0 ? index : 0 );
291 void FilterActionWithStringList::clearParamWidget( QWidget *paramWidget ) const
293 static_cast<MinimumComboBox*>( paramWidget )->setCurrentIndex( 0 );
296 void FilterActionWithStringList::argsFromString( const QString &argsStr )
298 int index = mParameterList.indexOf( argsStr );
299 if ( index < 0 ) {
300 mParameterList.append( argsStr );
301 index = mParameterList.count() - 1;
304 mParameter = mParameterList.at( index );
308 //=============================================================================
310 // class FilterActionWithFolder
312 //=============================================================================
314 FilterActionWithFolder::FilterActionWithFolder( const char *name, const QString &label, QObject *parent )
315 : FilterAction( name, label, parent )
319 bool FilterActionWithFolder::isEmpty() const
321 return (!mFolder.isValid() && mFolderName.isEmpty());
324 QWidget* FilterActionWithFolder::createParamWidget( QWidget *parent ) const
326 FolderRequester *requester = new FolderRequester( parent );
327 requester->setShowOutbox( false );
328 setParamWidgetValue( requester );
330 connect( requester, SIGNAL(folderChanged(Akonadi::Collection)),
331 this, SIGNAL(filterActionModified()) );
333 return requester;
336 void FilterActionWithFolder::applyParamWidgetValue( QWidget *paramWidget )
338 mFolder = static_cast<FolderRequester*>( paramWidget )->folderCollection();
339 mFolderName = static_cast<FolderRequester*>( paramWidget )->folderId();
342 void FilterActionWithFolder::setParamWidgetValue( QWidget *paramWidget ) const
344 if ( mFolder.isValid() )
345 static_cast<FolderRequester*>( paramWidget )->setFolder( mFolder );
346 else
347 static_cast<FolderRequester*>( paramWidget )->setFolder( mFolderName );
350 void FilterActionWithFolder::clearParamWidget( QWidget *paramWidget ) const
352 static_cast<FolderRequester*>( paramWidget )->setFolder( CommonKernel->draftsCollectionFolder() );
355 void FilterActionWithFolder::argsFromString( const QString &argsStr )
357 bool ok = false;
358 const Akonadi::Collection::Id id = argsStr.toLongLong( &ok );
359 if ( ok ) {
360 mFolder = Akonadi::Collection( id );
361 mFolderName= QString::number( mFolder.id() );
362 } else {
363 mFolderName = argsStr;
367 QString FilterActionWithFolder::argsAsString() const
369 QString result;
370 if ( mFolder.isValid() )
371 result = QString::number( mFolder.id() );
372 else
373 result = mFolderName;
375 return result;
378 QString FilterActionWithFolder::displayString() const
380 QString result;
381 if ( mFolder.isValid() )
382 result = mFolder.url().path();
383 else
384 result = mFolderName;
386 return label() + QLatin1String( " \"" ) + Qt::escape( result ) + QLatin1String( "\"" );
389 bool FilterActionWithFolder::folderRemoved( const Akonadi::Collection &oldFolder, const Akonadi::Collection &newFolder )
391 if ( oldFolder == mFolder ) {
392 mFolder = newFolder;
393 if ( newFolder.isValid() )
394 mFolderName = mFolder.id();
395 return true;
396 } else
397 return false;
400 //=============================================================================
402 // class FilterActionWithAddress
404 //=============================================================================
406 FilterActionWithAddress::FilterActionWithAddress( const char *name, const QString &label, QObject *parent )
407 : FilterActionWithString( name, label, parent )
411 QWidget* FilterActionWithAddress::createParamWidget( QWidget *parent ) const
413 MessageCore::EmailAddressRequester *requester = new MessageCore::EmailAddressRequester( parent );
414 requester->setText( mParameter );
416 connect( requester, SIGNAL(textChanged()), this, SIGNAL(filterActionModified()) );
418 return requester;
421 void FilterActionWithAddress::applyParamWidgetValue( QWidget *paramWidget )
423 mParameter = qobject_cast<MessageCore::EmailAddressRequester*>( paramWidget )->text();
426 void FilterActionWithAddress::setParamWidgetValue( QWidget *paramWidget ) const
428 qobject_cast<MessageCore::EmailAddressRequester*>( paramWidget )->setText( mParameter );
431 void FilterActionWithAddress::clearParamWidget( QWidget *paramWidget ) const
433 qobject_cast<MessageCore::EmailAddressRequester*>( paramWidget )->clear();
436 //=============================================================================
438 // class FilterActionWithCommand
440 //=============================================================================
442 FilterActionWithCommand::FilterActionWithCommand( const char *name, const QString &label, QObject *parent )
443 : FilterActionWithUrl( name, label, parent )
447 QWidget* FilterActionWithCommand::createParamWidget( QWidget *parent ) const
449 return FilterActionWithUrl::createParamWidget( parent );
452 void FilterActionWithCommand::applyParamWidgetValue( QWidget *paramWidget )
454 FilterActionWithUrl::applyParamWidgetValue( paramWidget );
457 void FilterActionWithCommand::setParamWidgetValue( QWidget *paramWidget ) const
459 FilterActionWithUrl::setParamWidgetValue( paramWidget );
462 void FilterActionWithCommand::clearParamWidget( QWidget *paramWidget ) const
464 FilterActionWithUrl::clearParamWidget( paramWidget );
467 static KMime::Content* findMimeNodeForIndex( KMime::Content* node, int &index )
469 if ( index <= 0 )
470 return node;
472 foreach ( KMime::Content* child, node->contents() ) {
473 KMime::Content *result = findMimeNodeForIndex( child, --index );
474 if ( result )
475 return result;
478 return 0;
481 QString FilterActionWithCommand::substituteCommandLineArgsFor( const KMime::Message::Ptr &aMsg, QList<KTemporaryFile*> &aTempFileList ) const
483 QString result = mParameter;
484 QList<int> argList;
485 QRegExp r( "%[0-9-]+" );
487 // search for '%n'
488 int start = -1;
489 while ( ( start = r.indexIn( result, start + 1 ) ) > 0 ) {
490 const int len = r.matchedLength();
492 // and save the encountered 'n' in a list.
493 bool ok = false;
494 const int n = result.mid( start + 1, len - 1 ).toInt( &ok );
495 if ( ok )
496 argList.append( n );
499 // sort the list of n's
500 qSort( argList );
502 // and use QString::arg to substitute filenames for the %n's.
503 int lastSeen = -2;
504 QString tempFileName;
505 for ( QList<int>::Iterator it = argList.begin() ; it != argList.end() ; ++it ) {
506 // setup temp files with check for duplicate %n's
507 if ( (*it) != lastSeen ) {
508 KTemporaryFile *tempFile = new KTemporaryFile();
509 if ( !tempFile->open() ) {
510 delete tempFile;
511 kDebug() << "FilterActionWithCommand: Could not create temp file!";
512 return QString();
515 aTempFileList.append( tempFile );
516 tempFileName = tempFile->fileName();
518 if ( (*it) == -1 )
519 KPIMUtils::kByteArrayToFile( aMsg->encodedContent(), tempFileName, //###
520 false, false, false );
521 else if (aMsg->contents().size() == 0)
522 KPIMUtils::kByteArrayToFile( aMsg->decodedContent(), tempFileName,
523 false, false, false );
524 else {
525 int index = *it; // we pass by reference below, so this is not const
526 KMime::Content *content = findMimeNodeForIndex( aMsg.get(), index );
527 if ( content ) {
528 KPIMUtils::kByteArrayToFile( content->decodedContent(), tempFileName,
529 false, false, false );
532 tempFile->close();
535 // QString( "%0 and %1 and %1" ).arg( 0 ).arg( 1 )
536 // returns "0 and 1 and %1", so we must call .arg as
537 // many times as there are %n's, regardless of their multiplicity.
538 if ( (*it) == -1 )
539 result.replace( "%-1", tempFileName );
540 else
541 result = result.arg( tempFileName );
544 return result;
547 namespace {
550 * Substitutes placeholders in the command line with the
551 * content of the correspoding header in the message.
552 * %{From} -> Joe Author <joe@acme.com>
554 void substituteMessageHeaders( const KMime::Message::Ptr &aMsg, QString &result )
556 // Replace the %{foo} with the content of the foo header field.
557 // If the header doesn't exist, remove the placeholder.
558 QRegExp header_rx( "%\\{([a-z0-9-]+)\\}", Qt::CaseInsensitive );
559 int idx = 0;
560 while ( ( idx = header_rx.indexIn( result, idx ) ) != -1 ) {
561 const KMime::Headers::Base* header = aMsg->headerByType( header_rx.cap(1).toLatin1() );
562 QString replacement;
563 if ( header )
564 replacement = KShell::quoteArg( header->as7BitString() );
565 result.replace( idx, header_rx.matchedLength(), replacement );
566 idx += replacement.length();
571 * Substitutes placeholders in the command line with the
572 * corresponding information from the item. Currently supported
573 * are %{itemid} and %{itemurl}.
575 void substituteCommandLineArgsForItem( const Akonadi::Item &item, QString &commandLine )
577 commandLine.replace( QLatin1String( "%{itemurl}" ), item.url( Akonadi::Item::UrlWithMimeType ).url() );
578 commandLine.replace( QLatin1String( "%{itemid}" ), QString::number( item.id() ) );
583 FilterAction::ReturnCode FilterActionWithCommand::genericProcess( const Akonadi::Item &item, bool withOutput ) const
585 const KMime::Message::Ptr aMsg = item.payload<KMime::Message::Ptr>();
586 Q_ASSERT( aMsg );
588 if ( mParameter.isEmpty() )
589 return ErrorButGoOn;
591 // KProcess doesn't support a QProcess::launch() equivalent, so
592 // we must use a temp file :-(
593 KTemporaryFile * inFile = new KTemporaryFile;
594 if ( !inFile->open() )
595 return ErrorButGoOn;
597 QList<KTemporaryFile*> atmList;
598 atmList.append( inFile );
600 QString commandLine = substituteCommandLineArgsFor( aMsg, atmList );
601 substituteCommandLineArgsForItem( item, commandLine );
602 substituteMessageHeaders( aMsg, commandLine );
604 if ( commandLine.isEmpty() ) {
605 qDeleteAll( atmList );
606 atmList.clear();
607 return ErrorButGoOn;
609 // The parentheses force the creation of a subshell
610 // in which the user-specified command is executed.
611 // This is to really catch all output of the command as well
612 // as to avoid clashes of our redirection with the ones
613 // the user may have specified. In the long run, we
614 // shouldn't be using tempfiles at all for this class, due
615 // to security aspects. (mmutz)
616 commandLine = QLatin1Char( '(' ) + commandLine + QLatin1String( ") <" ) + inFile->fileName();
618 // write message to file
619 QString tempFileName = inFile->fileName();
620 if ( !KPIMUtils::kByteArrayToFile( aMsg->encodedContent(), tempFileName, //###
621 false, false, false ) ) {
622 qDeleteAll( atmList );
623 atmList.clear();
624 return CriticalError;
627 inFile->close();
629 KProcess shProc;
630 shProc.setOutputChannelMode( KProcess::SeparateChannels );
631 shProc.setShellCommand( commandLine );
632 int result = shProc.execute();
634 if ( result != 0 ) {
635 qDeleteAll( atmList );
636 atmList.clear();
637 return ErrorButGoOn;
640 if ( withOutput ) {
641 // read altered message:
642 const QByteArray msgText = shProc.readAllStandardOutput();
644 if ( !msgText.isEmpty() ) {
645 /* If the pipe through alters the message, it could very well
646 happen that it no longer has a X-UID header afterwards. That is
647 unfortunate, as we need to removed the original from the folder
648 using that, and look it up in the message. When the (new) message
649 is uploaded, the header is stripped anyhow. */
650 const QString uid = aMsg->headerByType( "X-UID" ) ? aMsg->headerByType( "X-UID" )->asUnicodeString() : "";
651 aMsg->setContent( msgText );
653 KMime::Headers::Generic *header = new KMime::Headers::Generic( "X-UID", aMsg.get(), uid, "utf-8" );
654 aMsg->setHeader( header );
656 new Akonadi::ItemModifyJob( item, FilterIf->filterManager() ); //TODO: check for errors
657 } else {
658 qDeleteAll( atmList );
659 atmList.clear();
660 return ErrorButGoOn;
664 qDeleteAll( atmList );
665 atmList.clear();
667 return GoOn;
671 //=============================================================================
673 // Specific Filter Actions
675 //=============================================================================
677 //=============================================================================
678 // FilterActionSendReceipt - send receipt
679 // Return delivery receipt.
680 //=============================================================================
681 class FilterActionSendReceipt : public FilterActionWithNone
683 public:
684 FilterActionSendReceipt( QObject *parent = 0 );
685 virtual ReturnCode process( const Akonadi::Item &item ) const;
686 static FilterAction* newAction();
689 FilterAction* FilterActionSendReceipt::newAction()
691 return new FilterActionSendReceipt;
694 FilterActionSendReceipt::FilterActionSendReceipt( QObject *parent )
695 : FilterActionWithNone( "confirm delivery", i18n( "Confirm Delivery" ), parent )
699 FilterAction::ReturnCode FilterActionSendReceipt::process( const Akonadi::Item &item ) const
701 const KMime::Message::Ptr msg = item.payload<KMime::Message::Ptr>();
703 MessageFactory factory( msg, item.id() );
704 factory.setFolderIdentity( Util::folderIdentity( item ) );
705 factory.setIdentityManager( KernelIf->identityManager() );
707 const KMime::Message::Ptr receipt = factory.createDeliveryReceipt();
708 if ( !receipt )
709 return ErrorButGoOn;
711 // Queue message. This is a) so that the user can check
712 // the receipt before sending and b) for speed reasons.
713 KernelIf->msgSender()->send( receipt, MessageSender::SendLater );
715 return GoOn;
719 //=============================================================================
720 // FilterActionSetTransport - set transport to...
721 // Specify mail transport (smtp server) to be used when replying to a message
722 // TODO: use TransportComboBox so the user does not enter an invalid transport
723 //=============================================================================
724 class FilterActionTransport: public FilterActionWithString
726 public:
727 FilterActionTransport( QObject *parent = 0 );
728 virtual ReturnCode process( const Akonadi::Item &item ) const;
729 static FilterAction* newAction();
732 FilterAction* FilterActionTransport::newAction()
734 return new FilterActionTransport;
737 FilterActionTransport::FilterActionTransport( QObject *parent )
738 : FilterActionWithString( "set transport", i18n( "Set Transport To" ), parent )
742 FilterAction::ReturnCode FilterActionTransport::process( const Akonadi::Item &item ) const
744 if ( mParameter.isEmpty() )
745 return ErrorButGoOn;
747 const KMime::Message::Ptr msg = item.payload<KMime::Message::Ptr>();
748 KMime::Headers::Generic *header = new KMime::Headers::Generic( "X-KMail-Transport", msg.get(), mParameter, "utf-8" );
749 msg->setHeader( header );
750 msg->assemble();
752 new Akonadi::ItemModifyJob( item, FilterIf->filterManager() );
754 return GoOn;
758 //=============================================================================
759 // FilterActionReplyTo - set Reply-To to
760 // Set the Reply-to header in a message
761 //=============================================================================
762 class FilterActionReplyTo: public FilterActionWithString
764 public:
765 FilterActionReplyTo( QObject *parent = 0 );
766 virtual ReturnCode process( const Akonadi::Item &item ) const;
767 static FilterAction* newAction();
770 FilterAction* FilterActionReplyTo::newAction()
772 return new FilterActionReplyTo;
775 FilterActionReplyTo::FilterActionReplyTo( QObject *parent )
776 : FilterActionWithString( "set Reply-To", i18n( "Set Reply-To To" ), parent )
778 mParameter = "";
781 FilterAction::ReturnCode FilterActionReplyTo::process( const Akonadi::Item &item ) const
783 const KMime::Message::Ptr msg = item.payload<KMime::Message::Ptr>();
784 KMime::Headers::Generic *header = new KMime::Headers::Generic( "Reply-To", msg.get(), mParameter, "utf-8" );
785 msg->setHeader( header );
786 msg->assemble();
788 new Akonadi::ItemModifyJob( item, FilterIf->filterManager() );
790 return GoOn;
794 //=============================================================================
795 // FilterActionIdentity - set identity to
796 // Specify Identity to be used when replying to a message
797 //=============================================================================
798 class FilterActionIdentity: public FilterActionWithUOID
800 public:
801 FilterActionIdentity( QObject *parent = 0 );
802 virtual ReturnCode process( const Akonadi::Item &item ) const;
803 static FilterAction* newAction();
805 QWidget * createParamWidget( QWidget *parent ) const;
806 void applyParamWidgetValue( QWidget *parent );
807 void setParamWidgetValue( QWidget *parent ) const;
808 void clearParamWidget( QWidget *param ) const;
811 FilterAction* FilterActionIdentity::newAction()
813 return new FilterActionIdentity;
816 FilterActionIdentity::FilterActionIdentity( QObject *parent )
817 : FilterActionWithUOID( "set identity", i18n( "Set Identity To" ), parent )
819 mParameter = KernelIf->identityManager()->defaultIdentity().uoid();
822 FilterAction::ReturnCode FilterActionIdentity::process( const Akonadi::Item &item ) const
824 const KMime::Message::Ptr msg = item.payload<KMime::Message::Ptr>();
825 KMime::Headers::Generic *header = new KMime::Headers::Generic( "X-KMail-Identity", msg.get(), QString::number( mParameter ), "utf-8" );
826 msg->setHeader( header );
827 msg->assemble();
829 new Akonadi::ItemModifyJob( item, FilterIf->filterManager() );
831 return GoOn;
834 QWidget* FilterActionIdentity::createParamWidget( QWidget *parent ) const
836 KPIMIdentities::IdentityCombo *comboBox = new KPIMIdentities::IdentityCombo( KernelIf->identityManager(), parent );
837 comboBox->setCurrentIdentity( mParameter );
839 connect( comboBox, SIGNAL(currentIndexChanged(int)), this, SIGNAL(filterActionModified()) );
841 return comboBox;
844 void FilterActionIdentity::applyParamWidgetValue( QWidget *paramWidget )
846 const KPIMIdentities::IdentityCombo *comboBox = dynamic_cast<KPIMIdentities::IdentityCombo*>( paramWidget );
847 Q_ASSERT( comboBox );
849 mParameter = comboBox->currentIdentity();
852 void FilterActionIdentity::clearParamWidget( QWidget *paramWidget ) const
854 KPIMIdentities::IdentityCombo *comboBox = dynamic_cast<KPIMIdentities::IdentityCombo*>( paramWidget );
855 Q_ASSERT( comboBox );
857 comboBox->setCurrentIndex( 0 );
860 void FilterActionIdentity::setParamWidgetValue( QWidget *paramWidget ) const
862 KPIMIdentities::IdentityCombo *comboBox = dynamic_cast<KPIMIdentities::IdentityCombo*>( paramWidget );
863 Q_ASSERT( comboBox );
865 comboBox->setCurrentIdentity( mParameter );
869 //=============================================================================
870 // FilterActionSetStatus - set status to
871 // Set the status of messages
872 //=============================================================================
873 class FilterActionSetStatus: public FilterActionWithStringList
875 public:
876 FilterActionSetStatus( QObject *parent = 0 );
877 virtual ReturnCode process( const Akonadi::Item &item ) const;
878 virtual bool requiresBody() const;
880 static FilterAction* newAction();
882 virtual bool isEmpty() const { return false; }
884 virtual void argsFromString( const QString &argsStr );
885 virtual QString argsAsString() const;
886 virtual QString displayString() const;
889 static const Akonadi::MessageStatus stati[] =
891 Akonadi::MessageStatus::statusImportant(),
892 Akonadi::MessageStatus::statusRead(),
893 Akonadi::MessageStatus::statusUnread(),
894 Akonadi::MessageStatus::statusReplied(),
895 Akonadi::MessageStatus::statusForwarded(),
896 Akonadi::MessageStatus::statusWatched(),
897 Akonadi::MessageStatus::statusIgnored(),
898 Akonadi::MessageStatus::statusSpam(),
899 Akonadi::MessageStatus::statusHam(),
900 Akonadi::MessageStatus::statusToAct()
903 static const int StatiCount = sizeof( stati ) / sizeof( Akonadi::MessageStatus );
905 FilterAction* FilterActionSetStatus::newAction()
907 return new FilterActionSetStatus;
910 FilterActionSetStatus::FilterActionSetStatus( QObject *parent )
911 : FilterActionWithStringList( "set status", i18n( "Mark As" ), parent )
913 // if you change this list, also update
914 // FilterActionSetStatus::stati above
915 mParameterList.append( "" );
916 mParameterList.append( i18nc( "msg status", "Important" ) );
917 mParameterList.append( i18nc( "msg status", "Read" ) );
918 mParameterList.append( i18nc( "msg status", "Unread" ) );
919 mParameterList.append( i18nc( "msg status", "Replied" ) );
920 mParameterList.append( i18nc( "msg status", "Forwarded" ) );
921 mParameterList.append( i18nc( "msg status", "Watched" ) );
922 mParameterList.append( i18nc( "msg status", "Ignored" ) );
923 mParameterList.append( i18nc( "msg status", "Spam" ) );
924 mParameterList.append( i18nc( "msg status", "Ham" ) );
925 mParameterList.append( i18nc( "msg status", "Action Item" ) );
927 mParameter = mParameterList.at( 0 );
930 FilterAction::ReturnCode FilterActionSetStatus::process( const Akonadi::Item &item ) const
932 const int index = mParameterList.indexOf( mParameter );
933 if ( index < 1 )
934 return ErrorButGoOn;
936 Akonadi::MessageStatus status;
937 status.setStatusFromFlags( item.flags() );
939 const Akonadi::MessageStatus newStatus = stati[ index - 1 ];
940 if ( newStatus == Akonadi::MessageStatus::statusUnread() )
941 status.setRead( false );
942 else
943 status.set( newStatus );
945 Akonadi::Item newItem( item.id() );
946 newItem.setRevision( item.revision() );
947 newItem.setFlags( status.statusFlags() );
948 new Akonadi::ItemModifyJob( newItem, FilterIf->filterManager() ); // TODO handle error
950 return GoOn;
953 bool FilterActionSetStatus::requiresBody() const
955 return false;
958 static QString realStatusString( const QString &statusStr )
960 QString result( statusStr );
962 if ( result.size() == 2 )
963 result.remove( QLatin1Char( 'U' ) );
965 return result;
968 void FilterActionSetStatus::argsFromString( const QString &argsStr )
970 if ( argsStr.length() == 1 ) {
971 Akonadi::MessageStatus status;
973 for ( int i = 0 ; i < StatiCount ; ++i ) {
974 status = stati[i];
975 if ( realStatusString( status.statusStr() ) == argsStr.toLatin1() ) {
976 mParameter = mParameterList.at( i + 1 );
977 return;
982 mParameter = mParameterList.at( 0 );
985 QString FilterActionSetStatus::argsAsString() const
987 const int index = mParameterList.indexOf( mParameter );
988 if ( index < 1 )
989 return QString();
991 return realStatusString( stati[index - 1].statusStr() );
994 QString FilterActionSetStatus::displayString() const
996 return label() + QLatin1String( " \"" ) + Qt::escape( argsAsString() ) + QLatin1String( "\"" );
1000 //=============================================================================
1001 // FilterActionAddTag - append tag to message
1002 // Appends a tag to messages
1003 //=============================================================================
1004 class FilterActionAddTag: public FilterActionWithStringList
1006 public:
1007 FilterActionAddTag( QObject *parent = 0 );
1008 virtual ReturnCode process( const Akonadi::Item &item ) const;
1009 virtual bool requiresBody() const;
1011 static FilterAction* newAction();
1013 virtual bool isEmpty() const { return false; }
1015 virtual void argsFromString( const QString &argsStr );
1016 virtual QString argsAsString() const;
1017 virtual QString displayString() const;
1019 private:
1020 QStringList mLabelList;
1023 FilterAction* FilterActionAddTag::newAction()
1025 return new FilterActionAddTag;
1028 FilterActionAddTag::FilterActionAddTag( QObject *parent )
1029 : FilterActionWithStringList( "add tag", i18n( "Add Tag" ), parent )
1031 #ifndef KDEPIM_NO_NEPOMUK
1032 foreach( const Nepomuk::Tag &tag, Nepomuk::Tag::allTags() ) {
1033 mParameterList.append( tag.label() );
1034 mLabelList.append( tag.resourceUri().toString() );
1036 #endif
1039 FilterAction::ReturnCode FilterActionAddTag::process( const Akonadi::Item &item ) const
1041 #ifndef KDEPIM_NO_NEPOMUK
1042 const int index = mParameterList.indexOf( mParameter );
1043 if ( index == -1 )
1044 return ErrorButGoOn;
1046 Nepomuk::Resource resource( item.url() );
1047 resource.addTag( mParameter );
1048 #endif
1050 return GoOn;
1053 bool FilterActionAddTag::requiresBody() const
1055 return false;
1058 void FilterActionAddTag::argsFromString( const QString &argsStr )
1060 foreach ( const QString& tag, mParameterList ) {
1061 if ( tag == argsStr ) {
1062 mParameter = tag;
1063 return;
1067 if ( mParameterList.size() > 0 )
1068 mParameter = mParameterList.at( 0 );
1071 QString FilterActionAddTag::argsAsString() const
1073 const int index = mParameterList.indexOf( mParameter );
1074 if ( index == -1 )
1075 return QString();
1077 return mParameterList.at( index );
1080 QString FilterActionAddTag::displayString() const
1082 return label() + QLatin1String( " \"" ) + Qt::escape( argsAsString() ) + QLatin1String( "\"" );
1086 //=============================================================================
1087 // FilterActionFakeDisposition - send fake MDN
1088 // Sends a fake MDN or forces an ignore.
1089 //=============================================================================
1090 class FilterActionFakeDisposition: public FilterActionWithStringList
1092 public:
1093 FilterActionFakeDisposition( QObject *parent = 0 );
1094 virtual ReturnCode process( const Akonadi::Item &item ) const;
1095 static FilterAction* newAction()
1097 return new FilterActionFakeDisposition;
1100 virtual bool isEmpty() const { return false; }
1102 virtual void argsFromString( const QString &argsStr );
1103 virtual QString argsAsString() const;
1104 virtual QString displayString() const;
1108 // if you change this list, also update
1109 // the count in argsFromString
1110 static const KMime::MDN::DispositionType mdns[] =
1112 KMime::MDN::Displayed,
1113 KMime::MDN::Deleted,
1114 KMime::MDN::Dispatched,
1115 KMime::MDN::Processed,
1116 KMime::MDN::Denied,
1117 KMime::MDN::Failed,
1119 static const int numMDNs = sizeof( mdns ) / sizeof( *mdns );
1122 FilterActionFakeDisposition::FilterActionFakeDisposition( QObject *parent )
1123 : FilterActionWithStringList( "fake mdn", i18n( "Send Fake MDN" ), parent )
1125 // if you change this list, also update
1126 // mdns above
1127 mParameterList.append( "" );
1128 mParameterList.append( i18nc( "MDN type", "Ignore" ) );
1129 mParameterList.append( i18nc( "MDN type", "Displayed" ) );
1130 mParameterList.append( i18nc( "MDN type", "Deleted" ) );
1131 mParameterList.append( i18nc( "MDN type", "Dispatched" ) );
1132 mParameterList.append( i18nc( "MDN type", "Processed" ) );
1133 mParameterList.append( i18nc( "MDN type", "Denied" ) );
1134 mParameterList.append( i18nc( "MDN type", "Failed" ) );
1136 mParameter = mParameterList.at( 0 );
1139 FilterAction::ReturnCode FilterActionFakeDisposition::process( const Akonadi::Item &item ) const
1141 const int index = mParameterList.indexOf( mParameter );
1142 if ( index < 1 )
1143 return ErrorButGoOn;
1145 if ( index == 1 ) { // ignore
1146 if ( item.hasAttribute<MessageCore::MDNStateAttribute>() ) {
1147 item.attribute<MessageCore::MDNStateAttribute>()->setMDNState( MessageCore::MDNStateAttribute::MDNIgnore );
1148 Akonadi::ItemModifyJob* modifyJob = new Akonadi::ItemModifyJob( item );
1149 modifyJob->setIgnorePayload( true );
1151 } else // send
1152 sendMDN( item, mdns[ index - 2 ] ); // skip first two entries: "" and "ignore"
1154 return GoOn;
1157 void FilterActionFakeDisposition::argsFromString( const QString &argsStr )
1159 if ( argsStr.length() == 1 ) {
1160 if ( argsStr[ 0 ] == 'I' ) { // ignore
1161 mParameter = mParameterList.at( 1 );
1162 return;
1165 for ( int i = 0 ; i < numMDNs ; i++ ) {
1166 if ( char( mdns[ i ] ) == argsStr[ 0 ] ) { // send
1167 mParameter = mParameterList.at( i + 2 );
1168 return;
1173 mParameter = mParameterList.at( 0 );
1176 QString FilterActionFakeDisposition::argsAsString() const
1178 const int index = mParameterList.indexOf( mParameter );
1179 if ( index < 1 )
1180 return QString();
1182 return QString( QChar( index < 2 ? 'I' : char( mdns[ index - 2 ] ) ) );
1185 QString FilterActionFakeDisposition::displayString() const
1187 return label() + QLatin1String( " \"" ) + Qt::escape( argsAsString() ) + QLatin1String( "\"" );
1191 //=============================================================================
1192 // FilterActionRemoveHeader - remove header
1193 // Remove all instances of the given header field.
1194 //=============================================================================
1195 class FilterActionRemoveHeader: public FilterActionWithStringList
1197 public:
1198 FilterActionRemoveHeader( QObject *parent = 0 );
1199 virtual ReturnCode process( const Akonadi::Item &item ) const;
1200 virtual QWidget* createParamWidget( QWidget *parent ) const;
1201 virtual void setParamWidgetValue( QWidget *paramWidget ) const;
1203 static FilterAction* newAction();
1206 FilterAction* FilterActionRemoveHeader::newAction()
1208 return new FilterActionRemoveHeader;
1211 FilterActionRemoveHeader::FilterActionRemoveHeader( QObject *parent )
1212 : FilterActionWithStringList( "remove header", i18n( "Remove Header" ), parent )
1214 mParameterList << ""
1215 << "Reply-To"
1216 << "Delivered-To"
1217 << "X-KDE-PR-Message"
1218 << "X-KDE-PR-Package"
1219 << "X-KDE-PR-Keywords";
1221 mParameter = mParameterList.at( 0 );
1224 QWidget* FilterActionRemoveHeader::createParamWidget( QWidget *parent ) const
1226 MinimumComboBox *comboBox = new MinimumComboBox( parent );
1227 comboBox->setEditable( true );
1228 comboBox->setInsertPolicy( QComboBox::InsertAtBottom );
1229 setParamWidgetValue( comboBox );
1231 connect( comboBox, SIGNAL(currentIndexChanged(int)),
1232 this, SIGNAL(filterActionModified()) );
1234 return comboBox;
1237 FilterAction::ReturnCode FilterActionRemoveHeader::process( const Akonadi::Item &item ) const
1239 if ( mParameter.isEmpty() )
1240 return ErrorButGoOn;
1242 KMime::Message::Ptr msg = item.payload<KMime::Message::Ptr>();
1243 while ( msg->headerByType( mParameter.toLatin1() ) )
1244 msg->removeHeader( mParameter.toLatin1() );
1246 msg->assemble();
1248 new Akonadi::ItemModifyJob( item, FilterIf->filterManager() );
1250 return GoOn;
1253 void FilterActionRemoveHeader::setParamWidgetValue( QWidget *paramWidget ) const
1255 MinimumComboBox *comboBox = dynamic_cast<MinimumComboBox*>(paramWidget );
1256 Q_ASSERT( comboBox );
1258 const int index = mParameterList.indexOf( mParameter );
1259 comboBox->clear();
1260 comboBox->addItems( mParameterList );
1261 if ( index < 0 ) {
1262 comboBox->addItem( mParameter );
1263 comboBox->setCurrentIndex( comboBox->count() - 1 );
1264 } else {
1265 comboBox->setCurrentIndex( index );
1270 //=============================================================================
1271 // FilterActionAddHeader - add header
1272 // Add a header with the given value.
1273 //=============================================================================
1274 class FilterActionAddHeader: public FilterActionWithStringList
1276 public:
1277 FilterActionAddHeader( QObject *parent = 0 );
1278 virtual ReturnCode process( const Akonadi::Item &item ) const;
1279 virtual QWidget* createParamWidget( QWidget *parent ) const;
1280 virtual void setParamWidgetValue( QWidget *paramWidget ) const;
1281 virtual void applyParamWidgetValue( QWidget *paramWidget );
1282 virtual void clearParamWidget( QWidget *paramWidget ) const;
1284 virtual QString argsAsString() const;
1285 virtual void argsFromString( const QString &argsStr );
1287 virtual QString displayString() const;
1289 static FilterAction* newAction()
1291 return new FilterActionAddHeader;
1294 private:
1295 QString mValue;
1298 FilterActionAddHeader::FilterActionAddHeader( QObject *parent )
1299 : FilterActionWithStringList( "add header", i18n( "Add Header" ), parent )
1301 mParameterList << ""
1302 << "Reply-To"
1303 << "Delivered-To"
1304 << "X-KDE-PR-Message"
1305 << "X-KDE-PR-Package"
1306 << "X-KDE-PR-Keywords";
1308 mParameter = mParameterList.at( 0 );
1311 FilterAction::ReturnCode FilterActionAddHeader::process( const Akonadi::Item &item ) const
1313 if ( mParameter.isEmpty() )
1314 return ErrorButGoOn;
1316 KMime::Message::Ptr msg = item.payload<KMime::Message::Ptr>();
1318 KMime::Headers::Base *header = KMime::Headers::createHeader( mParameter.toLatin1() );
1319 if ( !header ) {
1320 header = new KMime::Headers::Generic( mParameter.toLatin1(), msg.get(), mValue, "utf-8" );
1321 } else {
1322 header->fromUnicodeString( mValue, "utf-8" );
1325 msg->setHeader( header );
1326 msg->assemble();
1328 new Akonadi::ItemModifyJob( item, FilterIf->filterManager() );
1330 return GoOn;
1333 QWidget* FilterActionAddHeader::createParamWidget( QWidget *parent ) const
1335 QWidget *widget = new QWidget( parent );
1336 QHBoxLayout *layout = new QHBoxLayout( widget );
1337 layout->setSpacing( 4 );
1338 layout->setMargin( 0 );
1340 MinimumComboBox *comboBox = new MinimumComboBox( widget );
1341 comboBox->setObjectName( "combo" );
1342 comboBox->setEditable( true );
1343 comboBox->setInsertPolicy( QComboBox::InsertAtBottom );
1344 layout->addWidget( comboBox, 0 /* stretch */ );
1346 QLabel *label = new QLabel( i18n( "With value:" ), widget );
1347 label->setFixedWidth( label->sizeHint().width() );
1348 layout->addWidget( label, 0 );
1350 KLineEdit *lineEdit = new KLineEdit( widget );
1351 lineEdit->setObjectName( "ledit" );
1352 lineEdit->setClearButtonShown( true );
1353 layout->addWidget( lineEdit, 1 );
1355 setParamWidgetValue( widget );
1357 connect( comboBox, SIGNAL(currentIndexChanged(int)),
1358 this, SIGNAL(filterActionModified()) );
1359 connect( lineEdit, SIGNAL(textChanged(QString)),
1360 this, SIGNAL(filterActionModified()) );
1362 return widget;
1365 void FilterActionAddHeader::setParamWidgetValue( QWidget *paramWidget ) const
1367 const int index = mParameterList.indexOf( mParameter );
1369 MinimumComboBox *comboBox = paramWidget->findChild<MinimumComboBox*>( "combo" );
1370 Q_ASSERT( comboBox );
1371 comboBox->clear();
1372 comboBox->addItems( mParameterList );
1374 if ( index < 0 ) {
1375 comboBox->addItem( mParameter );
1376 comboBox->setCurrentIndex( comboBox->count() - 1 );
1377 } else {
1378 comboBox->setCurrentIndex( index );
1381 KLineEdit *lineEdit = paramWidget->findChild<KLineEdit*>( "ledit" );
1382 Q_ASSERT( lineEdit );
1384 lineEdit->setText( mValue );
1387 void FilterActionAddHeader::applyParamWidgetValue( QWidget *paramWidget )
1389 const MinimumComboBox *comboBox = paramWidget->findChild<MinimumComboBox*>( "combo" );
1390 Q_ASSERT( comboBox );
1391 mParameter = comboBox->currentText();
1393 const KLineEdit *lineEdit = paramWidget->findChild<KLineEdit*>( "ledit" );
1394 Q_ASSERT( lineEdit );
1395 mValue = lineEdit->text();
1398 void FilterActionAddHeader::clearParamWidget( QWidget *paramWidget ) const
1400 MinimumComboBox *comboBox = paramWidget->findChild<MinimumComboBox*>( "combo" );
1401 Q_ASSERT( comboBox );
1402 comboBox->setCurrentIndex( 0 );
1404 KLineEdit *lineEdit = paramWidget->findChild<KLineEdit*>( "ledit" );
1405 Q_ASSERT( lineEdit );
1406 lineEdit->clear();
1409 QString FilterActionAddHeader::argsAsString() const
1411 QString result = mParameter;
1412 result += QLatin1Char( '\t' );
1413 result += mValue;
1415 return result;
1418 QString FilterActionAddHeader::displayString() const
1420 return label() + QLatin1String( " \"" ) + Qt::escape( argsAsString() ) + QLatin1String( "\"" );
1423 void FilterActionAddHeader::argsFromString( const QString &argsStr )
1425 const QStringList list = argsStr.split( QLatin1Char( '\t' ) );
1426 QString result;
1427 if ( list.count() < 2 ) {
1428 result = list[ 0 ];
1429 mValue = "";
1430 } else {
1431 result = list[ 0 ];
1432 mValue = list[ 1 ];
1435 int index = mParameterList.indexOf( result );
1436 if ( index < 0 ) {
1437 mParameterList.append( result );
1438 index = mParameterList.count() - 1;
1441 mParameter = mParameterList.at( index );
1445 //=============================================================================
1446 // FilterActionRewriteHeader - rewrite header
1447 // Rewrite a header using a regexp.
1448 //=============================================================================
1449 class FilterActionRewriteHeader: public FilterActionWithStringList
1451 public:
1452 FilterActionRewriteHeader( QObject *parent = 0 );
1453 virtual ReturnCode process( const Akonadi::Item &item ) const;
1454 virtual QWidget* createParamWidget( QWidget *parent ) const;
1455 virtual void setParamWidgetValue( QWidget *paramWidget ) const;
1456 virtual void applyParamWidgetValue( QWidget *paramWidget );
1457 virtual void clearParamWidget( QWidget *paramWidget ) const;
1459 virtual QString argsAsString() const;
1460 virtual void argsFromString( const QString &argsStr );
1462 virtual QString displayString() const;
1464 static FilterAction* newAction()
1466 return new FilterActionRewriteHeader;
1469 private:
1470 QRegExp mRegExp;
1471 QString mReplacementString;
1474 FilterActionRewriteHeader::FilterActionRewriteHeader( QObject *parent )
1475 : FilterActionWithStringList( "rewrite header", i18n( "Rewrite Header" ), parent )
1477 mParameterList << ""
1478 << "Subject"
1479 << "Reply-To"
1480 << "Delivered-To"
1481 << "X-KDE-PR-Message"
1482 << "X-KDE-PR-Package"
1483 << "X-KDE-PR-Keywords";
1485 mParameter = mParameterList.at( 0 );
1488 FilterAction::ReturnCode FilterActionRewriteHeader::process( const Akonadi::Item &item ) const
1490 if ( mParameter.isEmpty() || !mRegExp.isValid() )
1491 return ErrorButGoOn;
1493 const KMime::Message::Ptr msg = item.payload<KMime::Message::Ptr>();
1495 KMime::Headers::Base *header = msg->headerByType( mParameter.toLatin1() );
1496 QString value = header ? header->asUnicodeString(): "";
1498 const QString newValue = value.replace( mRegExp, mReplacementString );
1500 if ( !header ) {
1501 return GoOn; //TODO: Maybe create a new header by type?
1504 header->fromUnicodeString( newValue, "utf-8" );
1505 msg->assemble();
1507 new Akonadi::ItemModifyJob( item, FilterIf->filterManager() );
1509 return GoOn;
1512 QWidget* FilterActionRewriteHeader::createParamWidget( QWidget *parent ) const
1514 QWidget *widget = new QWidget( parent );
1515 QHBoxLayout *layout = new QHBoxLayout( widget );
1516 layout->setSpacing( 4 );
1517 layout->setMargin( 0 );
1519 MinimumComboBox *comboBox = new MinimumComboBox( widget );
1520 comboBox->setEditable( true );
1521 comboBox->setObjectName( "combo" );
1522 comboBox->setInsertPolicy( QComboBox::InsertAtBottom );
1523 layout->addWidget( comboBox, 0 /* stretch */ );
1525 QLabel *label = new QLabel( i18n( "Replace:" ), widget );
1526 label->setFixedWidth( label->sizeHint().width() );
1527 layout->addWidget( label, 0 );
1529 RegExpLineEdit *regExpLineEdit = new RegExpLineEdit( widget );
1530 regExpLineEdit->setObjectName( "search" );
1531 layout->addWidget( regExpLineEdit, 1 );
1533 label = new QLabel( i18n( "With:" ), widget );
1534 label->setFixedWidth( label->sizeHint().width() );
1535 layout->addWidget( label, 0 );
1537 KLineEdit *lineEdit = new KLineEdit( widget );
1538 lineEdit->setObjectName( "replace" );
1539 lineEdit->setClearButtonShown( true );
1540 layout->addWidget( lineEdit, 1 );
1542 setParamWidgetValue( widget );
1544 connect( comboBox, SIGNAL(currentIndexChanged(int)),
1545 this, SIGNAL(filterActionModified()) );
1546 connect( regExpLineEdit, SIGNAL(textChanged(QString)),
1547 this, SIGNAL(filterActionModified()) );
1548 connect( lineEdit, SIGNAL(textChanged(QString)),
1549 this, SIGNAL(filterActionModified()) );
1551 return widget;
1554 void FilterActionRewriteHeader::setParamWidgetValue( QWidget *paramWidget ) const
1556 const int index = mParameterList.indexOf( mParameter );
1557 MinimumComboBox *comboBox = paramWidget->findChild<MinimumComboBox*>( "combo" );
1558 Q_ASSERT( comboBox );
1560 comboBox->clear();
1561 comboBox->addItems( mParameterList );
1562 if ( index < 0 ) {
1563 comboBox->addItem( mParameter );
1564 comboBox->setCurrentIndex( comboBox->count() - 1 );
1565 } else {
1566 comboBox->setCurrentIndex( index );
1569 RegExpLineEdit *regExpLineEdit = paramWidget->findChild<RegExpLineEdit*>( "search" );
1570 Q_ASSERT( regExpLineEdit );
1571 regExpLineEdit->setText( mRegExp.pattern() );
1573 KLineEdit *lineEdit = paramWidget->findChild<KLineEdit*>( "replace" );
1574 Q_ASSERT( lineEdit );
1575 lineEdit->setText( mReplacementString );
1578 void FilterActionRewriteHeader::applyParamWidgetValue( QWidget *paramWidget )
1580 const MinimumComboBox *comboBox = paramWidget->findChild<MinimumComboBox*>( "combo" );
1581 Q_ASSERT( comboBox );
1582 mParameter = comboBox->currentText();
1584 const RegExpLineEdit *regExpLineEdit = paramWidget->findChild<RegExpLineEdit*>( "search" );
1585 Q_ASSERT( regExpLineEdit );
1586 mRegExp.setPattern( regExpLineEdit->text() );
1588 const KLineEdit *lineEdit = paramWidget->findChild<KLineEdit*>( "replace" );
1589 Q_ASSERT( lineEdit );
1590 mReplacementString = lineEdit->text();
1593 void FilterActionRewriteHeader::clearParamWidget( QWidget *paramWidget ) const
1595 MinimumComboBox *comboBox = paramWidget->findChild<MinimumComboBox*>( "combo" );
1596 Q_ASSERT( comboBox );
1597 comboBox->setCurrentIndex( 0 );
1599 RegExpLineEdit *regExpLineEdit = paramWidget->findChild<RegExpLineEdit*>( "search" );
1600 Q_ASSERT( regExpLineEdit );
1601 regExpLineEdit->clear();
1603 KLineEdit *lineEdit = paramWidget->findChild<KLineEdit*>( "replace" );
1604 Q_ASSERT( lineEdit );
1605 lineEdit->clear();
1608 QString FilterActionRewriteHeader::argsAsString() const
1610 QString result = mParameter;
1611 result += QLatin1Char( '\t' );
1612 result += mRegExp.pattern();
1613 result += QLatin1Char( '\t' );
1614 result += mReplacementString;
1616 return result;
1619 QString FilterActionRewriteHeader::displayString() const
1621 return label() + QLatin1String( " \"" ) + Qt::escape( argsAsString() ) + QLatin1String( "\"" );
1624 void FilterActionRewriteHeader::argsFromString( const QString &argsStr )
1626 const QStringList list = argsStr.split( QLatin1Char( '\t' ) );
1627 QString result;
1629 result = list[ 0 ];
1630 mRegExp.setPattern( list[ 1 ] );
1631 mReplacementString = list[ 2 ];
1633 int index = mParameterList.indexOf( result );
1634 if ( index < 0 ) {
1635 mParameterList.append( result );
1636 index = mParameterList.count() - 1;
1639 mParameter = mParameterList.at( index );
1643 //=============================================================================
1644 // FilterActionMove - move into folder
1645 // File message into another mail folder
1646 //=============================================================================
1647 class FilterActionMove: public FilterActionWithFolder
1649 public:
1650 FilterActionMove( QObject *parent = 0 );
1651 virtual ReturnCode process( const Akonadi::Item &item ) const;
1652 virtual bool requiresBody() const;
1653 static FilterAction* newAction();
1656 FilterAction* FilterActionMove::newAction()
1658 return new FilterActionMove;
1661 FilterActionMove::FilterActionMove( QObject *parent )
1662 : FilterActionWithFolder( "transfer", i18n( "Move Into Folder" ), parent )
1666 FilterAction::ReturnCode FilterActionMove::process( const Akonadi::Item &item ) const
1668 if ( !mFolder.isValid() ) {
1669 const Akonadi::Collection targetFolder = CommonKernel->collectionFromId( mFolderName );
1670 if ( !targetFolder.isValid() )
1671 return ErrorButGoOn;
1673 MessageProperty::setFilterFolder( item, targetFolder );
1674 return GoOn;
1677 MessageProperty::setFilterFolder( item, mFolder );
1678 return GoOn;
1681 bool FilterActionMove::requiresBody() const
1683 return false;
1687 //=============================================================================
1688 // FilterActionCopy - copy into folder
1689 // Copy message into another mail folder
1690 //=============================================================================
1691 class FilterActionCopy: public FilterActionWithFolder
1693 public:
1694 FilterActionCopy( QObject *parent = 0 );
1695 virtual ReturnCode process( const Akonadi::Item &item ) const;
1696 virtual bool requiresBody() const;
1697 static FilterAction* newAction();
1700 FilterAction* FilterActionCopy::newAction()
1702 return new FilterActionCopy;
1705 FilterActionCopy::FilterActionCopy( QObject *parent )
1706 : FilterActionWithFolder( "copy", i18n( "Copy Into Folder" ), parent )
1710 FilterAction::ReturnCode FilterActionCopy::process( const Akonadi::Item &item ) const
1712 // copy the message 1:1
1713 new Akonadi::ItemCopyJob( item, mFolder, FilterIf->filterManager() ); // TODO handle error
1715 return GoOn;
1718 bool FilterActionCopy::requiresBody() const
1720 return false;
1724 //=============================================================================
1725 // FilterActionForward - forward to
1726 // Forward message to another user, with a defined template
1727 //=============================================================================
1728 class FilterActionForward: public FilterActionWithAddress
1730 public:
1731 FilterActionForward( QObject *parent = 0 );
1732 static FilterAction* newAction();
1733 virtual ReturnCode process( const Akonadi::Item &item ) const;
1734 virtual QWidget* createParamWidget( QWidget *parent ) const;
1735 virtual void applyParamWidgetValue( QWidget *paramWidget );
1736 virtual void setParamWidgetValue( QWidget *paramWidget ) const;
1737 virtual void clearParamWidget( QWidget *paramWidget ) const;
1738 virtual void argsFromString( const QString &argsStr );
1739 virtual QString argsAsString() const;
1740 virtual QString displayString() const;
1742 private:
1743 mutable QString mTemplate;
1746 FilterAction *FilterActionForward::newAction()
1748 return new FilterActionForward;
1751 FilterActionForward::FilterActionForward( QObject *parent )
1752 : FilterActionWithAddress( "forward", i18n( "Forward To" ), parent )
1756 FilterAction::ReturnCode FilterActionForward::process( const Akonadi::Item &item ) const
1758 if ( mParameter.isEmpty() )
1759 return ErrorButGoOn;
1761 const KMime::Message::Ptr msg = item.payload<KMime::Message::Ptr>();
1762 // avoid endless loops when this action is used in a filter
1763 // which applies to sent messages
1764 if ( MessageCore::StringUtil::addressIsInAddressList( mParameter,
1765 QStringList( msg->to()->asUnicodeString() ) ) ) {
1766 kWarning() << "Attempt to forward to receipient of original message, ignoring.";
1767 return ErrorButGoOn;
1770 MessageFactory factory( msg, item.id() );
1771 factory.setIdentityManager( KernelIf->identityManager() );
1772 factory.setFolderIdentity( Util::folderIdentity( item ) );
1773 factory.setTemplate( mTemplate );
1775 KMime::Message::Ptr fwdMsg = factory.createForward();
1776 fwdMsg->to()->fromUnicodeString( fwdMsg->to()->asUnicodeString() + QLatin1Char( ',' ) + mParameter, "utf-8" );
1777 if ( !KernelIf->msgSender()->send( fwdMsg, MessageSender::SendDefault ) ) {
1778 kWarning() << "FilterAction: could not forward message (sending failed)";
1779 return ErrorButGoOn; // error: couldn't send
1780 } else
1781 sendMDN( item, KMime::MDN::Dispatched );
1783 // (the msgSender takes ownership of the message, so don't delete it here)
1784 return GoOn;
1787 QWidget* FilterActionForward::createParamWidget( QWidget *parent ) const
1789 QWidget *addressAndTemplate = new QWidget( parent );
1790 QHBoxLayout *layout = new QHBoxLayout( addressAndTemplate );
1791 layout->setMargin( 0 );
1793 QWidget *addressEdit = FilterActionWithAddress::createParamWidget( addressAndTemplate );
1794 addressEdit->setObjectName( "addressEdit" );
1795 layout->addWidget( addressEdit );
1797 MessageCore::EmailAddressRequester *addressRequester = qobject_cast<MessageCore::EmailAddressRequester*>( addressEdit );
1798 Q_ASSERT( addressRequester );
1799 KLineEdit *lineEdit = addressRequester->lineEdit();
1800 lineEdit->setToolTip( i18n( "The addressee to whom the message will be forwarded." ) );
1801 lineEdit->setWhatsThis( i18n( "The filter will forward the message to the addressee entered here." ) );
1803 MinimumComboBox *templateCombo = new MinimumComboBox( addressAndTemplate );
1804 templateCombo->setObjectName( "templateCombo" );
1805 layout->addWidget( templateCombo );
1807 templateCombo->addItem( i18n( "Default Template" ) );
1809 const QStringList templateNames = SettingsIf->customTemplates();
1810 foreach( const QString &templateName, templateNames ) {
1811 CTemplates templat( templateName );
1812 if ( templat.type() == CustomTemplates::TForward ||
1813 templat.type() == CustomTemplates::TUniversal )
1814 templateCombo->addItem( templateName );
1817 templateCombo->setEnabled( templateCombo->count() > 1 );
1818 templateCombo->setToolTip( i18n( "The template used when forwarding" ) );
1819 templateCombo->setWhatsThis( i18n( "Set the forwarding template that will be used with this filter." ) );
1821 connect( templateCombo, SIGNAL(currentIndexChanged(int)),
1822 this, SIGNAL(filterActionModified()) );
1823 connect( addressRequester, SIGNAL(textChanged()),
1824 this, SIGNAL(filterActionModified()) );
1826 return addressAndTemplate;
1829 void FilterActionForward::applyParamWidgetValue( QWidget *paramWidget )
1831 QWidget *addressEdit = paramWidget->findChild<QWidget*>( "addressEdit" );
1832 Q_ASSERT( addressEdit );
1833 FilterActionWithAddress::applyParamWidgetValue( addressEdit );
1835 const MinimumComboBox *templateCombo = paramWidget->findChild<MinimumComboBox*>( "templateCombo" );
1836 Q_ASSERT( templateCombo );
1838 if ( templateCombo->currentIndex() == 0 ) {
1839 // Default template, so don't use a custom one
1840 mTemplate.clear();
1841 } else {
1842 mTemplate = templateCombo->currentText();
1846 void FilterActionForward::setParamWidgetValue( QWidget *paramWidget ) const
1848 QWidget *addressEdit = paramWidget->findChild<QWidget*>( "addressEdit" );
1849 Q_ASSERT( addressEdit );
1850 FilterActionWithAddress::setParamWidgetValue( addressEdit );
1852 MinimumComboBox *templateCombo = paramWidget->findChild<MinimumComboBox*>( "templateCombo" );
1853 Q_ASSERT( templateCombo );
1855 if ( mTemplate.isEmpty() ) {
1856 templateCombo->setCurrentIndex( 0 );
1857 } else {
1858 int templateIndex = templateCombo->findText( mTemplate );
1859 if ( templateIndex != -1 ) {
1860 templateCombo->setCurrentIndex( templateIndex );
1861 } else {
1862 mTemplate.clear();
1867 void FilterActionForward::clearParamWidget( QWidget *paramWidget ) const
1869 QWidget *addressEdit = paramWidget->findChild<QWidget*>( "addressEdit" );
1870 Q_ASSERT( addressEdit );
1871 FilterActionWithAddress::clearParamWidget( addressEdit );
1873 MinimumComboBox *templateCombo = paramWidget->findChild<MinimumComboBox*>( "templateCombo" );
1874 Q_ASSERT( templateCombo );
1876 templateCombo->setCurrentIndex( 0 );
1879 // We simply place a "@$$@" between the two parameters. The template is the last
1880 // parameter in the string, for compatibility reasons.
1881 static const QString forwardFilterArgsSeperator = "@$$@";
1883 void FilterActionForward::argsFromString( const QString &argsStr )
1885 const int seperatorPos = argsStr.indexOf( forwardFilterArgsSeperator );
1887 if ( seperatorPos == - 1 ) {
1888 // Old config, assume that the whole string is the addressee
1889 FilterActionWithAddress::argsFromString( argsStr );
1890 } else {
1891 const QString addressee = argsStr.left( seperatorPos );
1892 mTemplate = argsStr.mid( seperatorPos + forwardFilterArgsSeperator.length() );
1893 FilterActionWithAddress::argsFromString( addressee );
1897 QString FilterActionForward::argsAsString() const
1899 return FilterActionWithAddress::argsAsString() + forwardFilterArgsSeperator + mTemplate;
1902 QString FilterActionForward::displayString() const
1904 if ( mTemplate.isEmpty() )
1905 return i18n( "Forward to %1 with default template", mParameter );
1906 else
1907 return i18n( "Forward to %1 with template %2", mParameter, mTemplate );
1911 //=============================================================================
1912 // FilterActionRedirect - redirect to
1913 // Redirect message to another user
1914 //=============================================================================
1915 class FilterActionRedirect: public FilterActionWithAddress
1917 public:
1918 FilterActionRedirect( QObject *parent = 0 );
1919 virtual ReturnCode process( const Akonadi::Item &item ) const;
1920 static FilterAction* newAction();
1923 FilterAction* FilterActionRedirect::newAction()
1925 return new FilterActionRedirect;
1928 FilterActionRedirect::FilterActionRedirect( QObject *parent )
1929 : FilterActionWithAddress( "redirect", i18n( "Redirect To" ), parent )
1933 FilterAction::ReturnCode FilterActionRedirect::process( const Akonadi::Item &item ) const
1935 if ( mParameter.isEmpty() )
1936 return ErrorButGoOn;
1938 KMime::Message::Ptr msg = MessageCore::Util::message( item );
1940 MessageFactory factory( msg, item.id() );
1941 factory.setFolderIdentity( Util::folderIdentity( item ) );
1942 factory.setIdentityManager( KernelIf->identityManager() );
1944 KMime::Message::Ptr rmsg = factory.createRedirect( mParameter );
1945 if ( !rmsg )
1946 return ErrorButGoOn;
1948 sendMDN( item, KMime::MDN::Dispatched );
1950 if ( !KernelIf->msgSender()->send( rmsg, MessageSender::SendLater ) ) {
1951 kDebug() << "FilterAction: could not redirect message (sending failed)";
1952 return ErrorButGoOn; // error: couldn't send
1955 return GoOn;
1959 //=============================================================================
1960 // FilterActionExec - execute command
1961 // Execute a shell command
1962 //=============================================================================
1963 class FilterActionExec : public FilterActionWithCommand
1965 public:
1966 FilterActionExec( QObject *parent = 0 );
1967 virtual ReturnCode process( const Akonadi::Item &item ) const;
1968 static FilterAction* newAction();
1971 FilterAction* FilterActionExec::newAction()
1973 return new FilterActionExec();
1976 FilterActionExec::FilterActionExec( QObject *parent )
1977 : FilterActionWithCommand( "execute", i18n( "Execute Command" ), parent )
1981 FilterAction::ReturnCode FilterActionExec::process( const Akonadi::Item &item ) const
1983 return FilterActionWithCommand::genericProcess( item, false ); // ignore output
1987 //=============================================================================
1988 // FilterActionExtFilter - use external filter app
1989 // External message filter: executes a shell command with message
1990 // on stdin; altered message is expected on stdout.
1991 //=============================================================================
1992 class FilterActionExtFilter: public FilterActionWithCommand
1994 public:
1995 FilterActionExtFilter( QObject *parent = 0 );
1996 virtual ReturnCode process( const Akonadi::Item &item ) const;
1997 static FilterAction* newAction();
2000 FilterAction* FilterActionExtFilter::newAction()
2002 return new FilterActionExtFilter;
2005 FilterActionExtFilter::FilterActionExtFilter( QObject *parent )
2006 : FilterActionWithCommand( "filter app", i18n( "Pipe Through" ), parent )
2010 FilterAction::ReturnCode FilterActionExtFilter::process( const Akonadi::Item &item ) const
2012 return FilterActionWithCommand::genericProcess( item, true ); // use output
2016 #ifndef _WIN32_WCE
2017 //=============================================================================
2018 // FilterActionExecSound - execute command
2019 // Execute a sound
2020 //=============================================================================
2021 class FilterActionExecSound : public FilterActionWithTest
2023 public:
2024 FilterActionExecSound( QObject *parent = 0 );
2025 ~FilterActionExecSound();
2026 virtual ReturnCode process( const Akonadi::Item &item ) const;
2027 virtual bool requiresBody() const;
2028 static FilterAction* newAction();
2030 private:
2031 mutable Phonon::MediaObject* mPlayer;
2034 FilterActionWithTest::FilterActionWithTest( const char *name, const QString &label, QObject *parent )
2035 : FilterAction( name, label, parent )
2039 FilterActionWithTest::~FilterActionWithTest()
2043 bool FilterActionWithTest::isEmpty() const
2045 return mParameter.trimmed().isEmpty();
2048 QWidget* FilterActionWithTest::createParamWidget( QWidget *parent ) const
2050 SoundTestWidget *soundWidget = new SoundTestWidget( parent );
2051 soundWidget->setUrl( mParameter );
2053 connect( soundWidget, SIGNAL(textChanged(QString)),
2054 this, SIGNAL(filterActionModified()) );
2056 return soundWidget;
2060 void FilterActionWithTest::applyParamWidgetValue( QWidget *paramWidget )
2062 mParameter = static_cast<SoundTestWidget*>( paramWidget )->url();
2065 void FilterActionWithTest::setParamWidgetValue( QWidget *paramWidget ) const
2067 static_cast<SoundTestWidget*>( paramWidget )->setUrl( mParameter );
2070 void FilterActionWithTest::clearParamWidget( QWidget *paramWidget ) const
2072 static_cast<SoundTestWidget*>( paramWidget )->clear();
2075 void FilterActionWithTest::argsFromString( const QString &argsStr )
2077 mParameter = argsStr;
2080 QString FilterActionWithTest::argsAsString() const
2082 return mParameter;
2085 QString FilterActionWithTest::displayString() const
2087 return label() + QLatin1String( " \"" ) + Qt::escape( argsAsString() ) + QLatin1String( "\"" );
2090 FilterActionExecSound::FilterActionExecSound( QObject *parent )
2091 : FilterActionWithTest( "play sound", i18n( "Play Sound" ) ),
2092 mPlayer( 0 )
2096 FilterActionExecSound::~FilterActionExecSound()
2098 delete mPlayer;
2101 FilterAction* FilterActionExecSound::newAction()
2103 return new FilterActionExecSound();
2106 FilterAction::ReturnCode FilterActionExecSound::process( const Akonadi::Item& ) const
2108 if ( mParameter.isEmpty() )
2109 return ErrorButGoOn;
2111 if ( !mPlayer )
2112 mPlayer = Phonon::createPlayer( Phonon::NotificationCategory );
2114 mPlayer->setCurrentSource( mParameter );
2115 mPlayer->play();
2117 return GoOn;
2120 bool FilterActionExecSound::requiresBody() const
2122 return false;
2125 #endif
2127 FilterActionWithUrl::FilterActionWithUrl( const char *name, const QString &label, QObject *parent )
2128 : FilterAction( name, label, parent )
2132 FilterActionWithUrl::~FilterActionWithUrl()
2136 bool FilterActionWithUrl::isEmpty() const
2138 return mParameter.trimmed().isEmpty();
2141 QWidget* FilterActionWithUrl::createParamWidget( QWidget *parent ) const
2143 KUrlRequester *requester = new KUrlRequester( parent );
2144 requester->setUrl( KUrl( mParameter ) );
2146 connect( requester, SIGNAL(textChanged(QString)), this, SIGNAL(filterActionModified()) );
2148 return requester;
2152 void FilterActionWithUrl::applyParamWidgetValue( QWidget *paramWidget )
2154 const KUrl url = static_cast<KUrlRequester*>( paramWidget )->url();
2156 mParameter = (url.isLocalFile() ? url.toLocalFile() : url.path());
2159 void FilterActionWithUrl::setParamWidgetValue( QWidget *paramWidget ) const
2161 static_cast<KUrlRequester*>( paramWidget )->setUrl( KUrl( mParameter ) );
2164 void FilterActionWithUrl::clearParamWidget( QWidget *paramWidget ) const
2166 static_cast<KUrlRequester*>( paramWidget )->clear();
2169 void FilterActionWithUrl::argsFromString( const QString &argsStr )
2171 mParameter = argsStr;
2174 QString FilterActionWithUrl::argsAsString() const
2176 return mParameter;
2179 QString FilterActionWithUrl::displayString() const
2181 return label() + QLatin1String( " \"" ) + Qt::escape( argsAsString() ) + QLatin1String( "\"" );
2185 //=============================================================================
2186 // FilterActionAddToAddressBook
2187 // - add email address from header to address book
2188 //=============================================================================
2189 class FilterActionAddToAddressBook: public FilterActionWithStringList
2191 public:
2192 FilterActionAddToAddressBook( QObject *parent = 0 );
2193 virtual ReturnCode process( const Akonadi::Item &item ) const;
2194 static FilterAction* newAction();
2196 virtual bool isEmpty() const { return false; }
2198 virtual QWidget* createParamWidget( QWidget *parent ) const;
2199 virtual void setParamWidgetValue( QWidget *paramWidget ) const;
2200 virtual void applyParamWidgetValue( QWidget *paramWidget );
2201 virtual void clearParamWidget( QWidget *paramWidget ) const;
2203 virtual QString argsAsString() const;
2204 virtual void argsFromString( const QString &argsStr );
2206 private:
2207 enum HeaderType
2209 FromHeader,
2210 ToHeader,
2211 CcHeader,
2212 BccHeader
2215 const QString mFromStr, mToStr, mCCStr, mBCCStr;
2216 HeaderType mHeaderType;
2217 Akonadi::Collection::Id mCollectionId;
2218 QString mCategory;
2221 FilterAction* FilterActionAddToAddressBook::newAction()
2223 return new FilterActionAddToAddressBook;
2226 FilterActionAddToAddressBook::FilterActionAddToAddressBook( QObject *parent )
2227 : FilterActionWithStringList( "add to address book", i18n( "Add to Address Book" ), parent ),
2228 mFromStr( i18nc( "Email sender", "From" ) ),
2229 mToStr( i18nc( "Email recipient", "To" ) ),
2230 mCCStr( i18n( "CC" ) ),
2231 mBCCStr( i18n( "BCC" ) ),
2232 mHeaderType( FromHeader ),
2233 mCollectionId( -1 ),
2234 mCategory( i18n( "KMail Filter" ) )
2238 FilterAction::ReturnCode FilterActionAddToAddressBook::process( const Akonadi::Item &item ) const
2240 const KMime::Message::Ptr msg = item.payload<KMime::Message::Ptr>();
2242 QString headerLine;
2243 switch ( mHeaderType ) {
2244 case FromHeader: headerLine = msg->from()->asUnicodeString(); break;
2245 case ToHeader: headerLine = msg->to()->asUnicodeString(); break;
2246 case CcHeader: headerLine = msg->cc()->asUnicodeString(); break;
2247 case BccHeader: headerLine = msg->bcc()->asUnicodeString(); break;
2250 const QStringList emails = KPIMUtils::splitAddressList( headerLine );
2252 foreach ( const QString& singleEmail, emails ) {
2253 QString name, email;
2254 KABC::Addressee::parseEmailAddress( singleEmail, name, email );
2256 KABC::Addressee contact;
2257 contact.setNameFromString( name );
2258 contact.insertEmail( email, true );
2259 if ( !mCategory.isEmpty() )
2260 contact.insertCategory( mCategory );
2262 KPIM::AddContactJob *job = new KPIM::AddContactJob( contact, Akonadi::Collection( mCollectionId ) );
2263 job->start();
2266 return GoOn;
2269 QWidget* FilterActionAddToAddressBook::createParamWidget( QWidget *parent ) const
2271 QWidget *widget = new QWidget( parent );
2272 QGridLayout *layout = new QGridLayout( widget );
2274 MinimumComboBox *headerCombo = new MinimumComboBox( widget );
2275 headerCombo->setObjectName( "HeaderComboBox" );
2276 layout->addWidget( headerCombo, 0, 0, 2, 1, Qt::AlignVCenter );
2278 QLabel *label = new QLabel( i18n( "with category" ), widget );
2279 layout->addWidget( label, 0, 1 );
2281 KLineEdit *categoryEdit = new KLineEdit( widget );
2282 categoryEdit->setObjectName( "CategoryEdit" );
2283 layout->addWidget( categoryEdit, 0, 2 );
2285 label = new QLabel( i18n( "in address book" ), widget );
2286 layout->addWidget( label, 1, 1 );
2288 Akonadi::CollectionComboBox *collectionComboBox = new Akonadi::CollectionComboBox( widget );
2289 collectionComboBox->setMimeTypeFilter( QStringList() << KABC::Addressee::mimeType() );
2290 collectionComboBox->setAccessRightsFilter( Akonadi::Collection::CanCreateItem );
2292 collectionComboBox->setObjectName( "AddressBookComboBox" );
2293 collectionComboBox->setToolTip( i18n( "<p>This defines the preferred address book.<br />"
2294 "If it is not accessible, the filter will fallback to the default address book.</p>" ) );
2295 layout->addWidget( collectionComboBox, 1, 2 );
2297 connect( categoryEdit, SIGNAL(textChanged(QString)),
2298 this, SIGNAL(filterActionModified()) );
2299 connect( headerCombo, SIGNAL(currentIndexChanged(int)),
2300 this, SIGNAL(filterActionModified()) );
2302 setParamWidgetValue( widget );
2304 return widget;
2307 void FilterActionAddToAddressBook::setParamWidgetValue( QWidget *paramWidget ) const
2309 MinimumComboBox *headerCombo = paramWidget->findChild<MinimumComboBox*>( "HeaderComboBox" );
2310 Q_ASSERT( headerCombo );
2311 headerCombo->clear();
2312 headerCombo->addItem( mFromStr, FromHeader );
2313 headerCombo->addItem( mToStr, ToHeader );
2314 headerCombo->addItem( mCCStr, CcHeader );
2315 headerCombo->addItem( mBCCStr, BccHeader );
2317 headerCombo->setCurrentIndex( headerCombo->findData( mHeaderType ) );
2319 KLineEdit *categoryEdit = paramWidget->findChild<KLineEdit*>( "CategoryEdit" );
2320 Q_ASSERT( categoryEdit );
2321 categoryEdit->setText( mCategory );
2323 Akonadi::CollectionComboBox *collectionComboBox = paramWidget->findChild<Akonadi::CollectionComboBox*>( "AddressBookComboBox" );
2324 Q_ASSERT( collectionComboBox );
2325 collectionComboBox->setDefaultCollection( Akonadi::Collection( mCollectionId ) );
2326 collectionComboBox->setProperty( "collectionId", mCollectionId );
2329 void FilterActionAddToAddressBook::applyParamWidgetValue( QWidget *paramWidget )
2331 const MinimumComboBox *headerCombo = paramWidget->findChild<MinimumComboBox*>( "HeaderComboBox" );
2332 Q_ASSERT( headerCombo );
2333 mHeaderType = static_cast<HeaderType>( headerCombo->itemData( headerCombo->currentIndex() ).toInt() );
2335 const KLineEdit *categoryEdit = paramWidget->findChild<KLineEdit*>( "CategoryEdit" );
2336 Q_ASSERT( categoryEdit );
2337 mCategory = categoryEdit->text();
2339 const Akonadi::CollectionComboBox *collectionComboBox = paramWidget->findChild<Akonadi::CollectionComboBox*>( "AddressBookComboBox" );
2340 Q_ASSERT( collectionComboBox );
2341 const Akonadi::Collection collection = collectionComboBox->currentCollection();
2343 // it might be that the model of collectionComboBox has not finished loading yet, so
2344 // we use the previously 'stored' value from the 'collectionId' property
2345 if ( collection.isValid() ) {
2346 mCollectionId = collection.id();
2347 connect( collectionComboBox, SIGNAL(currentIndexChanged(int)),
2348 this, SIGNAL(filterActionModified()) );
2349 } else {
2350 const QVariant value = collectionComboBox->property( "collectionId" );
2351 if ( value.isValid() )
2352 mCollectionId = value.toLongLong();
2356 void FilterActionAddToAddressBook::clearParamWidget( QWidget *paramWidget ) const
2358 MinimumComboBox *headerCombo = paramWidget->findChild<MinimumComboBox*>( "HeaderComboBox" );
2359 Q_ASSERT( headerCombo );
2360 headerCombo->setCurrentItem( 0 );
2362 KLineEdit *categoryEdit = paramWidget->findChild<KLineEdit*>( "CategoryEdit" );
2363 Q_ASSERT( categoryEdit );
2364 categoryEdit->setText( mCategory );
2367 QString FilterActionAddToAddressBook::argsAsString() const
2369 QString result;
2371 switch ( mHeaderType ) {
2372 case FromHeader: result = QLatin1String( "From" ); break;
2373 case ToHeader: result = QLatin1String( "To" ); break;
2374 case CcHeader: result = QLatin1String( "CC" ); break;
2375 case BccHeader: result = QLatin1String( "BCC" ); break;
2378 result += QLatin1Char( '\t' );
2379 result += QString::number( mCollectionId );
2380 result += QLatin1Char( '\t' );
2381 result += mCategory;
2383 return result;
2386 void FilterActionAddToAddressBook::argsFromString( const QString &argsStr )
2388 const QStringList parts = argsStr.split( QLatin1Char( '\t' ), QString::KeepEmptyParts );
2389 if ( parts[ 0 ] == QLatin1String( "From" ) )
2390 mHeaderType = FromHeader;
2391 else if ( parts[ 0 ] == QLatin1String( "To" ) )
2392 mHeaderType = ToHeader;
2393 else if ( parts[ 0 ] == QLatin1String( "CC" ) )
2394 mHeaderType = CcHeader;
2395 else if ( parts[ 0 ] == QLatin1String( "BCC" ) )
2396 mHeaderType = BccHeader;
2398 if ( parts.count() >= 2 )
2399 mCollectionId = parts[ 1 ].toLongLong();
2401 if ( parts.count() < 3 )
2402 mCategory.clear();
2403 else
2404 mCategory = parts[ 2 ];
2408 //=============================================================================
2410 // Filter Action Dictionary
2412 //=============================================================================
2413 FilterActionDict::~FilterActionDict()
2415 qDeleteAll( mList );
2418 void FilterActionDict::init()
2420 insert( FilterActionMove::newAction );
2421 insert( FilterActionCopy::newAction );
2422 insert( FilterActionIdentity::newAction );
2423 insert( FilterActionSetStatus::newAction );
2424 insert( FilterActionAddTag::newAction );
2425 insert( FilterActionFakeDisposition::newAction );
2426 insert( FilterActionTransport::newAction );
2427 insert( FilterActionReplyTo::newAction );
2428 insert( FilterActionForward::newAction );
2429 insert( FilterActionRedirect::newAction );
2430 insert( FilterActionSendReceipt::newAction );
2431 insert( FilterActionExec::newAction );
2432 insert( FilterActionExtFilter::newAction );
2433 insert( FilterActionRemoveHeader::newAction );
2434 insert( FilterActionAddHeader::newAction );
2435 insert( FilterActionRewriteHeader::newAction );
2436 #ifndef _WIN32_WCE
2437 insert( FilterActionExecSound::newAction );
2438 #endif
2439 insert( FilterActionAddToAddressBook::newAction );
2440 // Register custom filter actions below this line.
2443 // The int in the QDict constructor (41) must be a prime
2444 // and should be greater than the double number of FilterAction types
2445 FilterActionDict::FilterActionDict()
2446 : QMultiHash<QString, FilterActionDesc*>()
2448 init();
2451 void FilterActionDict::insert( FilterActionNewFunc aNewFunc )
2453 FilterAction *action = aNewFunc();
2454 FilterActionDesc* desc = new FilterActionDesc;
2455 desc->name = action->name();
2456 desc->label = action->label();
2457 desc->create = aNewFunc;
2459 QMultiHash<QString, FilterActionDesc*>::insert( desc->name, desc );
2460 QMultiHash<QString, FilterActionDesc*>::insert( desc->label, desc );
2461 mList.append( desc );
2463 delete action;
2466 const QList<FilterActionDesc*>& FilterActionDict::list() const
2468 return mList;
2472 #include "filteraction.moc"