kmail

antispamwizard.cpp
1/*
2 This file is part of KMail.
3 Copyright (c) 2003 Andreas Gungl <a.gungl@gmx.de>
4
5 KMail is free software; you can redistribute it and/or modify it
6 under the terms of the GNU General Public License, version 2, as
7 published by the Free Software Foundation.
8
9 KMail is distributed in the hope that it will be useful, but
10 WITHOUT ANY WARRANTY; without even the implied warranty of
11 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 General Public License for more details.
13
14 You should have received a copy of the GNU General Public License
15 along with this program; if not, write to the Free Software
16 Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
17
18 In addition, as a special exception, the copyright holders give
19 permission to link the code of this program with any edition of
20 the TQt library by Trolltech AS, Norway (or with modified versions
21 of TQt that use the same license as TQt), and distribute linked
22 combinations including the two. You must obey the GNU General
23 Public License in all respects for all of the code used other than
24 TQt. If you modify this file, you may extend this exception to
25 your version of the file, but you are not obligated to do so. If
26 you do not wish to do so, delete this exception statement from
27 your version.
28*/
29
30#include "antispamwizard.h"
31#include "kcursorsaver.h"
32#include "accountmanager.h"
33#include "kmfilter.h"
34#include "kmfilteraction.h"
35#include "kmfiltermgr.h"
36#include "kmkernel.h"
37#include "kmfoldertree.h"
38#include "kmmainwin.h"
39#include "networkaccount.h"
40#include "folderrequester.h"
41
42#include <tdeaction.h>
43#include <tdeapplication.h>
44#include <kdebug.h>
45#include <kdialog.h>
46#include <kiconloader.h>
47#include <tdelocale.h>
48#include <tdemessagebox.h>
49#include <tdeprocess.h>
50
51#include <tqdom.h>
52#include <tqlabel.h>
53#include <tqlayout.h>
54#include <tqtooltip.h>
55#include <tqwhatsthis.h>
56
57using namespace KMail;
58
59AntiSpamWizard::AntiSpamWizard( WizardMode mode,
60 TQWidget* parent, KMFolderTree * mainFolderTree )
61 : KWizard( parent ),
62 mInfoPage( 0 ),
63 mSpamRulesPage( 0 ),
64 mVirusRulesPage( 0 ),
65 mSummaryPage( 0 ),
66 mMode( mode )
67{
68 // read the configuration for the anti-spam tools
69 ConfigReader reader( mMode, mToolList );
70 reader.readAndMergeConfig();
71 mToolList = reader.getToolList();
72
73#ifndef NDEBUG
74 if ( mMode == AntiSpam )
75 kdDebug(5006) << endl << "Considered anti-spam tools: " << endl;
76 else
77 kdDebug(5006) << endl << "Considered anti-virus tools: " << endl;
78#endif
79 for ( TQValueListIterator<SpamToolConfig> it = mToolList.begin();
80 it != mToolList.end(); ++it ) {
81#ifndef NDEBUG
82 kdDebug(5006) << "Predefined tool: " << (*it).getId() << endl;
83 kdDebug(5006) << "Config version: " << (*it).getVersion() << endl;
84 kdDebug(5006) << "Selection priority: " << (*it).getPrio() << endl;
85 kdDebug(5006) << "Displayed name: " << (*it).getVisibleName() << endl;
86 kdDebug(5006) << "Executable: " << (*it).getExecutable() << endl;
87 kdDebug(5006) << "WhatsThis URL: " << (*it).getWhatsThisText() << endl;
88 kdDebug(5006) << "Filter name: " << (*it).getFilterName() << endl;
89 kdDebug(5006) << "Detection command: " << (*it).getDetectCmd() << endl;
90 kdDebug(5006) << "Learn spam command: " << (*it).getSpamCmd() << endl;
91 kdDebug(5006) << "Learn ham command: " << (*it).getHamCmd() << endl;
92 kdDebug(5006) << "Detection header: " << (*it).getDetectionHeader() << endl;
93 kdDebug(5006) << "Detection pattern: " << (*it).getDetectionPattern() << endl;
94 kdDebug(5006) << "Use as RegExp: " << (*it).isUseRegExp() << endl;
95 kdDebug(5006) << "Supports Bayes Filter: " << (*it).useBayesFilter() << endl;
96 kdDebug(5006) << "Type: " << (*it).getType() << endl << endl;
97#endif
98 }
99
100 setCaption( ( mMode == AntiSpam ) ? i18n( "Anti-Spam Wizard" )
101 : i18n( "Anti-Virus Wizard" ) );
102 mInfoPage = new ASWizInfoPage( mMode, 0, "" );
103 addPage( mInfoPage,
104 ( mMode == AntiSpam )
105 ? i18n( "Welcome to the KMail Anti-Spam Wizard" )
106 : i18n( "Welcome to the KMail Anti-Virus Wizard" ) );
107 connect( mInfoPage, TQ_SIGNAL( selectionChanged( void ) ),
108 this, TQ_SLOT( checkProgramsSelections( void ) ) );
109
110 if ( mMode == AntiSpam ) {
111 mSpamRulesPage = new ASWizSpamRulesPage( 0, "", mainFolderTree );
112 addPage( mSpamRulesPage, i18n( "Options to fine-tune the handling of spam messages" ));
113 connect( mSpamRulesPage, TQ_SIGNAL( selectionChanged( void ) ),
114 this, TQ_SLOT( slotBuildSummary( void ) ) );
115 }
116 else {
117 mVirusRulesPage = new ASWizVirusRulesPage( 0, "", mainFolderTree );
118 addPage( mVirusRulesPage, i18n( "Options to fine-tune the handling of virus messages" ));
119 connect( mVirusRulesPage, TQ_SIGNAL( selectionChanged( void ) ),
120 this, TQ_SLOT( checkVirusRulesSelections( void ) ) );
121 }
122
123 connect( this, TQ_SIGNAL( helpClicked( void) ),
124 this, TQ_SLOT( slotHelpClicked( void ) ) );
125
126 setNextEnabled( mInfoPage, false );
127
128 if ( mMode == AntiSpam ) {
129 mSummaryPage = new ASWizSummaryPage( 0, "" );
130 addPage( mSummaryPage, i18n( "Summary of changes to be made by this wizard" ) );
131 setNextEnabled( mSpamRulesPage, true );
132 setFinishEnabled( mSummaryPage, true );
133 }
134
135 TQTimer::singleShot( 0, this, TQ_SLOT( checkToolAvailability( void ) ) );
136}
137
138
140{
141 if ( mSpamRulesPage ) {
142 kdDebug( 5006 ) << "Folder name for messages classified as spam is "
143 << mSpamRulesPage->selectedSpamFolderName() << endl;
144 kdDebug( 5006 ) << "Folder name for messages classified as unsure is "
145 << mSpamRulesPage->selectedUnsureFolderName() << endl;
146 }
147 if ( mVirusRulesPage )
148 kdDebug( 5006 ) << "Folder name for viruses is "
149 << mVirusRulesPage->selectedFolderName() << endl;
150
152 TQValueList<KMFilter*> filterList;
153 bool replaceExistingFilters = false;
154
155 // Let's start with virus detection and handling,
156 // so we can avoid spam checks for viral messages
157 if ( mMode == AntiVirus ) {
158 for ( TQValueListIterator<SpamToolConfig> it = mToolList.begin();
159 it != mToolList.end(); ++it ) {
160 if ( mInfoPage->isProgramSelected( (*it).getVisibleName() ) &&
161 ( mVirusRulesPage->pipeRulesSelected() && (*it).isVirusTool() ) )
162 {
163 // pipe messages through the anti-virus tools,
164 // one single filter for each tool
165 // (could get combined but so it's easier to understand for the user)
166 KMFilter* pipeFilter = new KMFilter();
167 TQPtrList<KMFilterAction>* pipeFilterActions = pipeFilter->actions();
168 KMFilterAction* pipeFilterAction = dict["filter app"]->create();
169 pipeFilterAction->argsFromString( (*it).getDetectCmd() );
170 pipeFilterActions->append( pipeFilterAction );
171 KMSearchPattern* pipeFilterPattern = pipeFilter->pattern();
172 pipeFilterPattern->setName( uniqueNameFor( (*it).getFilterName() ) );
173 pipeFilterPattern->append( KMSearchRule::createInstance( "<size>",
174 KMSearchRule::FuncIsGreaterOrEqual, "0" ) );
175 pipeFilter->setApplyOnOutbound( false);
176 pipeFilter->setApplyOnInbound();
177 pipeFilter->setApplyOnExplicit();
178 pipeFilter->setStopProcessingHere( false );
179 pipeFilter->setConfigureShortcut( false );
180
181 filterList.append( pipeFilter );
182 }
183 }
184
185 if ( mVirusRulesPage->moveRulesSelected() )
186 {
187 // Sort out viruses depending on header fields set by the tools
188 KMFilter* virusFilter = new KMFilter();
189 TQPtrList<KMFilterAction>* virusFilterActions = virusFilter->actions();
190 KMFilterAction* virusFilterAction1 = dict["transfer"]->create();
191 virusFilterAction1->argsFromString( mVirusRulesPage->selectedFolderName() );
192 virusFilterActions->append( virusFilterAction1 );
193 if ( mVirusRulesPage->markReadRulesSelected() ) {
194 KMFilterAction* virusFilterAction2 = dict["set status"]->create();
195 virusFilterAction2->argsFromString( "R" ); // Read
196 virusFilterActions->append( virusFilterAction2 );
197 }
198 KMSearchPattern* virusFilterPattern = virusFilter->pattern();
199 virusFilterPattern->setName( uniqueNameFor( i18n( "Virus handling" ) ) );
200 virusFilterPattern->setOp( KMSearchPattern::OpOr );
201 for ( TQValueListIterator<SpamToolConfig> it = mToolList.begin();
202 it != mToolList.end(); ++it ) {
203 if ( mInfoPage->isProgramSelected( (*it).getVisibleName() ))
204 {
205 if ( (*it).isVirusTool() )
206 {
207 const TQCString header = (*it).getDetectionHeader().ascii();
208 const TQString & pattern = (*it).getDetectionPattern();
209 if ( (*it).isUseRegExp() )
210 virusFilterPattern->append(
212 KMSearchRule::FuncRegExp, pattern ) );
213 else
214 virusFilterPattern->append(
216 KMSearchRule::FuncContains, pattern ) );
217 }
218 }
219 }
220 virusFilter->setApplyOnOutbound( false);
221 virusFilter->setApplyOnInbound();
222 virusFilter->setApplyOnExplicit();
223 virusFilter->setStopProcessingHere( true );
224 virusFilter->setConfigureShortcut( false );
225
226 filterList.append( virusFilter );
227 }
228 }
229 else { // AntiSpam mode
230 // TODO Existing filters with same name are replaced. This is hardcoded
231 // ATM and needs to be replaced with a value from a (still missing)
232 // checkbox in the GUI. At least, the replacement is announced in the GUI.
233 replaceExistingFilters = true;
234 for ( TQValueListIterator<SpamToolConfig> it = mToolList.begin();
235 it != mToolList.end(); ++it ) {
236 if ( mInfoPage->isProgramSelected( (*it).getVisibleName() ) &&
237 (*it).isSpamTool() && !(*it).isDetectionOnly() )
238 {
239 // pipe messages through the anti-spam tools,
240 // one single filter for each tool
241 // (could get combined but so it's easier to understand for the user)
242 KMFilter* pipeFilter = new KMFilter();
243 TQPtrList<KMFilterAction>* pipeFilterActions = pipeFilter->actions();
244 KMFilterAction* pipeFilterAction = dict["filter app"]->create();
245 pipeFilterAction->argsFromString( (*it).getDetectCmd() );
246 pipeFilterActions->append( pipeFilterAction );
247 KMSearchPattern* pipeFilterPattern = pipeFilter->pattern();
248 if ( replaceExistingFilters )
249 pipeFilterPattern->setName( (*it).getFilterName() );
250 else
251 pipeFilterPattern->setName( uniqueNameFor( (*it).getFilterName() ) );
252 pipeFilterPattern->append( KMSearchRule::createInstance( "<size>",
253 KMSearchRule::FuncIsLessOrEqual, "256000" ) );
254 pipeFilter->setApplyOnOutbound( false);
255 pipeFilter->setApplyOnInbound();
256 pipeFilter->setApplyOnExplicit();
257 pipeFilter->setStopProcessingHere( false );
258 pipeFilter->setConfigureShortcut( false );
259
260 filterList.append( pipeFilter );
261 }
262 }
263
264 // Sort out spam depending on header fields set by the tools
265 KMFilter* spamFilter = new KMFilter();
266 TQPtrList<KMFilterAction>* spamFilterActions = spamFilter->actions();
267 if ( mSpamRulesPage->moveSpamSelected() )
268 {
269 KMFilterAction* spamFilterAction1 = dict["transfer"]->create();
270 spamFilterAction1->argsFromString( mSpamRulesPage->selectedSpamFolderName() );
271 spamFilterActions->append( spamFilterAction1 );
272 }
273 KMFilterAction* spamFilterAction2 = dict["set status"]->create();
274 spamFilterAction2->argsFromString( "P" ); // Spam
275 spamFilterActions->append( spamFilterAction2 );
276 if ( mSpamRulesPage->markAsReadSelected() ) {
277 KMFilterAction* spamFilterAction3 = dict["set status"]->create();
278 spamFilterAction3->argsFromString( "R" ); // Read
279 spamFilterActions->append( spamFilterAction3 );
280 }
281 KMSearchPattern* spamFilterPattern = spamFilter->pattern();
282 if ( replaceExistingFilters )
283 spamFilterPattern->setName( i18n( "Spam handling" ) );
284 else
285 spamFilterPattern->setName( uniqueNameFor( i18n( "Spam handling" ) ) );
286 spamFilterPattern->setOp( KMSearchPattern::OpOr );
287 for ( TQValueListIterator<SpamToolConfig> it = mToolList.begin();
288 it != mToolList.end(); ++it ) {
289 if ( mInfoPage->isProgramSelected( (*it).getVisibleName() ) )
290 {
291 if ( (*it).isSpamTool() )
292 {
293 const TQCString header = (*it).getDetectionHeader().ascii();
294 const TQString & pattern = (*it).getDetectionPattern();
295 if ( (*it).isUseRegExp() )
296 spamFilterPattern->append(
298 KMSearchRule::FuncRegExp, pattern ) );
299 else
300 spamFilterPattern->append(
302 KMSearchRule::FuncContains, pattern ) );
303 }
304 }
305 }
306 spamFilter->setApplyOnOutbound( false);
307 spamFilter->setApplyOnInbound();
308 spamFilter->setApplyOnExplicit();
309 spamFilter->setStopProcessingHere( true );
310 spamFilter->setConfigureShortcut( false );
311 filterList.append( spamFilter );
312
313 if ( mSpamRulesPage->moveUnsureSelected() )
314 {
315 // Sort out messages classified as unsure
316 bool atLeastOneUnsurePattern = false;
317 KMFilter* unsureFilter = new KMFilter();
318 TQPtrList<KMFilterAction>* unsureFilterActions = unsureFilter->actions();
319 KMFilterAction* unsureFilterAction1 = dict["transfer"]->create();
320 unsureFilterAction1->argsFromString( mSpamRulesPage->selectedUnsureFolderName() );
321 unsureFilterActions->append( unsureFilterAction1 );
322 KMSearchPattern* unsureFilterPattern = unsureFilter->pattern();
323 if ( replaceExistingFilters )
324 unsureFilterPattern->setName( i18n( "Semi spam (unsure) handling" ) );
325 else
326 unsureFilterPattern->setName( uniqueNameFor( i18n( "Semi spam (unsure) handling" ) ) );
327 unsureFilterPattern->setOp( KMSearchPattern::OpOr );
328 for ( TQValueListIterator<SpamToolConfig> it = mToolList.begin();
329 it != mToolList.end(); ++it ) {
330 if ( mInfoPage->isProgramSelected( (*it).getVisibleName() ) )
331 {
332 if ( (*it).isSpamTool() && (*it).hasTristateDetection())
333 {
334 atLeastOneUnsurePattern = true;
335 const TQCString header = (*it).getDetectionHeader().ascii();
336 const TQString & pattern = (*it).getDetectionPattern2();
337 if ( (*it).isUseRegExp() )
338 unsureFilterPattern->append(
340 KMSearchRule::FuncRegExp, pattern ) );
341 else
342 unsureFilterPattern->append(
344 KMSearchRule::FuncContains, pattern ) );
345 }
346 }
347 }
348 unsureFilter->setApplyOnOutbound( false);
349 unsureFilter->setApplyOnInbound();
350 unsureFilter->setApplyOnExplicit();
351 unsureFilter->setStopProcessingHere( true );
352 unsureFilter->setConfigureShortcut( false );
353
354 if ( atLeastOneUnsurePattern )
355 filterList.append( unsureFilter );
356 else
357 delete unsureFilter;
358 }
359
360 // Classify messages manually as Spam
361 KMFilter* classSpamFilter = new KMFilter();
362 classSpamFilter->setIcon( "mail_spam" );
363 TQPtrList<KMFilterAction>* classSpamFilterActions = classSpamFilter->actions();
364 KMFilterAction* classSpamFilterActionFirst = dict["set status"]->create();
365 classSpamFilterActionFirst->argsFromString( "P" );
366 classSpamFilterActions->append( classSpamFilterActionFirst );
367 for ( TQValueListIterator<SpamToolConfig> it = mToolList.begin();
368 it != mToolList.end(); ++it ) {
369 if ( mInfoPage->isProgramSelected( (*it).getVisibleName() )
370 && (*it).useBayesFilter() && !(*it).isDetectionOnly() )
371 {
372 KMFilterAction* classSpamFilterAction = dict["execute"]->create();
373 classSpamFilterAction->argsFromString( (*it).getSpamCmd() );
374 classSpamFilterActions->append( classSpamFilterAction );
375 }
376 }
377 if ( mSpamRulesPage->moveSpamSelected() )
378 {
379 KMFilterAction* classSpamFilterActionLast = dict["transfer"]->create();
380 classSpamFilterActionLast->argsFromString( mSpamRulesPage->selectedSpamFolderName() );
381 classSpamFilterActions->append( classSpamFilterActionLast );
382 }
383
384 KMSearchPattern* classSpamFilterPattern = classSpamFilter->pattern();
385 if ( replaceExistingFilters )
386 classSpamFilterPattern->setName( i18n( "Classify as spam" ) );
387 else
388 classSpamFilterPattern->setName( uniqueNameFor( i18n( "Classify as spam" ) ) );
389 classSpamFilterPattern->append( KMSearchRule::createInstance( "<size>",
390 KMSearchRule::FuncIsGreaterOrEqual, "0" ) );
391 classSpamFilter->setApplyOnOutbound( false);
392 classSpamFilter->setApplyOnInbound( false );
393 classSpamFilter->setApplyOnExplicit( false );
394 classSpamFilter->setStopProcessingHere( true );
395 classSpamFilter->setConfigureShortcut( true );
396 classSpamFilter->setConfigureToolbar( true );
397 filterList.append( classSpamFilter );
398
399 // Classify messages manually as not Spam / as Ham
400 KMFilter* classHamFilter = new KMFilter();
401 classHamFilter->setIcon( "mail_ham" );
402 TQPtrList<KMFilterAction>* classHamFilterActions = classHamFilter->actions();
403 KMFilterAction* classHamFilterActionFirst = dict["set status"]->create();
404 classHamFilterActionFirst->argsFromString( "H" );
405 classHamFilterActions->append( classHamFilterActionFirst );
406 for ( TQValueListIterator<SpamToolConfig> it = mToolList.begin();
407 it != mToolList.end(); ++it ) {
408 if ( mInfoPage->isProgramSelected( (*it).getVisibleName() )
409 && (*it).useBayesFilter() && !(*it).isDetectionOnly() )
410 {
411 KMFilterAction* classHamFilterAction = dict["execute"]->create();
412 classHamFilterAction->argsFromString( (*it).getHamCmd() );
413 classHamFilterActions->append( classHamFilterAction );
414 }
415 }
416 KMSearchPattern* classHamFilterPattern = classHamFilter->pattern();
417 if ( replaceExistingFilters )
418 classHamFilterPattern->setName( i18n( "Classify as NOT spam" ) );
419 else
420 classHamFilterPattern->setName( uniqueNameFor( i18n( "Classify as NOT spam" ) ) );
421 classHamFilterPattern->append( KMSearchRule::createInstance( "<size>",
422 KMSearchRule::FuncIsGreaterOrEqual, "0" ) );
423 classHamFilter->setApplyOnOutbound( false);
424 classHamFilter->setApplyOnInbound( false );
425 classHamFilter->setApplyOnExplicit( false );
426 classHamFilter->setStopProcessingHere( true );
427 classHamFilter->setConfigureShortcut( true );
428 classHamFilter->setConfigureToolbar( true );
429 filterList.append( classHamFilter );
430 }
431
432 /* Now that all the filters have been added to the list, tell
433 * the filter manager about it. That will emit filterListUpdate
434 * which will result in the filter list in kmmainwidget being
435 * initialized. This should happend only once. */
436 KMKernel::self()->filterMgr()->appendFilters( filterList );
437
438 /* Now that all the filters have been added to the list, tell
439 * the filter manager about it. That will emit filterListUpdate
440 * which will result in the filter list in kmmainwidget being
441 * initialized. This should happend only once. */
442 if ( !filterList.isEmpty() )
443 KMKernel::self()->filterMgr()->appendFilters(
444 filterList, replaceExistingFilters );
445
446 TQDialog::accept();
447}
448
449
451{
452 bool status = false;
453 bool supportUnsure = false;
454
455 mSpamToolsUsed = false;
456 mVirusToolsUsed = false;
457 for ( TQValueListIterator<SpamToolConfig> it = mToolList.begin();
458 it != mToolList.end(); ++it ) {
459 if ( mInfoPage->isProgramSelected( (*it).getVisibleName() ) )
460 {
461 status = true;
462 if ( (*it).isSpamTool() ) {
463 mSpamToolsUsed = true;
464 if ( (*it).hasTristateDetection() )
465 supportUnsure = true;
466 }
467 if ( (*it).isVirusTool() )
468 mVirusToolsUsed = true;
469 }
470 }
471
472 if ( mMode == AntiSpam ) {
473 mSpamRulesPage->allowUnsureFolderSelection( supportUnsure );
475 }
476
477 if ( ( mMode == AntiVirus ) && mVirusToolsUsed )
479
480 setNextEnabled( mInfoPage, status );
481}
482
483
485{
486 setFinishEnabled( mVirusRulesPage, anyVirusOptionChecked() );
487}
488
489
491{
492 // this can take some time to find the tools
493 KCursorSaver busy( KBusyPtr::busy() );
494
495 bool found = false;
496 for ( TQValueListIterator<SpamToolConfig> it = mToolList.begin();
497 it != mToolList.end(); ++it ) {
498 TQString text( i18n("Scanning for %1...").arg( (*it).getId() ) );
499 mInfoPage->setScanProgressText( text );
500 if ( (*it).isSpamTool() && (*it).isServerBased() ) {
501 // check the configured account for pattern in <server>
502 TQString pattern = (*it).getServerPattern();
503 kdDebug(5006) << "Testing for server pattern:" << pattern << endl;
504
505 AccountManager* mgr = kmkernel->acctMgr();
506 KMAccount* account = mgr->first();
507 while ( account ) {
508 if ( account->type() == "pop" || account->type().contains( "imap" ) ) {
509 const NetworkAccount * n = dynamic_cast<const NetworkAccount*>( account );
510 if ( n && n->host().lower().contains( pattern.lower() ) ) {
511 mInfoPage->addAvailableTool( (*it).getVisibleName() );
512 found = true;
513 }
514 }
515 account = mgr->next();
516 }
517 }
518 else {
519 // check the availability of the application
520 tdeApp->processEvents( 200 );
521 if ( !checkForProgram( (*it).getExecutable() ) ) {
522 mInfoPage->addAvailableTool( (*it).getVisibleName() );
523 found = true;
524 }
525 }
526 }
527 if ( found )
528 mInfoPage->setScanProgressText( ( mMode == AntiSpam )
529 ? i18n("Scanning for anti-spam tools finished.")
530 : i18n("Scanning for anti-virus tools finished.") );
531 else
532 mInfoPage->setScanProgressText( ( mMode == AntiSpam )
533 ? i18n("<p>No spam detection tools have been found. "
534 "Install your spam detection software and "
535 "re-run this wizard.</p>")
536 : i18n("Scanning complete. No anti-virus tools found.") );
537}
538
539
541{
542 if ( mMode == AntiSpam )
543 tdeApp->invokeHelp( "the-anti-spam-wizard", "kmail" );
544 else
545 tdeApp->invokeHelp( "the-anti-virus-wizard", "kmail" );
546}
547
548
550{
551 TQString text;
552 TQString newFilters;
553 TQString replaceFilters;
554
555 if ( mMode == AntiVirus ) {
556 text = ""; // TODO add summary for the virus part
557 }
558 else { // AntiSpam mode
559 if ( mSpamRulesPage->markAsReadSelected() )
560 text = i18n( "<p>Messages classified as spam are marked as read." );
561 else
562 text = i18n( "<p>Messages classified as spam are not marked as read." );
563
564 if ( mSpamRulesPage->moveSpamSelected() )
565 text += i18n( "<br>Spam messages are moved into the folder named <i>" )
566 + mSpamRulesPage->selectedSpamFolderName() + "</i>.</p>";
567 else
568 text += i18n( "<br>Spam messages are not moved into a certain folder.</p>" );
569
570 for ( TQValueListIterator<SpamToolConfig> it = mToolList.begin();
571 it != mToolList.end(); ++it ) {
572 if ( mInfoPage->isProgramSelected( (*it).getVisibleName() ) &&
573 (*it).isSpamTool() && !(*it).isDetectionOnly() ) {
574 sortFilterOnExistance( (*it).getFilterName(), newFilters, replaceFilters );
575 }
576 }
577 sortFilterOnExistance( i18n( "Spam handling" ), newFilters, replaceFilters );
578
579 // The need for a andling of status "probably spam" depends on the tools chosen
580 if ( mSpamRulesPage->moveUnsureSelected() ) {
581 bool atLeastOneUnsurePattern = false;
582 for ( TQValueListIterator<SpamToolConfig> it = mToolList.begin();
583 it != mToolList.end(); ++it ) {
584 if ( mInfoPage->isProgramSelected( (*it).getVisibleName() ) ) {
585 if ( (*it).isSpamTool() && (*it).hasTristateDetection())
586 atLeastOneUnsurePattern = true;
587 }
588 }
589 if ( atLeastOneUnsurePattern ) {
590 sortFilterOnExistance( i18n( "Semi spam (unsure) handling" ),
591 newFilters, replaceFilters );
592 text += i18n( "<p>The folder for messages classified as unsure (probably spam) is <i>" )
593 + mSpamRulesPage->selectedUnsureFolderName() + "</i>.</p>";
594 }
595 }
596
597 // Manual classification via toolbar icon / manually applied filter action
598 sortFilterOnExistance( i18n( "Classify as spam" ),
599 newFilters, replaceFilters );
600 sortFilterOnExistance( i18n( "Classify as NOT spam" ),
601 newFilters, replaceFilters );
602
603 // Show the filters in the summary
604 if ( !newFilters.isEmpty() )
605 text += i18n( "<p>The wizard will create the following filters:<ul>" )
606 + newFilters + "</ul></p>";
607 if ( !replaceFilters.isEmpty() )
608 text += i18n( "<p>The wizard will replace the following filters:<ul>" )
609 + replaceFilters + "</ul></p>";
610 }
611
612 mSummaryPage->setSummaryText( text );
613}
614
615
616int AntiSpamWizard::checkForProgram( const TQString &executable )
617{
618 kdDebug(5006) << "Testing for executable:" << executable << endl;
619 TDEProcess process;
620 process << executable;
621 process.setUseShell( true );
622 process.start( TDEProcess::Block );
623 return process.exitStatus();
624}
625
626
627bool AntiSpamWizard::anyVirusOptionChecked()
628{
629 return ( mVirusRulesPage->moveRulesSelected()
630 || mVirusRulesPage->pipeRulesSelected() );
631}
632
633
634const TQString AntiSpamWizard::uniqueNameFor( const TQString & name )
635{
636 return KMKernel::self()->filterMgr()->createUniqueName( name );
637}
638
639
640void AntiSpamWizard::sortFilterOnExistance(
641 const TQString & intendedFilterName,
642 TQString & newFilters, TQString & replaceFilters )
643{
644 if ( uniqueNameFor( intendedFilterName ) == intendedFilterName )
645 newFilters += "<li>" + intendedFilterName + "</li>";
646 else
647 replaceFilters += "<li>" + intendedFilterName + "</li>";
648}
649
650
651//---------------------------------------------------------------------------
652AntiSpamWizard::SpamToolConfig::SpamToolConfig( TQString toolId,
653 int configVersion, int prio, TQString name, TQString exec,
654 TQString url, TQString filter, TQString detection, TQString spam, TQString ham,
655 TQString header, TQString pattern, TQString pattern2, TQString serverPattern,
656 bool detectionOnly, bool regExp, bool bayesFilter, bool tristateDetection,
657 WizardMode type )
658 : mId( toolId ), mVersion( configVersion ), mPrio( prio ),
659 mVisibleName( name ), mExecutable( exec ), mWhatsThisText( url ),
660 mFilterName( filter ), mDetectCmd( detection ), mSpamCmd( spam ),
661 mHamCmd( ham ), mDetectionHeader( header ), mDetectionPattern( pattern ),
662 mDetectionPattern2( pattern2 ), mServerPattern( serverPattern ),
663 mDetectionOnly( detectionOnly ),
664 mUseRegExp( regExp ), mSupportsBayesFilter( bayesFilter ),
665 mSupportsUnsure( tristateDetection ), mType( type )
666{
667}
668
669
670bool AntiSpamWizard::SpamToolConfig::isServerBased() const
671{
672 return !mServerPattern.isEmpty();
673}
674
675
676//---------------------------------------------------------------------------
677AntiSpamWizard::ConfigReader::ConfigReader( WizardMode mode,
678 TQValueList<SpamToolConfig> & configList )
679 : mToolList( configList ),
680 mMode( mode )
681{
682 if ( mMode == AntiSpam )
683 mConfig = new TDEConfig( "kmail.antispamrc", true );
684 else
685 mConfig = new TDEConfig( "kmail.antivirusrc", true );
686}
687
688AntiSpamWizard::ConfigReader::~ConfigReader( )
689{
690 delete mConfig;
691}
692
693
694void AntiSpamWizard::ConfigReader::readAndMergeConfig()
695{
696 TQString groupName = ( mMode == AntiSpam )
697 ? TQString("Spamtool #%1")
698 : TQString("Virustool #%1");
699 // read the configuration from the global config file
700 mConfig->setReadDefaults( true );
701 TDEConfigGroup general( mConfig, "General" );
702 int registeredTools = general.readNumEntry( "tools", 0 );
703 for (int i = 1; i <= registeredTools; i++)
704 {
705 TDEConfigGroup toolConfig( mConfig, groupName.arg( i ) );
706 if( !toolConfig.readBoolEntry( "HeadersOnly", false ) )
707 mToolList.append( readToolConfig( toolConfig ) );
708 }
709
710 // read the configuration from the user config file
711 // and merge newer config data
712 mConfig->setReadDefaults( false );
713 TDEConfigGroup user_general( mConfig, "General" );
714 int user_registeredTools = user_general.readNumEntry( "tools", 0 );
715 for (int i = 1; i <= user_registeredTools; i++)
716 {
717 TDEConfigGroup toolConfig( mConfig, groupName.arg( i ) );
718 if( !toolConfig.readBoolEntry( "HeadersOnly", false ) )
719 mergeToolConfig( readToolConfig( toolConfig ) );
720 }
721 // Make sure to have add least one tool listed even when the
722 // config file was not found or whatever went wrong
723 // Currently only works for spam tools
724 if ( mMode == AntiSpam ) {
725 if ( registeredTools < 1 && user_registeredTools < 1 )
726 mToolList.append( createDummyConfig() );
727 sortToolList();
728 }
729}
730
731
733 AntiSpamWizard::ConfigReader::readToolConfig( TDEConfigGroup & configGroup )
734{
735 TQString id = configGroup.readEntry( "Ident" );
736 int version = configGroup.readNumEntry( "Version" );
737#ifndef NDEBUG
738 kdDebug(5006) << "Found predefined tool: " << id << endl;
739 kdDebug(5006) << "With config version : " << version << endl;
740#endif
741 int prio = configGroup.readNumEntry( "Priority", 1 );
742 TQString name = configGroup.readEntry( "VisibleName" );
743 TQString executable = configGroup.readEntry( "Executable" );
744 TQString url = configGroup.readEntry( "URL" );
745 TQString filterName = configGroup.readEntry( "PipeFilterName" );
746 TQString detectCmd = configGroup.readEntry( "PipeCmdDetect" );
747 TQString spamCmd = configGroup.readEntry( "ExecCmdSpam" );
748 TQString hamCmd = configGroup.readEntry( "ExecCmdHam" );
749 TQString header = configGroup.readEntry( "DetectionHeader" );
750 TQString pattern = configGroup.readEntry( "DetectionPattern" );
751 TQString pattern2 = configGroup.readEntry( "DetectionPattern2" );
752 TQString serverPattern = configGroup.readEntry( "ServerPattern" );
753 bool detectionOnly = configGroup.readBoolEntry( "DetectionOnly", false );
754 bool useRegExp = configGroup.readBoolEntry( "UseRegExp" );
755 bool supportsBayes = configGroup.readBoolEntry( "SupportsBayes", false );
756 bool supportsUnsure = configGroup.readBoolEntry( "SupportsUnsure", false );
757 return SpamToolConfig( id, version, prio, name, executable, url,
758 filterName, detectCmd, spamCmd, hamCmd,
759 header, pattern, pattern2, serverPattern,
760 detectionOnly, useRegExp,
761 supportsBayes, supportsUnsure, mMode );
762}
763
764
765AntiSpamWizard::SpamToolConfig AntiSpamWizard::ConfigReader::createDummyConfig()
766{
767 return SpamToolConfig( "spamassassin", 0, 1,
768 "SpamAssassin", "spamassassin -V",
769 "http://spamassassin.org", "SpamAssassin Check",
770 "spamassassin -L",
771 "sa-learn -L --spam --no-rebuild --single",
772 "sa-learn -L --ham --no-rebuild --single",
773 "X-Spam-Flag", "yes", "", "",
774 false, false, true, false, AntiSpam );
775}
776
777
778void AntiSpamWizard::ConfigReader::mergeToolConfig( AntiSpamWizard::SpamToolConfig config )
779{
780 bool found = false;
781 for ( TQValueListIterator<SpamToolConfig> it = mToolList.begin();
782 it != mToolList.end(); ++it ) {
783#ifndef NDEBUG
784 kdDebug(5006) << "Check against tool: " << (*it).getId() << endl;
785 kdDebug(5006) << "Against version : " << (*it).getVersion() << endl;
786#endif
787 if ( (*it).getId() == config.getId() )
788 {
789 found = true;
790 if ( (*it).getVersion() < config.getVersion() )
791 {
792#ifndef NDEBUG
793 kdDebug(5006) << "Replacing config ..." << endl;
794#endif
795 mToolList.remove( it );
796 mToolList.append( config );
797 }
798 break;
799 }
800 }
801 if ( !found )
802 mToolList.append( config );
803}
804
805
806void AntiSpamWizard::ConfigReader::sortToolList()
807{
808 TQValueList<SpamToolConfig> tmpList;
809 SpamToolConfig config;
810
811 while ( !mToolList.isEmpty() ) {
812 TQValueListIterator<SpamToolConfig> highest;
813 int priority = 0; // ascending
814 for ( TQValueListIterator<SpamToolConfig> it = mToolList.begin();
815 it != mToolList.end(); ++it ) {
816 if ( (*it).getPrio() > priority ) {
817 priority = (*it).getPrio();
818 highest = it;
819 }
820 }
821 config = (*highest);
822 tmpList.append( config );
823 mToolList.remove( highest );
824 }
825 for ( TQValueListIterator<SpamToolConfig> it = tmpList.begin();
826 it != tmpList.end(); ++it ) {
827 mToolList.append( (*it) );
828 }
829}
830
831
832//---------------------------------------------------------------------------
833ASWizPage::ASWizPage( TQWidget * parent, const char * name,
834 const TQString *bannerName )
835 : TQWidget( parent, name )
836{
837 TQString banner = "kmwizard.png";
838 if ( bannerName && !bannerName->isEmpty() )
839 banner = *bannerName;
840
841 mLayout = new TQHBoxLayout( this, KDialog::marginHint(), KDialog::spacingHint() );
842 mBannerLabel = new TQLabel( this );
843 mBannerLabel->setPixmap( UserIcon(banner) );
844 mBannerLabel->setScaledContents( false );
845 mBannerLabel->setFrameShape( TQFrame::StyledPanel );
846 mBannerLabel->setFrameShadow( TQFrame::Sunken );
847
848 mLayout->addWidget( mBannerLabel );
849 mLayout->addItem( new TQSpacerItem( 5, 5, TQSizePolicy::Minimum, TQSizePolicy::Expanding ) );
850}
851
852
853//---------------------------------------------------------------------------
854ASWizInfoPage::ASWizInfoPage( AntiSpamWizard::WizardMode mode,
855 TQWidget * parent, const char * name )
856 : ASWizPage( parent, name )
857{
858 TQBoxLayout * layout = new TQVBoxLayout( mLayout );
859
860 mIntroText = new TQLabel( this );
861 mIntroText->setText(
862 ( mode == AntiSpamWizard::AntiSpam )
863 ? i18n(
864 "The wizard will search for any tools to do spam detection\n"
865 "and setup KMail to work with them."
866 )
867 : i18n(
868 "<p>Here you can get some assistance in setting up KMail's filter "
869 "rules to use some commonly-known anti-virus tools.</p>"
870 "<p>The wizard can detect those tools on your computer as "
871 "well as create filter rules to classify messages using these "
872 "tools and to separate messages containing viruses. "
873 "The wizard will not take any existing filter "
874 "rules into consideration: it will always append the new rules.</p>"
875 "<p><b>Warning:</b> As KMail appears to be frozen during the scan of the "
876 "messages for viruses, you may encounter problems with "
877 "the responsiveness of KMail because anti-virus tool "
878 "operations are usually time consuming; please consider "
879 "deleting the filter rules created by the wizard to get "
880 "back to the former behavior."
881 ) );
882 layout->addWidget( mIntroText );
883
884 mScanProgressText = new TQLabel( this );
885 mScanProgressText->setText( "" ) ;
886 layout->addWidget( mScanProgressText );
887
888 mToolsList = new TDEListBox( this );
889 mToolsList->hide();
890 mToolsList->setSelectionMode( TQListBox::Multi );
891 mToolsList->setRowMode( TQListBox::FixedNumber );
892 mToolsList->setRowMode( 10 );
893 layout->addWidget( mToolsList );
894 connect( mToolsList, TQ_SIGNAL(selectionChanged()),
895 this, TQ_SLOT(processSelectionChange(void)) );
896
897 mSelectionHint = new TQLabel( this );
898 mSelectionHint->setText( "" );
899 layout->addWidget( mSelectionHint );
900
901 layout->addStretch();
902}
903
904
905void ASWizInfoPage::setScanProgressText( const TQString &toolName )
906{
907 mScanProgressText->setText( toolName );
908}
909
910
911void ASWizInfoPage::addAvailableTool( const TQString &visibleName )
912{
913 TQString listName = visibleName;
914 mToolsList->insertItem( listName );
915 if ( !mToolsList->isVisible() )
916 {
917 mToolsList->show();
918 mToolsList->setSelected( 0, true );
919 mSelectionHint->setText( i18n("<p>Please select the tools to be used "
920 "for the detection and go "
921 "to the next page.</p>") );
922 }
923}
924
925bool ASWizInfoPage::isProgramSelected( const TQString &visibleName )
926{
927 TQString listName = visibleName;
928 return mToolsList->isSelected( mToolsList->findItem( listName ) );
929}
930
931
932void ASWizInfoPage::processSelectionChange()
933{
934 emit selectionChanged();
935}
936
937
938//---------------------------------------------------------------------------
939ASWizSpamRulesPage::ASWizSpamRulesPage( TQWidget * parent, const char * name,
940 KMFolderTree * mainFolderTree )
941 : ASWizPage( parent, name )
942{
943 TQVBoxLayout *layout = new TQVBoxLayout( mLayout );
944
945 mMarkRules = new TQCheckBox( i18n("&Mark detected spam messages as read"), this );
946 TQWhatsThis::add( mMarkRules,
947 i18n( "Mark messages which have been classified as spam as read.") );
948 layout->addWidget( mMarkRules);
949
950 mMoveSpamRules = new TQCheckBox( i18n("Move &known spam to:"), this );
951 TQWhatsThis::add( mMoveSpamRules,
952 i18n( "The default folder for spam messages is the trash folder, "
953 "but you may change that in the folder view below.") );
954 layout->addWidget( mMoveSpamRules );
955
956 mFolderReqForSpamFolder = new FolderRequester( this, mainFolderTree );
957 mFolderReqForSpamFolder->setFolder( "trash" );
958 mFolderReqForSpamFolder->setMustBeReadWrite( true );
959 mFolderReqForSpamFolder->setShowOutbox( false );
960 mFolderReqForSpamFolder->setShowImapFolders( false );
961
962 TQHBoxLayout *hLayout1 = new TQHBoxLayout( layout );
963 hLayout1->addSpacing( KDialog::spacingHint() * 3 );
964 hLayout1->addWidget( mFolderReqForSpamFolder );
965
966 mMoveUnsureRules = new TQCheckBox( i18n("Move &probable spam to:"), this );
967 TQWhatsThis::add( mMoveUnsureRules,
968 i18n( "The default folder is the inbox folder, but you may change that "
969 "in the folder view below.<p>"
970 "Not all tools support a classification as unsure. If you haven't "
971 "selected a capable tool, you can't select a folder as well.") );
972 layout->addWidget( mMoveUnsureRules );
973
974 mFolderReqForUnsureFolder = new FolderRequester( this, mainFolderTree );
975 mFolderReqForUnsureFolder->setFolder( "inbox" );
976 mFolderReqForUnsureFolder->setMustBeReadWrite( true );
977 mFolderReqForUnsureFolder->setShowOutbox( false );
978 mFolderReqForUnsureFolder->setShowImapFolders( false );
979
980 TQHBoxLayout *hLayout2 = new TQHBoxLayout( layout );
981 hLayout2->addSpacing( KDialog::spacingHint() * 3 );
982 hLayout2->addWidget( mFolderReqForUnsureFolder );
983
984 layout->addStretch();
985
986 connect( mMarkRules, TQ_SIGNAL(clicked()),
987 this, TQ_SLOT(processSelectionChange(void)) );
988 connect( mMoveSpamRules, TQ_SIGNAL(clicked()),
989 this, TQ_SLOT(processSelectionChange(void)) );
990 connect( mMoveUnsureRules, TQ_SIGNAL(clicked()),
991 this, TQ_SLOT(processSelectionChange(void)) );
992 connect( mFolderReqForSpamFolder, TQ_SIGNAL(folderChanged(KMFolder*)),
993 this, TQ_SLOT(processSelectionChange(KMFolder*)) );
994 connect( mFolderReqForUnsureFolder, TQ_SIGNAL(folderChanged(KMFolder*)),
995 this, TQ_SLOT(processSelectionChange(KMFolder*)) );
996
997 mMarkRules->setChecked( true );
998 mMoveSpamRules->setChecked( true );
999}
1000
1001
1002bool ASWizSpamRulesPage::markAsReadSelected() const
1003{
1004 return mMarkRules->isChecked();
1005}
1006
1007
1008bool ASWizSpamRulesPage::moveSpamSelected() const
1009{
1010 return mMoveSpamRules->isChecked();
1011}
1012
1013
1014bool ASWizSpamRulesPage::moveUnsureSelected() const
1015{
1016 return mMoveUnsureRules->isChecked();
1017}
1018
1019
1020TQString ASWizSpamRulesPage::selectedSpamFolderName() const
1021{
1022 TQString name = "trash";
1023 if ( mFolderReqForSpamFolder->folder() )
1024 name = mFolderReqForSpamFolder->folder()->idString();
1025 return name;
1026}
1027
1028
1029TQString ASWizSpamRulesPage::selectedUnsureFolderName() const
1030{
1031 TQString name = "inbox";
1032 if ( mFolderReqForUnsureFolder->folder() )
1033 name = mFolderReqForUnsureFolder->folder()->idString();
1034 return name;
1035}
1036
1037
1038void ASWizSpamRulesPage::processSelectionChange()
1039{
1040 mFolderReqForSpamFolder->setEnabled( mMoveSpamRules->isChecked() );
1041 mFolderReqForUnsureFolder->setEnabled( mMoveUnsureRules->isChecked() );
1042 emit selectionChanged();
1043}
1044
1045
1046void ASWizSpamRulesPage::processSelectionChange( KMFolder* )
1047{
1048 processSelectionChange();
1049}
1050
1051
1052void ASWizSpamRulesPage::allowUnsureFolderSelection( bool enabled )
1053{
1054 mMoveUnsureRules->setEnabled( enabled );
1055 mMoveUnsureRules->setShown( enabled );
1056 mFolderReqForUnsureFolder->setEnabled( enabled );
1057 mFolderReqForUnsureFolder->setShown( enabled );
1058}
1059
1060
1061//---------------------------------------------------------------------------
1062ASWizVirusRulesPage::ASWizVirusRulesPage( TQWidget * parent, const char * name,
1063 KMFolderTree * mainFolderTree )
1064 : ASWizPage( parent, name )
1065{
1066 TQGridLayout *grid = new TQGridLayout( mLayout, 5, 1, KDialog::spacingHint() );
1067
1068 mPipeRules = new TQCheckBox( i18n("Check messages using the anti-virus tools"), this );
1069 TQWhatsThis::add( mPipeRules,
1070 i18n( "Let the anti-virus tools check your messages. The wizard "
1071 "will create appropriate filters. The messages are usually "
1072 "marked by the tools so that following filters can react "
1073 "on this and, for example, move virus messages to a special folder.") );
1074 grid->addWidget( mPipeRules, 0, 0 );
1075
1076 mMoveRules = new TQCheckBox( i18n("Move detected viral messages to the selected folder"), this );
1077 TQWhatsThis::add( mMoveRules,
1078 i18n( "A filter to detect messages classified as virus-infected and to move "
1079 "those messages into a predefined folder is created. The "
1080 "default folder is the trash folder, but you may change that "
1081 "in the folder view.") );
1082 grid->addWidget( mMoveRules, 1, 0 );
1083
1084 mMarkRules = new TQCheckBox( i18n("Additionally, mark detected viral messages as read"), this );
1085 mMarkRules->setEnabled( false );
1086 TQWhatsThis::add( mMarkRules,
1087 i18n( "Mark messages which have been classified as "
1088 "virus-infected as read, as well as moving them "
1089 "to the selected folder.") );
1090 grid->addWidget( mMarkRules, 2, 0 );
1091
1092 TQString s = "trash";
1093 mFolderTree = new SimpleFolderTree( this, mainFolderTree, s, true );
1094 grid->addWidget( mFolderTree, 3, 0 );
1095
1096 connect( mPipeRules, TQ_SIGNAL(clicked()),
1097 this, TQ_SLOT(processSelectionChange(void)) );
1098 connect( mMoveRules, TQ_SIGNAL(clicked()),
1099 this, TQ_SLOT(processSelectionChange(void)) );
1100 connect( mMarkRules, TQ_SIGNAL(clicked()),
1101 this, TQ_SLOT(processSelectionChange(void)) );
1102 connect( mMoveRules, TQ_SIGNAL( toggled( bool ) ),
1103 mMarkRules, TQ_SLOT( setEnabled( bool ) ) );
1104}
1105
1106bool ASWizVirusRulesPage::pipeRulesSelected() const
1107{
1108 return mPipeRules->isChecked();
1109}
1110
1111
1112bool ASWizVirusRulesPage::moveRulesSelected() const
1113{
1114 return mMoveRules->isChecked();
1115}
1116
1117bool ASWizVirusRulesPage::markReadRulesSelected() const
1118{
1119 return mMarkRules->isChecked();
1120}
1121
1122
1123TQString ASWizVirusRulesPage::selectedFolderName() const
1124{
1125 TQString name = "trash";
1126 if ( mFolderTree->folder() )
1127 name = mFolderTree->folder()->idString();
1128 return name;
1129}
1130
1131void ASWizVirusRulesPage::processSelectionChange()
1132{
1133 emit selectionChanged();
1134}
1135
1136
1137//---------------------------------------------------------------------------
1138ASWizSummaryPage::ASWizSummaryPage( TQWidget * parent, const char * name )
1139 : ASWizPage( parent, name )
1140{
1141 TQBoxLayout * layout = new TQVBoxLayout( mLayout );
1142
1143 mSummaryText = new TQLabel( this );
1144 layout->addWidget( mSummaryText );
1145 layout->addStretch();
1146}
1147
1148
1149void ASWizSummaryPage::setSummaryText( const TQString & text )
1150{
1151 mSummaryText->setText( text );
1152}
1153
1154
1155#include "antispamwizard.moc"
sets a cursor and makes sure it's restored on destruction Create a KCursorSaver object when you want ...
Definition: kcursorsaver.h:14
Dictionary that contains a list of all registered filter actions with their creation functions.
Abstract base class for KMail's filter actions.
virtual void argsFromString(const TQString argsStr)=0
Read extra arguments from given string.
Mail folder.
Definition: kmfolder.h:69
static KMKernel * self()
normal control stuff
Definition: kmkernel.h:259
This class is an abstraction of a search over messages.
void setOp(KMSearchPattern::Operator aOp)
Set the filter operator.
void setName(const TQString &newName)
Set the name of the search pattern.
static KMSearchRule * createInstance(const TQCString &field=0, Function function=FuncContains, const TQString &contents=TQString())
Create a search rule of a certain type by instantiating the appro- priate subclass depending on the f...
The account manager is responsible for creating accounts of various types via the factory method crea...
const KMAccount * next() const
Next account of the list.
const KMAccount * first() const
First account of the list.
Instances of this class control reading the configuration of the anti-spam tools from global and user...
Instances of this class store the settings for one tool as read from the config file.
void slotBuildSummary()
Create the summary text based on the current settings.
void checkToolAvailability()
Check if the spam tools are available via the PATH.
void checkProgramsSelections()
Modify the status of the wizard to reflect the selection of spam tools.
WizardMode
The wizard can be used for setting up anti-spam tools and for setting up anti-virus tools.
void checkVirusRulesSelections()
Modify the status of the wizard to reflect the selected functionality.
void slotHelpClicked()
Show a help topic.
void accept()
Evaluate the settings made and create the appropriate filter rules.
A widget that contains a KLineEdit which shows the current folder and a button that fires a KMFolderS...
folderdiaquotatab.h
Definition: aboutdata.cpp:40