00001
00002
00003
00004
00005
00006 #include <config.h>
00007 #include "kmsearchpatternedit.h"
00008
00009 #include "kmsearchpattern.h"
00010 #include "rulewidgethandlermanager.h"
00011 using KMail::RuleWidgetHandlerManager;
00012
00013 #include <tdelocale.h>
00014 #include <kdialog.h>
00015 #include <kdebug.h>
00016
00017 #include <tqradiobutton.h>
00018 #include <tqcombobox.h>
00019 #include <tqbuttongroup.h>
00020 #include <tqwidgetstack.h>
00021 #include <tqlayout.h>
00022
00023 #include <assert.h>
00024
00025
00026
00027
00028
00029
00030 static const struct {
00031 const char *internalName;
00032 const char *displayName;
00033 } SpecialRuleFields[] = {
00034 { "<message>", I18N_NOOP( "Complete Message" ) },
00035 { "<body>", I18N_NOOP( "Body of Message" ) },
00036 { "<any header>", I18N_NOOP( "Anywhere in Headers" ) },
00037 { "<recipients>", I18N_NOOP( "All Recipients" ) },
00038 { "<size>", I18N_NOOP( "Size in Bytes" ) },
00039 { "<age in days>", I18N_NOOP( "Age in Days" ) },
00040 { "<status>", I18N_NOOP( "Message Status" ) },
00041 { "Subject", I18N_NOOP( "Subject" ) },
00042 { "From", I18N_NOOP( "From" ) },
00043 { "To", I18N_NOOP( "To" ) },
00044 { "CC", I18N_NOOP( "CC" ) },
00045 { "Reply-To", I18N_NOOP( "Reply To" ) },
00046 { "Organization", I18N_NOOP( "Organization" ) }
00047 };
00048 static const int SpecialRuleFieldsCount =
00049 sizeof( SpecialRuleFields ) / sizeof( *SpecialRuleFields );
00050
00051
00052
00053
00054
00055
00056
00057 KMSearchRuleWidget::KMSearchRuleWidget( TQWidget *parent, KMSearchRule *aRule,
00058 const char *name, bool headersOnly,
00059 bool absoluteDates )
00060 : TQWidget( parent, name ),
00061 mRuleField( 0 ),
00062 mFunctionStack( 0 ),
00063 mValueStack( 0 ),
00064 mAbsoluteDates( absoluteDates )
00065 {
00066 initFieldList( headersOnly, absoluteDates );
00067 initWidget();
00068
00069 if ( aRule )
00070 setRule( aRule );
00071 else
00072 reset();
00073 }
00074
00075 void KMSearchRuleWidget::setHeadersOnly( bool headersOnly )
00076 {
00077 KMSearchRule* srule = rule();
00078 TQCString currentText = srule->field();
00079 delete srule;
00080 initFieldList( headersOnly, mAbsoluteDates );
00081
00082 mRuleField->clear();
00083 mRuleField->insertStringList( mFilterFieldList );
00084 mRuleField->setSizeLimit( mRuleField->count() );
00085 mRuleField->adjustSize();
00086
00087 if (( currentText != "<message>") &&
00088 ( currentText != "<body>"))
00089 mRuleField->changeItem( TQString(TQString::fromAscii( currentText )), 0 );
00090 else
00091 mRuleField->changeItem( TQString(), 0 );
00092 }
00093
00094 void KMSearchRuleWidget::initWidget()
00095 {
00096 TQHBoxLayout * hlay = new TQHBoxLayout( this, 0, KDialog::spacingHint() );
00097
00098
00099 mRuleField = new TQComboBox( true, this, "mRuleField" );
00100 mRuleField->insertStringList( mFilterFieldList );
00101
00102 mRuleField->setSizeLimit( mRuleField->count() );
00103 mRuleField->adjustSize();
00104 hlay->addWidget( mRuleField );
00105
00106
00107 mFunctionStack = new TQWidgetStack( this, "mFunctionStack" );
00108
00109 mFunctionStack->setSizePolicy( TQSizePolicy::Preferred,TQSizePolicy::Fixed );
00110
00111 hlay->addWidget( mFunctionStack );
00112
00113 mValueStack = new TQWidgetStack( this, "mValueStack" );
00114 mValueStack->setSizePolicy( TQSizePolicy::Preferred,TQSizePolicy::Fixed );
00115 hlay->addWidget( mValueStack );
00116 hlay->setStretchFactor( mValueStack, 10 );
00117
00118 RuleWidgetHandlerManager::instance()->createWidgets( mFunctionStack,
00119 mValueStack,
00120 TQT_TQOBJECT(this) );
00121
00122
00123 setFocusProxy( mRuleField );
00124
00125 connect( mRuleField, TQT_SIGNAL( activated( const TQString & ) ),
00126 this, TQT_SLOT( slotRuleFieldChanged( const TQString & ) ) );
00127 connect( mRuleField, TQT_SIGNAL( textChanged( const TQString & ) ),
00128 this, TQT_SLOT( slotRuleFieldChanged( const TQString & ) ) );
00129 connect( mRuleField, TQT_SIGNAL( textChanged( const TQString & ) ),
00130 this, TQT_SIGNAL( fieldChanged( const TQString & ) ) );
00131 }
00132
00133 void KMSearchRuleWidget::setRule( KMSearchRule *aRule )
00134 {
00135 assert ( aRule );
00136
00137
00138
00139
00140
00141 int i = indexOfRuleField( aRule->field() );
00142
00143 mRuleField->blockSignals( true );
00144
00145 if ( i < 0 ) {
00146 mRuleField->changeItem( TQString::fromLatin1( aRule->field() ), 0 );
00147 i = 0;
00148 } else {
00149 mRuleField->changeItem( TQString(), 0 );
00150 }
00151
00152 mRuleField->setCurrentItem( i );
00153 mRuleField->blockSignals( false );
00154
00155 RuleWidgetHandlerManager::instance()->setRule( mFunctionStack, mValueStack,
00156 aRule );
00157 }
00158
00159 KMSearchRule* KMSearchRuleWidget::rule() const {
00160 const TQCString ruleField = ruleFieldToEnglish( mRuleField->currentText() );
00161 const KMSearchRule::Function function =
00162 RuleWidgetHandlerManager::instance()->function( ruleField,
00163 mFunctionStack );
00164 const TQString value =
00165 RuleWidgetHandlerManager::instance()->value( ruleField, mFunctionStack,
00166 mValueStack );
00167
00168 return KMSearchRule::createInstance( ruleField, function, value );
00169 }
00170
00171 void KMSearchRuleWidget::reset()
00172 {
00173 mRuleField->blockSignals( true );
00174 mRuleField->changeItem( "", 0 );
00175 mRuleField->setCurrentItem( 0 );
00176 mRuleField->blockSignals( false );
00177
00178 RuleWidgetHandlerManager::instance()->reset( mFunctionStack, mValueStack );
00179 }
00180
00181 void KMSearchRuleWidget::slotFunctionChanged()
00182 {
00183 const TQCString ruleField = ruleFieldToEnglish( mRuleField->currentText() );
00184 RuleWidgetHandlerManager::instance()->update( ruleField,
00185 mFunctionStack,
00186 mValueStack );
00187 }
00188
00189 void KMSearchRuleWidget::slotValueChanged()
00190 {
00191 const TQCString ruleField = ruleFieldToEnglish( mRuleField->currentText() );
00192 const TQString prettyValue =
00193 RuleWidgetHandlerManager::instance()->prettyValue( ruleField,
00194 mFunctionStack,
00195 mValueStack );
00196 emit contentsChanged( prettyValue );
00197 }
00198
00199 TQCString KMSearchRuleWidget::ruleFieldToEnglish( const TQString & i18nVal )
00200 {
00201 for ( int i = 0; i < SpecialRuleFieldsCount; ++i ) {
00202 if ( i18nVal == i18n( SpecialRuleFields[i].displayName ) )
00203 return SpecialRuleFields[i].internalName;
00204 }
00205 return i18nVal.latin1();
00206 }
00207
00208 int KMSearchRuleWidget::ruleFieldToId( const TQString & i18nVal )
00209 {
00210 for ( int i = 0; i < SpecialRuleFieldsCount; ++i ) {
00211 if ( i18nVal == i18n( SpecialRuleFields[i].displayName ) )
00212 return i;
00213 }
00214 return -1;
00215 }
00216
00217 static TQString displayNameFromInternalName( const TQString & internal )
00218 {
00219 for ( int i = 0; i < SpecialRuleFieldsCount; ++i ) {
00220 if ( internal == SpecialRuleFields[i].internalName )
00221 return i18n(SpecialRuleFields[i].displayName);
00222 }
00223 return internal.latin1();
00224 }
00225
00226
00227
00228 int KMSearchRuleWidget::indexOfRuleField( const TQCString & aName ) const
00229 {
00230 if ( aName.isEmpty() )
00231 return -1;
00232
00233 TQString i18n_aName = displayNameFromInternalName( aName );
00234
00235 for ( int i = 1; i < mRuleField->count(); ++i ) {
00236 if ( mRuleField->text( i ) == i18n_aName )
00237 return i;
00238 }
00239
00240 return -1;
00241 }
00242
00243 void KMSearchRuleWidget::initFieldList( bool headersOnly, bool absoluteDates )
00244 {
00245 mFilterFieldList.clear();
00246 mFilterFieldList.append("");
00247 if( !headersOnly ) {
00248 mFilterFieldList.append( i18n( SpecialRuleFields[Message].displayName ) );
00249 mFilterFieldList.append( i18n( SpecialRuleFields[Body].displayName ) );
00250 }
00251 mFilterFieldList.append( i18n( SpecialRuleFields[AnyHeader].displayName ) );
00252 mFilterFieldList.append( i18n( SpecialRuleFields[Recipients].displayName ) );
00253 mFilterFieldList.append( i18n( SpecialRuleFields[Size].displayName ) );
00254 if ( !absoluteDates )
00255 mFilterFieldList.append( i18n( SpecialRuleFields[AgeInDays].displayName ) );
00256 mFilterFieldList.append( i18n( SpecialRuleFields[Subject].displayName ) );
00257 mFilterFieldList.append( i18n( SpecialRuleFields[From].displayName ) );
00258 mFilterFieldList.append( i18n( SpecialRuleFields[To].displayName ) );
00259 mFilterFieldList.append( i18n( SpecialRuleFields[CC].displayName ) );
00260 mFilterFieldList.append( i18n( SpecialRuleFields[ReplyTo].displayName ) );
00261 mFilterFieldList.append( i18n( SpecialRuleFields[Organization].displayName ) );
00262
00263
00264
00265 mFilterFieldList.append("List-Id");
00266 mFilterFieldList.append("Resent-From");
00267 mFilterFieldList.append("X-Loop");
00268 mFilterFieldList.append("X-Mailing-List");
00269 mFilterFieldList.append("X-Spam-Flag");
00270 }
00271
00272 void KMSearchRuleWidget::slotRuleFieldChanged( const TQString & field )
00273 {
00274 RuleWidgetHandlerManager::instance()->update( ruleFieldToEnglish( field ),
00275 mFunctionStack,
00276 mValueStack );
00277 }
00278
00279
00280
00281
00282
00283
00284
00285 KMSearchRuleWidgetLister::KMSearchRuleWidgetLister( TQWidget *parent, const char* name, bool headersOnly, bool absoluteDates )
00286 : KWidgetLister( 2, FILTER_MAX_RULES, parent, name )
00287 {
00288 mRuleList = 0;
00289 mHeadersOnly = headersOnly;
00290 mAbsoluteDates = absoluteDates;
00291 }
00292
00293 KMSearchRuleWidgetLister::~KMSearchRuleWidgetLister()
00294 {
00295 }
00296
00297 void KMSearchRuleWidgetLister::setRuleList( TQPtrList<KMSearchRule> *aList )
00298 {
00299 assert ( aList );
00300
00301 if ( mRuleList && mRuleList != aList )
00302 regenerateRuleListFromWidgets();
00303
00304 mRuleList = aList;
00305
00306 if ( mWidgetList.first() )
00307 mWidgetList.first()->blockSignals(true);
00308
00309 if ( aList->count() == 0 ) {
00310 slotClear();
00311 mWidgetList.first()->blockSignals(false);
00312 return;
00313 }
00314
00315 int superfluousItems = (int)mRuleList->count() - mMaxWidgets ;
00316 if ( superfluousItems > 0 ) {
00317 kdDebug(5006) << "KMSearchRuleWidgetLister: Clipping rule list to "
00318 << mMaxWidgets << " items!" << endl;
00319
00320 for ( ; superfluousItems ; superfluousItems-- )
00321 mRuleList->removeLast();
00322 }
00323
00324
00325 setNumberOfShownWidgetsTo( TQMAX((int)mRuleList->count(),mMinWidgets)+1 );
00326
00327 setNumberOfShownWidgetsTo( TQMAX((int)mRuleList->count(),mMinWidgets) );
00328
00329
00330 TQPtrListIterator<KMSearchRule> rIt( *mRuleList );
00331 TQPtrListIterator<TQWidget> wIt( mWidgetList );
00332 for ( rIt.toFirst(), wIt.toFirst() ;
00333 rIt.current() && wIt.current() ; ++rIt, ++wIt ) {
00334 static_cast<KMSearchRuleWidget*>(*wIt)->setRule( (*rIt) );
00335 }
00336 for ( ; wIt.current() ; ++wIt )
00337 ((KMSearchRuleWidget*)(*wIt))->reset();
00338
00339 assert( mWidgetList.first() );
00340 mWidgetList.first()->blockSignals(false);
00341 }
00342
00343 void KMSearchRuleWidgetLister::setHeadersOnly( bool headersOnly )
00344 {
00345 TQPtrListIterator<TQWidget> wIt( mWidgetList );
00346 for ( wIt.toFirst() ; wIt.current() ; ++wIt ) {
00347 (static_cast<KMSearchRuleWidget*>(*wIt))->setHeadersOnly( headersOnly );
00348 }
00349 }
00350
00351 void KMSearchRuleWidgetLister::reset()
00352 {
00353 if ( mRuleList )
00354 regenerateRuleListFromWidgets();
00355
00356 mRuleList = 0;
00357 slotClear();
00358 }
00359
00360 TQWidget* KMSearchRuleWidgetLister::createWidget( TQWidget *parent )
00361 {
00362 return new KMSearchRuleWidget(parent, 0, 0, mHeadersOnly, mAbsoluteDates);
00363 }
00364
00365 void KMSearchRuleWidgetLister::clearWidget( TQWidget *aWidget )
00366 {
00367 if ( aWidget )
00368 ((KMSearchRuleWidget*)aWidget)->reset();
00369 }
00370
00371 void KMSearchRuleWidgetLister::regenerateRuleListFromWidgets()
00372 {
00373 if ( !mRuleList ) return;
00374
00375 mRuleList->clear();
00376
00377 TQPtrListIterator<TQWidget> it( mWidgetList );
00378 for ( it.toFirst() ; it.current() ; ++it ) {
00379 KMSearchRule *r = ((KMSearchRuleWidget*)(*it))->rule();
00380 if ( r )
00381 mRuleList->append( r );
00382 }
00383 }
00384
00385
00386
00387
00388
00389
00390
00391
00392
00393
00394 KMSearchPatternEdit::KMSearchPatternEdit(TQWidget *parent, const char *name, bool headersOnly, bool absoluteDates )
00395 : TQGroupBox( 1, Qt::Horizontal, parent, name )
00396 {
00397 setTitle( i18n("Search Criteria") );
00398 initLayout( headersOnly, absoluteDates );
00399 }
00400
00401 KMSearchPatternEdit::KMSearchPatternEdit(const TQString & title, TQWidget *parent, const char *name, bool headersOnly, bool absoluteDates)
00402 : TQGroupBox( 1, Qt::Horizontal, title, parent, name )
00403 {
00404 initLayout( headersOnly, absoluteDates );
00405 }
00406
00407 KMSearchPatternEdit::~KMSearchPatternEdit()
00408 {
00409 }
00410
00411 void KMSearchPatternEdit::initLayout(bool headersOnly, bool absoluteDates)
00412 {
00413
00414 mAllRBtn = new TQRadioButton( i18n("Match a&ll of the following"), this, "mAllRBtn" );
00415 mAnyRBtn = new TQRadioButton( i18n("Match an&y of the following"), this, "mAnyRBtn" );
00416
00417 mAllRBtn->setChecked(true);
00418 mAnyRBtn->setChecked(false);
00419
00420 TQButtonGroup *bg = new TQButtonGroup( this );
00421 bg->hide();
00422 bg->insert( mAllRBtn, (int)KMSearchPattern::OpAnd );
00423 bg->insert( mAnyRBtn, (int)KMSearchPattern::OpOr );
00424
00425
00426 mRuleLister = new KMSearchRuleWidgetLister( this, "swl", headersOnly, absoluteDates );
00427 mRuleLister->slotClear();
00428
00429
00430 connect( bg, TQT_SIGNAL(clicked(int)),
00431 this, TQT_SLOT(slotRadioClicked(int)) );
00432
00433 KMSearchRuleWidget *srw = (KMSearchRuleWidget*)mRuleLister->mWidgetList.first();
00434 if ( srw ) {
00435 connect( srw, TQT_SIGNAL(fieldChanged(const TQString &)),
00436 this, TQT_SLOT(slotAutoNameHack()) );
00437 connect( srw, TQT_SIGNAL(contentsChanged(const TQString &)),
00438 this, TQT_SLOT(slotAutoNameHack()) );
00439 } else
00440 kdDebug(5006) << "KMSearchPatternEdit: no first KMSearchRuleWidget, though slotClear() has been called!" << endl;
00441 }
00442
00443 void KMSearchPatternEdit::setSearchPattern( KMSearchPattern *aPattern )
00444 {
00445 assert( aPattern );
00446
00447 mRuleLister->setRuleList( aPattern );
00448
00449 mPattern = aPattern;
00450
00451 blockSignals(true);
00452 if ( mPattern->op() == KMSearchPattern::OpOr )
00453 mAnyRBtn->setChecked(true);
00454 else
00455 mAllRBtn->setChecked(true);
00456 blockSignals(false);
00457
00458 setEnabled( true );
00459 }
00460
00461 void KMSearchPatternEdit::setHeadersOnly( bool headersOnly )
00462 {
00463 mRuleLister->setHeadersOnly( headersOnly );
00464 }
00465
00466 void KMSearchPatternEdit::reset()
00467 {
00468 mRuleLister->reset();
00469
00470 blockSignals(true);
00471 mAllRBtn->setChecked( true );
00472 blockSignals(false);
00473
00474 setEnabled( false );
00475 }
00476
00477 void KMSearchPatternEdit::slotRadioClicked(int aIdx)
00478 {
00479 if ( mPattern )
00480 mPattern->setOp( (KMSearchPattern::Operator)aIdx );
00481 }
00482
00483 void KMSearchPatternEdit::slotAutoNameHack()
00484 {
00485 mRuleLister->regenerateRuleListFromWidgets();
00486 emit maybeNameChanged();
00487 }
00488
00489 #include "kmsearchpatternedit.moc"