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