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