33 #include "messageviewer/utils/kcursorsaver.h"
37 #include "folderrequester.h"
38 #include "foldertreewidget.h"
39 #include "foldertreeview.h"
40 #include "foldertreewidgetproxymodel.h"
41 #include "mailcommon/pop3settings.h"
42 #include "mailcommon/util/mailutil.h"
43 #include "pimcommon/imapresourcesettings.h"
44 #include "mailcommon/kernel/mailkernel.h"
45 #include "mailcommon/filter/mailfilter.h"
46 #include "mailcommon/filter/filteraction.h"
47 #include "mailcommon/filter/filteractiondict.h"
48 #include "mailcommon/filter/filtermanager.h"
50 #include "pimcommon/util/pimutil.h"
52 #include <Akonadi/AgentInstance>
56 #include <kiconloader.h>
59 #include <ktoolinvocation.h>
60 #include <kconfiggroup.h>
65 #include <QGridLayout>
66 #include <QHBoxLayout>
68 #include <QVBoxLayout>
70 #include <QListWidget>
72 using namespace KMail;
73 using namespace MailCommon;
91 kDebug() << endl <<
"Considered anti-spam tools:";
93 kDebug() << endl <<
"Considered anti-virus tools:";
97 kDebug() <<
"Predefined tool:" << (*it).getId();
98 kDebug() <<
"Config version:" << (*it).getVersion();
99 kDebug() <<
"Selection priority:" << (*it).getPrio();
100 kDebug() <<
"Displayed name:" << (*it).getVisibleName();
101 kDebug() <<
"Executable:" << (*it).getExecutable();
102 kDebug() <<
"WhatsThis URL:" << (*it).getWhatsThisText();
103 kDebug() <<
"Filter name:" << (*it).getFilterName();
104 kDebug() <<
"Detection command:" << (*it).getDetectCmd();
105 kDebug() <<
"Learn spam command:" << (*it).getSpamCmd();
106 kDebug() <<
"Learn ham command:" << (*it).getHamCmd();
107 kDebug() <<
"Detection header:" << (*it).getDetectionHeader();
108 kDebug() <<
"Detection pattern:" << (*it).getDetectionPattern();
109 kDebug() <<
"Use as RegExp:" << (*it).isUseRegExp();
110 kDebug() <<
"Supports Bayes Filter:" << (*it).useBayesFilter();
111 kDebug() <<
"Type:" << (*it).getType();
115 const bool isAntiSpam = (mMode ==
AntiSpam);
116 setWindowTitle( isAntiSpam ? i18n(
"Anti-Spam Wizard" )
117 : i18n(
"Anti-Virus Wizard" ) );
119 mInfoPageItem = addPage( mInfoPage,
121 ? i18n(
"Welcome to the KMail Anti-Spam Wizard" )
122 : i18n(
"Welcome to the KMail Anti-Virus Wizard" ) );
123 connect( mInfoPage, SIGNAL(selectionChanged()),
128 mSpamRulesPageItem = addPage( mSpamRulesPage, i18n(
"Options to fine-tune the handling of spam messages" ));
129 connect( mSpamRulesPage, SIGNAL(selectionChanged()),
133 mSummaryPageItem = addPage( mSummaryPage, i18n(
"Summary of changes to be made by this wizard" ) );
136 mVirusRulesPageItem = addPage( mVirusRulesPage, i18n(
"Options to fine-tune the handling of virus messages" ));
137 connect( mVirusRulesPage, SIGNAL(selectionChanged()),
141 connect(
this, SIGNAL(helpClicked()),
150 if ( mSpamRulesPage ) {
151 kDebug() <<
"Folder name for messages classified as spam is"
153 kDebug() <<
"Folder name for messages classified as unsure is"
156 if ( mVirusRulesPage ) {
157 kDebug() <<
"Folder name for viruses is"
161 FilterActionDict dict;
163 bool replaceExistingFilters =
false;
168 if ( !mVirusToolsUsed ) {
180 MailFilter* pipeFilter =
new MailFilter();
182 FilterAction* pipeFilterAction = dict.value( QLatin1String(
"filter app") )->create();
183 pipeFilterAction->argsFromString( (*it).getDetectCmd() );
184 pipeFilterActions->append( pipeFilterAction );
185 SearchPattern* pipeFilterPattern = pipeFilter->pattern();
186 pipeFilterPattern->setName( uniqueNameFor( (*it).getFilterName() ) );
187 pipeFilterPattern->append( SearchRule::createInstance(
"<size>",
188 SearchRule::FuncIsGreaterOrEqual, QLatin1String(
"0") ) );
189 pipeFilter->setApplyOnOutbound(
false);
190 pipeFilter->setApplyOnInbound();
191 pipeFilter->setApplyOnExplicit();
192 pipeFilter->setStopProcessingHere(
false );
193 pipeFilter->setConfigureShortcut(
false );
195 filterList.append( pipeFilter );
201 MailFilter* virusFilter =
new MailFilter();
203 FilterAction* virusFilterAction1 = dict.value( QLatin1String(
"transfer") )->create();
205 virusFilterActions->append( virusFilterAction1 );
207 FilterAction* virusFilterAction2 = dict.value( QLatin1String(
"set status" ))->create();
208 virusFilterAction2->argsFromString( QLatin1String(
"R") );
209 virusFilterActions->append( virusFilterAction2 );
211 SearchPattern* virusFilterPattern = virusFilter->pattern();
212 virusFilterPattern->setName( uniqueNameFor( i18n(
"Virus handling" ) ) );
213 virusFilterPattern->setOp( SearchPattern::OpOr );
216 it != endSpamTool; ++it ) {
218 if ( (*it).isVirusTool() ) {
219 const QByteArray header = (*it).getDetectionHeader().toLatin1();
220 const QString & pattern = (*it).getDetectionPattern();
221 if ( (*it).isUseRegExp() )
222 virusFilterPattern->append(
223 SearchRule::createInstance( header,
224 SearchRule::FuncRegExp, pattern ) );
226 virusFilterPattern->append(
227 SearchRule::createInstance( header,
228 SearchRule::FuncContains, pattern ) );
232 virusFilter->setApplyOnOutbound(
false);
233 virusFilter->setApplyOnInbound();
234 virusFilter->setApplyOnExplicit();
235 virusFilter->setStopProcessingHere(
true );
236 virusFilter->setConfigureShortcut(
false );
238 filterList.append( virusFilter );
241 if ( !mSpamToolsUsed ) {
248 replaceExistingFilters =
true;
253 (*it).isSpamTool() && !(*it).isDetectionOnly() ) {
257 MailFilter* pipeFilter =
new MailFilter();
259 FilterAction* pipeFilterAction = dict.value(QLatin1String(
"filter app") )->create();
260 pipeFilterAction->argsFromString( (*it).getDetectCmd() );
261 pipeFilterActions->append( pipeFilterAction );
262 SearchPattern* pipeFilterPattern = pipeFilter->pattern();
263 if ( replaceExistingFilters )
264 pipeFilterPattern->setName( (*it).getFilterName() );
266 pipeFilterPattern->setName( uniqueNameFor( (*it).getFilterName() ) );
267 pipeFilterPattern->append( SearchRule::createInstance(
"<size>",
268 SearchRule::FuncIsLessOrEqual, QLatin1String(
"256000") ) );
269 pipeFilter->setApplyOnOutbound(
false);
270 pipeFilter->setApplyOnInbound();
271 pipeFilter->setApplyOnExplicit();
272 pipeFilter->setStopProcessingHere(
false );
273 pipeFilter->setConfigureShortcut(
false );
275 filterList.append( pipeFilter );
280 MailFilter* spamFilter =
new MailFilter();
283 FilterAction* spamFilterAction1 = dict.value( QLatin1String(
"transfer") )->create();
285 spamFilterActions->append( spamFilterAction1 );
287 FilterAction* spamFilterAction2 = dict.value( QLatin1String(
"set status") )->create();
288 spamFilterAction2->argsFromString( QLatin1String(
"P") );
289 spamFilterActions->append( spamFilterAction2 );
291 FilterAction* spamFilterAction3 = dict.value( QLatin1String(
"set status") )->create();
292 spamFilterAction3->argsFromString( QLatin1String(
"R") );
293 spamFilterActions->append( spamFilterAction3 );
295 SearchPattern* spamFilterPattern = spamFilter->pattern();
296 if ( replaceExistingFilters )
297 spamFilterPattern->setName( i18n(
"Spam Handling" ) );
299 spamFilterPattern->setName( uniqueNameFor( i18n(
"Spam Handling" ) ) );
300 spamFilterPattern->setOp( SearchPattern::OpOr );
303 it != endToolList; ++it ) {
305 if ( (*it).isSpamTool() ) {
306 const QByteArray header = (*it).getDetectionHeader().toLatin1();
307 const QString & pattern = (*it).getDetectionPattern();
308 if ( (*it).isUseRegExp() )
309 spamFilterPattern->append(
310 SearchRule::createInstance( header,
311 SearchRule::FuncRegExp, pattern ) );
313 spamFilterPattern->append(
314 SearchRule::createInstance( header,
315 SearchRule::FuncContains, pattern ) );
319 spamFilter->setApplyOnOutbound(
false);
320 spamFilter->setApplyOnInbound();
321 spamFilter->setApplyOnExplicit();
322 spamFilter->setStopProcessingHere(
true );
323 spamFilter->setConfigureShortcut(
false );
324 filterList.append( spamFilter );
328 bool atLeastOneUnsurePattern =
false;
329 MailFilter* unsureFilter =
new MailFilter();
331 FilterAction* unsureFilterAction1 = dict.value( QLatin1String(
"transfer") )->create();
333 unsureFilterActions->append( unsureFilterAction1 );
334 SearchPattern* unsureFilterPattern = unsureFilter->pattern();
335 if ( replaceExistingFilters )
336 unsureFilterPattern->setName( i18n(
"Semi spam (unsure) handling" ) );
338 unsureFilterPattern->setName( uniqueNameFor( i18n(
"Semi spam (unsure) handling" ) ) );
339 unsureFilterPattern->setOp( SearchPattern::OpOr );
345 if ( (*it).isSpamTool() && (*it).hasTristateDetection())
347 atLeastOneUnsurePattern =
true;
348 const QByteArray header = (*it).getDetectionHeader().toLatin1();
349 const QString & pattern = (*it).getDetectionPattern2();
350 if ( (*it).isUseRegExp() )
351 unsureFilterPattern->append(
352 SearchRule::createInstance( header,
353 SearchRule::FuncRegExp, pattern ) );
355 unsureFilterPattern->append(
356 SearchRule::createInstance( header,
357 SearchRule::FuncContains, pattern ) );
361 unsureFilter->setApplyOnOutbound(
false);
362 unsureFilter->setApplyOnInbound();
363 unsureFilter->setApplyOnExplicit();
364 unsureFilter->setStopProcessingHere(
true );
365 unsureFilter->setConfigureShortcut(
false );
367 if ( atLeastOneUnsurePattern )
368 filterList.append( unsureFilter );
374 MailFilter* classSpamFilter =
new MailFilter();
375 classSpamFilter->setIcon( QLatin1String(
"mail-mark-junk") );
377 FilterAction* classSpamFilterActionFirst = dict.value( QLatin1String(
"set status") )->create();
378 classSpamFilterActionFirst->argsFromString( QLatin1String(
"P") );
379 classSpamFilterActions->append( classSpamFilterActionFirst );
382 it != endToolList2; ++it ) {
384 && (*it).useBayesFilter() && !(*it).isDetectionOnly() )
386 FilterAction* classSpamFilterAction = dict.value( QLatin1String(
"execute") )->create();
387 classSpamFilterAction->argsFromString( (*it).getSpamCmd() );
388 classSpamFilterActions->append( classSpamFilterAction );
392 FilterAction* classSpamFilterActionLast = dict.value( QLatin1String(
"transfer" ))->create();
394 classSpamFilterActions->append( classSpamFilterActionLast );
397 SearchPattern* classSpamFilterPattern = classSpamFilter->pattern();
398 if ( replaceExistingFilters )
399 classSpamFilterPattern->setName( i18n(
"Classify as Spam" ) );
401 classSpamFilterPattern->setName( uniqueNameFor( i18n(
"Classify as Spam" ) ) );
402 classSpamFilterPattern->append( SearchRule::createInstance(
"<size>",
403 SearchRule::FuncIsGreaterOrEqual, QLatin1String(
"0") ) );
404 classSpamFilter->setApplyOnOutbound(
false);
405 classSpamFilter->setApplyOnInbound(
false );
406 classSpamFilter->setApplyOnExplicit(
false );
407 classSpamFilter->setStopProcessingHere(
true );
408 classSpamFilter->setConfigureShortcut(
true );
409 classSpamFilter->setConfigureToolbar(
true );
410 classSpamFilter->setToolbarName( i18n(
"Spam" ) );
411 filterList.append( classSpamFilter );
414 MailFilter* classHamFilter =
new MailFilter();
415 classHamFilter->setIcon( QLatin1String(
"mail-mark-notjunk") );
417 FilterAction* classHamFilterActionFirst = dict.value( QLatin1String(
"set status") )->create();
418 classHamFilterActionFirst->argsFromString( QLatin1String(
"H") );
419 classHamFilterActions->append( classHamFilterActionFirst );
420 end = mToolList.constEnd();
424 && (*it).useBayesFilter() && !(*it).isDetectionOnly() )
426 FilterAction* classHamFilterAction = dict.value( QLatin1String(
"execute") )->create();
427 classHamFilterAction->argsFromString( (*it).getHamCmd() );
428 classHamFilterActions->append( classHamFilterAction );
431 end = mToolList.constEnd();
435 && (*it).useBayesFilter() && !(*it).isDetectionOnly() )
437 FilterAction* classHamFilterAction = dict.value( QLatin1String(
"filter app") )->create();
438 classHamFilterAction->argsFromString( (*it).getNoSpamCmd() );
439 classHamFilterActions->append( classHamFilterAction );
442 SearchPattern* classHamFilterPattern = classHamFilter->pattern();
443 if ( replaceExistingFilters )
444 classHamFilterPattern->setName( i18n(
"Classify as NOT Spam" ) );
446 classHamFilterPattern->setName( uniqueNameFor( i18n(
"Classify as NOT Spam" ) ) );
447 classHamFilterPattern->append( SearchRule::createInstance(
"<size>",
448 SearchRule::FuncIsGreaterOrEqual, QLatin1String(
"0") ) );
449 classHamFilter->setApplyOnOutbound(
false);
450 classHamFilter->setApplyOnInbound(
false );
451 classHamFilter->setApplyOnExplicit(
false );
452 classHamFilter->setStopProcessingHere(
true );
453 classHamFilter->setConfigureShortcut(
true );
454 classHamFilter->setConfigureToolbar(
true );
455 classHamFilter->setToolbarName( i18n(
"Ham" ) );
456 filterList.append( classHamFilter );
463 if ( !filterList.isEmpty() )
464 MailCommon::FilterManager::instance()->appendFilters( filterList, replaceExistingFilters );
472 bool supportUnsure =
false;
474 mSpamToolsUsed =
false;
475 mVirusToolsUsed =
false;
480 if ( (*it).isSpamTool() ) {
481 mSpamToolsUsed =
true;
482 if ( (*it).hasTristateDetection() )
483 supportUnsure =
true;
485 if ( (*it).isVirusTool() )
486 mVirusToolsUsed =
true;
488 if ( mSpamToolsUsed && mVirusToolsUsed && supportUnsure )
497 setAppropriate( mSpamRulesPageItem, mSpamToolsUsed );
498 setAppropriate( mSummaryPageItem, mSpamToolsUsed );
501 if ( mVirusToolsUsed )
503 setAppropriate( mVirusRulesPageItem, mVirusToolsUsed );
518 MessageViewer::KCursorSaver busy( MessageViewer::KBusyPtr::busy() );
524 const QString
text( i18n(
"Scanning for %1...", (*it).getId() ) );
526 if ( (*it).isSpamTool() && (*it).isServerBased() ) {
528 QString pattern = (*it).getServerPattern();
529 kDebug() <<
"Testing for server pattern:" << pattern;
530 const Akonadi::AgentInstance::List lst = MailCommon::Util::agentInstances();
531 foreach(
const Akonadi::AgentInstance& type, lst ) {
532 if ( type.status() == Akonadi::AgentInstance::Broken )
534 if ( type.identifier().contains( IMAP_RESOURCE_IDENTIFIER ) ) {
535 OrgKdeAkonadiImapSettingsInterface *iface = PimCommon::Util::createImapSettingsInterface( type.identifier() );
536 if ( iface->isValid() ) {
537 const QString host = iface->imapServer();
538 if ( host.toLower().contains( pattern.toLower() ) ) {
545 else if ( type.identifier().contains( POP3_RESOURCE_IDENTIFIER ) ) {
546 OrgKdeAkonadiPOP3SettingsInterface *iface = MailCommon::Util::createPop3SettingsInterface( type.identifier() );
547 if ( iface->isValid() ) {
548 const QString host = iface->host();
549 if ( host.toLower().contains( pattern.toLower() ) ) {
560 qApp->processEvents( QEventLoop::ExcludeUserInputEvents, 200 );
561 if ( !checkForProgram( (*it).getExecutable() ) ) {
569 ? i18n(
"Scanning for anti-spam tools finished.")
570 : i18n(
"Scanning for anti-virus tools finished.") );
573 ? i18n(
"<p>Sorry, no spam detection tools have been found. "
574 "Install your spam detection software and "
575 "re-run this wizard.</p>")
576 : i18n(
"Scanning complete. No anti-virus tools found.") );
585 KToolInvocation::invokeHelp( QLatin1String(
"the-anti-spam-wizard"), QLatin1String(
"kmail") );
587 KToolInvocation::invokeHelp( QLatin1String(
"the-anti-virus-wizard"), QLatin1String(
"kmail") );
595 QString replaceFilters;
603 text = i18n(
"<p>Messages classified as spam are marked as read."
604 "<br />Spam messages are moved into the folder named <i>%1</i>.</p>"
607 text = i18n(
"<p>Messages classified as spam are marked as read."
608 "<br />Spam messages are not moved into a certain folder.</p>" );
612 text = i18n(
"<p>Messages classified as spam are not marked as read."
613 "<br />Spam messages are moved into the folder named <i>%1</i>.</p>"
616 text = i18n(
"<p>Messages classified as spam are not marked as read."
617 "<br />Spam messages are not moved into a certain folder.</p>" );
623 (*it).isSpamTool() && !(*it).isDetectionOnly() ) {
624 sortFilterOnExistance( (*it).getFilterName(), newFilters, replaceFilters );
627 sortFilterOnExistance( i18n(
"Spam Handling" ), newFilters, replaceFilters );
631 bool atLeastOneUnsurePattern =
false;
632 end = mToolList.constEnd();
636 if ( (*it).isSpamTool() && (*it).hasTristateDetection()) {
637 atLeastOneUnsurePattern =
true;
642 if ( atLeastOneUnsurePattern ) {
643 sortFilterOnExistance( i18n(
"Semi spam (unsure) handling" ),
644 newFilters, replaceFilters );
645 text += i18n(
"<p>The folder for messages classified as unsure (probably spam) is <i>%1</i>.</p>"
651 sortFilterOnExistance( i18n(
"Classify as Spam" ),
652 newFilters, replaceFilters );
653 sortFilterOnExistance( i18n(
"Classify as NOT Spam" ),
654 newFilters, replaceFilters );
657 if ( !newFilters.isEmpty() )
658 text += i18n(
"<p>The wizard will create the following filters:<ul>%1</ul></p>"
660 if ( !replaceFilters.isEmpty() )
661 text += i18n(
"<p>The wizard will replace the following filters:<ul>%1</ul></p>"
669 int AntiSpamWizard::checkForProgram(
const QString &executable )
const
671 kDebug() <<
"Testing for executable:" << executable;
673 process.setShellCommand( executable );
674 return process.execute ();
678 bool AntiSpamWizard::anyVirusOptionChecked()
const
685 const QString AntiSpamWizard::uniqueNameFor(
const QString & name )
687 return MailCommon::FilterManager::instance()->createUniqueFilterName( name );
691 void AntiSpamWizard::sortFilterOnExistance(
692 const QString & intendedFilterName,
693 QString & newFilters, QString & replaceFilters )
695 if ( uniqueNameFor( intendedFilterName ) == intendedFilterName )
696 newFilters += QLatin1String(
"<li>") + intendedFilterName + QLatin1String(
"</li>");
698 replaceFilters += QLatin1String(
"<li>") + intendedFilterName + QLatin1String(
"</li>");
704 int configVersion,
int prio,
const QString &name,
const QString &exec,
705 const QString &url,
const QString &filter,
const QString &detection,
706 const QString &spam,
const QString &ham,
const QString &noSpam,
707 const QString &header,
const QString &pattern,
const QString &pattern2,
708 const QString &serverPattern,
bool detectionOnly,
bool regExp,
709 bool bayesFilter,
bool tristateDetection,
WizardMode type )
710 : mId( toolId ), mVersion( configVersion ), mPrio( prio ),
711 mVisibleName( name ), mExecutable( exec ), mWhatsThisText( url ),
712 mFilterName( filter ), mDetectCmd( detection ), mSpamCmd( spam ),
713 mHamCmd( ham ), mNoSpamCmd( noSpam ), mDetectionHeader( header ),
714 mDetectionPattern( pattern ), mDetectionPattern2( pattern2 ),
715 mServerPattern( serverPattern ), mDetectionOnly( detectionOnly ),
716 mUseRegExp( regExp ), mSupportsBayesFilter( bayesFilter ),
717 mSupportsUnsure( tristateDetection ), mType( type )
724 return !mServerPattern.isEmpty();
731 : mToolList( configList ),
735 mConfig = KSharedConfig::openConfig( QLatin1String(
"kmail.antispamrc") );
737 mConfig = KSharedConfig::openConfig( QLatin1String(
"kmail.antivirusrc") );
747 QString groupName = ( mMode ==
AntiSpam )
748 ? QString::fromLatin1(
"Spamtool #%1")
749 : QString::fromLatin1(
"Virustool #%1");
751 mConfig->setReadDefaults(
true );
752 KConfigGroup general( mConfig,
"General" );
753 const int registeredTools = general.readEntry(
"tools", 0 );
754 for (
int i = 1; i <= registeredTools; ++i)
756 KConfigGroup toolConfig( mConfig, groupName.arg( i ) );
757 if( !toolConfig.readEntry(
"HeadersOnly",
false ) )
758 mToolList.append( readToolConfig( toolConfig ) );
763 mConfig->setReadDefaults(
false );
764 KConfigGroup user_general( mConfig,
"General" );
765 const int user_registeredTools = user_general.readEntry(
"tools", 0 );
766 for (
int i = 1; i <= user_registeredTools; ++i)
768 KConfigGroup toolConfig( mConfig, groupName.arg( i ) );
769 if( !toolConfig.readEntry(
"HeadersOnly",
false ) )
770 mergeToolConfig( readToolConfig( toolConfig ) );
776 if ( registeredTools < 1 && user_registeredTools < 1 )
777 mToolList.append( createDummyConfig() );
784 AntiSpamWizard::ConfigReader::readToolConfig( KConfigGroup & configGroup )
786 const QString
id = configGroup.readEntry(
"Ident" );
787 const int version = configGroup.readEntry(
"Version", 0 );
789 kDebug() <<
"Found predefined tool:" << id;
790 kDebug() <<
"With config version :" << version;
792 const int prio = configGroup.readEntry(
"Priority", 1 );
793 const QString name = configGroup.readEntry(
"VisibleName" );
794 const QString executable = configGroup.readEntry(
"Executable" );
795 const QString url = configGroup.readEntry(
"URL" );
796 const QString filterName = configGroup.readEntry(
"PipeFilterName" );
797 const QString detectCmd = configGroup.readEntry(
"PipeCmdDetect" );
798 const QString spamCmd = configGroup.readEntry(
"ExecCmdSpam" );
799 const QString hamCmd = configGroup.readEntry(
"ExecCmdHam" );
800 const QString noSpamCmd = configGroup.readEntry(
"PipeCmdNoSpam" );
801 const QString header = configGroup.readEntry(
"DetectionHeader" );
802 const QString pattern = configGroup.readEntry(
"DetectionPattern" );
803 const QString pattern2 = configGroup.readEntry(
"DetectionPattern2" );
804 const QString serverPattern = configGroup.readEntry(
"ServerPattern" );
805 const bool detectionOnly = configGroup.readEntry(
"DetectionOnly",
false );
806 const bool useRegExp = configGroup.readEntry(
"UseRegExp",
false );
807 const bool supportsBayes = configGroup.readEntry(
"SupportsBayes",
false );
808 const bool supportsUnsure = configGroup.readEntry(
"SupportsUnsure",
false );
810 filterName, detectCmd, spamCmd, hamCmd, noSpamCmd,
811 header, pattern, pattern2, serverPattern,
812 detectionOnly, useRegExp,
813 supportsBayes, supportsUnsure, mMode );
819 return SpamToolConfig( QLatin1String(
"spamassassin"), 0, 1,
820 QLatin1String(
"SpamAssassin"), QLatin1String(
"spamassassin -V"),
821 QLatin1String(
"http://spamassassin.org"), QLatin1String(
"SpamAssassin Check"),
822 QLatin1String(
"spamassassin -L"),
823 QLatin1String(
"sa-learn -L --spam --no-sync --single"),
824 QLatin1String(
"sa-learn -L --ham --no-sync --single"),
825 QLatin1String(
"spamassassin -d"),
826 QLatin1String(
"X-Spam-Flag"), QLatin1String(
"yes"), QString(), QString(),
827 false,
false,
true,
false,
AntiSpam );
838 kDebug() <<
"Check against tool:" << (*it).getId();
839 kDebug() <<
"Against version :" << (*it).getVersion();
841 if ( (*it).getId() == config.
getId() )
844 if ( (*it).getVersion() < config.
getVersion() )
847 kDebug() <<
"Replacing config ...";
849 mToolList.erase( it );
850 mToolList.append( config );
856 mToolList.append( config );
860 void AntiSpamWizard::ConfigReader::sortToolList()
863 SpamToolConfig config;
865 while ( !mToolList.isEmpty() ) {
871 if ( (*it).getPrio() > priority ) {
872 priority = (*it).getPrio();
877 tmpList.append( config );
878 mToolList.erase( highest );
883 mToolList.append( (*it) );
890 const QString *bannerName )
893 setObjectName( name );
894 QString banner = QLatin1String(
"kmwizard.png");
895 if ( bannerName && !bannerName->isEmpty() )
896 banner = *bannerName;
897 mLayout =
new QHBoxLayout(
this );
898 mLayout->setSpacing( KDialog::spacingHint() );
899 mLayout->setMargin( KDialog::marginHint() );
901 QVBoxLayout * sideLayout =
new QVBoxLayout();
902 mLayout->addItem( sideLayout );
903 mLayout->addItem(
new QSpacerItem( 5, 5, QSizePolicy::Minimum, QSizePolicy::Expanding ) );
905 mBannerLabel =
new QLabel(
this );
906 mBannerLabel->setPixmap( UserIcon(banner) );
907 mBannerLabel->setScaledContents(
false );
908 mBannerLabel->setFrameShape( QFrame::StyledPanel );
909 mBannerLabel->setFrameShadow( QFrame::Sunken );
910 mBannerLabel->setSizePolicy( QSizePolicy::Fixed, QSizePolicy::Fixed );
912 sideLayout->addWidget( mBannerLabel );
913 sideLayout->addItem(
new QSpacerItem( 5, 5, QSizePolicy::Minimum, QSizePolicy::Expanding ) );
919 QWidget * parent,
const QString &name )
922 QBoxLayout * layout =
new QVBoxLayout();
925 mIntroText =
new QTextEdit(
this );
929 "The wizard will search for any tools to do spam detection\n"
930 "and setup KMail to work with them."
933 "<p>Here you can get some assistance in setting up KMail's filter "
934 "rules to use some commonly-known anti-virus tools.</p>"
935 "<p>The wizard can detect those tools on your computer as "
936 "well as create filter rules to classify messages using these "
937 "tools and to separate messages containing viruses. "
938 "The wizard will not take any existing filter "
939 "rules into consideration: it will always append the new rules.</p>"
940 "<p><b>Warning:</b> As KMail appears to be frozen during the scan of the "
941 "messages for viruses, you may encounter problems with "
942 "the responsiveness of KMail because anti-virus tool "
943 "operations are usually time consuming; please consider "
944 "deleting the filter rules created by the wizard to get "
945 "back to the former behavior.</p>"
947 mIntroText->setReadOnly(
true );
948 mIntroText->setSizePolicy( QSizePolicy( QSizePolicy::Expanding, QSizePolicy::Expanding ) );
949 layout->addWidget( mIntroText );
951 mScanProgressText =
new QLabel(
this );
952 mScanProgressText->clear();
953 mScanProgressText->setWordWrap(
true );
954 layout->addWidget( mScanProgressText );
958 mToolsList->setSelectionMode( QAbstractItemView::MultiSelection );
959 mToolsList->setLayoutMode( QListView::Batched );
960 mToolsList->setBatchSize( 10 );
961 mToolsList->setSizePolicy( QSizePolicy( QSizePolicy::Expanding, QSizePolicy::Maximum ) );
962 layout->addWidget( mToolsList );
963 connect( mToolsList->selectionModel(), SIGNAL(
selectionChanged(QItemSelection,QItemSelection)),
964 this, SLOT(processSelectionChange()) );
966 mSelectionHint =
new QLabel(
this );
967 mSelectionHint->clear();
968 mSelectionHint->setWordWrap(
true );
969 layout->addWidget( mSelectionHint );
975 mScanProgressText->setText( toolName );
981 mToolsList->addItem( visibleName );
982 if ( !mToolsList->isVisible() )
985 mToolsList->selectionModel()->clearSelection();
986 mToolsList->setCurrentRow( 0 );
987 mSelectionHint->setText( i18n(
"<p>Please select the tools to be used "
988 "for the detection and go "
989 "to the next page.</p>") );
996 return (!foundItems.isEmpty() && foundItems[0]->isSelected());
1000 void ASWizInfoPage::processSelectionChange()
1010 QVBoxLayout *layout =
new QVBoxLayout();
1013 mMarkRules =
new QCheckBox( i18n(
"&Mark detected spam messages as read"),
this );
1014 mMarkRules->setWhatsThis(
1015 i18n(
"Mark messages which have been classified as spam as read.") );
1016 layout->addWidget( mMarkRules);
1018 mMoveSpamRules =
new QCheckBox( i18n(
"Move &known spam to:"),
this );
1019 mMoveSpamRules->setWhatsThis(
1020 i18n(
"The default folder for spam messages is the trash folder, "
1021 "but you may change that in the folder view below.") );
1022 layout->addWidget( mMoveSpamRules );
1024 mFolderReqForSpamFolder =
new FolderRequester(
this );
1025 mFolderReqForSpamFolder->setCollection( CommonKernel->trashCollectionFolder() );
1026 mFolderReqForSpamFolder->setMustBeReadWrite(
true );
1027 mFolderReqForSpamFolder->setShowOutbox(
false );
1029 QHBoxLayout *hLayout1 =
new QHBoxLayout();
1030 layout->addItem( hLayout1 );
1031 hLayout1->addSpacing( KDialog::spacingHint() * 3 );
1032 hLayout1->addWidget( mFolderReqForSpamFolder );
1034 mMoveUnsureRules =
new QCheckBox( i18n(
"Move &probable spam to:"),
this );
1035 mMoveUnsureRules->setWhatsThis(
1036 i18n(
"The default folder is the inbox folder, but you may change that "
1037 "in the folder view below.<p>"
1038 "Not all tools support a classification as unsure. If you have not "
1039 "selected a capable tool, you cannot select a folder as well.</p>") );
1040 layout->addWidget( mMoveUnsureRules );
1042 mFolderReqForUnsureFolder =
new FolderRequester(
this );
1043 mFolderReqForUnsureFolder->setCollection( CommonKernel->inboxCollectionFolder() );
1044 mFolderReqForUnsureFolder->setMustBeReadWrite(
true );
1045 mFolderReqForUnsureFolder->setShowOutbox(
false );
1047 QHBoxLayout *hLayout2 =
new QHBoxLayout();
1048 layout->addItem( hLayout2 );
1049 hLayout2->addSpacing( KDialog::spacingHint() * 3 );
1050 hLayout2->addWidget( mFolderReqForUnsureFolder );
1052 layout->addStretch();
1054 connect( mMarkRules, SIGNAL(clicked()),
1055 this, SLOT(processSelectionChange()) );
1056 connect( mMoveSpamRules, SIGNAL(clicked()),
1057 this, SLOT(processSelectionChange()) );
1058 connect( mMoveUnsureRules, SIGNAL(clicked()),
1059 this, SLOT(processSelectionChange()) );
1060 connect( mFolderReqForSpamFolder, SIGNAL(folderChanged(Akonadi::Collection)),
1061 this, SLOT(processSelectionChange(Akonadi::Collection)) );
1062 connect( mFolderReqForUnsureFolder, SIGNAL(folderChanged(Akonadi::Collection)),
1063 this, SLOT(processSelectionChange(Akonadi::Collection)) );
1065 mMarkRules->setChecked(
true );
1066 mMoveSpamRules->setChecked(
true );
1072 return mMarkRules->isChecked();
1078 return mMoveSpamRules->isChecked();
1084 return mMoveUnsureRules->isChecked();
1099 if ( mFolderReqForSpamFolder->hasCollection() )
1100 return mFolderReqForSpamFolder->collection();
1102 return CommonKernel->trashCollectionFolder();
1108 if ( mFolderReqForUnsureFolder->hasCollection() )
1109 return mFolderReqForUnsureFolder->collection();
1111 return CommonKernel->inboxCollectionFolder();
1125 void ASWizSpamRulesPage::processSelectionChange()
1127 mFolderReqForSpamFolder->setEnabled( mMoveSpamRules->isChecked() );
1128 mFolderReqForUnsureFolder->setEnabled( mMoveUnsureRules->isChecked() );
1133 void ASWizSpamRulesPage::processSelectionChange(
const Akonadi::Collection& )
1135 processSelectionChange();
1141 mMoveUnsureRules->setEnabled( enabled );
1142 mMoveUnsureRules->setVisible( enabled );
1143 mFolderReqForUnsureFolder->setEnabled( enabled );
1144 mFolderReqForUnsureFolder->setVisible( enabled );
1149 mMarkRules->setEnabled( enabled );
1150 mMarkRules->setChecked( enabled );
1151 mMoveSpamRules->setEnabled( enabled );
1152 mMoveSpamRules->setChecked( enabled );
1160 QGridLayout *grid =
new QGridLayout();
1162 grid->setSpacing( KDialog::spacingHint() );
1164 mPipeRules =
new QCheckBox( i18n(
"Check messages using the anti-virus tools"),
this );
1165 mPipeRules->setWhatsThis(
1166 i18n(
"Let the anti-virus tools check your messages. The wizard "
1167 "will create appropriate filters. The messages are usually "
1168 "marked by the tools so that following filters can react "
1169 "on this and, for example, move virus messages to a special folder.") );
1170 grid->addWidget( mPipeRules, 0, 0 );
1172 mMoveRules =
new QCheckBox( i18n(
"Move detected viral messages to the selected folder"),
this );
1173 mMoveRules->setWhatsThis(
1174 i18n(
"A filter to detect messages classified as virus-infected and to move "
1175 "those messages into a predefined folder is created. The "
1176 "default folder is the trash folder, but you may change that "
1177 "in the folder view.") );
1178 grid->addWidget( mMoveRules, 1, 0 );
1180 mMarkRules =
new QCheckBox( i18n(
"Additionally, mark detected viral messages as read"),
this );
1181 mMarkRules->setEnabled(
false );
1182 mMarkRules->setWhatsThis(
1183 i18n(
"Mark messages which have been classified as "
1184 "virus-infected as read, as well as moving them "
1185 "to the selected folder.") );
1186 grid->addWidget( mMarkRules, 2, 0 );
1187 FolderTreeWidget::TreeViewOptions opt = FolderTreeWidget::None;
1188 opt |= FolderTreeWidget::UseDistinctSelectionModel;
1190 FolderTreeWidgetProxyModel::FolderTreeWidgetProxyModelOptions optReadableProxy = FolderTreeWidgetProxyModel::None;
1191 optReadableProxy |= FolderTreeWidgetProxyModel::HideVirtualFolder;
1192 optReadableProxy |= FolderTreeWidgetProxyModel::HideOutboxFolder;
1194 mFolderTree =
new FolderTreeWidget(
this, 0, opt, optReadableProxy );
1195 mFolderTree->readConfig();
1196 mFolderTree->folderTreeView()->expandAll();
1197 mFolderTree->folderTreeWidgetProxyModel()->setAccessRights( Akonadi::Collection::CanCreateCollection );
1199 mFolderTree->selectCollectionFolder( CommonKernel->trashCollectionFolder() );
1200 mFolderTree->folderTreeView()->setDragDropMode( QAbstractItemView::NoDragDrop );
1202 mFolderTree->disableContextMenuAndExtraColumn();
1203 grid->addWidget( mFolderTree, 3, 0 );
1205 connect( mPipeRules, SIGNAL(clicked()),
1206 this, SLOT(processSelectionChange()) );
1207 connect( mMoveRules, SIGNAL(clicked()),
1208 this, SLOT(processSelectionChange()) );
1209 connect( mMarkRules, SIGNAL(clicked()),
1210 this, SLOT(processSelectionChange()) );
1211 connect( mMoveRules, SIGNAL(toggled(
bool)),
1212 mMarkRules, SLOT(setEnabled(
bool)) );
1218 return mPipeRules->isChecked();
1224 return mMoveRules->isChecked();
1229 return mMarkRules->isChecked();
1235 if ( mFolderTree->selectedCollection().isValid() )
1236 return QString::number( mFolderTree->selectedCollection().id() );
1238 return QString::number( CommonKernel->trashCollectionFolder().id() );
1241 void ASWizVirusRulesPage::processSelectionChange()
1251 QBoxLayout * layout =
new QVBoxLayout();
1254 mSummaryText =
new QLabel(
this );
1255 layout->addWidget( mSummaryText );
1256 layout->addStretch();
1262 mSummaryText->setText( text );
1266 #include "antispamwizard.moc"
Akonadi::Collection selectedUnsureCollection() const
void setSummaryText(const QString &text)
QString selectedUnsureCollectionName() const
ASWizPage(QWidget *parent, const QString &name, const QString *bannerName=0)
void addAvailableTool(const QString &visibleName)
bool markAsReadSelected() const
void checkProgramsSelections()
Modify the status of the wizard to reflect the selection of spam tools.
QString selectedSpamCollectionName() const
virtual QByteArray text(quint32 serialNumber) const =0
WizardMode
The wizard can be used for setting up anti-spam tools and for setting up anti-virus tools...
void readAndMergeConfig()
ASWizSummaryPage(QWidget *parent, const QString &name)
bool moveUnsureSelected() const
QList< SpamToolConfig > & getToolList()
AntiSpamWizard(WizardMode mode, QWidget *parent)
Constructor that needs to initialize from the main folder tree of KMail.
QString selectedFolderName() const
ASWizVirusRulesPage(QWidget *parent, const QString &name)
QString selectedUnsureCollectionId() const
bool markReadRulesSelected() const
ConfigReader(WizardMode mode, QList< SpamToolConfig > &configList)
void slotBuildSummary()
Create the summary text based on the current settings.
void setScanProgressText(const QString &toolName)
void accept()
Evaluate the settings made and create the appropriate filter rules.
void allowUnsureFolderSelection(bool enabled)
bool isProgramSelected(const QString &visibleName) const
Akonadi::Collection selectedSpamCollection() const
Instances of this class control reading the configuration of the anti-spam tools from global and user...
ASWizSpamRulesPage(QWidget *parent, const QString &name)
void allowMoveSpam(bool enabled)
bool pipeRulesSelected() const
void slotHelpClicked()
Show a help topic.
void checkVirusRulesSelections()
Modify the status of the wizard to reflect the selected functionality.
bool moveRulesSelected() const
bool moveSpamSelected() const
QString selectedSpamCollectionId() const
ASWizInfoPage(AntiSpamWizard::WizardMode mode, QWidget *parent, const QString &name)
void checkToolAvailability()
Check if the spam tools are available via the PATH.