00001
00002
00003
00004
00005
#include <config.h>
00006
00007
#include "kmsearchpattern.h"
00008
#include "kmmessage.h"
00009
#include "kmmsgindex.h"
00010
#include "kmmsgdict.h"
00011
00012
#include <kglobal.h>
00013
#include <klocale.h>
00014
#include <kdebug.h>
00015
#include <kconfig.h>
00016
00017
#include <qregexp.h>
00018
00019
#include <mimelib/string.h>
00020
#include <mimelib/boyermor.h>
00021
00022
#include <assert.h>
00023
00024
static const char* funcConfigNames[] =
00025 {
"contains",
"contains-not",
"equals",
"not-equal",
"regexp",
00026
"not-regexp",
"greater",
"less-or-equal",
"less",
"greater-or-equal" };
00027
static const int numFuncConfigNames =
sizeof funcConfigNames /
sizeof *funcConfigNames;
00028
00029
00030
00031
00032
00033
00034
00035
00036 KMSearchRule::KMSearchRule(
const QCString & field, Function func,
const QString & contents )
00037 : mField( field ),
00038 mFunction( func ),
00039 mContents( contents )
00040 {
00041 }
00042
00043 KMSearchRule::KMSearchRule(
const KMSearchRule & other )
00044 : mField( other.mField ),
00045 mFunction( other.mFunction ),
00046 mContents( other.mContents )
00047 {
00048 }
00049
00050
const KMSearchRule & KMSearchRule::operator=(
const KMSearchRule & other ) {
00051
if (
this == &other )
00052
return *
this;
00053
00054 mField = other.
mField;
00055 mFunction = other.
mFunction;
00056 mContents = other.
mContents;
00057
00058
return *
this;
00059 }
00060
00061 KMSearchRule *
KMSearchRule::createInstance(
const QCString & field,
00062 Function func,
00063
const QString & contents )
00064 {
00065
KMSearchRule *ret;
00066
if (field ==
"<status>")
00067 ret =
new KMSearchRuleStatus( field, func, contents );
00068
else if ( field ==
"<age in days>" || field ==
"<size>" )
00069 ret =
new KMSearchRuleNumerical( field, func, contents );
00070
else
00071 ret =
new KMSearchRuleString( field, func, contents );
00072
00073
return ret;
00074 }
00075
00076
KMSearchRule * KMSearchRule::createInstance(
const QCString & field,
00077
const char *func,
00078
const QString & contents )
00079 {
00080
return ( createInstance( field, configValueToFunc( func ), contents ) );
00081 }
00082
00083
KMSearchRule *
KMSearchRule::createInstance(
const KMSearchRule & other )
00084 {
00085
return (
createInstance( other.
field(), other.
function(), other.
contents() ) );
00086 }
00087
00088 KMSearchRule *
KMSearchRule::createInstanceFromConfig(
const KConfig * config,
int aIdx )
00089 {
00090
const char cIdx = char(
int(
'A') + aIdx );
00091
00092
static const QString & field = KGlobal::staticQString(
"field" );
00093
static const QString & func = KGlobal::staticQString(
"func" );
00094
static const QString & contents = KGlobal::staticQString(
"contents" );
00095
00096
const QCString &field2 = config->readEntry( field + cIdx ).latin1();
00097
Function func2 = configValueToFunc( config->readEntry( func + cIdx ).latin1() );
00098
const QString & contents2 = config->readEntry( contents + cIdx );
00099
00100
if ( field2 ==
"<To or Cc>" )
00101
return KMSearchRule::createInstance(
"<recipients>", func2, contents2 );
00102
else
00103
return KMSearchRule::createInstance( field2, func2, contents2 );
00104 }
00105
00106 KMSearchRule::Function KMSearchRule::configValueToFunc(
const char * str ) {
00107
if ( !str )
return FuncContains;
00108
00109
for (
int i = 0 ; i < numFuncConfigNames ; ++i )
00110
if ( qstricmp( funcConfigNames[i], str ) == 0 )
return (Function)i;
00111
00112
return FuncContains;
00113 }
00114
00115 void KMSearchRule::writeConfig( KConfig * config,
int aIdx )
const {
00116
const char cIdx = char(
'A' + aIdx);
00117
static const QString & field = KGlobal::staticQString(
"field" );
00118
static const QString & func = KGlobal::staticQString(
"func" );
00119
static const QString & contents = KGlobal::staticQString(
"contents" );
00120
00121 config->writeEntry( field + cIdx, QString(mField) );
00122 config->writeEntry( func + cIdx, funcConfigNames[(
int)mFunction] );
00123 config->writeEntry( contents + cIdx, mContents );
00124 }
00125
00126 bool KMSearchRule::matches(
const DwString & aStr, KMMessage & msg,
00127
const DwBoyerMoore *,
int )
const
00128
{
00129
if ( !msg.isComplete() ) {
00130 msg.fromDwString( aStr );
00131 msg.setComplete(
true );
00132 }
00133
return matches( &msg );
00134 }
00135
00136
#ifndef NDEBUG
00137 const QString
KMSearchRule::asString()
const
00138
{
00139 QString result =
"\"" + mField +
"\" <";
00140 result += funcConfigNames[(
int)mFunction];
00141 result +=
"> \"" + mContents +
"\"";
00142
00143
return result;
00144 }
00145
#endif
00146
00147
00148
00149
00150
00151
00152
00153
00154
00155 KMSearchRuleString::KMSearchRuleString(
const QCString & field,
00156 Function func,
const QString & contents )
00157 :
KMSearchRule(field, func, contents)
00158 {
00159
if ( field.isEmpty() || field[0] ==
'<' )
00160 mBmHeaderField = 0;
00161
else
00162 mBmHeaderField =
new DwBoyerMoore((
"\n" + field +
": ").data());
00163 }
00164
00165 KMSearchRuleString::KMSearchRuleString(
const KMSearchRuleString & other )
00166 :
KMSearchRule( other ),
00167 mBmHeaderField( 0 )
00168 {
00169
if ( other.
mBmHeaderField )
00170 mBmHeaderField =
new DwBoyerMoore( *other.
mBmHeaderField );
00171 }
00172
00173
const KMSearchRuleString & KMSearchRuleString::operator=(
const KMSearchRuleString & other )
00174 {
00175
if (
this == &other )
00176
return *
this;
00177
00178
setField( other.
field() );
00179 mBmHeaderField =
new DwBoyerMoore( *other.
mBmHeaderField );
00180
setFunction( other.
function() );
00181
setContents( other.
contents() );
00182
delete mBmHeaderField; mBmHeaderField = 0;
00183
if ( other.
mBmHeaderField )
00184 mBmHeaderField =
new DwBoyerMoore( *other.
mBmHeaderField );
00185
00186
return *
this;
00187 }
00188
00189 KMSearchRuleString::~KMSearchRuleString()
00190 {
00191
delete mBmHeaderField;
00192 mBmHeaderField = 0;
00193 }
00194
00195 bool KMSearchRuleString::isEmpty()
const
00196
{
00197
return field().stripWhiteSpace().isEmpty() ||
contents().isEmpty();
00198 }
00199
00200 bool KMSearchRuleString::requiresBody()
const
00201
{
00202
if (mBmHeaderField || (
field() ==
"<recipients>" ))
00203
return false;
00204
return true;
00205 }
00206
00207 bool KMSearchRuleString::matches(
const DwString & aStr, KMMessage & msg,
00208
const DwBoyerMoore * aHeaderField,
int aHeaderLen )
const
00209
{
00210
if (
isEmpty() )
00211
return false;
00212
00213
const DwBoyerMoore * headerField = aHeaderField ? aHeaderField : mBmHeaderField ;
00214
00215
const int headerLen = ( aHeaderLen > -1 ? aHeaderLen :
field().length() ) + 2 ;
00216
00217
if ( headerField ) {
00218
static const DwBoyerMoore lf(
"\n" );
00219
static const DwBoyerMoore lflf(
"\n\n" );
00220
static const DwBoyerMoore lfcrlf(
"\n\r\n" );
00221
00222 size_t endOfHeader = lflf.FindIn( aStr, 0 );
00223
if ( endOfHeader == DwString::npos )
00224 endOfHeader = lfcrlf.FindIn( aStr, 0 );
00225
const DwString headers = ( endOfHeader == DwString::npos ) ? aStr : aStr.substr( 0, endOfHeader );
00226 size_t start = headerField->FindIn( headers, 0,
false );
00227
if ( start == DwString::npos )
00228
return false;
00229 start += headerLen;
00230 size_t stop = lf.FindIn( aStr, start );
00231
char ch =
'\0';
00232
while ( stop != DwString::npos && ( ch = aStr.at( stop + 1 ) ) ==
' ' || ch ==
'\t' )
00233 stop = lf.FindIn( aStr, stop + 1 );
00234
const int len = stop == DwString::npos ? aStr.length() - start : stop - start ;
00235
const QCString codedValue( aStr.data() + start, len + 1 );
00236
const QString msgContents = KMMsgBase::decodeRFC2047String( codedValue ).stripWhiteSpace();
00237
return matchesInternal( msgContents );
00238 }
else if (
field() ==
"<recipients>" ) {
00239
static const DwBoyerMoore to(
"\nTo: ");
00240
bool res =
matches( aStr, msg, &to, 2 );
00241
if ( !res ) {
00242
static const DwBoyerMoore cc(
"\nCc: ");
00243 res = matches( aStr, msg, &cc, 2 );
00244 }
00245
if ( !res ) {
00246
static const DwBoyerMoore bcc(
"\nBcc: ");
00247 res = matches( aStr, msg, &bcc, 3 );
00248 }
00249
return res;
00250 }
else {
00251
return KMSearchRule::matches( aStr, msg, aHeaderField, aHeaderLen );
00252 }
00253 }
00254
00255 bool KMSearchRuleString::matches(
const KMMessage * msg )
const
00256
{
00257 assert( msg );
00258
00259
if (
isEmpty() )
00260
return false;
00261
00262 QString msgContents;
00263
00264
if(
field() ==
"<message>" ) {
00265 msgContents = msg->asString();
00266 }
else if (
field() ==
"<body>" ) {
00267 msgContents = msg->bodyDecoded();
00268 }
else if (
field() ==
"<any header>" ) {
00269 msgContents = msg->headerAsString();
00270 }
else if (
field() ==
"<recipients>" ) {
00271
00272
00273
00274
if (
function() == FuncEquals ||
function() == FuncNotEqual )
00275
00276
00277
return matchesInternal( msg->headerField(
"To") )
00278 ||
matchesInternal( msg->headerField(
"Cc") )
00279 ||
matchesInternal( msg->headerField(
"Bcc") );
00280
00281 msgContents = msg->headerField(
"To") + msg->headerField(
"Cc")
00282 + msg->headerField(
"Bcc");
00283 }
else {
00284 msgContents = msg->headerField(
field() );
00285 }
00286
return matchesInternal( msgContents );
00287 }
00288
00289
00290 bool KMSearchRuleString::matchesInternal(
const QString & msgContents )
const
00291
{
00292
switch (
function() ) {
00293
case KMSearchRule::FuncEquals:
00294
return ( QString::compare( msgContents.lower(),
contents().lower() ) == 0 );
00295
00296
case KMSearchRule::FuncNotEqual:
00297
return ( QString::compare( msgContents.lower(),
contents().lower() ) != 0 );
00298
00299
case KMSearchRule::FuncContains:
00300
return ( msgContents.find(
contents(), 0,
false ) >= 0 );
00301
00302
case KMSearchRule::FuncContainsNot:
00303
return ( msgContents.find(
contents(), 0,
false ) < 0 );
00304
00305
case KMSearchRule::FuncRegExp:
00306 {
00307 QRegExp regexp(
contents(),
false );
00308
return ( regexp.search( msgContents ) >= 0 );
00309 }
00310
00311
case KMSearchRule::FuncNotRegExp:
00312 {
00313 QRegExp regexp(
contents(),
false );
00314
return ( regexp.search( msgContents ) < 0 );
00315 }
00316
00317
case FuncIsGreater:
00318
return ( QString::compare( msgContents.lower(),
contents().lower() ) > 0 );
00319
00320
case FuncIsLessOrEqual:
00321
return ( QString::compare( msgContents.lower(),
contents().lower() ) <= 0 );
00322
00323
case FuncIsLess:
00324
return ( QString::compare( msgContents.lower(),
contents().lower() ) < 0 );
00325
00326
case FuncIsGreaterOrEqual:
00327
return ( QString::compare( msgContents.lower(),
contents().lower() ) >= 0 );
00328 }
00329
00330
return false;
00331 }
00332
00333
00334
00335
00336
00337
00338
00339
00340 KMSearchRuleNumerical::KMSearchRuleNumerical(
const QCString & field,
00341 Function func,
const QString & contents )
00342 :
KMSearchRule(field, func, contents)
00343 {
00344 }
00345
00346 bool KMSearchRuleNumerical::isEmpty()
const
00347
{
00348
bool ok =
false;
00349
contents().toInt( &ok );
00350
00351
return !ok;
00352 }
00353
00354
00355 bool KMSearchRuleNumerical::matches(
const KMMessage * msg )
const
00356
{
00357
00358 QString msgContents;
00359
int numericalMsgContents = 0;
00360
int numericalValue = 0;
00361
00362
if (
field() ==
"<size>" ) {
00363 numericalMsgContents = int( msg->msgLength() );
00364 numericalValue =
contents().toInt();
00365 msgContents.setNum( numericalMsgContents );
00366 }
else if (
field() ==
"<age in days>" ) {
00367 QDateTime msgDateTime;
00368 msgDateTime.setTime_t( msg->date() );
00369 numericalMsgContents = msgDateTime.daysTo( QDateTime::currentDateTime() );
00370 numericalValue =
contents().toInt();
00371 msgContents.setNum( numericalMsgContents );
00372 }
00373
return matchesInternal( numericalValue, numericalMsgContents, msgContents );
00374 }
00375
00376 bool KMSearchRuleNumerical::matchesInternal(
unsigned long numericalValue,
00377
unsigned long numericalMsgContents,
const QString & msgContents )
const
00378
{
00379
switch (
function() ) {
00380
case KMSearchRule::FuncEquals:
00381
return ( numericalValue == numericalMsgContents );
00382
00383
case KMSearchRule::FuncNotEqual:
00384
return ( numericalValue != numericalMsgContents );
00385
00386
case KMSearchRule::FuncContains:
00387
return ( msgContents.find(
contents(), 0,
false ) >= 0 );
00388
00389
case KMSearchRule::FuncContainsNot:
00390
return ( msgContents.find(
contents(), 0,
false ) < 0 );
00391
00392
case KMSearchRule::FuncRegExp:
00393 {
00394 QRegExp regexp(
contents(),
false );
00395
return ( regexp.search( msgContents ) >= 0 );
00396 }
00397
00398
case KMSearchRule::FuncNotRegExp:
00399 {
00400 QRegExp regexp(
contents(),
false );
00401
return ( regexp.search( msgContents ) < 0 );
00402 }
00403
00404
case FuncIsGreater:
00405
return ( numericalMsgContents > numericalValue );
00406
00407
case FuncIsLessOrEqual:
00408
return ( numericalMsgContents <= numericalValue );
00409
00410
case FuncIsLess:
00411
return ( numericalMsgContents < numericalValue );
00412
00413
case FuncIsGreaterOrEqual:
00414
return ( numericalMsgContents >= numericalValue );
00415 }
00416
00417
return false;
00418 }
00419
00420
00421
00422
00423
00424
00425
00426
00427
00428 KMSearchRuleStatus::KMSearchRuleStatus(
const QCString & field,
00429 Function func,
const QString & aContents )
00430 :
KMSearchRule(field, func, aContents)
00431 {
00432
00433
00434
if ( ! aContents.compare(
"new") )
00435 mStatus = KMMsgStatusNew;
00436
if ( ! aContents.compare(
"unread") )
00437 mStatus = KMMsgStatusUnread;
00438
if ( ! aContents.compare(
"read") )
00439 mStatus = KMMsgStatusRead;
00440
if ( ! aContents.compare(
"old") )
00441 mStatus = KMMsgStatusOld;
00442
if ( ! aContents.compare(
"deleted") )
00443 mStatus = KMMsgStatusDeleted;
00444
if ( ! aContents.compare(
"replied") )
00445 mStatus = KMMsgStatusReplied;
00446
if ( ! aContents.compare(
"forwarded") )
00447 mStatus = KMMsgStatusForwarded;
00448
if ( ! aContents.compare(
"queued") )
00449 mStatus = KMMsgStatusQueued;
00450
if ( ! aContents.compare(
"sent") )
00451 mStatus = KMMsgStatusSent;
00452
if ( ! aContents.compare(
"important") )
00453 mStatus = KMMsgStatusFlag;
00454
if ( ! aContents.compare(
"watched") )
00455 mStatus = KMMsgStatusWatched;
00456
if ( ! aContents.compare(
"ignored") )
00457 mStatus = KMMsgStatusIgnored;
00458
00459
00460
00461
00462
if ( ! aContents.compare(
"spam") )
00463 mStatus = KMMsgStatusSpam;
00464
if ( ! aContents.compare(
"ham") )
00465 mStatus = KMMsgStatusHam;
00466 }
00467
00468 bool KMSearchRuleStatus::isEmpty()
const
00469
{
00470
return field().stripWhiteSpace().isEmpty() ||
contents().isEmpty();
00471 }
00472
00473 bool KMSearchRuleStatus::matches(
const DwString &, KMMessage &,
00474
const DwBoyerMoore *,
int )
const
00475
{
00476 assert( 0 );
00477
return false;
00478 }
00479
00480 bool KMSearchRuleStatus::matches(
const KMMessage * msg )
const
00481
{
00482
00483 KMMsgStatus msgStatus = msg->status();
00484
00485
switch (
function() ) {
00486
case FuncEquals:
00487
case FuncContains:
00488
if (msgStatus & mStatus)
00489
return true;
00490
break;
00491
case FuncNotEqual:
00492
case FuncContainsNot:
00493
if (! (msgStatus & mStatus) )
00494
return true;
00495
break;
00496
00497
00498
default:
00499
break;
00500 }
00501
00502
return false;
00503 }
00504
00505
00506
00507
00508
00509
00510
00511
00512
00513 KMSearchPattern::KMSearchPattern(
const KConfig * config )
00514 : QPtrList<
KMSearchRule>()
00515 {
00516 setAutoDelete(
true );
00517
if ( config )
00518
readConfig( config );
00519
else
00520 init();
00521 }
00522
00523 KMSearchPattern::~KMSearchPattern()
00524 {
00525 }
00526
00527 bool KMSearchPattern::matches(
const KMMessage * msg )
const {
00528
00529
if ( isEmpty() )
00530
return false;
00531 QPtrListIterator<KMSearchRule> it( *
this );
00532
switch ( mOperator ) {
00533
case OpAnd:
00534
for ( it.toFirst() ; it.current() ; ++it )
00535
if ( !(*it)->matches( msg ) )
00536
return false;
00537
return true;
00538
case OpOr:
00539
for ( it.toFirst() ; it.current() ; ++it )
00540
if ( (*it)->matches( msg ) )
00541
return true;
00542
00543
default:
00544
return false;
00545 }
00546 }
00547
00548
bool KMSearchPattern::matches(
const DwString & aStr )
const
00549
{
00550
if ( isEmpty() )
00551
return false;
00552 KMMessage msg;
00553 QPtrListIterator<KMSearchRule> it( *
this );
00554
switch ( mOperator ) {
00555
case OpAnd:
00556
for ( it.toFirst() ; it.current() ; ++it )
00557
if ( !(*it)->matches( aStr, msg ) )
00558
return false;
00559
return true;
00560
case OpOr:
00561
for ( it.toFirst() ; it.current() ; ++it )
00562
if ( (*it)->matches( aStr, msg ) )
00563
return true;
00564
00565
default:
00566
return false;
00567 }
00568 }
00569
00570
bool KMSearchPattern::matches( Q_UINT32 serNum )
const
00571
{
00572
bool res;
00573
int idx = -1;
00574
KMFolder *folder = 0;
00575 kmkernel->msgDict()->getLocation(serNum, &folder, &idx);
00576
if (!folder || (idx == -1) || (idx >= folder->
count())) {
00577
return false;
00578 }
00579
00580 folder->
open();
00581 KMMsgBase *msgBase = folder->
getMsgBase(idx);
00582
if (
requiresBody()) {
00583
bool unGet = !msgBase->isMessage();
00584 KMMessage *msg = folder->
getMsg(idx);
00585 res =
matches( msg );
00586
if (unGet)
00587 folder->
unGetMsg(idx);
00588 }
else {
00589 res =
matches( folder->
getDwString(idx) );
00590 }
00591 folder->
close();
00592
return res;
00593 }
00594
00595 bool KMSearchPattern::requiresBody()
const {
00596 QPtrListIterator<KMSearchRule> it( *
this );
00597
for ( it.toFirst() ; it.current() ; ++it )
00598
if ( (*it)->requiresBody() )
00599
return true;
00600
return false;
00601 }
00602
00603 void KMSearchPattern::purify() {
00604 QPtrListIterator<KMSearchRule> it( *
this );
00605 it.toLast();
00606
while ( it.current() )
00607
if ( (*it)->isEmpty() ) {
00608
#ifndef NDEBUG
00609
kdDebug(5006) <<
"KMSearchPattern::purify(): removing " << (*it)->asString() << endl;
00610
#endif
00611
remove( *it );
00612 }
else {
00613 --it;
00614 }
00615 }
00616
00617 void KMSearchPattern::readConfig(
const KConfig * config ) {
00618 init();
00619
00620 mName = config->readEntry(
"name");
00621
if ( !config->hasKey(
"rules") ) {
00622 kdDebug(5006) <<
"KMSearchPattern::readConfig: found legacy config! Converting." << endl;
00623 importLegacyConfig( config );
00624
return;
00625 }
00626
00627 mOperator = config->readEntry(
"operator") ==
"or" ? OpOr : OpAnd;
00628
00629
const int nRules = config->readNumEntry(
"rules", 0 );
00630
00631
for (
int i = 0 ; i < nRules ; i++ ) {
00632
KMSearchRule * r = KMSearchRule::createInstanceFromConfig( config, i );
00633
if ( r->
isEmpty() )
00634
delete r;
00635
else
00636 append( r );
00637 }
00638 }
00639
00640
void KMSearchPattern::importLegacyConfig(
const KConfig * config ) {
00641
KMSearchRule * rule = KMSearchRule::createInstance( config->readEntry(
"fieldA").latin1(),
00642 config->readEntry(
"funcA").latin1(),
00643 config->readEntry(
"contentsA") );
00644
if ( rule->
isEmpty() ) {
00645
00646
00647
delete rule;
00648
return;
00649 }
00650 append( rule );
00651
00652
const QString sOperator = config->readEntry(
"operator");
00653
if ( sOperator ==
"ignore" )
return;
00654
00655 rule =
KMSearchRule::createInstance( config->readEntry(
"fieldB").latin1(),
00656 config->readEntry(
"funcB").latin1(),
00657 config->readEntry(
"contentsB") );
00658
if ( rule->
isEmpty() ) {
00659
delete rule;
00660
return;
00661 }
00662 append( rule );
00663
00664
if ( sOperator ==
"or" ) {
00665 mOperator = OpOr;
00666
return;
00667 }
00668
00669
if ( sOperator ==
"unless" ) {
00670
00671
00672
00673
KMSearchRule::Function func = last()->function();
00674
unsigned int intFunc = (
unsigned int)func;
00675 func =
KMSearchRule::Function( intFunc ^ 0x1 );
00676
00677 last()->setFunction( func );
00678 }
00679
00680
00681 }
00682
00683 void KMSearchPattern::writeConfig( KConfig * config )
const {
00684 config->writeEntry(
"name", mName);
00685 config->writeEntry(
"operator", (mOperator == KMSearchPattern::OpOr) ?
"or" :
"and" );
00686
00687
int i = 0;
00688
for ( QPtrListIterator<KMSearchRule> it( *
this ) ; it.current() && i < FILTER_MAX_RULES ; ++i , ++it )
00689
00690
00691 (*it)->writeConfig( config, i );
00692
00693
00694 config->writeEntry(
"rules", i );
00695 }
00696
00697
void KMSearchPattern::init() {
00698 clear();
00699 mOperator = OpAnd;
00700 mName =
'<' + i18n(
"name used for a virgin filter",
"unknown") +
'>';
00701 }
00702
00703
#ifndef NDEBUG
00704 QString
KMSearchPattern::asString()
const {
00705 QString result =
"Match ";
00706 result += ( mOperator == OpOr ) ?
"any" :
"all";
00707 result +=
" of the following:\n";
00708
00709
for ( QPtrListIterator<KMSearchRule> it( *
this ) ; it.current() ; ++it )
00710 result += (*it)->asString() +
'\n';
00711
00712
return result;
00713 }
00714
#endif
00715
00716 const KMSearchPattern &
KMSearchPattern::operator=(
const KMSearchPattern & other ) {
00717
if (
this == &other )
00718
return *
this;
00719
00720
setOp( other.
op() );
00721
setName( other.
name() );
00722
00723 clear();
00724
for ( QPtrListIterator<KMSearchRule> it( other ) ; it.current() ; ++it )
00725 append( KMSearchRule::createInstance( **it ) );
00726
00727
return *
this;
00728 }