kmail Library API Documentation

kmsearchpatternedit.cpp

00001 // -*- mode: C++; c-file-style: "gnu" -*-
00002 // kmsearchpatternedit.cpp
00003 // Author: Marc Mutz <Marc@Mutz.com>
00004 // This code is under GPL
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 // Definition of special rule field strings
00026 // Note: Also see KMSearchRule::matches() and ruleFieldToEnglish() if
00027 //       you change the following i18n-ized strings!
00028 // Note: The index of the values in the following array has to correspond to
00029 //       the value of the entries in the enum in KMSearchRuleWidget.
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 // class KMSearchRuleWidget
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   // initialize the header field combo box
00091   mRuleField = new QComboBox( true, this, "mRuleField" );
00092   mRuleField->insertStringList( mFilterFieldList );
00093   // don't show sliders when popping up this menu
00094   mRuleField->setSizeLimit( mRuleField->count() );
00095   mRuleField->adjustSize();
00096   hlay->addWidget( mRuleField );
00097 
00098   // initialize the function/value widget stack
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   // redirect focus to the header field combo box
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   //kdDebug(5006) << "KMSearchRuleWidget::setRule( "
00126   //              << aRule->asString() << " )" << endl;
00127 
00128   //--------------set the field
00129   int i = indexOfRuleField( aRule->field() );
00130 
00131   mRuleField->blockSignals( true );
00132 
00133   if ( i < 0 ) { // not found -> user defined field
00134     mRuleField->changeItem( QString::fromLatin1( aRule->field() ), 0 );
00135     i = 0;
00136   } else { // found in the list of predefined fields
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; // no pseudo header
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(""); // empty entry for user input
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   // these others only represent message headers and you can add to
00235   // them as you like
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 // class KMFilterActionWidgetLister (the filter action editor)
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() ) // move this below next 'if'?
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   // HACK to workaround regression in Qt 3.1.3 and Qt 3.2.0 (fixes bug #63537)
00302   setNumberOfShownWidgetsTo( QMAX((int)mRuleList->count(),mMinWidgets)+1 );
00303   // set the right number of widgets
00304   setNumberOfShownWidgetsTo( QMAX((int)mRuleList->count(),mMinWidgets) );
00305 
00306   // load the actions into the widgets
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 // class KMSearchPatternEdit
00368 //
00369 //=============================================================================
00370 
00371 KMSearchPatternEdit::KMSearchPatternEdit(QWidget *parent, const char *name, bool headersOnly, bool absoluteDates )
00372   : QGroupBox( 1/*columns*/, 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/*column*/, 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   //------------the radio buttons
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   //------------the list of KMSearchRuleWidget's
00403   mRuleLister = new KMSearchRuleWidgetLister( this, "swl", headersOnly, absoluteDates );
00404   mRuleLister->slotClear();
00405 
00406   //------------connect a few signals
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"
KDE Logo
This file is part of the documentation for kmail Library Version 3.3.2.
Documentation copyright © 1996-2004 the KDE developers.
Generated on Thu May 3 20:23:32 2007 by doxygen 1.4.2 written by Dimitri van Heesch, © 1997-2003