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