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